<?php

/**
 * Project:
 * Contenido Content Management System
 *
 * Description:
 * Class for the dynamic Contenido backend navigation
 *
 * Requirements:
 * @con_php_req 5.0
 *
 *
 * @package    Contenido Backend classes
 * @version    1.0.4
 * @author     Jan Lengowski
 * @copyright  four for business AG <www.4fb.de>
 * @license    http://www.contenido.org/license/LIZENZ.txt
 * @link       http://www.4fb.de
 * @link       http://www.contenido.org
 * @since      file available since contenido release <= 4.6
 *
 * {@internal
 *   created unknown
 *   modified 2008-06-30, Dominik Ziegler, add security fix
 *   modified 2008-07-08  Thorsten Granz, added option to disable menu hover effect. clicking is now possible again
 *   modified 2009-12-17, Dominik Ziegler, added support for username fallback and fixed double quote
 *   modified 2009-12-16  Corrected rendering of multiple apostrophes in anchors
 *   modified 2010-01-15, Dominik Ziegler, added frontend url to client name
 *   modified 2011-01-28, Dominik Ziegler, added check for client existance for link to frontend [#CON-378]
 *
 *   $Id$:
 * }}
 *
 */
if (!defined('CON_FRAMEWORK')) {
    die('Illegal call');
}

cInclude('includes', 'functions.api.string.php');
cInclude('includes', 'functions.api.images.php');

/**
 * Backend navigaton class. Renders the header navigation document containing the navigtion structure.
 *
 * @category    Contenido
 * @package     Backend
 * @subpackage  Navigation
 */
class Contenido_Navigation {

    /**
     * Flag to debug this vlass
     * @var  bool
     */
    var $debug = 0;

    /**
     * Array storing all data
     * @var  array
     */
    var $data = array();

    /**
     * Constructor. Loads the XML language file using XML_Doc.
     */
    function __construct() {
        global $cfg, $belang;

        $this->xml = new XML_Doc();
        $this->plugxml = new XML_Doc();

        // Load language file
        if ($this->xml->load($cfg['path']['xml'] . $cfg['lang'][$belang]) == false) {
            if ($this->xml->load($cfg['path']['xml'] . 'lang_en_US.xml') == false) {
                die('Unable to load any XML language file');
            }
        }
    }

    /**
     * Extracts caption from the XML language file including plugins extended multilang version.
     *
     * @param  string  $location  The location of navigation item caption. Feasible values are
     *                            - "{xmlFilePath};{XPath}": Path to XML File and the XPath value
     *                                                       separated by semicolon. This type is used
     *                                                       to extract caption from a plugin XML file.
     *                            - "{XPath}": XPath value to extract caption from Contenido XML file
     * @return  string  The found caption
     */
    function getName($location) {
        global $cfg, $belang;

        # If a ";" is found entry is from a plugin -> explode location, first is xml file path,
        # second is xpath location in xml file
        if (strstr($location, ';')) {

            $locs = explode(';', $location);
            $file = trim($locs[0]);
            $xpath = trim($locs[1]);

            $filepath = explode('/', $file);
            $counter = count($filepath) - 1;

            if ($filepath[$counter] == '') {
                unset($filepath[$counter]);
                $counter--;
            }

            if (strstr($filepath[$counter], '.xml')) {
                $filename = $filepath[$counter];
                unset($filepath[$counter]);
                $counter--;
            }

            $filepath[($counter + 1)] = '';

            $filepath = implode('/', $filepath);

            if ($this->plugxml->load($cfg['path']['plugins'] . $filepath . $cfg['lang'][$belang]) == false) {
                if (!isset($filename)) {
                    $filename = 'lang_en_US.xml';
                }
                if ($this->plugxml->load($cfg['path']['plugins'] . $filepath . $filename) == false) {
                    die("Unable to load $filepath XML language file");
                }
            }
            $caption = $this->plugxml->valueOf($xpath);
        } else {
            $caption = $this->xml->valueOf($location);
        }

        return $caption;
    }

    /**
     * Reads and fills the navigation structure data
     *
     * @return  void
     */
    function _buildHeaderData() {
        global $cfg, $perm, $belang;

        $db = new DB_ConLite();
        $db2 = new DB_ConLite();

        # Load main items
        $sql = "SELECT idnavm, location FROM " . $cfg['tab']['nav_main'] . " ORDER BY idnavm";

        $db->query($sql);

        # Loop result and build array
        while ($db->next_record()) {

            # Extract names from the XML document.
            $main = $this->getName($db->f('location'));

            # Build data array
            $this->data[$db->f('idnavm')] = array($main);

            $sql = "SELECT
                        a.location AS location, b.name AS area, b.relevant
                    FROM
                        " . $cfg['tab']['nav_sub'] . " AS a, " . $cfg['tab']['area'] . " AS b
                    WHERE
                        a.idnavm = '" . $db->f('idnavm') . "' AND
                        a.level  = '0' AND
                        b.idarea = a.idarea AND
                        a.online = '1' AND
                        b.online = '1'
                    ORDER BY
                        a.idnavs";

            $db2->query($sql);

            while ($db2->next_record()) {
                $area = $db2->f('area');
                if ($perm->have_perm_area_action($area) || $db2->f('relevant') == 0) {
                    # Extract names from the XML document.
                    $name = $this->getName($db2->f('location'));
                    $this->data[$db->f('idnavm')][] = array($name, $area);
                }
            }
        }

        # debugging information
        if ($this->debug) {
            echo '<pre>' . print_r($this->data, true) . '</pre>';
        }
    }

