oxcategorylist.php

Go to the documentation of this file.
00001 <?php
00002 
00003 
00010 class oxCategoryList extends oxList
00011 {
00012 
00018     protected $_sObjectsInListName = 'oxcategory';
00019 
00025     protected $_blHideEmpty = false;
00026 
00032     protected $_blForceFull = false;
00033 
00039     protected $_iForceLevel = 2;
00040 
00046     protected $_sActCat = null;
00047 
00053     protected $_aPath = array();
00054 
00060     protected $_aUpdateInfo = array();
00061 
00069     public function __construct($sObjectsInListName = 'oxcategory')
00070     {
00071         $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
00072         parent::__construct($sObjectsInListName);
00073     }
00074 
00080     public function setLoadFull($blForceFull)
00081     {
00082         $this->_blForceFull = $blForceFull;
00083     }
00084 
00090     public function getLoadFull()
00091     {
00092         return $this->_blForceFull;
00093     }
00094 
00100     public function setLoadLevel($iForceLevel)
00101     {
00102         if ($iForceLevel > 2) {
00103             $iForceLevel = 2;
00104         } elseif ($iForceLevel < 1) {
00105             $iForceLevel = 0;
00106         }
00107         $this->_iForceLevel = $iForceLevel;
00108     }
00109 
00115     public function getLoadLevel()
00116     {
00117         return $this->_iForceLevel;
00118     }
00119 
00128     protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
00129     {
00130         if ($aColumns && count($aColumns)) {
00131             foreach ($aColumns as $key => $val) {
00132                 $aColumns[$key] .= ' as ' . $val;
00133             }
00134 
00135             return "$sTable." . implode(", $sTable.", $aColumns);
00136         }
00137 
00138         $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
00139                       . " $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
00140                       . " $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
00141                       . " $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
00142                       . " $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
00143                       . " $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
00144                       . " $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
00145                       . " $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink,"
00146                       . " $sTable.oxthumb as oxthumb, $sTable.oxpromoicon as oxpromoicon";
00147 
00148         $sFieldList .= ",not $sTable.oxactive as oxppremove";
00149 
00150 
00151         return $sFieldList;
00152     }
00153 
00163     protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00164     {
00165         $sViewName = $this->getBaseObject()->getViewName();
00166         $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00167 
00168         //excluding long desc
00169         if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
00170             $oCat = oxNew('oxCategory');
00171             if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00172                 $oCat = null;
00173                 $this->_sActCat = null;
00174             }
00175 
00176             $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00177             $sWhere = $this->_getDepthSqlSnippet($oCat);
00178         } else {
00179             $sUnion = '';
00180             $sWhere = '1';
00181         }
00182 
00183         if (!$sOrder) {
00184             $sOrdDir = $blReverse ? 'desc' : 'asc';
00185             $sOrder = "oxrootid $sOrdDir, oxleft $sOrdDir";
00186         }
00187 
00188         return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00189     }
00190 
00199     protected function _getDepthSqlSnippet($oCat)
00200     {
00201         $sViewName = $this->getBaseObject()->getViewName();
00202         $sDepthSnippet = ' ( 0';
00203 
00204         // load complete tree of active category, if it exists
00205         if ($oCat) {
00206             // select children here, siblings will be selected from union
00207             $sDepthSnippet .= " or ($sViewName.oxparentid = " . oxDb::getDb()->quote($oCat->oxcategories__oxid->value) . ")";
00208         }
00209 
00210         // load 1'st category level (roots)
00211         if ($this->getLoadLevel() >= 1) {
00212             $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00213         }
00214 
00215         // load 2'nd category level ()
00216         if ($this->getLoadLevel() >= 2) {
00217             $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00218         }
00219 
00220         $sDepthSnippet .= ' ) ';
00221 
00222         return $sDepthSnippet;
00223     }
00224 
00235     protected function _getDepthSqlUnion($oCat, $aColumns = null)
00236     {
00237         if (!$oCat) {
00238             return '';
00239         }
00240 
00241         $sViewName = $this->getBaseObject()->getViewName();
00242 
00243         return "UNION SELECT " . $this->_getSqlSelectFieldsForTree('maincats', $aColumns)
00244                . " FROM oxcategories AS subcats"
00245                . " LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
00246                . " WHERE subcats.oxrootid = " . oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
00247                . " AND subcats.oxleft <= " . (int) $oCat->oxcategories__oxleft->value
00248                . " AND subcats.oxright >= " . (int) $oCat->oxcategories__oxright->value;
00249     }
00250 
00251 
00252 
00258     protected function _loadFromDb()
00259     {
00260         $sSql = $this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle');
00261         $aData = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->getAll($sSql);
00262 
00263         return $aData;
00264     }
00265 
00269     public function load()
00270     {
00271 
00272         $aData = $this->_loadFromDb();
00273 
00274         $this->assignArray($aData);
00275     }
00276 
00277 
00285     public function buildTree($sActCat)
00286     {
00287         startProfile("buildTree");
00288 
00289         $this->_sActCat = $sActCat;
00290         $this->load();
00291 
00292         // PostProcessing
00293         if (!$this->isAdmin()) {
00294 
00295             // remove inactive categories
00296             $this->_ppRemoveInactiveCategories();
00297 
00298             // add active cat as full object
00299             $this->_ppLoadFullCategory($sActCat);
00300 
00301             // builds navigation path
00302             $this->_ppAddPathInfo();
00303 
00304             // add content categories
00305             $this->_ppAddContentCategories();
00306 
00307             // build tree structure
00308             $this->_ppBuildTree();
00309         }
00310 
00311         stopProfile("buildTree");
00312     }
00313 
00319     protected function _ppLoadFullCategory($sId)
00320     {
00321         if (isset($this->_aArray[$sId])) {
00322             $oNewCat = oxNew('oxCategory');
00323             if ($oNewCat->load($sId)) {
00324                 // replace aArray object with fully loaded category
00325                 $this->_aArray[$sId] = $oNewCat;
00326             }
00327         } else {
00328             $this->_sActCat = null;
00329         }
00330     }
00331 
00335     public function loadList()
00336     {
00337         startProfile('buildCategoryList');
00338 
00339         $this->setLoadFull(true);
00340         $this->selectString($this->_getSelectString(false));
00341 
00342         // build tree structure
00343         $this->_ppBuildTree();
00344 
00345         // PostProcessing
00346         // add tree depth info
00347         $this->_ppAddDepthInformation();
00348         stopProfile('buildCategoryList');
00349     }
00350 
00356     public function setShopID($sShopID)
00357     {
00358         $this->_sShopID = $sShopID;
00359     }
00360 
00366     public function getPath()
00367     {
00368         return $this->_aPath;
00369     }
00370 
00376     public function getClickCat()
00377     {
00378         if (count($this->_aPath)) {
00379             return end($this->_aPath);
00380         }
00381     }
00382 
00388     public function getClickRoot()
00389     {
00390         if (count($this->_aPath)) {
00391             return array(reset($this->_aPath));
00392         }
00393     }
00394 
00398     protected function _ppRemoveInactiveCategories()
00399     {
00400         // Collect all items which must be remove
00401         $aRemoveList = array();
00402         foreach ($this->_aArray as $sId => $oCat) {
00403             if ($oCat->oxcategories__oxppremove->value) {
00404                 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00405                     $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00406                 }
00407                 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00408                 unset($this->_aArray[$sId]);
00409             } else {
00410                 unset($oCat->oxcategories__oxppremove);
00411             }
00412         }
00413 
00414         // Remove collected item's children from the list too (in the ranges).
00415         foreach ($this->_aArray as $sId => $oCat) {
00416             if (isset($aRemoveList[$oCat->oxcategories__oxrootid->value]) &&
00417                 is_array($aRemoveList[$oCat->oxcategories__oxrootid->value])
00418             ) {
00419                 foreach ($aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight) {
00420                     if (
00421                         ($iLeft <= $oCat->oxcategories__oxleft->value)
00422                         && ($iRight >= $oCat->oxcategories__oxleft->value)
00423                     ) {
00424                         // this is a child in an inactive range (parent already gone)
00425                         unset($this->_aArray[$sId]);
00426                         break 1;
00427                     }
00428                 }
00429             }
00430         }
00431     }
00432 
00438     protected function _ppAddPathInfo()
00439     {
00440         if (is_null($this->_sActCat)) {
00441             return;
00442         }
00443 
00444         $aPath = array();
00445         $sCurrentCat = $this->_sActCat;
00446 
00447         while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00448             $oCat = $this[$sCurrentCat];
00449             $oCat->setExpanded(true);
00450             $aPath[$sCurrentCat] = $oCat;
00451             $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00452         }
00453 
00454         $this->_aPath = array_reverse($aPath);
00455     }
00456 
00460     protected function _ppAddContentCategories()
00461     {
00462         // load content pages for adding them into menu tree
00463         $oContentList = oxNew("oxContentList");
00464         $oContentList->loadCatMenues();
00465 
00466         foreach ($oContentList as $sCatId => $aContent) {
00467             if (array_key_exists($sCatId, $this->_aArray)) {
00468                 $this[$sCatId]->setContentCats($aContent);
00469 
00470             }
00471         }
00472     }
00473 
00477     protected function _ppBuildTree()
00478     {
00479         $aTree = array();
00480         foreach ($this->_aArray as $oCat) {
00481             $sParentId = $oCat->oxcategories__oxparentid->value;
00482             if ($sParentId != 'oxrootid') {
00483                 if (isset($this->_aArray[$sParentId])) {
00484                     $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId());
00485                 }
00486             } else {
00487                 $aTree[$oCat->getId()] = $oCat;
00488             }
00489         }
00490 
00491         $this->assign($aTree);
00492     }
00493 
00498     protected function _ppAddDepthInformation()
00499     {
00500         $aStack = array();
00501         $iDepth = 0;
00502         $sPrevParent = '';
00503 
00504         $aTree = array();
00505         foreach ($this->_aArray as $oCat) {
00506 
00507             $aTree[$oCat->getId()] = $oCat;
00508             $aSubCats = $oCat->getSubCats();
00509             if (count($aSubCats) > 0) {
00510                 foreach ($aSubCats as $oSubCat) {
00511                     $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00512                 }
00513             }
00514         }
00515         $this->assign($aTree);
00516     }
00517 
00527     protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00528     {
00529         $sDepth .= "-";
00530         $oCat->oxcategories__oxtitle->setValue($sDepth . ' ' . $oCat->oxcategories__oxtitle->value);
00531         $aTree[$oCat->getId()] = $oCat;
00532         $aSubCats = $oCat->getSubCats();
00533         if (count($aSubCats) > 0) {
00534             foreach ($aSubCats as $oSubCat) {
00535                 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00536             }
00537         }
00538 
00539         return $aTree;
00540     }
00541 
00548     public function updateCategoryTree($blVerbose = true, $sShopID = null)
00549     {
00550         $oDb = oxDb::getDb();
00551         $sWhere = '1';
00552 
00553 
00554         $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00555         $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00556 
00557         // Get all root categories
00558         $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false);
00559         if ($rs != false && $rs->recordCount() > 0) {
00560             while (!$rs->EOF) {
00561                 $this->_aUpdateInfo[] = "<b>Processing : " . $rs->fields[1] . "</b>(" . $rs->fields[0] . ")<br>";
00562                 if ($blVerbose) {
00563                     echo next($this->_aUpdateInfo);
00564                 }
00565                 $oxRootId = $rs->fields[0];
00566 
00567                 $this->_updateNodes($oxRootId, true, $oxRootId);
00568                 $rs->moveNext();
00569             }
00570         }
00571     }
00572 
00578     public function getUpdateInfo()
00579     {
00580         return $this->_aUpdateInfo;
00581     }
00582 
00590     protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
00591     {
00592         $oDb = oxDb::getDb();
00593 
00594         if ($isRoot) {
00595             $thisRoot = $oxRootId;
00596         }
00597 
00598         // Get sub categories of root categories
00599         $rs = $oDb->execute("update oxcategories set oxrootid = " . $oDb->quote($thisRoot) . " where oxparentid = " . $oDb->quote($oxRootId));
00600         $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = " . $oDb->quote($oxRootId) . " order by oxsort", false, false);
00601         // If there are sub categories
00602         if ($rs != false && $rs->recordCount() > 0) {
00603             while (!$rs->EOF) {
00604                 $parentId = $rs->fields[1];
00605                 $actOxid = $rs->fields[0];
00606                 $sActOxidQuoted = $oDb->quote($actOxid);
00607 
00608                 // Get the data of the parent category to the current Cat
00609                 $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = " . $oDb->quote($parentId), false, false);
00610                 while (!$rs3->EOF) {
00611                     $parentOxRootId = $rs3->fields[0];
00612                     $parentRight = (int) $rs3->fields[1];
00613                     $rs3->moveNext();
00614                 }
00615                 $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
00616                 $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00617                 $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00618                 $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00619                 $this->_updateNodes($actOxid, false, $thisRoot);
00620                 $rs->moveNext();
00621             }
00622         }
00623     }
00624 
00632     public function __get($sName)
00633     {
00634         switch ($sName) {
00635             case 'aPath':
00636             case 'aFullPath':
00637                 return $this->getPath();
00638                 break;
00639         }
00640         return parent::__get($sName);
00641     }
00642 }