OXID eShop CE  4.8.12
 All Classes Files Functions Variables Pages
oxcategorylist.php
Go to the documentation of this file.
1 <?php
2 
3 
10 class oxCategoryList extends oxList
11 {
17  protected $_sObjectsInListName = 'oxcategory';
18 
24  protected $_blHideEmpty = false;
25 
31  protected $_blForceFull = false;
32 
38  protected $_iForceLevel = 2;
39 
45  protected $_sActCat = null;
46 
52  protected $_aPath = array();
53 
59  protected $_aUpdateInfo = array();
60 
68  public function __construct( $sObjectsInListName = 'oxcategory')
69  {
70  $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
71  parent::__construct( $sObjectsInListName );
72  }
73 
81  public function setLoadFull( $blForceFull )
82  {
83  $this->_blForceFull = $blForceFull;
84  }
85 
91  public function getLoadFull()
92  {
93  return $this->_blForceFull;
94  }
95 
103  public function setLoadLevel( $iForceLevel )
104  {
105  if ( $iForceLevel > 2 ) {
106  $iForceLevel = 2;
107  } elseif ( $iForceLevel < 1 ) {
108  $iForceLevel = 0;
109  }
110  $this->_iForceLevel = $iForceLevel;
111  }
112 
118  public function getLoadLevel()
119  {
120  return $this->_iForceLevel;
121  }
122 
131  protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
132  {
133  if ($aColumns && count($aColumns)) {
134  foreach ($aColumns as $key=>$val) {
135  $aColumns[$key].=' as '.$val;
136  }
137  return "$sTable.".implode(", $sTable.", $aColumns);
138  }
139 
140  $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
141  ." $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
142  ." $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
143  ." $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
144  ." $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
145  ." $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
146  ." $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
147  ." $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink,"
148  ." $sTable.oxthumb as oxthumb, $sTable.oxpromoicon as oxpromoicon";
149 
150  $sFieldList.= ",not $sTable.oxactive as oxppremove";
151 
152 
153  return $sFieldList;
154  }
155 
165  protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
166  {
167  $sViewName = $this->getBaseObject()->getViewName();
168  $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
169 
170  //excluding long desc
171  if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
172  $oCat = oxNew( 'oxCategory' );
173  if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
174  $oCat = null;
175  $this->_sActCat = null;
176  }
177 
178  $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
179  $sWhere = $this->_getDepthSqlSnippet($oCat);
180  } else {
181  $sUnion = '';
182  $sWhere = '1';
183  }
184 
185  if (!$sOrder) {
186  $sOrdDir = $blReverse?'desc':'asc';
187  $sOrder = "oxrootid $sOrdDir, oxleft $sOrdDir";
188  }
189 
190  return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
191  }
192 
201  protected function _getDepthSqlSnippet($oCat)
202  {
203  $sViewName = $this->getBaseObject()->getViewName();
204  $sDepthSnippet = ' ( 0';
205 
206  // load complete tree of active category, if it exists
207  if ($oCat) {
208  // select children here, siblings will be selected from union
209  $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
210  }
211 
212  // load 1'st category level (roots)
213  if ($this->getLoadLevel() >= 1) {
214  $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
215  }
216 
217  // load 2'nd category level ()
218  if ($this->getLoadLevel() >= 2) {
219  $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
220  }
221 
222  $sDepthSnippet .= ' ) ';
223  return $sDepthSnippet;
224  }
225 
236  protected function _getDepthSqlUnion($oCat, $aColumns = null)
237  {
238  if (!$oCat) {
239  return '';
240  }
241 
242  $sViewName = $this->getBaseObject()->getViewName();
243 
244  return "UNION SELECT ".$this->_getSqlSelectFieldsForTree('maincats', $aColumns)
245  ." FROM oxcategories AS subcats"
246  ." LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
247  ." WHERE subcats.oxrootid = ".oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
248  ." AND subcats.oxleft <= ". (int)$oCat->oxcategories__oxleft->value
249  ." AND subcats.oxright >= ".(int)$oCat->oxcategories__oxright->value;
250  }
251 
252 
253 
259  protected function _loadFromDb()
260  {
261  $sSql = $this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle');
262  $aData = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->getAll( $sSql );
263 
264  return $aData;
265  }
266 
272  public function load()
273  {
274 
275  $aData = $this->_loadFromDb();
276 
277  $this->assignArray( $aData );
278  }
279 
280 
290  public function buildTree( $sActCat )
291  {
292  startProfile("buildTree");
293 
294  $this->_sActCat = $sActCat;
295  $this->load();
296 
297  // PostProcessing
298  if ( !$this->isAdmin() ) {
299 
300  // remove inactive categories
302 
303  // add active cat as full object
304  $this->_ppLoadFullCategory( $sActCat );
305 
306  // builds navigation path
307  $this->_ppAddPathInfo();
308 
309  // add content categories
310  $this->_ppAddContentCategories();
311 
312  // build tree structure
313  $this->_ppBuildTree();
314  }
315 
316  stopProfile("buildTree");
317  }
318 
326  protected function _ppLoadFullCategory( $sId )
327  {
328  if ( isset($this->_aArray[$sId])) {
329  $oNewCat = oxNew( 'oxCategory' );
330  if ( $oNewCat->load($sId)) {
331  // replace aArray object with fully loaded category
332  $this->_aArray[$sId] = $oNewCat;
333  }
334  } else {
335  $this->_sActCat = null;
336  }
337  }
338 
344  public function loadList()
345  {
346  startProfile('buildCategoryList');
347 
348  $this->setLoadFull(true);
349  $this->selectString($this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle'));
350 
351  // build tree structure
352  $this->_ppBuildTree();
353 
354  // PostProcessing
355  // add tree depth info
356  $this->_ppAddDepthInformation();
357  stopProfile('buildCategoryList');
358  }
359 
360 
370  public function buildList( $blLoad )
371  {
372  if (!$blLoad) {
373  return;
374  }
375 
376  $this->loadList();
377  }
378 
386  public function setShopID($sShopID)
387  {
388  $this->_sShopID = $sShopID;
389  }
390 
396  public function getPath()
397  {
398  return $this->_aPath;
399  }
400 
406  public function getClickCat()
407  {
408  if (count($this->_aPath)) {
409  return end($this->_aPath);
410  }
411  }
412 
418  public function getClickRoot()
419  {
420  if (count($this->_aPath)) {
421  return array(reset($this->_aPath));
422  }
423  }
424 
430  protected function _ppRemoveInactiveCategories()
431  {
432  // Collect all items which must be remove
433  $aRemoveList = array();
434  foreach ($this->_aArray as $sId => $oCat) {
435  if ($oCat->oxcategories__oxppremove->value) {
436  if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
437  $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
438  }
439  $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
440  unset( $this->_aArray[$sId] );
441  } else {
442  unset($oCat->oxcategories__oxppremove);
443  }
444  }
445 
446  // Remove collected item's children from the list too (in the ranges).
447  foreach ($this->_aArray as $sId => $oCat) {
448  if ( isset( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) &&
449  is_array( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) ) {
450  foreach ( $aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight ) {
451  if (
452  ($iLeft <= $oCat->oxcategories__oxleft->value)
453  && ($iRight >= $oCat->oxcategories__oxleft->value)
454  ) {
455  // this is a child in an inactive range (parent already gone)
456  unset( $this->_aArray[$sId] );
457  break 1;
458  }
459  }
460  }
461  }
462  }
463 
469  protected function _ppAddPathInfo()
470  {
471  if (is_null($this->_sActCat)) {
472  return;
473  }
474 
475  $aPath = array();
476  $sCurrentCat = $this->_sActCat;
477 
478  while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
479  $oCat = $this[$sCurrentCat];
480  $oCat->setExpanded( true );
481  $aPath[$sCurrentCat] = $oCat;
482  $sCurrentCat = $oCat->oxcategories__oxparentid->value;
483  }
484 
485  $this->_aPath = array_reverse($aPath);
486  }
487 
493  protected function _ppAddContentCategories()
494  {
495  // load content pages for adding them into menu tree
496  $oContentList = oxNew( "oxContentList" );
497  $oContentList->loadCatMenues();
498 
499  foreach ($oContentList as $sCatId => $aContent) {
500  if (array_key_exists($sCatId, $this->_aArray)) {
501  $this[$sCatId]->setContentCats($aContent);
502 
503  }
504  }
505  }
506 
512  protected function _ppBuildTree()
513  {
514  $aTree = array();
515  foreach ($this->_aArray as $oCat) {
516  $sParentId = $oCat->oxcategories__oxparentid->value;
517  if ( $sParentId != 'oxrootid') {
518  if (isset($this->_aArray[$sParentId])) {
519  $this->_aArray[$sParentId]->setSubCat( $oCat, $oCat->getId() );
520  }
521  } else {
522  $aTree[$oCat->getId()] = $oCat;
523  }
524  }
525 
526  $this->assign($aTree);
527  }
528 
535  protected function _ppAddDepthInformation()
536  {
537  $aStack = array();
538  $iDepth = 0;
539  $sPrevParent = '';
540 
541  $aTree = array();
542  foreach ($this->_aArray as $oCat) {
543 
544  $aTree[$oCat->getId()] = $oCat;
545  $aSubCats = $oCat->getSubCats();
546  if ( count($aSubCats) > 0 ) {
547  foreach ($aSubCats as $oSubCat) {
548  $aTree = $this->_addDepthInfo($aTree, $oSubCat);
549  }
550  }
551  }
552  $this->assign($aTree);
553  }
554 
564  protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
565  {
566  $sDepth .= "-";
567  $oCat->oxcategories__oxtitle->setValue($sDepth.' '.$oCat->oxcategories__oxtitle->value);
568  $aTree[$oCat->getId()] = $oCat;
569  $aSubCats = $oCat->getSubCats();
570  if ( count($aSubCats) > 0 ) {
571  foreach ($aSubCats as $oSubCat) {
572  $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
573  }
574  }
575  return $aTree;
576  }
585  public function updateCategoryTree($blVerbose = true, $sShopID = null)
586  {
587  $oDb = oxDb::getDb();
588  $sWhere = '1';
589 
590 
591  $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
592  $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
593 
594  // Get all root categories
595  $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false );
596  if ($rs != false && $rs->recordCount() > 0) {
597  while (!$rs->EOF) {
598  $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
599  if ( $blVerbose ) {
600  echo next( $this->_aUpdateInfo );
601  }
602  $oxRootId = $rs->fields[0];
603 
604  $this->_updateNodes($oxRootId, true, $oxRootId);
605  $rs->moveNext();
606  }
607  }
608  }
609 
615  public function getUpdateInfo()
616  {
617  return $this->_aUpdateInfo;
618  }
619 
629  protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
630  {
631  $oDb = oxDb::getDb();
632 
633  if ($isRoot) {
634  $thisRoot = $oxRootId;
635  }
636 
637  // Get sub categories of root categories
638  $rs = $oDb->execute("update oxcategories set oxrootid = ".$oDb->quote($thisRoot)." where oxparentid = ".$oDb->quote($oxRootId));
639  $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = ".$oDb->quote($oxRootId)." order by oxsort", false, false);
640  // If there are sub categories
641  if ($rs != false && $rs->recordCount() > 0) {
642  while (!$rs->EOF) {
643  $parentId = $rs->fields[1];
644  $actOxid = $rs->fields[0];
645  $sActOxidQuoted = $oDb->quote($actOxid);
646 
647  // Get the data of the parent category to the current Cat
648  $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = ".$oDb->quote($parentId), false, false );
649  while (!$rs3->EOF) {
650  $parentOxRootId = $rs3->fields[0];
651  $parentRight = (int)$rs3->fields[1];
652  $rs3->moveNext();
653  }
654  $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
655  $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
656  $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
657  $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
658  $this->_updateNodes($actOxid, false, $thisRoot);
659  $rs->moveNext();
660  }
661  }
662  }
663 
671  public function __get($sName)
672  {
673  switch ($sName) {
674  case 'aPath':
675  case 'aFullPath':
676  return $this->getPath();
677  break;
678  }
679  return parent::__get($sName);
680  }
681 
682 }