oxcategorylist.php

Go to the documentation of this file.
00001 <?php
00002 
00003 
00009 class oxCategoryList extends oxList
00010 {
00016     protected $_sObjectsInListName = 'oxcategory';
00017 
00023     protected $_blHideEmpty = false;
00024 
00030     protected $_blForceFull = false;
00031 
00037     protected $_iForceLevel = 1;
00038 
00044     protected $_sActCat     = null;
00045 
00051     protected $_aPath = array();
00052 
00058     protected $_aUpdateInfo = array();
00059 
00067     public function __construct( $sObjectsInListName = 'oxcategory')
00068     {
00069         $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
00070         parent::__construct( $sObjectsInListName );
00071     }
00072 
00081     protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
00082     {
00083         if ($aColumns && count($aColumns)) {
00084             foreach ($aColumns as $key=>$val) {
00085                 $aColumns[$key].=' as '.$val;
00086             }
00087             return "$sTable.".implode(", $sTable.", $aColumns);
00088         }
00089 
00090         $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
00091                     ." $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
00092                     ." $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
00093                     ." $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
00094                     ." $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
00095                     ." $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
00096                     ." $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
00097                     ." $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink ";
00098 
00099             $sFieldList.= ",not $sTable.oxactive as oxppremove";
00100 
00101 
00102         return $sFieldList;
00103     }
00104 
00114     protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00115     {
00116         $sViewName  = $this->getBaseObject()->getViewName();
00117         $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00118 
00119         //excluding long desc
00120         if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->_blForceFull) {
00121             $oCat = oxNew('oxcategory');
00122             if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00123                 $oCat = null;
00124                 $this->_sActCat = null;
00125             }
00126             $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00127             $sWhere = $this->_getDepthSqlSnippet($oCat);
00128         } else {
00129             $sUnion = '';
00130             $sWhere = '1';
00131         }
00132 
00133         if (!$sOrder) {
00134             $sOrdDir    = $blReverse?'desc':'asc';
00135             $sOrder     = "oxrootid $sOrdDir, oxleft $sOrdDir";
00136         }
00137 
00138         return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00139     }
00140 
00150     protected function _getDepthSqlSnippet($oCat)
00151     {
00152         $sViewName  = $this->getBaseObject()->getViewName();
00153         $sDepthSnippet = ' ( 0';
00154 
00155         // load compleate tree of active category, if it exists
00156         if ($oCat) {
00157             // select children here, siblings will be selected from union
00158             $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00159         }
00160 
00161         // load 1'st category level (roots)
00162         if ($this->_iForceLevel >= 1) {
00163             $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00164         }
00165 
00166         // load 2'nd category level ()
00167         if ($this->_iForceLevel >= 2) {
00168             $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00169         }
00170 
00171         $sDepthSnippet .= ' ) ';
00172         return $sDepthSnippet;
00173     }
00174 
00185     protected function _getDepthSqlUnion($oCat, $aColumns = null)
00186     {
00187         if (!$oCat) {
00188             return '';
00189         }
00190 
00191         $sViewName = $this->getBaseObject()->getViewName();
00192 
00193         return "UNION SELECT ".$this->_getSqlSelectFieldsForTree('maincats', $aColumns)
00194                 ." FROM oxcategories AS subcats"
00195                 ." LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
00196                 ." WHERE subcats.oxrootid = ".oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
00197                 ." AND subcats.oxleft <= ". (int)$oCat->oxcategories__oxleft->value
00198                 ." AND subcats.oxright >= ".(int)$oCat->oxcategories__oxright->value;
00199     }
00200 
00201 
00214     public function buildTree($sActCat, $blLoadFullTree, $blPerfLoadTreeForSearch, $blTopNaviLayout)
00215     {
00216         startProfile("buildTree");
00217         $this->_sActCat     = $sActCat;
00218         $this->_blForceFull = $blLoadFullTree || $blPerfLoadTreeForSearch;
00219         $this->_iForceLevel = $blTopNaviLayout?2:1;
00220 
00221         $sSelect = $this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle');
00222         $this->selectString($sSelect);
00223 
00224         // PostProcessing
00225         if ( !$this->isAdmin() ) {
00226             // remove inactive categories
00227             $this->_ppRemoveInactiveCategories();
00228 
00229             // add active cat as full object
00230             $this->_ppLoadFullCategory($sActCat);
00231 
00232             // builds navigation path
00233             $this->_ppAddPathInfo();
00234 
00235             // add content categories
00236             $this->_ppAddContentCategories();
00237 
00238             // build tree structure
00239             $this->_ppBuildTree();
00240         }
00241 
00242         stopProfile("buildTree");
00243     }
00244 
00252     protected function _ppLoadFullCategory( $sId )
00253     {
00254         if ( isset($this->_aArray[$sId])) {
00255             $oNewCat = oxNew('oxcategory');
00256             if ( $oNewCat->load($sId)) {
00257                 // replace aArray object with fully loaded category
00258                 $this->_aArray[$sId] = $oNewCat;
00259             }
00260         } else {
00261             $this->_sActCat = null;
00262         }
00263     }
00264 
00272     public function buildList($blLoad)
00273     {
00274 
00275         if (!$blLoad) {
00276             return;
00277         }
00278 
00279         startProfile('buildCategoryList');
00280 
00281         $this->_blForceFull = true;
00282         $this->selectString($this->_getSelectString(false));
00283 
00284         // build tree structure
00285         $this->_ppBuildTree();
00286 
00287         // PostProcessing
00288         // add tree depth info
00289         $this->_ppAddDepthInformation();
00290         stopProfile('buildCategoryList');
00291     }
00292 
00300     public function setShopID($sShopID)
00301     {
00302         $this->_sShopID = $sShopID;
00303     }
00304 
00310     public function getPath()
00311     {
00312         return $this->_aPath;
00313     }
00314 
00320     public function getHtmlPath()
00321     {
00322         $sHtmlCatTree = '';
00323         $sSep         = '';
00324         foreach ( $this->_aPath as $oCategory ) {
00325             $sHtmlCatTree .= " $sSep<a href='".$oCategory->getLink()."'>".$oCategory->oxcategories__oxtitle->value."</a>";
00326             $sSep = '/ ';
00327         }
00328         return $sHtmlCatTree;
00329     }
00330 
00336     public function getClickCat()
00337     {
00338         if (count($this->_aPath)) {
00339             return end($this->_aPath);
00340         }
00341     }
00342 
00348     public function getClickRoot()
00349     {
00350         if (count($this->_aPath)) {
00351             return array(reset($this->_aPath));
00352         }
00353     }
00354 
00360     protected function _ppRemoveInactiveCategories()
00361     {
00362         // Colect all items whitch must be remove
00363         $aRemoveList = array();
00364         foreach ($this->_aArray as $sId => $oCat) {
00365             if ($oCat->oxcategories__oxppremove->value) {
00366                 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00367                     $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00368                 }
00369                 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00370                 unset( $this->_aArray[$sId] );
00371             } else {
00372                 unset($oCat->oxcategories__oxppremove);
00373             }
00374         }
00375 
00376         // Remove colected item's children from the list too (in the ranges).
00377         foreach ($this->_aArray as $sId => $oCat) {
00378             if ( isset( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) &&
00379                  is_array( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) ) {
00380                 foreach ( $aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight ) {
00381                     if (
00382                             ($iLeft  <= $oCat->oxcategories__oxleft->value)
00383                          && ($iRight >= $oCat->oxcategories__oxleft->value)
00384                        ) {
00385                         // this is a child in an inactive range (parent already gone)
00386                         unset( $this->_aArray[$sId] );
00387                         break 1;
00388                     }
00389                 }
00390             }
00391         }
00392     }
00393 
00399     protected function _ppAddPathInfo()
00400     {
00401         if (is_null($this->_sActCat)) {
00402             return;
00403         }
00404 
00405         $aPath = array();
00406         $sCurrentCat  = $this->_sActCat;
00407 
00408         while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00409             $oCat = $this[$sCurrentCat];
00410             $oCat->setExpanded(true);
00411             $aPath[$sCurrentCat] = $oCat;
00412             $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00413         }
00414 
00415         $this->_aPath = array_reverse($aPath);
00416     }
00417 
00423     protected function _ppAddContentCategories()
00424     {
00425         // load content pages for adding them into menue tree
00426         $oContentList = oxNew( "oxcontentlist" );
00427         $oContentList->loadCatMenues();
00428 
00429         foreach ($oContentList as $sCatId => $aContent) {
00430             if (array_key_exists($sCatId, $this->_aArray)) {
00431                 $this[$sCatId]->setContentCats($aContent);
00432 
00433             }
00434         }
00435     }
00436 
00442     protected function _ppBuildTree()
00443     {
00444         $aTree = array();
00445         foreach ($this->_aArray as $oCat) {
00446             $sParentId = $oCat->oxcategories__oxparentid->value;
00447             if ( $sParentId != 'oxrootid') {
00448                 if (isset($this->_aArray[$sParentId])) {
00449                     $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId(), true);
00450                 }
00451             } else {
00452                 $aTree[$oCat->getId()] = $oCat;
00453             }
00454         }
00455 
00456         $this->assign($aTree);
00457     }
00458 
00465     protected function _ppAddDepthInformation()
00466     {
00467         $aStack = array();
00468         $iDepth = 0;
00469         $sPrevParent = '';
00470 
00471         $aTree = array();
00472         foreach ($this->_aArray as $oCat) {
00473 
00474             $aTree[$oCat->getId()] = $oCat;
00475             $aSubCats = $oCat->getSubCats();
00476             if ( count($aSubCats) > 0 ) {
00477                 foreach ($aSubCats as $oSubCat) {
00478                     $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00479                 }
00480             }
00481         }
00482         $this->assign($aTree);
00483     }
00484 
00494     protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00495     {
00496         $sDepth .= "-";
00497         $oCat->oxcategories__oxtitle->setValue($sDepth.' '.$oCat->oxcategories__oxtitle->value);
00498         $aTree[$oCat->getId()] = $oCat;
00499         $aSubCats = $oCat->getSubCats();
00500         if ( count($aSubCats) > 0 ) {
00501             foreach ($aSubCats as $oSubCat) {
00502                 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00503             }
00504         }
00505         return $aTree;
00506     }
00515     public function updateCategoryTree($blVerbose = true, $sShopID = null)
00516     {
00517         $oDB = oxDb::getDb();
00518         $sWhere = '1';
00519 
00520 
00521         $oDB->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00522         $oDB->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00523 
00524         // Get all root categories
00525         $rs = $oDB->execute("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort");
00526         if ($rs != false && $rs->recordCount() > 0) {
00527             while (!$rs->EOF) {
00528                 $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
00529                 if ( $blVerbose ) {
00530                     echo next( $this->_aUpdateInfo );
00531                 }
00532                 $oxRootId = $rs->fields[0];
00533 
00534                 $updn = $this->_updateNodes($oxRootId, true, $oxRootId);
00535                 $rs->moveNext();
00536             }
00537         }
00538     }
00539 
00545     public function getUpdateInfo()
00546     {
00547         return $this->_aUpdateInfo;
00548     }
00549 
00559     protected function _updateNodes($oxRootId, $isroot, $thisRoot)
00560     {
00561         $oDB = oxDb::getDb();
00562 
00563         if ($isroot) {
00564             $thisRoot = $oxRootId;
00565         }
00566 
00567         // Get sub categories of root categorie
00568         $rs = $oDB->execute("update oxcategories set oxrootid = ".$oDB->quote($thisRoot)." where oxparentid = ".$oDB->quote($oxRootId));
00569         $rs = $oDB->execute("select oxid, oxparentid from oxcategories where oxparentid = ".$oDB->quote($oxRootId)." order by oxsort");
00570         // If there are sub categories
00571         if ($rs != false && $rs->recordCount() > 0) {
00572             while (!$rs->EOF) {
00573                 $parentId = $rs->fields[1];
00574                 $actOxid = $rs->fields[0];
00575                 $sActOxidQuoted = $oDB->quote($actOxid);
00576 
00577                 // Get the data of the parent category to the current Cat
00578                 $rs3 = $oDB->execute("select oxrootid, oxright from oxcategories where oxid = ".$oDB->quote($parentId));
00579                 while (!$rs3->EOF) {
00580                     $parentOxRootId = $rs3->fields[0];
00581                     $parentRight    = (int)$rs3->fields[1];
00582                     $rs3->moveNext();
00583                 }
00584                 $sParentOxRootIdQuoted = $oDB->quote($parentOxRootId);
00585                 $oDB->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00586                 $oDB->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00587                 $oDB->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00588                 $this->_updateNodes($actOxid, false, $thisRoot);
00589                 $rs->moveNext();
00590             }
00591         }
00592     }
00593 
00601     public function __get($sName)
00602     {
00603         switch ($sName) {
00604             case 'aPath':
00605             case 'aFullPath':
00606                 return $this->getPath();
00607                 break;
00608         }
00609         return parent::__get($sName);
00610     }
00611 
00612 }