OXID eShop CE  4.10.0
 All Classes Namespaces Files Functions Variables Pages
oxcategorylist.php
Go to the documentation of this file.
1 <?php
2 
3 
10 class oxCategoryList extends oxList
11 {
12 
18  protected $_sObjectsInListName = 'oxcategory';
19 
25  protected $_blHideEmpty = false;
26 
32  protected $_blForceFull = false;
33 
39  protected $_iForceLevel = 2;
40 
46  protected $_sActCat = null;
47 
53  protected $_aPath = array();
54 
60  protected $_aUpdateInfo = array();
61 
69  public function __construct($sObjectsInListName = 'oxcategory')
70  {
71  $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
72  parent::__construct($sObjectsInListName);
73  }
74 
80  public function setLoadFull($blForceFull)
81  {
82  $this->_blForceFull = $blForceFull;
83  }
84 
90  public function getLoadFull()
91  {
92  return $this->_blForceFull;
93  }
94 
100  public function setLoadLevel($iForceLevel)
101  {
102  if ($iForceLevel > 2) {
103  $iForceLevel = 2;
104  } elseif ($iForceLevel < 1) {
105  $iForceLevel = 0;
106  }
107  $this->_iForceLevel = $iForceLevel;
108  }
109 
115  public function getLoadLevel()
116  {
117  return $this->_iForceLevel;
118  }
119 
128  protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
129  {
130  if ($aColumns && count($aColumns)) {
131  foreach ($aColumns as $key => $val) {
132  $aColumns[$key] .= ' as ' . $val;
133  }
134 
135  return "$sTable." . implode(", $sTable.", $aColumns);
136  }
137 
138  $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
139  . " $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
140  . " $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
141  . " $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
142  . " $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
143  . " $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
144  . " $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
145  . " $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink,"
146  . " $sTable.oxthumb as oxthumb, $sTable.oxpromoicon as oxpromoicon";
147 
148  $sFieldList .= ",not $sTable.oxactive as oxppremove";
149 
150 
151  return $sFieldList;
152  }
153 
163  protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
164  {
165  $sViewName = $this->getBaseObject()->getViewName();
166  $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
167 
168  //excluding long desc
169  if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
170  $oCat = oxNew('oxCategory');
171  if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
172  $oCat = null;
173  $this->_sActCat = null;
174  }
175 
176  $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
177  $sWhere = $this->_getDepthSqlSnippet($oCat);
178  } else {
179  $sUnion = '';
180  $sWhere = '1';
181  }
182 
183  if (!$sOrder) {
184  $sOrdDir = $blReverse ? 'desc' : 'asc';
185  $sOrder = "oxrootid $sOrdDir, oxleft $sOrdDir";
186  }
187 
188  return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
189  }
190 
199  protected function _getDepthSqlSnippet($oCat)
200  {
201  $sViewName = $this->getBaseObject()->getViewName();
202  $sDepthSnippet = ' ( 0';
203 
204  // load complete tree of active category, if it exists
205  if ($oCat) {
206  // select children here, siblings will be selected from union
207  $sDepthSnippet .= " or ($sViewName.oxparentid = " . oxDb::getDb()->quote($oCat->oxcategories__oxid->value) . ")";
208  }
209 
210  // load 1'st category level (roots)
211  if ($this->getLoadLevel() >= 1) {
212  $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
213  }
214 
215  // load 2'nd category level ()
216  if ($this->getLoadLevel() >= 2) {
217  $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
218  }
219 
220  $sDepthSnippet .= ' ) ';
221 
222  return $sDepthSnippet;
223  }
224 
235  protected function _getDepthSqlUnion($oCat, $aColumns = null)
236  {
237  if (!$oCat) {
238  return '';
239  }
240 
241  $sViewName = $this->getBaseObject()->getViewName();
242 
243  return "UNION SELECT " . $this->_getSqlSelectFieldsForTree('maincats', $aColumns)
244  . " FROM oxcategories AS subcats"
245  . " LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
246  . " WHERE subcats.oxrootid = " . oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
247  . " AND subcats.oxleft <= " . (int) $oCat->oxcategories__oxleft->value
248  . " AND subcats.oxright >= " . (int) $oCat->oxcategories__oxright->value;
249  }
250 
251 
252 
258  protected function _loadFromDb()
259  {
260  $sSql = $this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle');
261  $aData = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->getAll($sSql);
262 
263  return $aData;
264  }
265 
269  public function load()
270  {
271 
272  $aData = $this->_loadFromDb();
273 
274  $this->assignArray($aData);
275  }
276 
277 
285  public function buildTree($sActCat)
286  {
287  startProfile("buildTree");
288 
289  $this->_sActCat = $sActCat;
290  $this->load();
291 
292  // PostProcessing
293  if (!$this->isAdmin()) {
294 
295  // remove inactive categories
297 
298  // add active cat as full object
299  $this->_ppLoadFullCategory($sActCat);
300 
301  // builds navigation path
302  $this->_ppAddPathInfo();
303 
304  // add content categories
305  $this->_ppAddContentCategories();
306 
307  // build tree structure
308  $this->_ppBuildTree();
309  }
310 
311  stopProfile("buildTree");
312  }
313 
319  protected function _ppLoadFullCategory($sId)
320  {
321  if (isset($this->_aArray[$sId])) {
322  $oNewCat = oxNew('oxCategory');
323  if ($oNewCat->load($sId)) {
324  // replace aArray object with fully loaded category
325  $this->_aArray[$sId] = $oNewCat;
326  }
327  } else {
328  $this->_sActCat = null;
329  }
330  }
331 
335  public function loadList()
336  {
337  startProfile('buildCategoryList');
338 
339  $this->setLoadFull(true);
340  $this->selectString($this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle'));
341 
342  // build tree structure
343  $this->_ppBuildTree();
344 
345  // PostProcessing
346  // add tree depth info
347  $this->_ppAddDepthInformation();
348  stopProfile('buildCategoryList');
349  }
350 
356  public function setShopID($sShopID)
357  {
358  $this->_sShopID = $sShopID;
359  }
360 
366  public function getPath()
367  {
368  return $this->_aPath;
369  }
370 
376  public function getClickCat()
377  {
378  if (count($this->_aPath)) {
379  return end($this->_aPath);
380  }
381  }
382 
388  public function getClickRoot()
389  {
390  if (count($this->_aPath)) {
391  return array(reset($this->_aPath));
392  }
393  }
394 
398  protected function _ppRemoveInactiveCategories()
399  {
400  // Collect all items which must be remove
401  $aRemoveList = array();
402  foreach ($this->_aArray as $sId => $oCat) {
403  if ($oCat->oxcategories__oxppremove->value) {
404  if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
405  $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
406  }
407  $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
408  unset($this->_aArray[$sId]);
409  } else {
410  unset($oCat->oxcategories__oxppremove);
411  }
412  }
413 
414  // Remove collected item's children from the list too (in the ranges).
415  foreach ($this->_aArray as $sId => $oCat) {
416  if (isset($aRemoveList[$oCat->oxcategories__oxrootid->value]) &&
417  is_array($aRemoveList[$oCat->oxcategories__oxrootid->value])
418  ) {
419  foreach ($aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight) {
420  if (
421  ($iLeft <= $oCat->oxcategories__oxleft->value)
422  && ($iRight >= $oCat->oxcategories__oxleft->value)
423  ) {
424  // this is a child in an inactive range (parent already gone)
425  unset($this->_aArray[$sId]);
426  break 1;
427  }
428  }
429  }
430  }
431  }
432 
438  protected function _ppAddPathInfo()
439  {
440  if (is_null($this->_sActCat)) {
441  return;
442  }
443 
444  $aPath = array();
445  $sCurrentCat = $this->_sActCat;
446 
447  while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
448  $oCat = $this[$sCurrentCat];
449  $oCat->setExpanded(true);
450  $aPath[$sCurrentCat] = $oCat;
451  $sCurrentCat = $oCat->oxcategories__oxparentid->value;
452  }
453 
454  $this->_aPath = array_reverse($aPath);
455  }
456 
460  protected function _ppAddContentCategories()
461  {
462  // load content pages for adding them into menu tree
463  $oContentList = oxNew("oxContentList");
464  $oContentList->loadCatMenues();
465 
466  foreach ($oContentList as $sCatId => $aContent) {
467  if (array_key_exists($sCatId, $this->_aArray)) {
468  $this[$sCatId]->setContentCats($aContent);
469 
470  }
471  }
472  }
473 
477  protected function _ppBuildTree()
478  {
479  $aTree = array();
480  foreach ($this->_aArray as $oCat) {
481  $sParentId = $oCat->oxcategories__oxparentid->value;
482  if ($sParentId != 'oxrootid') {
483  if (isset($this->_aArray[$sParentId])) {
484  $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId());
485  }
486  } else {
487  $aTree[$oCat->getId()] = $oCat;
488  }
489  }
490 
491  $this->assign($aTree);
492  }
493 
498  protected function _ppAddDepthInformation()
499  {
500  $aStack = array();
501  $iDepth = 0;
502  $sPrevParent = '';
503 
504  $aTree = array();
505  foreach ($this->_aArray as $oCat) {
506 
507  $aTree[$oCat->getId()] = $oCat;
508  $aSubCats = $oCat->getSubCats();
509  if (count($aSubCats) > 0) {
510  foreach ($aSubCats as $oSubCat) {
511  $aTree = $this->_addDepthInfo($aTree, $oSubCat);
512  }
513  }
514  }
515  $this->assign($aTree);
516  }
517 
527  protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
528  {
529  $sDepth .= "-";
530  $oCat->oxcategories__oxtitle->setValue($sDepth . ' ' . $oCat->oxcategories__oxtitle->value);
531  $aTree[$oCat->getId()] = $oCat;
532  $aSubCats = $oCat->getSubCats();
533  if (count($aSubCats) > 0) {
534  foreach ($aSubCats as $oSubCat) {
535  $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
536  }
537  }
538 
539  return $aTree;
540  }
541 
548  public function updateCategoryTree($blVerbose = true, $sShopID = null)
549  {
550  $oDb = oxDb::getDb();
551  $sWhere = '1';
552 
553 
554  $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
555  $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
556 
557  // Get all root categories
558  $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false);
559  if ($rs != false && $rs->recordCount() > 0) {
560  while (!$rs->EOF) {
561  $this->_aUpdateInfo[] = "<b>Processing : " . $rs->fields[1] . "</b>(" . $rs->fields[0] . ")<br>";
562  if ($blVerbose) {
563  echo next($this->_aUpdateInfo);
564  }
565  $oxRootId = $rs->fields[0];
566 
567  $this->_updateNodes($oxRootId, true, $oxRootId);
568  $rs->moveNext();
569  }
570  }
571  }
572 
578  public function getUpdateInfo()
579  {
580  return $this->_aUpdateInfo;
581  }
582 
590  protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
591  {
592  $oDb = oxDb::getDb();
593 
594  if ($isRoot) {
595  $thisRoot = $oxRootId;
596  }
597 
598  // Get sub categories of root categories
599  $rs = $oDb->execute("update oxcategories set oxrootid = " . $oDb->quote($thisRoot) . " where oxparentid = " . $oDb->quote($oxRootId));
600  $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = " . $oDb->quote($oxRootId) . " order by oxsort", false, false);
601  // If there are sub categories
602  if ($rs != false && $rs->recordCount() > 0) {
603  while (!$rs->EOF) {
604  $parentId = $rs->fields[1];
605  $actOxid = $rs->fields[0];
606  $sActOxidQuoted = $oDb->quote($actOxid);
607 
608  // Get the data of the parent category to the current Cat
609  $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = " . $oDb->quote($parentId), false, false);
610  while (!$rs3->EOF) {
611  $parentOxRootId = $rs3->fields[0];
612  $parentRight = (int) $rs3->fields[1];
613  $rs3->moveNext();
614  }
615  $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
616  $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
617  $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
618  $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
619  $this->_updateNodes($actOxid, false, $thisRoot);
620  $rs->moveNext();
621  }
622  }
623  }
624 
632  public function __get($sName)
633  {
634  switch ($sName) {
635  case 'aPath':
636  case 'aFullPath':
637  return $this->getPath();
638  break;
639  }
640  return parent::__get($sName);
641  }
642 }