00001 <?php
00002
00006 class OxNavigationTree extends oxSuperCfg
00007 {
00008
00012 protected $_oDom = null;
00013
00017 protected $_oInitialDom = null;
00018
00024 protected $_sDynIncludeUrl = null;
00025
00031 protected $_aSupportedExpathXmlEncodings = array('utf-8', 'utf-16', 'iso-8859-1', 'us-ascii');
00032
00040 protected function _cleanEmptyParents($oDom, $sParentXPath, $sChildXPath)
00041 {
00042 $oXPath = new DomXPath($oDom);
00043 $oNodeList = $oXPath->query($sParentXPath);
00044
00045 foreach ($oNodeList as $oNode) {
00046 $sId = $oNode->getAttribute('id');
00047 $oChildList = $oXPath->query("{$sParentXPath}[@id='$sId']/$sChildXPath");
00048 if (!$oChildList->length) {
00049 $oNode->parentNode->removeChild($oNode);
00050 }
00051 }
00052 }
00053
00059 protected function _addLinks($oDom)
00060 {
00061 $sURL = 'index.php?';
00062 $oXPath = new DomXPath($oDom);
00063
00064
00065 $oNodeList = $oXPath->query("//SUBMENU[@cl]");
00066 foreach ($oNodeList as $oNode) {
00067
00068 $sCl = $oNode->getAttribute('cl');
00069 $sCl = $sCl ? "cl=$sCl" : '';
00070
00071
00072 $sParam = $oNode->getAttribute('clparam');
00073 $sParam = $sParam ? "&$sParam" : '';
00074
00075
00076 $oNode->setAttribute('link', "{$sURL}{$sCl}{$sParam}");
00077 }
00078 }
00079
00086 protected function _loadFromFile($sMenuFile, $oDom)
00087 {
00088 $blMerge = false;
00089 $oDomFile = new DomDocument();
00090 $oDomFile->preserveWhiteSpace = false;
00091 if (!@$oDomFile->load($sMenuFile)) {
00092 $blMerge = true;
00093 } elseif (is_readable($sMenuFile) && ($sXml = @file_get_contents($sMenuFile))) {
00094
00095
00096 if (getStr()->preg_match("/encoding\=(.*)\?>/", $sXml, $aMatches) !== 0) {
00097 if (isset($aMatches[1])) {
00098 $sCurrEncoding = trim($aMatches[1], "\"");
00099 if (!in_array(strtolower($sCurrEncoding), $this->_aSupportedExpathXmlEncodings)) {
00100 $sXml = str_replace($aMatches[1], "\"UTF-8\"", $sXml);
00101 $sXml = iconv($sCurrEncoding, "UTF-8", $sXml);
00102 }
00103 }
00104 }
00105
00106
00107 if (@$oDomFile->loadXml($sXml)) {
00108 $blMerge = true;
00109 }
00110 }
00111
00112 if ($blMerge) {
00113 $this->_merge($oDomFile, $oDom);
00114 }
00115 }
00116
00122 protected function _addDynLinks($oDom)
00123 {
00124 $myConfig = $this->getConfig();
00125 $myUtilsFile = oxRegistry::get("oxUtilsFile");
00126
00127 $sURL = 'index.php?';
00128
00129 $oXPath = new DomXPath($oDom);
00130 $oNodeList = $oXPath->query("//OXMENU[@type='dyn']/MAINMENU/SUBMENU");
00131
00132 foreach ($oNodeList as $oNode) {
00133
00134
00135 $sCl = $oNode->getAttribute('cl');
00136 $sCl = "cl=dynscreen&menu=$sCl";
00137
00138
00139 $sParam = $oNode->getAttribute('clparam');
00140 $sParam = $sParam ? "&$sParam" : '';
00141
00142
00143 if (!$oNode->getAttribute('list')) {
00144 $oNode->setAttribute('list', 'dynscreen_list');
00145 $oNode->setAttribute('listparam', 'menu=' . $oNode->getAttribute('cl'));
00146 }
00147
00148
00149 $oNode->setAttribute('link', "{$sURL}{$sCl}{$sParam}");
00150
00151
00152 $oNode->parentNode->setAttribute('id', 'dyn_menu');
00153
00154
00155
00156
00157 $sFile = $oNode->getAttribute('cl');
00158
00159
00160
00161 if ($myUtilsFile->checkFile("{$this->_sDynIncludeUrl}pages/{$sFile}_about.php")) {
00162 $oTabElem = new DOMElement('TAB');
00163 $oNode->appendChild($oTabElem);
00164 $oTabElem->setAttribute('external', 'true');
00165 $oTabElem->setAttribute('location', "{$this->_sDynIncludeUrl}pages/{$sFile}_about.php");
00166 $oTabElem->setAttribute('id', 'dyn_about');
00167 }
00168
00169
00170 if ($myUtilsFile->checkFile("{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php")) {
00171 $oTabElem = new DOMElement('TAB');
00172 $oNode->appendChild($oTabElem);
00173 $oTabElem->setAttribute('external', 'true');
00174 $oTabElem->setAttribute('location', "{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php");
00175 $oTabElem->setAttribute('id', 'dyn_interface');
00176 }
00177
00178
00179 if (file_exists($myConfig->getConfigParam('sShopDir') . "/application/controllers/admin/{$sFile}.php")) {
00180 $oTabElem = new DOMElement('TAB');
00181 $oNode->appendChild($oTabElem);
00182 $oTabElem->setAttribute('id', 'dyn_interface');
00183 $oTabElem->setAttribute('cl', $sFile);
00184 }
00185 }
00186 }
00187
00193 protected function _sessionizeLocalUrls($oDom)
00194 {
00195 $sURL = $this->_getAdminUrl();
00196 $oXPath = new DomXPath($oDom);
00197 $oStr = getStr();
00198 foreach (array('url', 'link') as $sAttrType) {
00199 foreach ($oXPath->query("//OXMENU//*[@$sAttrType]") as $oNode) {
00200 $sLocalUrl = $oNode->getAttribute($sAttrType);
00201 if (strpos($sLocalUrl, 'index.php?') === 0) {
00202 $sLocalUrl = $oStr->preg_replace('#^index.php\?#', $sURL, $sLocalUrl);
00203 $oNode->setAttribute($sAttrType, $sLocalUrl);
00204 }
00205 }
00206 }
00207 }
00208
00214 protected function _checkRights($oDom)
00215 {
00216 $oXPath = new DomXPath($oDom);
00217 $oNodeList = $oXPath->query('//*[@rights or @norights]');
00218
00219 foreach ($oNodeList as $oNode) {
00220
00221 if (($sReq = $oNode->getAttribute('rights'))) {
00222 $aPerm = explode(',', $sReq);
00223 foreach ($aPerm as $sPerm) {
00224 if ($sPerm && !$this->_hasRights($sPerm)) {
00225 $oNode->parentNode->removeChild($oNode);
00226 }
00227 }
00228
00229 } elseif (($sNoReq = $oNode->getAttribute('norights'))) {
00230 $aPerm = explode(',', $sNoReq);
00231 foreach ($aPerm as $sPerm) {
00232 if ($sPerm && $this->_hasRights($sPerm)) {
00233 $oNode->parentNode->removeChild($oNode);
00234 }
00235 }
00236 }
00237 }
00238 }
00239
00245 protected function _checkGroups($oDom)
00246 {
00247 $oXPath = new DomXPath($oDom);
00248 $oNodeList = $oXPath->query("//*[@nogroup or @group]");
00249
00250 foreach ($oNodeList as $oNode) {
00251
00252 if (($sReq = $oNode->getAttribute('group'))) {
00253 $aPerm = explode(',', $sReq);
00254 foreach ($aPerm as $sPerm) {
00255 if ($sPerm && !$this->_hasGroup($sPerm)) {
00256 $oNode->parentNode->removeChild($oNode);
00257 }
00258 }
00259
00260 } elseif (($sNoReq = $oNode->getAttribute('nogroup'))) {
00261 $aPerm = explode(',', $sNoReq);
00262 foreach ($aPerm as $sPerm) {
00263 if ($sPerm && $this->_hasGroup($sPerm)) {
00264 $oNode->parentNode->removeChild($oNode);
00265 }
00266 }
00267 }
00268 }
00269 }
00270
00278 protected function _checkDemoShopDenials($oDom)
00279 {
00280 if (!$this->getConfig()->isDemoShop()) {
00281
00282 return;
00283 }
00284
00285 $oXPath = new DomXPath($oDom);
00286 $oNodeList = $oXPath->query("//*[@disableForDemoShop]");
00287 foreach ($oNodeList as $oNode) {
00288 if ($oNode->getAttribute('disableForDemoShop')) {
00289 $oNode->parentNode->removeChild($oNode);
00290 }
00291 }
00292 }
00293
00300 protected function _copyAttributes($oDomElemTo, $oDomElemFrom)
00301 {
00302 foreach ($oDomElemFrom->attributes as $oAttr) {
00303 $oDomElemTo->setAttribute($oAttr->nodeName, $oAttr->nodeValue);
00304 }
00305 }
00306
00316 protected function _mergeNodes($oDomElemTo, $oDomElemFrom, $oXPathTo, $oDomDocTo, $sQueryStart)
00317 {
00318 foreach ($oDomElemFrom->childNodes as $oFromNode) {
00319 if ($oFromNode->nodeType === XML_ELEMENT_NODE) {
00320
00321 $sFromAttrName = $oFromNode->getAttribute('id');
00322 $sFromNodeName = $oFromNode->tagName;
00323
00324
00325 $sQuery = "{$sQueryStart}/{$sFromNodeName}[@id='{$sFromAttrName}']";
00326 $oCurNode = $oXPathTo->query($sQuery);
00327
00328
00329 if ($oCurNode->length == 0) {
00330 $oDomElemTo->appendChild($oDomDocTo->importNode($oFromNode, true));
00331 } else {
00332
00333 $oCurNode = $oCurNode->item(0);
00334
00335
00336 $this->_copyAttributes($oCurNode, $oFromNode);
00337
00338 if ($oFromNode->childNodes->length) {
00339 $this->_mergeNodes($oCurNode, $oFromNode, $oXPathTo, $oDomDocTo, $sQuery);
00340 }
00341 }
00342 }
00343 }
00344 }
00345
00352 protected function _merge($oDomNew, $oDom)
00353 {
00354 $oXPath = new DOMXPath($oDom);
00355 $this->_mergeNodes($oDom->documentElement, $oDomNew->documentElement, $oXPath, $oDom, '/OX');
00356 }
00357
00367 public function getTabs($sId, $iAct, $blSetActive = true)
00368 {
00369 $oXPath = new DOMXPath($this->getDomXml());
00370
00371 $oNodeList = $oXPath->query("//SUBMENU[@cl='$sId']/TAB | //SUBMENU[@list='$sId']/TAB | //SUBMENU/../TAB[@cl='$sId']");
00372
00373 $iAct = ($iAct > $oNodeList->length) ? ($oNodeList->length - 1) : $iAct;
00374
00375 if ($blSetActive) {
00376 foreach ($oNodeList as $iPos => $oNode) {
00377 if ($iPos == $iAct) {
00378
00379 $oNode->setAttribute('active', 1);
00380 }
00381 }
00382 }
00383
00384 return $oNodeList;
00385 }
00386
00395 public function getActiveTab($sId, $iAct)
00396 {
00397 $sTab = null;
00398 $oNodeList = $this->getTabs($sId, $iAct, false);
00399 $iAct = ($iAct > $oNodeList->length) ? ($oNodeList->length - 1) : $iAct;
00400 if ($oNodeList->length && ($oNode = $oNodeList->item($iAct))) {
00401 $sTab = $oNode->getAttribute('cl');
00402 }
00403
00404 return $sTab;
00405 }
00406
00414 public function getBtn($sClass)
00415 {
00416 $oButtons = null;
00417 $oXPath = new DOMXPath($this->getDomXml());
00418 $oNodeList = $oXPath->query("//TAB[@cl='$sClass']/../BTN");
00419 if ($oNodeList->length) {
00420 $oButtons = new stdClass();
00421 foreach ($oNodeList as $oNode) {
00422 $sBtnID = $oNode->getAttribute('id');
00423 $oButtons->$sBtnID = 1;
00424 }
00425 }
00426
00427 return $oButtons;
00428 }
00429
00435 protected function _getMenuFiles()
00436 {
00437 $myConfig = $this->getConfig();
00438 $myOxUtlis = oxRegistry::getUtils();
00439
00440 $sFullAdminDir = getShopBasePath() . 'application/views/admin';
00441 $sMenuFile = "/menu.xml";
00442
00443 $sTmpDir = $myConfig->getConfigParam('sCompileDir');
00444 $sDynLang = $this->_getDynMenuLang();
00445 $sLocalDynPath = "{$sTmpDir}{$sDynLang}_dynscreen.xml";
00446
00447
00448
00449 if (file_exists($sFullAdminDir . $sMenuFile)) {
00450 $aFilesToLoad[] = $sFullAdminDir . $sMenuFile;
00451 }
00452
00453
00454 if (file_exists("$sFullAdminDir/user.xml")) {
00455 $aFilesToLoad[] = "$sFullAdminDir/user.xml";
00456 }
00457
00458
00459 $sPath = getShopBasePath();
00460 $oModulelist = oxNew('oxmodulelist');
00461 $aActiveModuleInfo = $oModulelist->getActiveModuleInfo();
00462 if (is_array($aActiveModuleInfo)) {
00463 foreach ($aActiveModuleInfo as $sModulePath) {
00464 $sFullPath = $sPath . "modules/" . $sModulePath;
00465
00466 if (is_dir($sFullPath)) {
00467
00468 $sMenuFile = $sFullPath . "/menu.xml";
00469 if (file_exists($sMenuFile) && is_readable($sMenuFile)) {
00470 $aFilesToLoad[] = $sMenuFile;
00471 }
00472 }
00473 }
00474 }
00475
00476 $blLoadDynContents = $myConfig->getConfigParam('blLoadDynContents');
00477 $sShopCountry = $myConfig->getConfigParam('sShopCountry');
00478
00479
00480 $sDynPath = null;
00481
00482 if ($blLoadDynContents) {
00483 if ($sShopCountry) {
00484 $sRemoteDynUrl = $this->_getDynMenuUrl($sDynLang, $blLoadDynContents);
00485
00486
00487 $blLoadRemote = oxRegistry::getSession()->getVariable("loadedremotexml");
00488
00489
00490 if ((!isset($blLoadRemote) || $blLoadRemote) && ($sDynPath = $myOxUtlis->getRemoteCachePath($sRemoteDynUrl, $sLocalDynPath))) {
00491 $sDynPath = $this->_checkDynFile($sDynPath);
00492 }
00493
00494
00495 oxRegistry::getSession()->setVariable("loadedremotexml", $sDynPath ? true : false);
00496 }
00497 } else {
00498 if ($sShopCountry) {
00499
00500 }
00501 }
00502
00503
00504 if ($sDynPath) {
00505 $aFilesToLoad[] = $sDynPath;
00506 }
00507
00508 return $aFilesToLoad;
00509 }
00510
00518 protected function _checkDynFile($sDynFilePath)
00519 {
00520 $sDynFile = null;
00521 if (file_exists($sDynFilePath)) {
00522 $sLine = null;
00523 if (($rHandle = @fopen($sDynFilePath, 'r'))) {
00524 $sLine = stream_get_line($rHandle, 100, "?>");
00525 fclose($rHandle);
00526
00527
00528 if ($sLine && stripos($sLine, '<?xml') !== false) {
00529 $sDynFile = $sDynFilePath;
00530 }
00531 }
00532
00533
00534 if (!$sDynFile) {
00535 @unlink($sDynFilePath);
00536 }
00537 }
00538
00539 return $sDynFile;
00540 }
00541
00553 protected function _processCachedFile($sCacheContents)
00554 {
00555
00556 return $sCacheContents;
00557 }
00558
00564 protected function _getInitialDom()
00565 {
00566 if ($this->_oInitialDom === null) {
00567 $myOxUtlis = oxRegistry::getUtils();
00568
00569 if (is_array($aFilesToLoad = $this->_getMenuFiles())) {
00570
00571
00572 $blReload = false;
00573 $sDynLang = $this->_getDynMenuLang();
00574
00575 $sShopId = $this->getConfig()->getActiveShop()->getShopId();
00576 $sCacheName = 'menu_' . $sDynLang . $sShopId . '_xml';
00577 $sCacheFile = $myOxUtlis->getCacheFilePath($sCacheName);
00578 $sCacheContents = $myOxUtlis->fromFileCache($sCacheName);
00579 if ($sCacheContents && file_exists($sCacheFile) && ($iCacheModTime = filemtime($sCacheFile))) {
00580 foreach ($aFilesToLoad as $sDynPath) {
00581 if ($iCacheModTime < filemtime($sDynPath)) {
00582 $blReload = true;
00583 }
00584 }
00585 } else {
00586 $blReload = true;
00587 }
00588
00589 $this->_oInitialDom = new DOMDocument();
00590 if ($blReload) {
00591
00592 $this->_oInitialDom->appendChild(new DOMElement('OX'));
00593
00594 foreach ($aFilesToLoad as $sDynPath) {
00595 $this->_loadFromFile($sDynPath, $this->_oInitialDom);
00596 }
00597
00598
00599 $this->_addLinks($this->_oInitialDom);
00600
00601
00602 $this->_addDynLinks($this->_oInitialDom);
00603
00604
00605 $myOxUtlis->toFileCache($sCacheName, $this->_oInitialDom->saveXML());
00606 } else {
00607 $sCacheContents = $this->_processCachedFile($sCacheContents);
00608
00609 $this->_oInitialDom->preserveWhiteSpace = false;
00610 $this->_oInitialDom->loadXML($sCacheContents);
00611 }
00612
00613
00614 $this->_sessionizeLocalUrls($this->_oInitialDom);
00615 }
00616 }
00617
00618 return $this->_oInitialDom;
00619 }
00620
00626 public function getDomXml()
00627 {
00628 if ($this->_oDom === null) {
00629 $this->_oDom = clone $this->_getInitialDom();
00630
00631
00632 $this->_checkGroups($this->_oDom);
00633
00634
00635 $this->_checkRights($this->_oDom);
00636
00637
00638 $this->_checkDemoShopDenials($this->_oDom);
00639
00640
00641 $this->_cleanEmptyParents($this->_oDom, '//SUBMENU[@id][@list]', 'TAB');
00642 $this->_cleanEmptyParents($this->_oDom, '//MAINMENU[@id]', 'SUBMENU');
00643 }
00644
00645 return $this->_oDom;
00646 }
00647
00655 public function getListNodes($aNodes)
00656 {
00657 $oXPath = new DOMXPath($this->getDomXml());
00658 $oNodeList = $oXPath->query("//SUBMENU[@cl='" . implode("' or @cl='", $aNodes) . "']");
00659
00660 return ($oNodeList->length) ? $oNodeList : null;
00661 }
00662
00668 public function markNodeActive($sNodeId)
00669 {
00670 $oXPath = new DOMXPath($this->getDomXml());
00671 $oNodeList = $oXPath->query("//*[@cl='{$sNodeId}' or @list='{$sNodeId}']");
00672
00673 if ($oNodeList->length) {
00674 foreach ($oNodeList as $oNode) {
00675
00676 $oNode->setAttribute('active', 1);
00677 $oNode->parentNode->setAttribute('active', 1);
00678 }
00679 }
00680
00681 }
00682
00690 public function getListUrl($sId)
00691 {
00692 $sUrl = null;
00693 $oXPath = new DOMXPath($this->getDomXml());
00694 $oNodeList = $oXPath->query("//SUBMENU[@cl='{$sId}']");
00695 if ($oNodeList->length && ($oNode = $oNodeList->item(0))) {
00696 $sCl = $oNode->getAttribute('list');
00697 $sCl = $sCl ? "cl=$sCl" : '';
00698
00699 $sParams = $oNode->getAttribute('listparam');
00700 $sParams = $sParams ? "&$sParams" : '';
00701
00702 $sUrl = "{$sCl}{$sParams}";
00703 }
00704
00705 return $sUrl;
00706 }
00707
00716 public function getEditUrl($sId, $iActTab)
00717 {
00718 $sUrl = null;
00719 $oXPath = new DOMXPath($this->getDomXml());
00720 $oNodeList = $oXPath->query("//SUBMENU[@cl='{$sId}']/TAB");
00721
00722 $iActTab = ($iActTab > $oNodeList->length) ? ($oNodeList->length - 1) : $iActTab;
00723 if ($oNodeList->length && ($oActTab = $oNodeList->item($iActTab))) {
00724
00725 if ($oActTab->getAttribute('external')) {
00726 $sUrl = $oActTab->getAttribute('location');
00727 } else {
00728 $sCl = $oActTab->getAttribute('cl');
00729 $sCl = $sCl ? "cl={$sCl}" : '';
00730
00731 $sParams = $oActTab->getAttribute('clparam');
00732 $sParams = $sParams ? "&{$sParams}" : '';
00733
00734 $sUrl = "{$sCl}{$sParams}";
00735 }
00736 }
00737
00738 return $sUrl;
00739 }
00740
00746 protected function _getAdminUrl()
00747 {
00748 $myConfig = $this->getConfig();
00749
00750 if (($sAdminSslUrl = $myConfig->getConfigParam('sAdminSSLURL'))) {
00751 $sURL = trim($sAdminSslUrl, '/');
00752 } else {
00753 $sURL = trim($myConfig->getConfigParam('sShopURL'), '/') . '/admin';
00754 }
00755
00756 return oxRegistry::get("oxUtilsUrl")->processUrl("{$sURL}/index.php", false);
00757 }
00758
00766 protected function _hasRights($sRights)
00767 {
00768 return $this->getUser()->oxuser__oxrights->value == $sRights;
00769 }
00770
00778 protected function _hasGroup($sGroupId)
00779 {
00780 return $this->getUser()->inGroup($sGroupId);
00781 }
00782
00790 public function getClassId($sClassName)
00791 {
00792 $sClassId = null;
00793
00794 $oXPath = new DOMXPath($this->_getInitialDom());
00795 $oNodeList = $oXPath->query("//*[@cl='{$sClassName}' or @list='{$sClassName}']");
00796 if ($oNodeList->length && ($oFirstItem = $oNodeList->item(0))) {
00797 $sClassId = $oFirstItem->getAttribute('id');
00798 }
00799
00800 return $sClassId;
00801 }
00802
00803
00812 protected function _getDynMenuUrl($iLang, $blLoadDynContents)
00813 {
00814 if (!$blLoadDynContents) {
00815
00816 $sFullAdminDir = getShopBasePath() . 'application/views/admin';
00817 $sUrl = $sFullAdminDir . "/dynscreen_local.xml";
00818 } else {
00819 $oAdminView = oxNew('oxadminview');
00820 $this->_sDynIncludeUrl = $oAdminView->getServiceUrl($iLang);
00821 $sUrl .= $this->_sDynIncludeUrl . "menue/dynscreen.xml";
00822 }
00823
00824 return $sUrl;
00825 }
00826
00832 protected function _getDynMenuLang()
00833 {
00834 $myConfig = $this->getConfig();
00835 $oLang = oxRegistry::getLang();
00836
00837 $iDynLang = $myConfig->getConfigParam('iDynInterfaceLanguage');
00838 $iDynLang = isset($iDynLang) ? $iDynLang : ($oLang->getTplLanguage());
00839
00840 $aLanguages = $oLang->getLanguageArray();
00841 $sLangAbr = $aLanguages[$iDynLang]->abbr;
00842
00843 return $sLangAbr;
00844 }
00845 }