00001 <?php
00002
00006 class OxNavigationTree extends oxSuperCfg
00007 {
00011 protected $_oDom = null;
00012
00016 protected $_oInitialDom = null;
00017
00023 protected $_sDynIncludeUrl = null;
00024
00032 public function init()
00033 {
00034 }
00035
00045 protected function _cleanEmptyParents($oDom, $sParentXPath, $sChildXPath)
00046 {
00047 $oXPath = new DomXPath( $oDom );
00048 $oNodeList = $oXPath->query( $sParentXPath );
00049
00050 foreach ( $oNodeList as $oNode ) {
00051 $sId = $oNode->getAttribute( 'id' );
00052 $oChildList = $oXPath->query( "{$sParentXPath}[@id='$sId']/$sChildXPath" );
00053 if (!$oChildList->length) {
00054 $oNode->parentNode->removeChild( $oNode );
00055 }
00056 }
00057 }
00058
00066 protected function _addLinks( $oDom )
00067 {
00068 $sURL = 'index.php?';
00069 $oXPath = new DomXPath( $oDom );
00070
00071
00072 $oNodeList = $oXPath->query( "//SUBMENU[@cl]" );
00073 foreach ( $oNodeList as $oNode ) {
00074
00075 $sCl = $oNode->getAttribute( 'cl' );
00076 $sCl = $sCl?"cl=$sCl":'';
00077
00078
00079 $sParam = $oNode->getAttribute( 'clparam' );
00080 $sParam = $sParam?"&$sParam":'';
00081
00082
00083 $oNode->setAttribute( 'link', "{$sURL}{$sCl}{$sParam}" );
00084 }
00085 }
00086
00095 protected function _loadFromFile( $sMenuFile, $oDom )
00096 {
00097 $oDomFile = new DomDocument();
00098 $oDomFile->preserveWhiteSpace = false;
00099 if ( @$oDomFile->load( $sMenuFile ) ) {
00100 $this->_merge( $oDomFile, $oDom );
00101 }
00102 }
00103
00111 protected function _addDynLinks( $oDom )
00112 {
00113 $myConfig = $this->getConfig();
00114 $myUtilsFile = oxUtilsFile::getInstance();
00115
00116 $sURL = 'index.php?';
00117
00118 $oXPath = new DomXPath( $oDom );
00119 $oNodeList = $oXPath->query( "//OXMENU[@type='dyn']/MAINMENU/SUBMENU" );
00120 foreach ( $oNodeList as $oNode ) {
00121
00122
00123 $sCl = $oNode->getAttribute( 'cl' );
00124 $sCl = "cl=dynscreen&menu=$sCl";
00125
00126
00127 $sParam = $oNode->getAttribute( 'clparam' );
00128 $sParam = $sParam?"&$sParam":'';
00129
00130
00131 if ( !$oNode->getAttribute( 'list' ) ) {
00132 $oNode->setAttribute( 'list', 'dynscreen_list' );
00133 $oNode->setAttribute( 'listparam', 'menu='.$oNode->getAttribute( 'cl' ) );
00134 }
00135
00136
00137 $oNode->setAttribute( 'link', "{$sURL}{$sCl}{$sParam}" );
00138
00139
00140 $oNode->parentNode->setAttribute( 'id', 'dyn_menu' );
00141
00142
00143
00144
00145 $sFile = $oNode->getAttribute( 'cl' );
00146
00147
00148 if ( $myUtilsFile->checkFile( "{$this->_sDynIncludeUrl}pages/{$sFile}_about.php" ) ) {
00149 $oTabElem = new DOMElement( 'TAB' );
00150 $oNode->appendChild( $oTabElem );
00151 $oTabElem->setAttribute( 'external', 'true' );
00152 $oTabElem->setAttribute( 'location', "{$this->_sDynIncludeUrl}pages/{$sFile}_about.php" );
00153 $oTabElem->setAttribute( 'id', 'dyn_about' );
00154 }
00155
00156
00157 if ( $myUtilsFile->checkFile( "{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php" ) ) {
00158 $oTabElem = new DOMElement( 'TAB' );
00159 $oNode->appendChild( $oTabElem );
00160 $oTabElem->setAttribute( 'external', 'true' );
00161 $oTabElem->setAttribute( 'location', "{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php" );
00162 $oTabElem->setAttribute( 'id', 'dyn_interface' );
00163 }
00164
00165
00166 if ( file_exists( $myConfig->getConfigParam( 'sShopDir' ).$myConfig->getConfigParam( 'sAdminDir' )."/{$sFile}.php" ) ) {
00167 $oTabElem = new DOMElement( 'TAB' );
00168 $oNode->appendChild( $oTabElem );
00169 $oTabElem->setAttribute( 'id', 'dyn_interface' );
00170 $oTabElem->setAttribute( 'cl', $sFile );
00171 }
00172 }
00173 }
00174
00182 protected function _sessionizeLocalUrls( $oDom )
00183 {
00184 $sURL = $this->_getAdminUrl();
00185 $oXPath = new DomXPath( $oDom );
00186 $oStr = getStr();
00187 foreach (array('url', 'link') as $sAttrType) {
00188 foreach ( $oXPath->query( "//OXMENU//*[@$sAttrType]" ) as $oNode ) {
00189 $sLocalUrl = $oNode->getAttribute( $sAttrType );
00190 if (strpos($sLocalUrl, 'index.php?') === 0) {
00191 $sLocalUrl = $oStr->preg_replace('#^index.php\?#', $sURL, $sLocalUrl);
00192 $oNode->setAttribute( $sAttrType, $sLocalUrl );
00193 }
00194 }
00195 }
00196 }
00197
00205 protected function _checkRights( $oDom )
00206 {
00207 $oXPath = new DomXPath( $oDom );
00208 $oNodeList = $oXPath->query( '//*[@rights or @norights]' );
00209
00210 foreach ( $oNodeList as $oNode ) {
00211
00212 if ( ( $sReq = $oNode->getAttribute( 'rights' ) ) ) {
00213 $aPerm = explode( ',', $sReq );
00214 foreach ( $aPerm as $sPerm ) {
00215 if ( $sPerm && !$this->_hasRights( $sPerm ) ) {
00216 $oNode->parentNode->removeChild( $oNode );
00217 }
00218 }
00219
00220 } elseif ( ( $sNoReq = $oNode->getAttribute( 'norights' ) ) ) {
00221 $aPerm = explode( ',', $sNoReq );
00222 foreach ( $aPerm as $sPerm ) {
00223 if ( $sPerm && $this->_hasRights( $sPerm ) ) {
00224 $oNode->parentNode->removeChild( $oNode );
00225 }
00226 }
00227 }
00228 }
00229 }
00230
00238 protected function _checkGroups( $oDom )
00239 {
00240 $oXPath = new DomXPath( $oDom );
00241 $oNodeList = $oXPath->query( "//*[@nogroup or @group]" );
00242
00243 foreach ( $oNodeList as $oNode ) {
00244
00245 if ( ( $sReq = $oNode->getAttribute('group') ) ) {
00246 $aPerm = explode( ',', $sReq );
00247 foreach ( $aPerm as $sPerm ) {
00248 if ( $sPerm && !$this->_hasGroup( $sPerm ) ) {
00249 $oNode->parentNode->removeChild($oNode);
00250 }
00251 }
00252
00253 } elseif ( ( $sNoReq = $oNode->getAttribute('nogroup') ) ) {
00254 $aPerm = explode( ',', $sNoReq );
00255 foreach ( $aPerm as $sPerm ) {
00256 if ( $sPerm && $this->_hasGroup( $sPerm ) ) {
00257 $oNode->parentNode->removeChild($oNode);
00258 }
00259 }
00260 }
00261 }
00262 }
00263
00271 protected function _checkDemoShopDenials( $oDom )
00272 {
00273 if (!$this->getConfig()->isDemoShop()) {
00274
00275 return;
00276 }
00277
00278 $oXPath = new DomXPath( $oDom );
00279 $oNodeList = $oXPath->query( "//*[@disableForDemoShop]" );
00280 foreach ( $oNodeList as $oNode ) {
00281 if ( $oNode->getAttribute('disableForDemoShop') ) {
00282 $oNode->parentNode->removeChild($oNode);
00283 }
00284 }
00285 }
00286
00295 protected function _copyAttributes( $oDomElemTo, $oDomElemFrom )
00296 {
00297 foreach ( $oDomElemFrom->attributes as $oAttr ) {
00298 $oDomElemTo->setAttribute( $oAttr->nodeName, $oAttr->nodeValue );
00299 }
00300 }
00301
00313 protected function _mergeNodes( $oDomElemTo, $oDomElemFrom, $oXPathTo, $oDomDocTo, $sQueryStart )
00314 {
00315 foreach ( $oDomElemFrom->childNodes as $oFromNode ) {
00316 if ( $oFromNode->nodeType === XML_ELEMENT_NODE ) {
00317
00318 $sFromAttrName = $oFromNode->getAttribute( 'id' );
00319 $sFromNodeName = $oFromNode->tagName;
00320
00321
00322 $sQuery = "{$sQueryStart}/{$sFromNodeName}[@id='{$sFromAttrName}']";
00323 $oCurNode = $oXPathTo->query( $sQuery );
00324
00325
00326 if ( $oCurNode->length == 0 ) {
00327 $oDomElemTo->appendChild( $oDomDocTo->importNode( $oFromNode, true ) );
00328 } else {
00329
00330 $oCurNode = $oCurNode->item( 0 );
00331
00332
00333 $this->_copyAttributes( $oCurNode, $oFromNode );
00334
00335 if ( $oFromNode->childNodes->length ) {
00336 $this->_mergeNodes( $oCurNode, $oFromNode, $oXPathTo, $oDomDocTo, $sQuery );
00337 }
00338 }
00339 }
00340 }
00341 }
00342
00351 protected function _merge( $oDomNew, $oDom )
00352 {
00353 $oXPath = new DOMXPath( $oDom );
00354 $this->_mergeNodes( $oDom->documentElement, $oDomNew->documentElement, $oXPath, $oDom, '/OX' );
00355 }
00356
00366 public function getTabs( $sId, $iAct, $blSetActive = true )
00367 {
00368 $oXPath = new DOMXPath( $this->getDomXml() );
00369
00370 $oNodeList = $oXPath->query( "//SUBMENU[@cl='$sId']/TAB | //SUBMENU[@list='$sId']/TAB | //SUBMENU/../TAB[@cl='$sId']" );
00371
00372 $iAct = ( $iAct > $oNodeList->length )?( $oNodeList->length - 1 ):$iAct;
00373
00374 if ( $blSetActive ) {
00375 foreach ( $oNodeList as $iPos => $oNode ) {
00376 if ( $iPos == $iAct ) {
00377
00378 $oNode->setAttribute( 'active', 1 );
00379 }
00380 }
00381 }
00382
00383 return $oNodeList;
00384 }
00385
00394 public function getActiveTab( $sId, $iAct )
00395 {
00396 $sTab = null;
00397 $oNodeList = $this->getTabs( $sId, $iAct, false );
00398 $iAct = ( $iAct > $oNodeList->length )?( $oNodeList->length - 1 ):$iAct;
00399 if ( $oNodeList->length && ( $oNode = $oNodeList->item( $iAct ) ) ) {
00400 $sTab = $oNode->getAttribute( 'cl' );
00401 }
00402
00403 return $sTab;
00404 }
00405
00413 public function getBtn( $sClass )
00414 {
00415 $oButtons = null;
00416 $oXPath = new DOMXPath($this->getDomXml());
00417 $oNodeList = $oXPath->query("//TAB[@cl='$sClass']/../BTN");
00418 if ($oNodeList->length) {
00419 $oButtons = new OxstdClass();
00420 foreach ($oNodeList as $oNode) {
00421 $sBtnID = $oNode->getAttribute('id');
00422 $oButtons->$sBtnID = 1;
00423 }
00424 }
00425 return $oButtons;
00426 }
00427
00433 protected function _getMenuFiles()
00434 {
00435 $myConfig = $this->getConfig();
00436 $myOxUtlis = oxUtils::getInstance();
00437
00438 $sFullAdminDir = getShopBasePath() . $myConfig->getConfigParam( 'sAdminDir' );
00439 $sMenuFile = "/menu.xml";
00440
00441 $sTmpDir = $myConfig->getConfigParam( 'sCompileDir' );
00442 $sDynLang = $this->_getDynMenuLang();
00443 $sLocalDynPath = "{$sTmpDir}{$sDynLang}_dynscreen.xml";
00444
00445
00446
00447 if ( file_exists( $sFullAdminDir.$sMenuFile ) ) {
00448 $aFilesToLoad[] = $sFullAdminDir.$sMenuFile;
00449 }
00450
00451
00452 if ( file_exists( "$sFullAdminDir/user.xml" ) ) {
00453 $aFilesToLoad[] = "$sFullAdminDir/user.xml";
00454 }
00455
00456
00457 $sPath = getShopBasePath();
00458 $aPathsToCheck = array( 'modules/' );
00459 $sPathToCheck = reset( $aPathsToCheck );
00460 while ( $sPathToCheck ) {
00461 $sFullPath = $sPath.$sPathToCheck;
00462
00463
00464 if ( is_dir( $sFullPath ) ) {
00465
00466
00467 $aSubF = glob( $sFullPath."*", GLOB_ONLYDIR );
00468 if ( is_array( $aSubF ) ) {
00469 foreach ( $aSubF as $sNewFolder ) {
00470 $aPathsToCheck[] = str_replace( $sPath, "", $sNewFolder ) . "/";
00471 }
00472 }
00473
00474
00475 $sMenuFile = "{$sFullPath}menu.xml";
00476 if ( file_exists( $sMenuFile ) && is_readable( $sMenuFile ) ) {
00477 $aFilesToLoad[] = $sMenuFile;
00478 }
00479 }
00480 $sPathToCheck = next( $aPathsToCheck );
00481 }
00482
00483 $blLoadDynContents = $myConfig->getConfigParam( 'blLoadDynContents' );
00484 $sShopCountry = $myConfig->getConfigParam( 'sShopCountry' );
00485
00486
00487 $sDynPath = null;
00488
00489 if ( $blLoadDynContents ) {
00490 if ( $sShopCountry ) {
00491 $sRemoteDynUrl = $this->_getDynMenuUrl( $sDynLang, $blLoadDynContents );
00492
00493
00494 $blLoadRemote = oxSession::getVar( "loadedremotexml" );
00495
00496
00497 if ( ( !isset( $blLoadRemote ) || $blLoadRemote ) && ( $sDynPath = $myOxUtlis->getRemoteCachePath( $sRemoteDynUrl, $sLocalDynPath ) ) ) {
00498 $sDynPath = $this->_checkDynFile( $sDynPath );
00499 }
00500
00501
00502 oxSession::setVar( "loadedremotexml", $sDynPath ? true : false );
00503 }
00504 } else {
00505 if ( $sShopCountry ) {
00506
00507 }
00508 }
00509
00510
00511 if ( $sDynPath ) {
00512 $aFilesToLoad[] = $sDynPath;
00513 }
00514 return $aFilesToLoad;
00515 }
00516
00524 protected function _checkDynFile( $sDynFilePath )
00525 {
00526 $sDynFile = null;
00527 if ( file_exists( $sDynFilePath ) ) {
00528 $sLine = null;
00529 if ( ( $rHandle = @fopen($sDynFilePath, 'r' ) ) ) {
00530 $sLine = stream_get_line( $rHandle, 100, "?>");
00531 fclose( $rHandle );
00532
00533
00534 if ( $sLine && stripos( $sLine, '<?xml' ) !== false ) {
00535 $sDynFile = $sDynFilePath;
00536 }
00537 }
00538
00539
00540 if ( !$sDynFile ) {
00541 @unlink( $sDynFilePath );
00542 }
00543 }
00544
00545 return $sDynFile;
00546 }
00547
00560 protected function _processCachedFile($sCacheContents)
00561 {
00562 return $sCacheContents;
00563 }
00564
00570 protected function _getInitialDom()
00571 {
00572 if ( $this->_oInitialDom === null ) {
00573 $myOxUtlis = oxUtils::getInstance();
00574
00575 if ( is_array( $aFilesToLoad = $this->_getMenuFiles() ) ) {
00576
00577
00578 $blReload = false;
00579 $sDynLang = $this->_getDynMenuLang();
00580
00581 $sCacheName = 'menu_' . $sDynLang . '_xml';
00582 $sCacheFile = $myOxUtlis->getCacheFilePath( $sCacheName );
00583 $sCacheContents = $myOxUtlis->fromFileCache( $sCacheName );
00584 if ( $sCacheContents && file_exists( $sCacheFile ) && ( $iCacheModTime = filemtime( $sCacheFile ) ) ) {
00585 foreach ( $aFilesToLoad as $sDynPath ) {
00586 if ( $iCacheModTime < filemtime( $sDynPath ) ) {
00587 $blReload = true;
00588 }
00589 }
00590 } else {
00591 $blReload = true;
00592 }
00593
00594 $this->_oInitialDom = new DOMDocument();
00595 if ( $blReload ) {
00596
00597 $this->_oInitialDom->appendChild( new DOMElement( 'OX' ) );
00598
00599 foreach ( $aFilesToLoad as $sDynPath ) {
00600 $this->_loadFromFile( $sDynPath, $this->_oInitialDom );
00601 }
00602
00603
00604 $this->_addLinks( $this->_oInitialDom );
00605
00606
00607 $this->_addDynLinks( $this->_oInitialDom );
00608
00609
00610 $myOxUtlis->toFileCache( $sCacheName, $this->_oInitialDom->saveXML() );
00611 } else {
00612 $sCacheContents = $this->_processCachedFile($sCacheContents);
00613
00614 $this->_oInitialDom->preserveWhiteSpace = false;
00615 $this->_oInitialDom->loadXML( $sCacheContents );
00616 }
00617
00618
00619 $this->_sessionizeLocalUrls( $this->_oInitialDom );
00620 }
00621 }
00622 return $this->_oInitialDom;
00623 }
00624
00630 public function getDomXml()
00631 {
00632 if ( $this->_oDom === null ) {
00633 $this->_oDom = clone $this->_getInitialDom();
00634
00635
00636 $this->_checkGroups( $this->_oDom );
00637
00638
00639 $this->_checkRights( $this->_oDom );
00640
00641
00642 $this->_checkDemoShopDenials( $this->_oDom );
00643
00644
00645 $this->_cleanEmptyParents( $this->_oDom, '//SUBMENU[@id][@list]', 'TAB');
00646 $this->_cleanEmptyParents( $this->_oDom, '//MAINMENU[@id]', 'SUBMENU');
00647 }
00648
00649 return $this->_oDom;
00650 }
00651
00659 public function getListNodes( $aNodes )
00660 {
00661 $oXPath = new DOMXPath( $this->getDomXml() );
00662 $oNodeList = $oXPath->query( "//SUBMENU[@cl='".implode("' or @cl='", $aNodes)."']" );
00663
00664 return ( $oNodeList->length ) ? $oNodeList : null;
00665 }
00666
00674 public function markNodeActive( $sNodeId )
00675 {
00676 $oXPath = new DOMXPath( $this->getDomXml() );
00677 $oNodeList = $oXPath->query( "//*[@cl='{$sNodeId}' or @list='{$sNodeId}']" );
00678
00679 if ( $oNodeList->length ) {
00680 foreach ( $oNodeList as $oNode ) {
00681
00682 $oNode->setAttribute( 'active', 1 );
00683 $oNode->parentNode->setAttribute( 'active', 1 );
00684 }
00685 }
00686
00687 }
00688
00696 public function getListUrl( $sId )
00697 {
00698 $sUrl = null;
00699 $oXPath = new DOMXPath( $this->getDomXml() );
00700 $oNodeList = $oXPath->query( "//SUBMENU[@cl='{$sId}']" );
00701 if ( $oNodeList->length && ( $oNode = $oNodeList->item( 0 ) ) ) {
00702 $sCl = $oNode->getAttribute('list');
00703 $sCl = $sCl?"cl=$sCl":'';
00704
00705 $sParams = $oNode->getAttribute('listparam');
00706 $sParams = $sParams?"&$sParams":'';
00707
00708 $sUrl = "{$sCl}{$sParams}";
00709 }
00710 return $sUrl;
00711 }
00712
00721 public function getEditUrl( $sId, $iActTab )
00722 {
00723 $sUrl = null;
00724 $oXPath = new DOMXPath( $this->getDomXml() );
00725 $oNodeList = $oXPath->query( "//SUBMENU[@cl='{$sId}']/TAB" );
00726
00727 $iActTab = ( $iActTab > $oNodeList->length )?( $oNodeList->length - 1 ) : $iActTab;
00728 if ( $oNodeList->length && ( $oActTab = $oNodeList->item( $iActTab ) ) ) {
00729
00730 if ( $oActTab->getAttribute( 'external' ) ) {
00731 $sUrl = $oActTab->getAttribute( 'location' );
00732 } else {
00733 $sCl = $oActTab->getAttribute( 'cl' );
00734 $sCl = $sCl?"cl={$sCl}":'';
00735
00736 $sParams = $oActTab->getAttribute( 'clparam' );
00737 $sParams = $sParams?"&{$sParams}":'';
00738
00739 $sUrl = "{$sCl}{$sParams}";
00740 }
00741 }
00742 return $sUrl;
00743 }
00744
00750 protected function _getAdminUrl()
00751 {
00752 $myConfig = $this->getConfig();
00753
00754 if ( ( $sAdminSslUrl = $myConfig->getConfigParam( 'sAdminSSLURL' ) ) ) {
00755 $sURL = trim( $sAdminSslUrl, '/' );
00756 } else {
00757 $sURL = trim( $myConfig->getConfigParam( 'sShopURL' ), '/' ).'/admin';
00758 }
00759 return oxUtilsUrl::getInstance()->appendParamSeparator($this->getSession()->url("{$sURL}/index.php"));
00760 }
00761
00769 protected function _hasRights( $sRights )
00770 {
00771 return $this->getUser()->oxuser__oxrights->value == $sRights;
00772 }
00773
00781 protected function _hasGroup( $sGroupId )
00782 {
00783 return $this->getUser()->inGroup( $sGroupId );
00784 }
00785
00793 public function getClassId( $sClassName )
00794 {
00795 $sClassId = null;
00796
00797 $oXPath = new DOMXPath( $this->_getInitialDom() );
00798 $oNodeList = $oXPath->query( "//*[@cl='{$sClassName}' or @list='{$sClassName}']" );
00799 if ( $oNodeList->length && ( $oFirstItem = $oNodeList->item( 0 ) ) ) {
00800 $sClassId = $oFirstItem->getAttribute( 'id' );
00801 }
00802
00803 return $sClassId;
00804 }
00805
00813 public function getShopVersionNr()
00814 {
00815 $sVersion = "";
00816 if ( ( $sShopId = $this->getConfig()->getShopId() ) ) {
00817 $sVersion = oxDb::getDb()->getOne( "select oxversion from oxshops where oxid = '$sShopId' " );
00818 $sVersion = preg_replace( "/(^[^0-9]+)(.+)$/", "\$2", $sVersion );
00819 }
00820
00821 return trim( $sVersion );
00822 }
00823
00824
00833 protected function _getDynMenuUrl( $iLang, $blLoadDynContents )
00834 {
00835 if ( !$blLoadDynContents ) {
00836
00837 $sFullAdminDir = getShopBasePath() . $this->getConfig()->getConfigParam( 'sAdminDir' );
00838 $sUrl = $sFullAdminDir . "/dynscreen_local.xml";
00839 } else {
00840 $oAdminView = oxNew( 'oxadminview' );
00841 $this->_sDynIncludeUrl = $oAdminView->getServiceUrl( $iLang );
00842 $sUrl .= $this->_sDynIncludeUrl . "menue/dynscreen.xml";
00843 }
00844
00845 return $sUrl;
00846 }
00847
00853 protected function _getDynMenuLang()
00854 {
00855 $myConfig = $this->getConfig();
00856 $oLang = oxLang::getInstance();
00857
00858 $iDynLang = $myConfig->getConfigParam( 'iDynInterfaceLanguage' );
00859 $iDynLang = isset( $iDynLang )?$iDynLang:( $oLang->getObjectTplLanguage() );
00860
00861 $aLanguages = $oLang->getLanguageArray();
00862 $sLangAbr = $aLanguages[$iDynLang]->abbr;
00863
00864 return $sLangAbr;
00865 }
00866 }