    /**
     * Function to build the Contenido header document for backend
     *
     * @param  int  $lang  The language to use for header doc creation
     */
    function buildHeader($lang) {

        global $cfg, $sess, $client, $auth, $cfgClient;

        $this->_buildHeaderData();

        $main = new Template();
        $sub = new Template();

        $cnt = 0;
        $t_sub = '';
        $numSubMenus = 0;

        $properties = new PropertyCollection();
        $clientImage = $properties->getValue('idclient', $client, 'backend', 'clientimage', false);

        $sJsEvents = '';
        foreach ($this->data as $id => $item) {
            $sub->reset();
            $genSubMenu = false;

            foreach ($item as $key => $value) {
                if (is_array($value)) {
                    $sub->set('s', 'SUBID', 'sub_' . $id);

                    // create sub menu link
                    $link = new cHTMLLink();
                    $link->disableAutomaticParameterAppend();
                    $link->setClass('sub');
                    $link->setID('sub_' . $value[1]);
                    $link->setLink($sess->url('frameset.php?area=' . $value[1]));
                    $link->setTargetFrame('content');
                    $link->setContent($value[0]);

                    if ($cfg['help'] == true) {
                        $sJsEvents .= "\n\t" . '$("#sub_' . $value[1] . '").click(function(){ $("#help").attr("data", "' . $value[1] . '"); });';
                    }
                    $sub->set('d', 'CAPTION', $link->render());

                    $sub->next();
                    $genSubMenu = true;
                }
            }

            if ($genSubMenu == true) {
                $link = new cHTMLLink();
                $link->setClass('main');
                $link->setID('main_' . $id);
                $link->setLink('javascript://');
                $link->setAttribute('ident', 'sub_' . $id);
                $link->setContent($item[0]);

                $main->set('d', 'CAPTION', $link->render());
                $main->next();

                $numSubMenus++;
            } else {
                # first entry in array is a main menu item
            }

            # generate a sub menu item.
            $t_sub .= $sub->generate($cfg['path']['templates'] . $cfg['templates']['submenu'], true);
            $cnt ++;
        }

        if ($cfg['help'] == true) {
            $sJsEvents .= "\n\t" . 'help.setArea("mycontenido");';
        }

        if ($numSubMenus == 0) {
            $main->set('d', 'CAPTION', '&nbsp;');
            $main->next();
        }

        $main->set('s', 'SUBMENUS', $t_sub);

        // my contenido link
        $oMyConLink = new cHTMLLink();
        $oMyConLink->setClass('main');
        $oMyConLink->setTargetFrame('content');
        $oMyConLink->attachEventDefinition('help_mycontenido', 'onclick', 'help.setArea("mycontenido")');
        $oMyConLink->setLink($sess->url("frameset.php?area=mycontenido&frame=4"));
        $oMyConLink->setContent('<img src="' . $cfg['path']['contenido_fullhtml'] . $cfg['path']['images'] . 'my_contenido.gif" border="0" alt="MyConLite" id="imgMyContenido" title="MyConLite">');
        $main->set('s', 'MYCONLITE', $oMyConLink->render());

        // info link
        $oInfoLink = new cHTMLLink();
        $oInfoLink->setClass('main');
        $oInfoLink->setTargetFrame('content');
        $oInfoLink->attachEventDefinition('help_info', 'onclick', 'help.setArea("info")');
        $oInfoLink->setLink($sess->url('frameset.php?area=info&frame=4'));
        $oInfoLink->setContent('<img src="' . $cfg['path']['contenido_fullhtml'] . $cfg['path']['images'] . 'info.gif" border="0" alt="Info" title="Info" id="imgInfo">');
        $main->set('s', 'INFO', $oInfoLink->render());

        $main->set('s', 'LOGOUT', $sess->url('logout.php'));

        if ($cfg['help'] == true) {
            // help link
            $oHelpLink = new cHTMLLink();
            $oHelpLink->setID('help');
            $oHelpLink->setClass('main');
            $oHelpLink->setLink('javascript://');
            $oHelpLink->setEvent('click', 'callHelp($(\'#help\').attr(\'data\'));');
            $oHelpLink->setContent('<img src="' . $cfg['path']['contenido_fullhtml'] . $cfg['path']['images'] . 'but_help.gif" border="0" alt="Hilfe" title="Hilfe">');
            $main->set('s', 'HELP', $oHelpLink->render());
        } else {
            $main->set('s', 'HELP', '');
        }

        $classuser = new User();
        $classclient = new Client();

        if (getEffectiveSetting('system', 'clickmenu') == 'true') {
            // set click menu
            $main->set('s', 'HEADER_MENU_OBJ', 'HeaderClickMenu');
            $main->set('s', 'HEADER_MENU_OPTIONS', '{menuId: "main_0", subMenuId: "sub_0"}');
        } else {
            // set delay menu
            $mouseOver = getEffectiveSetting('system', 'delaymenu_mouseover', 300);
            $mouseOot = getEffectiveSetting('system', 'delaymenu_mouseout', 1000);
            $main->set('s', 'HEADER_MENU_OBJ', 'HeaderDelayMenu');
            $main->set('s', 'HEADER_MENU_OPTIONS', '{menuId: "main_0", subMenuId: "sub_0", mouseOverDelay: ' . $mouseOver . ', mouseOutDelay: ' . $mouseOot . '}');
        }

        $main->set('s', 'ACTION', $sess->url('index.php'));
        $main->set('s', 'LANG', $this->_renderLanguageSelect());
        $main->set('s', 'WIDTH', '');

        $sClientName = $classclient->getClientName($client);
        if (strlen($sClientName) > 25) {
            $sClientName = capiStrTrimHard($sClientName, 25);
        }

        $client = Contenido_Security::toInteger($client);
        if ($client == 0) {
            $sClientNameTemplate = '<b>' . i18n("Client") . ':</b> %s';
            $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientName));
        } else {
            $sClientNameTemplate = '<b>' . i18n("Client") . ':</b> <a href="%s" target="_blank">%s</a>';

            $sClientName = $classclient->getClientName($client) . ' (' . $client . ')';
            $sClientUrl = $cfgClient[$client]["path"]["htmlpath"];

            if ($clientImage !== false && $clientImage != "" && file_exists($cfgClient[$client]['path']['frontend'] . $clientImage)) {
                $sClientImageTemplate = '<img src="%s" alt="%s" title="%s" />';

                $sThumbnailPath = capiImgScale($cfgClient[$client]['path']['frontend'] . $clientImage, 80, 25, 0, 1);
                $sClientImageTag = sprintf($sClientImageTemplate, $sThumbnailPath, $sClientName, $sClientName);

                $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientUrl, $sClientImageTag));
            } else {
                $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientUrl, $sClientName));
            }
        }

        $main->set('s', 'CHOSENUSER', "<b>" . i18n("User") . ":</b> " . $classuser->getRealname($auth->auth["uid"], true));
        $main->set('s', 'SID', $sess->id);
        $main->set('s', 'MAINLOGINLINK', $sess->url("frameset.php?area=mycontenido&frame=4"));

        // additional footer javascript
        $footerJs = '';
        if ($sJsEvents !== '') {
            $footerJs = '$(document).ready(function(){' . $sJsEvents . '});';
        }
        $main->set('s', 'FOOTER_JS', $footerJs);

        $main->generate($cfg['path']['templates'] . $cfg['templates']['header']);
    }

    /**
     * Renders the language select box
     * 
     * @todo recode and remove direct sql calls
     *
     * @return  string
     */
    function _renderLanguageSelect() {
        global $cfg, $client, $lang;

        $tpl = new Template();

        $tpl->set('s', 'NAME', 'changelang');
        $tpl->set('s', 'CLASS', 'text_medium');
        $tpl->set('s', 'ID', 'cLanguageSelect');
        $tpl->set('s', 'OPTIONS', 'onchange="changeContenidoLanguage(this.value)"');

        $availableLanguages = new cApiLanguageCollection();

        if (getEffectiveSetting('system', 'languageorder', 'name') == 'name') {
            $availableLanguages->select('', '', 'name ASC');
        } else {
            $availableLanguages->select('', '', 'idlang ASC');
        }

        $db = new DB_ConLite();

        if ($availableLanguages->count() > 0) {
            while ($myLang = $availableLanguages->nextAccessible()) {
                $key = $myLang->get('idlang');
                $value = $myLang->get('name');

                // I want to get rid of such silly constructs very soon :)

                $sql = "SELECT idclient FROM " . $cfg['tab']['clients_lang'] . " WHERE
                        idlang = '" . Contenido_Security::toInteger($key) . "'";

                $db->query($sql);

                if ($db->next_record()) {
                    if ($db->f('idclient') == $client) {
                        if ($key == $lang) {
                            $tpl->set('d', 'SELECTED', 'selected');
                        } else {
                            $tpl->set('d', 'SELECTED', '');
                        }

                        if (strlen($value) > 20) {
                            $value = capiStrTrimHard($value, 20);
                        }

                        $tpl->set('d', 'VALUE', $key);
                        $tpl->set('d', 'CAPTION', $value . ' (' . $key . ')');
                        $tpl->next();
                    }
                }
            }
        } else {
            $tpl->set('d', 'VALUE', 0);
            $tpl->set('d', 'CAPTION', i18n('-- No Language available --'));
            $tpl->next();
        }

        return $tpl->generate($cfg['path']['templates'] . $cfg['templates']['generic_select'], true);
    }

}
