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 = $this->_getAdminUrl();
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 = $this->_getAdminUrl();
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
00186 $oXPath = new DomXPath( $oDom );
00187 $oNodeList = $oXPath->query( "//OXMENU/*[@url]" );
00188 foreach ( $oNodeList as $oNode ) {
00189 $sLocalUrl = $oNode->getAttribute( 'url' );
00190 if (strpos($sLocalUrl, 'index.php?') === 0) {
00191 $sLocalUrl = preg_replace('#^index.php\?#', $sURL, $sLocalUrl);
00192 $oNode->setAttribute( 'url', $sLocalUrl );
00193 }
00194 }
00195 }
00196
00204 protected function _checkRights( $oDom )
00205 {
00206 $oXPath = new DomXPath( $oDom );
00207 $oNodeList = $oXPath->query( '//*[@rights or @norights]' );
00208
00209 foreach ( $oNodeList as $oNode ) {
00210
00211 if ( ( $sReq = $oNode->getAttribute( 'rights' ) ) ) {
00212 $aPerm = explode( ',', $sReq );
00213 foreach ( $aPerm as $sPerm ) {
00214 if ( $sPerm && !$this->_hasRights( $sPerm ) ) {
00215 $oNode->parentNode->removeChild( $oNode );
00216 }
00217 }
00218
00219 } elseif ( ( $sNoReq = $oNode->getAttribute( 'norights' ) ) ) {
00220 $aPerm = explode( ',', $sNoReq );
00221 foreach ( $aPerm as $sPerm ) {
00222 if ( $sPerm && $this->_hasRights( $sPerm ) ) {
00223 $oNode->parentNode->removeChild( $oNode );
00224 }
00225 }
00226 }
00227 }
00228 }
00229
00237 protected function _checkGroups( $oDom )
00238 {
00239 $oXPath = new DomXPath( $oDom );
00240 $oNodeList = $oXPath->query( "//*[@nogroup or @group]" );
00241
00242 foreach ( $oNodeList as $oNode ) {
00243
00244 if ( ( $sReq = $oNode->getAttribute('group') ) ) {
00245 $aPerm = explode( ',', $sReq );
00246 foreach ( $aPerm as $sPerm ) {
00247 if ( $sPerm && !$this->_hasGroup( $sPerm ) ) {
00248 $oNode->parentNode->removeChild($oNode);
00249 }
00250 }
00251
00252 } elseif ( ( $sNoReq = $oNode->getAttribute('nogroup') ) ) {
00253 $aPerm = explode( ',', $sNoReq );
00254 foreach ( $aPerm as $sPerm ) {
00255 if ( $sPerm && $this->_hasGroup( $sPerm ) ) {
00256 $oNode->parentNode->removeChild($oNode);
00257 }
00258 }
00259 }
00260 }
00261 }
00262
00270 protected function _checkDemoShopDenials( $oDom )
00271 {
00272 if (!$this->getConfig()->isDemoShop()) {
00273
00274 return;
00275 }
00276
00277 $oXPath = new DomXPath( $oDom );
00278 $oNodeList = $oXPath->query( "//*[@disableForDemoShop]" );
00279 foreach ( $oNodeList as $oNode ) {
00280 if ( $oNode->getAttribute('disableForDemoShop') ) {
00281 $oNode->parentNode->removeChild($oNode);
00282 }
00283 }
00284 }
00285
00294 protected function _copyAttributes( $oDomElemTo, $oDomElemFrom )
00295 {
00296 foreach ( $oDomElemFrom->attributes as $oAttr ) {
00297 $oDomElemTo->setAttribute( $oAttr->nodeName, $oAttr->nodeValue );
00298 }
00299 }
00300
00312 protected function _mergeNodes( $oDomElemTo, $oDomElemFrom, $oXPathTo, $oDomDocTo, $sQueryStart )
00313 {
00314 foreach ( $oDomElemFrom->childNodes as $oFromNode ) {
00315 if ( $oFromNode->nodeType === XML_ELEMENT_NODE ) {
00316
00317 $sFromAttrName = $oFromNode->getAttribute( 'id' );
00318 $sFromNodeName = $oFromNode->tagName;
00319
00320
00321 $sQuery = "{$sQueryStart}/{$sFromNodeName}[@id='{$sFromAttrName}']";
00322 $oCurNode = $oXPathTo->query( $sQuery );
00323
00324
00325 if ( $oCurNode->length == 0 ) {
00326 $oDomElemTo->appendChild( $oDomDocTo->importNode( $oFromNode, true ) );
00327 } else {
00328
00329 $oCurNode = $oCurNode->item( 0 );
00330
00331
00332 $this->_copyAttributes( $oCurNode, $oFromNode );
00333
00334 if ( $oFromNode->childNodes->length ) {
00335 $this->_mergeNodes( $oCurNode, $oFromNode, $oXPathTo, $oDomDocTo, $sQuery );
00336 }
00337 }
00338 }
00339 }
00340 }
00341
00350 protected function _merge( $oDomNew, $oDom )
00351 {
00352 $oXPath = new DOMXPath( $oDom );
00353 $this->_mergeNodes( $oDom->documentElement, $oDomNew->documentElement, $oXPath, $oDom, '/OX' );
00354 }
00355
00365 public function getTabs( $sId, $iAct, $blSetActive = true )
00366 {
00367 $oXPath = new DOMXPath( $this->getDomXml() );
00368
00369 $oNodeList = $oXPath->query( "//SUBMENU[@cl='$sId']/TAB | //SUBMENU[@list='$sId']/TAB | //SUBMENU/../TAB[@cl='$sId']" );
00370
00371 $iAct = ( $iAct > $oNodeList->length )?( $oNodeList->length - 1 ):$iAct;
00372
00373 if ( $blSetActive ) {
00374 foreach ( $oNodeList as $iPos => $oNode ) {
00375 if ( $iPos == $iAct ) {
00376
00377 $oNode->setAttribute( 'active', 1 );
00378 }
00379 }
00380 }
00381
00382 return $oNodeList;
00383 }
00384
00393 public function getActiveTab( $sId, $iAct )
00394 {
00395 $sTab = null;
00396 $oNodeList = $this->getTabs( $sId, $iAct, false );
00397 $iAct = ( $iAct > $oNodeList->length )?( $oNodeList->length - 1 ):$iAct;
00398 if ( $oNodeList->length && ( $oNode = $oNodeList->item( $iAct ) ) ) {
00399 $sTab = $oNode->getAttribute( 'cl' );
00400 }
00401
00402 return $sTab;
00403 }
00404
00412 public function getBtn( $sClass )
00413 {
00414 $oButtons = null;
00415 $oXPath = new DOMXPath($this->getDomXml());
00416 $oNodeList = $oXPath->query("//TAB[@cl='$sClass']/../BTN");
00417 if ($oNodeList->length) {
00418 $oButtons = new OxstdClass();
00419 foreach ($oNodeList as $oNode) {
00420 $sBtnID = $oNode->getAttribute('id');
00421 $oButtons->$sBtnID = 1;
00422 }
00423 }
00424 return $oButtons;
00425 }
00426
00432 protected function _getMenuFiles()
00433 {
00434 $myConfig = $this->getConfig();
00435 $myOxUtlis = oxUtils::getInstance();
00436
00437 $sFullAdminDir = getShopBasePath() . $myConfig->getConfigParam( 'sAdminDir' );
00438 $sMenuFile = "/menu.xml";
00439
00440 $sTmpDir = $myConfig->getConfigParam( 'sCompileDir' );
00441 $sDynLang = $this->_getDynMenuLang();
00442 $sLocalDynPath = "{$sTmpDir}{$sDynLang}_dynscreen.xml";
00443
00444
00445
00446 if ( file_exists( $sFullAdminDir.$sMenuFile ) ) {
00447 $aFilesToLoad[] = $sFullAdminDir.$sMenuFile;
00448 }
00449
00450
00451 if ( file_exists( "$sFullAdminDir/user.xml" ) ) {
00452 $aFilesToLoad[] = "$sFullAdminDir/user.xml";
00453 }
00454
00455
00456 $sSourceDir = getShopBasePath() . 'modules';
00457 $handle = opendir( $sSourceDir );
00458 while ( false !== ( $sFile = readdir( $handle ) ) ) {
00459 if ( $sFile != '.' && $sFile != '..') {
00460 $sDir = "$sSourceDir/$sFile";
00461 if ( is_dir( $sDir ) && file_exists( "$sDir/menu.xml" ) ) {
00462 $aFilesToLoad[] = "$sDir/menu.xml";
00463 }
00464 }
00465 }
00466
00467 $blLoadDynContents = $myConfig->getConfigParam( 'blLoadDynContents' );
00468 $sShopCountry = $myConfig->getConfigParam( 'sShopCountry' );
00469
00470
00471 $sDynPath = null;
00472
00473 if ( $blLoadDynContents ) {
00474 if ( $sShopCountry ) {
00475 $sRemoteDynUrl = $this->_getDynMenuUrl( $sDynLang, $blLoadDynContents );
00476
00477
00478 $blLoadRemote = oxSession::getVar( "loadedremotexml" );
00479
00480
00481 if ( ( !isset( $blLoadRemote ) || $blLoadRemote ) && ( $sDynPath = $myOxUtlis->getRemoteCachePath( $sRemoteDynUrl, $sLocalDynPath ) ) ) {
00482 $sDynPath = $this->_checkDynFile( $sDynPath );
00483 }
00484
00485
00486 oxSession::setVar( "loadedremotexml", $sDynPath ? true : false );
00487 }
00488 } else {
00489 if ( $sShopCountry ) {
00490
00491 }
00492 }
00493
00494
00495 if ( $sDynPath ) {
00496 $aFilesToLoad[] = $sDynPath;
00497 }
00498 return $aFilesToLoad;
00499 }
00500
00508 protected function _checkDynFile( $sDynFilePath )
00509 {
00510 $sDynFile = null;
00511 if ( file_exists( $sDynFilePath ) ) {
00512 $sLine = null;
00513 if ( ( $rHandle = @fopen($sDynFilePath, 'r' ) ) ) {
00514 $sLine = stream_get_line( $rHandle, 100, "?>");
00515 fclose( $rHandle );
00516
00517
00518 if ( $sLine && stripos( $sLine, '<?xml' ) !== false ) {
00519 $sDynFile = $sDynFilePath;
00520 }
00521 }
00522
00523
00524 if ( !$sDynFile ) {
00525 @unlink( $sDynFilePath );
00526 }
00527 }
00528
00529 return $sDynFile;
00530 }
00531
00539 protected function _processCachedFile($sCacheContents)
00540 {
00541 $sNewUrl = htmlentities($this->_getAdminUrl());
00542 $sTok = preg_quote("stoken=", '@');
00543 $sSearch = preg_replace('@'.preg_quote($sTok, '@').'[A-Z0-9]+@i', "{$sTok}[A-Z0-9]+", preg_quote($sNewUrl, '@'));
00544 return preg_replace("@$sSearch@i", $sNewUrl, $sCacheContents);
00545
00546 }
00547
00553 protected function _getInitialDom()
00554 {
00555 if ( $this->_oInitialDom === null ) {
00556 $myOxUtlis = oxUtils::getInstance();
00557
00558 if ( is_array( $aFilesToLoad = $this->_getMenuFiles() ) ) {
00559
00560
00561 $blReload = false;
00562 $sDynLang = $this->_getDynMenuLang();
00563
00564 $sCacheName = 'menu_' . $sDynLang . '_xml';
00565 $sCacheFile = $myOxUtlis->getCacheFilePath( $sCacheName );
00566 $sCacheContents = $myOxUtlis->fromFileCache( $sCacheName );
00567 if ( $sCacheContents && file_exists( $sCacheFile ) && ( $iCacheModTime = filemtime( $sCacheFile ) ) ) {
00568 foreach ( $aFilesToLoad as $sDynPath ) {
00569 if ( $iCacheModTime < filemtime( $sDynPath ) ) {
00570 $blReload = true;
00571 }
00572 }
00573 } else {
00574 $blReload = true;
00575 }
00576
00577 $this->_oInitialDom = new DOMDocument();
00578 if ( $blReload ) {
00579
00580 $this->_oInitialDom->appendChild( new DOMElement( 'OX' ) );
00581
00582 foreach ( $aFilesToLoad as $sDynPath ) {
00583 $this->_loadFromFile( $sDynPath, $this->_oInitialDom );
00584 }
00585
00586
00587 $this->_addLinks( $this->_oInitialDom );
00588
00589
00590 $this->_addDynLinks( $this->_oInitialDom );
00591
00592
00593 $this->_sessionizeLocalUrls( $this->_oInitialDom );
00594
00595
00596 $myOxUtlis->toFileCache( $sCacheName, $this->_oInitialDom->saveXML() );
00597 } else {
00598 $sCacheContents = $this->_processCachedFile($sCacheContents);
00599
00600 $this->_oInitialDom->preserveWhiteSpace = false;
00601 $this->_oInitialDom->loadXML( $sCacheContents );
00602 }
00603 }
00604 }
00605 return $this->_oInitialDom;
00606 }
00607
00613 public function getDomXml()
00614 {
00615 if ( $this->_oDom === null ) {
00616 $this->_oDom = clone $this->_getInitialDom();
00617
00618
00619 $this->_checkGroups( $this->_oDom );
00620
00621
00622 $this->_checkRights( $this->_oDom );
00623
00624
00625 $this->_checkDemoShopDenials( $this->_oDom );
00626
00627
00628 $this->_cleanEmptyParents( $this->_oDom, '//SUBMENU[@id][@list]', 'TAB');
00629 $this->_cleanEmptyParents( $this->_oDom, '//MAINMENU[@id]', 'SUBMENU');
00630 }
00631
00632 return $this->_oDom;
00633 }
00634
00642 public function getListNodes( $aNodes )
00643 {
00644 $oXPath = new DOMXPath( $this->getDomXml() );
00645 $oNodeList = $oXPath->query( "//SUBMENU[@cl='".implode("' or @cl='", $aNodes)."']" );
00646
00647 return ( $oNodeList->length ) ? $oNodeList : null;
00648 }
00649
00657 public function markNodeActive( $sNodeId )
00658 {
00659 $oXPath = new DOMXPath( $this->getDomXml() );
00660 $oNodeList = $oXPath->query( "//*[@cl='{$sNodeId}' or @list='{$sNodeId}']" );
00661
00662 if ( $oNodeList->length ) {
00663 foreach ( $oNodeList as $oNode ) {
00664
00665 $oNode->setAttribute( 'active', 1 );
00666 $oNode->parentNode->setAttribute( 'active', 1 );
00667 }
00668 }
00669
00670 }
00671
00679 public function getListUrl( $sId )
00680 {
00681 $sUrl = null;
00682 $oXPath = new DOMXPath( $this->getDomXml() );
00683 $oNodeList = $oXPath->query( "//SUBMENU[@cl='{$sId}']" );
00684 if ( $oNodeList->length && ( $oNode = $oNodeList->item( 0 ) ) ) {
00685 $sCl = $oNode->getAttribute('list');
00686 $sCl = $sCl?"cl=$sCl":'';
00687
00688 $sParams = $oNode->getAttribute('listparam');
00689 $sParams = $sParams?"&$sParams":'';
00690
00691 $sUrl = "{$sCl}{$sParams}";
00692 }
00693 return $sUrl;
00694 }
00695
00704 public function getEditUrl( $sId, $iActTab )
00705 {
00706 $sUrl = null;
00707 $oXPath = new DOMXPath( $this->getDomXml() );
00708 $oNodeList = $oXPath->query( "//SUBMENU[@cl='{$sId}']/TAB" );
00709
00710 $iActTab = ( $iActTab > $oNodeList->length )?( $oNodeList->length - 1 ) : $iActTab;
00711 if ( $oNodeList->length && ( $oActTab = $oNodeList->item( $iActTab ) ) ) {
00712
00713 if ( $oActTab->getAttribute( 'external' ) ) {
00714 $sUrl = $oActTab->getAttribute( 'location' );
00715 } else {
00716 $sCl = $oActTab->getAttribute( 'cl' );
00717 $sCl = $sCl?"cl={$sCl}":'';
00718
00719 $sParams = $oActTab->getAttribute( 'clparam' );
00720 $sParams = $sParams?"&{$sParams}":'';
00721
00722 $sUrl = "{$sCl}{$sParams}";
00723 }
00724 }
00725 return $sUrl;
00726 }
00727
00733 protected function _getAdminUrl()
00734 {
00735 $myConfig = $this->getConfig();
00736
00737 if ( ( $sAdminSslUrl = $myConfig->getConfigParam( 'sAdminSSLURL' ) ) ) {
00738 $sURL = trim( $sAdminSslUrl, '/' );
00739 } else {
00740 $sURL = trim( $myConfig->getConfigParam( 'sShopURL' ), '/' ).'/admin';
00741 }
00742 return oxUtilsUrl::getInstance()->appendParamSeparator($this->getSession()->url("{$sURL}/index.php"));
00743 }
00744
00752 protected function _hasRights( $sRights )
00753 {
00754 return $this->getUser()->oxuser__oxrights->value == $sRights;
00755 }
00756
00764 protected function _hasGroup( $sGroupId )
00765 {
00766 return $this->getUser()->inGroup( $sGroupId );
00767 }
00768
00776 public function getClassId( $sClassName )
00777 {
00778 $sClassId = null;
00779
00780 $oXPath = new DOMXPath( $this->_getInitialDom() );
00781 $oNodeList = $oXPath->query( "//*[@cl='{$sClassName}' or @list='{$sClassName}']" );
00782 if ( $oNodeList->length && ( $oFirstItem = $oNodeList->item( 0 ) ) ) {
00783 $sClassId = $oFirstItem->getAttribute( 'id' );
00784 }
00785
00786 return $sClassId;
00787 }
00788
00796 public function getShopVersionNr()
00797 {
00798 $sVersion = "";
00799 if ( ( $sShopId = $this->getConfig()->getShopId() ) ) {
00800 $sVersion = oxDb::getDb()->getOne( "select oxversion from oxshops where oxid = '$sShopId' " );
00801 $sVersion = preg_replace( "/(^[^0-9]+)(.+)$/", "\$2", $sVersion );
00802 }
00803
00804 return trim( $sVersion );
00805 }
00806
00807
00816 protected function _getDynMenuUrl( $iLang, $blLoadDynContents )
00817 {
00818 if ( !$blLoadDynContents ) {
00819
00820 $sFullAdminDir = getShopBasePath() . $this->getConfig()->getConfigParam( 'sAdminDir' );
00821 $sUrl = $sFullAdminDir . "/dynscreen_local.xml";
00822 } else {
00823 $oAdminView = oxNew( 'oxadminview' );
00824 $this->_sDynIncludeUrl = $oAdminView->getServiceUrl( $iLang );
00825 $sUrl .= $this->_sDynIncludeUrl . "menue/dynscreen.xml";
00826 }
00827
00828 return $sUrl;
00829 }
00830
00836 protected function _getDynMenuLang()
00837 {
00838 $myConfig = $this->getConfig();
00839 $oLang = oxLang::getInstance();
00840
00841 $iDynLang = $myConfig->getConfigParam( 'iDynInterfaceLanguage' );
00842 $iDynLang = isset( $iDynLang )?$iDynLang:( $oLang->getTplLanguage() );
00843
00844 $aLanguages = $oLang->getLanguageArray();
00845 $sLangAbr = $aLanguages[$iDynLang]->abbr;
00846
00847 return $sLangAbr;
00848 }
00849 }