OXID eShop CE  4.9.8
 All Classes Files Functions Variables Pages
oxnavigationtree.php
Go to the documentation of this file.
1 <?php
2 
7 {
8 
12  protected $_oDom = null;
13 
17  protected $_oInitialDom = null;
18 
24  protected $_sDynIncludeUrl = null;
25 
31  protected $_aSupportedExpathXmlEncodings = array('utf-8', 'utf-16', 'iso-8859-1', 'us-ascii');
32 
40  protected function _cleanEmptyParents($oDom, $sParentXPath, $sChildXPath)
41  {
42  $oXPath = new DomXPath($oDom);
43  $oNodeList = $oXPath->query($sParentXPath);
44 
45  foreach ($oNodeList as $oNode) {
46  $sId = $oNode->getAttribute('id');
47  $oChildList = $oXPath->query("{$sParentXPath}[@id='$sId']/$sChildXPath");
48  if (!$oChildList->length) {
49  $oNode->parentNode->removeChild($oNode);
50  }
51  }
52  }
53 
59  protected function _addLinks($oDom)
60  {
61  $sURL = 'index.php?'; // session parameters will be included later (after cache processor)
62  $oXPath = new DomXPath($oDom);
63 
64  // building
65  $oNodeList = $oXPath->query("//SUBMENU[@cl]");
66  foreach ($oNodeList as $oNode) {
67  // fetching class
68  $sCl = $oNode->getAttribute('cl');
69  $sCl = $sCl ? "cl=$sCl" : '';
70 
71  // fetching params
72  $sParam = $oNode->getAttribute('clparam');
73  $sParam = $sParam ? "&$sParam" : '';
74 
75  // setting link
76  $oNode->setAttribute('link', "{$sURL}{$sCl}{$sParam}");
77  }
78  }
79 
86  protected function _loadFromFile($sMenuFile, $oDom)
87  {
88  $blMerge = false;
89  $oDomFile = new DomDocument();
90  $oDomFile->preserveWhiteSpace = false;
91  if (!@$oDomFile->load($sMenuFile)) {
92  $blMerge = true;
93  } elseif (is_readable($sMenuFile) && ($sXml = @file_get_contents($sMenuFile))) {
94 
95  // looking for non supported character encoding
96  if (getStr()->preg_match("/encoding\=(.*)\?>/", $sXml, $aMatches) !== 0) {
97  if (isset($aMatches[1])) {
98  $sCurrEncoding = trim($aMatches[1], "\"");
99  if (!in_array(strtolower($sCurrEncoding), $this->_aSupportedExpathXmlEncodings)) {
100  $sXml = str_replace($aMatches[1], "\"UTF-8\"", $sXml);
101  $sXml = iconv($sCurrEncoding, "UTF-8", $sXml);
102  }
103  }
104  }
105 
106  // load XML as string
107  if (@$oDomFile->loadXml($sXml)) {
108  $blMerge = true;
109  }
110  }
111 
112  if ($blMerge) {
113  $this->_merge($oDomFile, $oDom);
114  }
115  }
116 
122  protected function _addDynLinks($oDom)
123  {
124  $myConfig = $this->getConfig();
125  $myUtilsFile = oxRegistry::get("oxUtilsFile");
126 
127  $sURL = 'index.php?'; // session parameters will be included later (after cache processor)
128 
129  $oXPath = new DomXPath($oDom);
130  $oNodeList = $oXPath->query("//OXMENU[@type='dyn']/MAINMENU/SUBMENU");
131 
132  foreach ($oNodeList as $oNode) {
133 
134  // fetching class
135  $sCl = $oNode->getAttribute('cl');
136  $sCl = "cl=dynscreen&menu=$sCl";
137 
138  // fetching params
139  $sParam = $oNode->getAttribute('clparam');
140  $sParam = $sParam ? "&$sParam" : '';
141 
142  // setting list node if its is not set yet
143  if (!$oNode->getAttribute('list')) {
144  $oNode->setAttribute('list', 'dynscreen_list');
145  $oNode->setAttribute('listparam', 'menu=' . $oNode->getAttribute('cl'));
146  }
147 
148  // setting link
149  $oNode->setAttribute('link', "{$sURL}{$sCl}{$sParam}");
150 
151  // setting id
152  $oNode->parentNode->setAttribute('id', 'dyn_menu');
153 
154  // setting id to its parent
155 
156  // fetching class
157  $sFile = $oNode->getAttribute('cl');
158 
159  // always display the "about" tab no matter what licence
160 
161  if ($myUtilsFile->checkFile("{$this->_sDynIncludeUrl}pages/{$sFile}_about.php")) {
162  $oTabElem = new DOMElement('TAB');
163  $oNode->appendChild($oTabElem);
164  $oTabElem->setAttribute('external', 'true');
165  $oTabElem->setAttribute('location', "{$this->_sDynIncludeUrl}pages/{$sFile}_about.php");
166  $oTabElem->setAttribute('id', 'dyn_about');
167  }
168 
169  // checking for technics page
170  if ($myUtilsFile->checkFile("{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php")) {
171  $oTabElem = new DOMElement('TAB');
172  $oNode->appendChild($oTabElem);
173  $oTabElem->setAttribute('external', 'true');
174  $oTabElem->setAttribute('location', "{$this->_sDynIncludeUrl}pages/{$sFile}_technics.php");
175  $oTabElem->setAttribute('id', 'dyn_interface');
176  }
177 
178  // checking for setup page
179  if (file_exists($myConfig->getConfigParam('sShopDir') . "/application/controllers/admin/{$sFile}.php")) {
180  $oTabElem = new DOMElement('TAB');
181  $oNode->appendChild($oTabElem);
182  $oTabElem->setAttribute('id', 'dyn_interface');
183  $oTabElem->setAttribute('cl', $sFile);
184  }
185  }
186  }
187 
193  protected function _sessionizeLocalUrls($oDom)
194  {
195  $sURL = $this->_getAdminUrl();
196  $oXPath = new DomXPath($oDom);
197  $oStr = getStr();
198  foreach (array('url', 'link') as $sAttrType) {
199  foreach ($oXPath->query("//OXMENU//*[@$sAttrType]") as $oNode) {
200  $sLocalUrl = $oNode->getAttribute($sAttrType);
201  if (strpos($sLocalUrl, 'index.php?') === 0) {
202  $sLocalUrl = $oStr->preg_replace('#^index.php\?#', $sURL, $sLocalUrl);
203  $oNode->setAttribute($sAttrType, $sLocalUrl);
204  }
205  }
206  }
207  }
208 
214  protected function _checkRights($oDom)
215  {
216  $oXPath = new DomXPath($oDom);
217  $oNodeList = $oXPath->query('//*[@rights or @norights]');
218 
219  foreach ($oNodeList as $oNode) {
220  // only allowed modules/user rights or so
221  if (($sReq = $oNode->getAttribute('rights'))) {
222  $aPerm = explode(',', $sReq);
223  foreach ($aPerm as $sPerm) {
224  if ($sPerm && !$this->_hasRights($sPerm)) {
225  $oNode->parentNode->removeChild($oNode);
226  }
227  }
228  // not allowed modules/user rights or so
229  } elseif (($sNoReq = $oNode->getAttribute('norights'))) {
230  $aPerm = explode(',', $sNoReq);
231  foreach ($aPerm as $sPerm) {
232  if ($sPerm && $this->_hasRights($sPerm)) {
233  $oNode->parentNode->removeChild($oNode);
234  }
235  }
236  }
237  }
238  }
239 
245  protected function _checkGroups($oDom)
246  {
247  $oXPath = new DomXPath($oDom);
248  $oNodeList = $oXPath->query("//*[@nogroup or @group]");
249 
250  foreach ($oNodeList as $oNode) {
251  // allowed only for groups
252  if (($sReq = $oNode->getAttribute('group'))) {
253  $aPerm = explode(',', $sReq);
254  foreach ($aPerm as $sPerm) {
255  if ($sPerm && !$this->_hasGroup($sPerm)) {
256  $oNode->parentNode->removeChild($oNode);
257  }
258  }
259  // not allowed for groups
260  } elseif (($sNoReq = $oNode->getAttribute('nogroup'))) {
261  $aPerm = explode(',', $sNoReq);
262  foreach ($aPerm as $sPerm) {
263  if ($sPerm && $this->_hasGroup($sPerm)) {
264  $oNode->parentNode->removeChild($oNode);
265  }
266  }
267  }
268  }
269  }
270 
278  protected function _checkDemoShopDenials($oDom)
279  {
280  if (!$this->getConfig()->isDemoShop()) {
281  // nothing to check for non demo shop
282  return;
283  }
284 
285  $oXPath = new DomXPath($oDom);
286  $oNodeList = $oXPath->query("//*[@disableForDemoShop]");
287  foreach ($oNodeList as $oNode) {
288  if ($oNode->getAttribute('disableForDemoShop')) {
289  $oNode->parentNode->removeChild($oNode);
290  }
291  }
292  }
293 
300  protected function _copyAttributes($oDomElemTo, $oDomElemFrom)
301  {
302  foreach ($oDomElemFrom->attributes as $oAttr) {
303  $oDomElemTo->setAttribute($oAttr->nodeName, $oAttr->nodeValue);
304  }
305  }
306 
316  protected function _mergeNodes($oDomElemTo, $oDomElemFrom, $oXPathTo, $oDomDocTo, $sQueryStart)
317  {
318  foreach ($oDomElemFrom->childNodes as $oFromNode) {
319  if ($oFromNode->nodeType === XML_ELEMENT_NODE) {
320 
321  $sFromAttrName = $oFromNode->getAttribute('id');
322  $sFromNodeName = $oFromNode->tagName;
323 
324  // find current item
325  $sQuery = "{$sQueryStart}/{$sFromNodeName}[@id='{$sFromAttrName}']";
326  $oCurNode = $oXPathTo->query($sQuery);
327 
328  // if not found - append
329  if ($oCurNode->length == 0) {
330  $oDomElemTo->appendChild($oDomDocTo->importNode($oFromNode, true));
331  } else {
332 
333  $oCurNode = $oCurNode->item(0);
334 
335  // if found copy all attributes and check childnodes
336  $this->_copyAttributes($oCurNode, $oFromNode);
337 
338  if ($oFromNode->childNodes->length) {
339  $this->_mergeNodes($oCurNode, $oFromNode, $oXPathTo, $oDomDocTo, $sQuery);
340  }
341  }
342  }
343  }
344  }
345 
352  protected function _merge($oDomNew, $oDom)
353  {
354  $oXPath = new DOMXPath($oDom);
355  $this->_mergeNodes($oDom->documentElement, $oDomNew->documentElement, $oXPath, $oDom, '/OX');
356  }
357 
367  public function getTabs($sId, $iAct, $blSetActive = true)
368  {
369  $oXPath = new DOMXPath($this->getDomXml());
370  //$oNodeList = $oXPath->query( "//SUBMENU[@cl='$sId' or @list='$sId']/TAB | //SUBMENU/../TAB[@cl='$sId']" );
371  $oNodeList = $oXPath->query("//SUBMENU[@cl='$sId']/TAB | //SUBMENU[@list='$sId']/TAB | //SUBMENU/../TAB[@cl='$sId']");
372 
373  $iAct = ($iAct > $oNodeList->length) ? ($oNodeList->length - 1) : $iAct;
374 
375  if ($blSetActive) {
376  foreach ($oNodeList as $iPos => $oNode) {
377  if ($iPos == $iAct) {
378  // marking active node
379  $oNode->setAttribute('active', 1);
380  }
381  }
382  }
383 
384  return $oNodeList;
385  }
386 
395  public function getActiveTab($sId, $iAct)
396  {
397  $sTab = null;
398  $oNodeList = $this->getTabs($sId, $iAct, false);
399  $iAct = ($iAct > $oNodeList->length) ? ($oNodeList->length - 1) : $iAct;
400  if ($oNodeList->length && ($oNode = $oNodeList->item($iAct))) {
401  $sTab = $oNode->getAttribute('cl');
402  }
403 
404  return $sTab;
405  }
406 
414  public function getBtn($sClass)
415  {
416  $oButtons = null;
417  $oXPath = new DOMXPath($this->getDomXml());
418  $oNodeList = $oXPath->query("//TAB[@cl='$sClass']/../BTN");
419  if ($oNodeList->length) {
420  $oButtons = new stdClass();
421  foreach ($oNodeList as $oNode) {
422  $sBtnID = $oNode->getAttribute('id');
423  $oButtons->$sBtnID = 1;
424  }
425  }
426 
427  return $oButtons;
428  }
429 
435  protected function _getMenuFiles()
436  {
437  $myConfig = $this->getConfig();
438  $myOxUtlis = oxRegistry::getUtils();
439 
440  $sFullAdminDir = getShopBasePath() . 'application/views/admin';
441  $sMenuFile = "/menu.xml";
442 
443  $sTmpDir = $myConfig->getConfigParam('sCompileDir');
444  $sDynLang = $this->_getDynMenuLang();
445  $sLocalDynPath = "{$sTmpDir}{$sDynLang}_dynscreen.xml";
446 
447 
448  // including std file
449  if (file_exists($sFullAdminDir . $sMenuFile)) {
450  $aFilesToLoad[] = $sFullAdminDir . $sMenuFile;
451  }
452 
453  // including custom file
454  if (file_exists("$sFullAdminDir/user.xml")) {
455  $aFilesToLoad[] = "$sFullAdminDir/user.xml";
456  }
457 
458  // including module menu files
459  $sPath = getShopBasePath();
460  $oModulelist = oxNew('oxmodulelist');
461  $aActiveModuleInfo = $oModulelist->getActiveModuleInfo();
462  if (is_array($aActiveModuleInfo)) {
463  foreach ($aActiveModuleInfo as $sModulePath) {
464  $sFullPath = $sPath . "modules/" . $sModulePath;
465  // missing file/folder?
466  if (is_dir($sFullPath)) {
467  // including menu file
468  $sMenuFile = $sFullPath . "/menu.xml";
469  if (file_exists($sMenuFile) && is_readable($sMenuFile)) {
470  $aFilesToLoad[] = $sMenuFile;
471  }
472  }
473  }
474  }
475 
476  $blLoadDynContents = $myConfig->getConfigParam('blLoadDynContents');
477  $sShopCountry = $myConfig->getConfigParam('sShopCountry');
478 
479  // including dyn menu file
480  $sDynPath = null;
481 
482  if ($blLoadDynContents) {
483  if ($sShopCountry) {
484  $sRemoteDynUrl = $this->_getDynMenuUrl($sDynLang, $blLoadDynContents);
485 
486  // loading remote file from server only once
487  $blLoadRemote = oxRegistry::getSession()->getVariable("loadedremotexml");
488 
489  // very basic check if its valid xml file
490  if ((!isset($blLoadRemote) || $blLoadRemote) && ($sDynPath = $myOxUtlis->getRemoteCachePath($sRemoteDynUrl, $sLocalDynPath))) {
491  $sDynPath = $this->_checkDynFile($sDynPath);
492  }
493 
494  // caching last load state
495  oxRegistry::getSession()->setVariable("loadedremotexml", $sDynPath ? true : false);
496  }
497  } else {
498  if ($sShopCountry) {
499  //non international country
500  }
501  }
502 
503  // loading dynpages
504  if ($sDynPath) {
505  $aFilesToLoad[] = $sDynPath;
506  }
507 
508  return $aFilesToLoad;
509  }
510 
518  protected function _checkDynFile($sDynFilePath)
519  {
520  $sDynFile = null;
521  if (file_exists($sDynFilePath)) {
522  $sLine = null;
523  if (($rHandle = @fopen($sDynFilePath, 'r'))) {
524  $sLine = stream_get_line($rHandle, 100, "?>");
525  fclose($rHandle);
526 
527  // checking xml file header
528  if ($sLine && stripos($sLine, '<?xml') !== false) {
529  $sDynFile = $sDynFilePath;
530  }
531  }
532 
533  // cleanup ..
534  if (!$sDynFile) {
535  @unlink($sDynFilePath);
536  }
537  }
538 
539  return $sDynFile;
540  }
541 
553  protected function _processCachedFile($sCacheContents)
554  {
555 
556  return $sCacheContents;
557  }
558 
564  protected function _getInitialDom()
565  {
566  if ($this->_oInitialDom === null) {
567  $myOxUtlis = oxRegistry::getUtils();
568 
569  if (is_array($aFilesToLoad = $this->_getMenuFiles())) {
570 
571  // now checking if xml files are newer than cached file
572  $blReload = false;
573  $sDynLang = $this->_getDynMenuLang();
574 
575  $sShopId = $this->getConfig()->getActiveShop()->getShopId();
576  $sCacheName = 'menu_' . $sDynLang . $sShopId . '_xml';
577  $sCacheFile = $myOxUtlis->getCacheFilePath($sCacheName);
578  $sCacheContents = $myOxUtlis->fromFileCache($sCacheName);
579  if ($sCacheContents && file_exists($sCacheFile) && ($iCacheModTime = filemtime($sCacheFile))) {
580  foreach ($aFilesToLoad as $sDynPath) {
581  if ($iCacheModTime < filemtime($sDynPath)) {
582  $blReload = true;
583  }
584  }
585  } else {
586  $blReload = true;
587  }
588 
589  $this->_oInitialDom = new DOMDocument();
590  if ($blReload) {
591  // fully reloading and building pathes
592  $this->_oInitialDom->appendChild(new DOMElement('OX'));
593 
594  foreach ($aFilesToLoad as $sDynPath) {
595  $this->_loadFromFile($sDynPath, $this->_oInitialDom);
596  }
597 
598  // adds links to menu items
599  $this->_addLinks($this->_oInitialDom);
600 
601  // adds links to dynamic parts
602  $this->_addDynLinks($this->_oInitialDom);
603 
604  // writing to cache
605  $myOxUtlis->toFileCache($sCacheName, $this->_oInitialDom->saveXML());
606  } else {
607  $sCacheContents = $this->_processCachedFile($sCacheContents);
608  // loading from cached file
609  $this->_oInitialDom->preserveWhiteSpace = false;
610  $this->_oInitialDom->loadXML($sCacheContents);
611  }
612 
613  // add session params
614  $this->_sessionizeLocalUrls($this->_oInitialDom);
615  }
616  }
617 
618  return $this->_oInitialDom;
619  }
620 
626  public function getDomXml()
627  {
628  if ($this->_oDom === null) {
629  $this->_oDom = clone $this->_getInitialDom();
630 
631  // removes items denied by user group
632  $this->_checkGroups($this->_oDom);
633 
634  // removes items denied by user rights
635  $this->_checkRights($this->_oDom);
636 
637  // check config params
638  $this->_checkDemoShopDenials($this->_oDom);
639 
640 
641  $this->_cleanEmptyParents($this->_oDom, '//SUBMENU[@id][@list]', 'TAB');
642  $this->_cleanEmptyParents($this->_oDom, '//MAINMENU[@id]', 'SUBMENU');
643  }
644 
645  return $this->_oDom;
646  }
647 
655  public function getListNodes($aNodes)
656  {
657  $oXPath = new DOMXPath($this->getDomXml());
658  $oNodeList = $oXPath->query("//SUBMENU[@cl='" . implode("' or @cl='", $aNodes) . "']");
659 
660  return ($oNodeList->length) ? $oNodeList : null;
661  }
662 
668  public function markNodeActive($sNodeId)
669  {
670  $oXPath = new DOMXPath($this->getDomXml());
671  $oNodeList = $oXPath->query("//*[@cl='{$sNodeId}' or @list='{$sNodeId}']");
672 
673  if ($oNodeList->length) {
674  foreach ($oNodeList as $oNode) {
675  // special case for external resources
676  $oNode->setAttribute('active', 1);
677  $oNode->parentNode->setAttribute('active', 1);
678  }
679  }
680 
681  }
682 
690  public function getListUrl($sId)
691  {
692  $sUrl = null;
693  $oXPath = new DOMXPath($this->getDomXml());
694  $oNodeList = $oXPath->query("//SUBMENU[@cl='{$sId}']");
695  if ($oNodeList->length && ($oNode = $oNodeList->item(0))) {
696  $sCl = $oNode->getAttribute('list');
697  $sCl = $sCl ? "cl=$sCl" : '';
698 
699  $sParams = $oNode->getAttribute('listparam');
700  $sParams = $sParams ? "&$sParams" : '';
701 
702  $sUrl = "{$sCl}{$sParams}";
703  }
704 
705  return $sUrl;
706  }
707 
716  public function getEditUrl($sId, $iActTab)
717  {
718  $sUrl = null;
719  $oXPath = new DOMXPath($this->getDomXml());
720  $oNodeList = $oXPath->query("//SUBMENU[@cl='{$sId}']/TAB");
721 
722  $iActTab = ($iActTab > $oNodeList->length) ? ($oNodeList->length - 1) : $iActTab;
723  if ($oNodeList->length && ($oActTab = $oNodeList->item($iActTab))) {
724  // special case for external resources
725  if ($oActTab->getAttribute('external')) {
726  $sUrl = $oActTab->getAttribute('location');
727  } else {
728  $sCl = $oActTab->getAttribute('cl');
729  $sCl = $sCl ? "cl={$sCl}" : '';
730 
731  $sParams = $oActTab->getAttribute('clparam');
732  $sParams = $sParams ? "&{$sParams}" : '';
733 
734  $sUrl = "{$sCl}{$sParams}";
735  }
736  }
737 
738  return $sUrl;
739  }
740 
746  protected function _getAdminUrl()
747  {
748  $myConfig = $this->getConfig();
749 
750  if (($sAdminSslUrl = $myConfig->getConfigParam('sAdminSSLURL'))) {
751  $sURL = trim($sAdminSslUrl, '/');
752  } else {
753  $sURL = trim($myConfig->getConfigParam('sShopURL'), '/') . '/admin';
754  }
755 
756  return oxRegistry::get("oxUtilsUrl")->processUrl("{$sURL}/index.php", false);
757  }
758 
766  protected function _hasRights($sRights)
767  {
768  return $this->getUser()->oxuser__oxrights->value == $sRights;
769  }
770 
778  protected function _hasGroup($sGroupId)
779  {
780  return $this->getUser()->inGroup($sGroupId);
781  }
782 
790  public function getClassId($sClassName)
791  {
792  $sClassId = null;
793 
794  $oXPath = new DOMXPath($this->_getInitialDom());
795  $oNodeList = $oXPath->query("//*[@cl='{$sClassName}' or @list='{$sClassName}']");
796  if ($oNodeList->length && ($oFirstItem = $oNodeList->item(0))) {
797  $sClassId = $oFirstItem->getAttribute('id');
798  }
799 
800  return $sClassId;
801  }
802 
803 
812  protected function _getDynMenuUrl($iLang, $blLoadDynContents)
813  {
814  if (!$blLoadDynContents) {
815  // getting dyn info from oxid server is off, so getting local menu path
816  $sFullAdminDir = getShopBasePath() . 'application/views/admin';
817  $sUrl = $sFullAdminDir . "/dynscreen_local.xml";
818  } else {
819  $oAdminView = oxNew('oxadminview');
820  $this->_sDynIncludeUrl = $oAdminView->getServiceUrl($iLang);
821  $sUrl .= $this->_sDynIncludeUrl . "menue/dynscreen.xml";
822  }
823 
824  return $sUrl;
825  }
826 
832  protected function _getDynMenuLang()
833  {
834  $myConfig = $this->getConfig();
835  $oLang = oxRegistry::getLang();
836 
837  $iDynLang = $myConfig->getConfigParam('iDynInterfaceLanguage');
838  $iDynLang = isset($iDynLang) ? $iDynLang : ($oLang->getTplLanguage());
839 
840  $aLanguages = $oLang->getLanguageArray();
841  $sLangAbr = $aLanguages[$iDynLang]->abbr;
842 
843  return $sLangAbr;
844  }
845 }