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         $oBaseObject = $this->getBaseObject();
00091         $sLangSuffix = oxLang::getInstance()->getLanguageTag();
00092 
00093         $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive$sLangSuffix as oxactive,"
00094                     ." $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
00095                     ." $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
00096                     ." $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
00097                     ." $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
00098                     ." $sTable.oxtitle$sLangSuffix as oxtitle, $sTable.oxdesc$sLangSuffix as oxdesc,"
00099                     ." $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
00100                     ." $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink ";
00101 
00102             $sFieldList.= ",not $sTable.".$oBaseObject->getSqlFieldName( 'oxactive' )." as oxppremove";
00103 
00104 
00105         return $sFieldList;
00106     }
00107 
00117     protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00118     {
00119         $sViewName  = $this->getBaseObject()->getViewName();
00120         $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00121 
00122         //excluding long desc
00123         if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->_blForceFull) {
00124             $oCat = oxNew('oxcategory');
00125             if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00126                 $oCat = null;
00127                 $this->_sActCat = null;
00128             }
00129             $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00130             $sWhere = $this->_getDepthSqlSnippet($oCat);
00131         } else {
00132             $sUnion = '';
00133             $sWhere = '1';
00134         }
00135 
00136         if (!$sOrder) {
00137             $sOrdDir    = $blReverse?'desc':'asc';
00138             $sOrder     = "oxrootid $sOrdDir, oxleft $sOrdDir";
00139         }
00140 
00141         return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00142     }
00143 
00153     protected function _getDepthSqlSnippet($oCat)
00154     {
00155         $sViewName  = $this->getBaseObject()->getViewName();
00156         $sDepthSnippet = ' ( 0';
00157 
00158         // load compleate tree of active category, if it exists
00159         if ($oCat) {
00160             // select children here, siblings will be selected from union
00161             $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00162         }
00163 
00164         // load 1'st category level (roots)
00165         if ($this->_iForceLevel >= 1) {
00166             $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00167         }
00168 
00169         // load 2'nd category level ()
00170         if ($this->_iForceLevel >= 2) {
00171             $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00172         }
00173 
00174         $sDepthSnippet .= ' ) ';
00175         return $sDepthSnippet;
00176     }
00177 
00188     protected function _getDepthSqlUnion($oCat, $aColumns = null)
00189     {
00190         if (!$oCat) {
00191             return '';
00192         }
00193 
00194         $sViewName = $this->getBaseObject()->getViewName();
00195 
00196         return "UNION SELECT ".$this->_getSqlSelectFieldsForTree('maincats', $aColumns)
00197                 ." FROM oxcategories AS subcats"
00198                 ." LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
00199                 ." WHERE subcats.oxrootid = ".oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
00200                 ." AND subcats.oxleft <= ". (int)$oCat->oxcategories__oxleft->value
00201                 ." AND subcats.oxright >= ".(int)$oCat->oxcategories__oxright->value;
00202     }
00203 
00204 
00217     public function buildTree($sActCat, $blLoadFullTree, $blPerfLoadTreeForSearch, $blTopNaviLayout)
00218     {
00219         startProfile("buildTree");
00220 
00221         $this->_sActCat     = $sActCat;
00222         $this->_blForceFull = $blLoadFullTree || $blPerfLoadTreeForSearch;
00223         $this->_iForceLevel = $blTopNaviLayout?2:1;
00224 
00225         $sSelect = $this->_getSelectString(true);
00226         $this->selectString($sSelect);
00227 
00228         // PostProcessing
00229         if ( !$this->isAdmin() ) {
00230             // remove inactive categories
00231             $this->_ppRemoveInactiveCategories();
00232 
00233             // add active cat as full object
00234             $this->_ppLoadFullCategory($sActCat);
00235 
00236             // builds navigation path
00237             $this->_ppAddPathInfo();
00238 
00239             // add content categories
00240             $this->_ppAddContentCategories();
00241 
00242             // build tree structure
00243             $this->_ppBuildTree();
00244         }
00245 
00246         stopProfile("buildTree");
00247     }
00248 
00256     protected function _ppLoadFullCategory( $sId )
00257     {
00258         if ( isset($this->_aArray[$sId])) {
00259             $oNewCat = oxNew('oxcategory');
00260             if ( $oNewCat->load($sId)) {
00261                 // replace aArray object with fully loaded category
00262                 $this->_aArray[$sId] = $oNewCat;
00263             }
00264         } else {
00265             $this->_sActCat = null;
00266         }
00267     }
00268 
00276     public function buildList($blLoad)
00277     {
00278 
00279         if (!$blLoad) {
00280             return;
00281         }
00282 
00283         startProfile('buildCategoryList');
00284 
00285         $this->_blForceFull = true;
00286         $this->selectString($this->_getSelectString(false));
00287 
00288         // build tree structure
00289         $this->_ppBuildTree();
00290 
00291         // PostProcessing
00292         // add tree depth info
00293         $this->_ppAddDepthInformation();
00294         stopProfile('buildCategoryList');
00295     }
00296 
00304     public function setShopID($sShopID)
00305     {
00306         $this->_sShopID = $sShopID;
00307     }
00308 
00314     public function getPath()
00315     {
00316         return $this->_aPath;
00317     }
00318 
00324     public function getHtmlPath()
00325     {
00326         $sHtmlCatTree = '';
00327         $sSep         = '';
00328         foreach ( $this->_aPath as $oCategory ) {
00329             $sHtmlCatTree .= " $sSep<a href='".$oCategory->getLink()."'>".$oCategory->oxcategories__oxtitle->value."</a>";
00330             $sSep = '/ ';
00331         }
00332         return $sHtmlCatTree;
00333     }
00334 
00340     public function getClickCat()
00341     {
00342         if (count($this->_aPath)) {
00343             return end($this->_aPath);
00344         }
00345     }
00346 
00352     public function getClickRoot()
00353     {
00354         if (count($this->_aPath)) {
00355             return array(reset($this->_aPath));
00356         }
00357     }
00358 
00364     protected function _ppRemoveInactiveCategories()
00365     {
00366         // Colect all items whitch must be remove
00367         $aRemoveList = array();
00368         foreach ($this->_aArray as $sId => $oCat) {
00369             if ($oCat->oxcategories__oxppremove->value) {
00370                 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00371                     $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00372                 }
00373                 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00374                 unset( $this->_aArray[$sId] );
00375             } else {
00376                 unset($oCat->oxcategories__oxppremove);
00377             }
00378         }
00379 
00380         // Remove colected item's children from the list too (in the ranges).
00381         foreach ($this->_aArray as $sId => $oCat) {
00382             if (is_array($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00383                 foreach ($aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft=>$iRight) {
00384                     if (
00385                             ($iLeft  <= $oCat->oxcategories__oxleft->value)
00386                          && ($iRight >= $oCat->oxcategories__oxleft->value)
00387                        ) {
00388                         // this is a child in an inactive range (parent already gone)
00389                         unset( $this->_aArray[$sId] );
00390                         break 1;
00391                     }
00392                 }
00393             }
00394         }
00395     }
00396 
00402     protected function _ppAddPathInfo()
00403     {
00404 
00405         if (is_null($this->_sActCat)) {
00406             return;
00407         }
00408 
00409         $aPath = array();
00410         $sCurrentCat  = $this->_sActCat;
00411 
00412         while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00413             $oCat = $this[$sCurrentCat];
00414             $oCat->setExpanded(true);
00415             $aPath[$sCurrentCat] = $oCat;
00416             $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00417         }
00418 
00419         $this->_aPath = array_reverse($aPath);
00420     }
00421 
00427     protected function _ppAddContentCategories()
00428     {
00429         // load content pages for adding them into menue tree
00430         $oContentList = oxNew( "oxcontentlist" );
00431         $oContentList->loadCatMenues();
00432 
00433         foreach ($oContentList as $sCatId => $aContent) {
00434             if (array_key_exists($sCatId, $this->_aArray)) {
00435                 $this[$sCatId]->setContentCats($aContent);
00436 
00437             }
00438         }
00439     }
00440 
00446     protected function _ppBuildTree()
00447     {
00448         startProfile("_sortCats");
00449         $aIds = $this->sortCats();
00450         stopProfile("_sortCats");
00451         $aTree = array();
00452         foreach ($this->_aArray as $oCat) {
00453             $sParentId = $oCat->oxcategories__oxparentid->value;
00454             if ( $sParentId != 'oxrootid') {
00455                 if (isset($this->_aArray[$sParentId])) {
00456                     $this->_aArray[$sParentId]->setSortingIds( $aIds );
00457                     $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId(), true);
00458                 }
00459             } else {
00460                 $aTree[$oCat->getId()] = $oCat;
00461             }
00462         }
00463 
00464         // run sorting only once on each parent
00465         $aParents = array();
00466         foreach ($this->_aArray as $oCat) {
00467             $aParents[$oCat->oxcategories__oxparentid->value] = true;
00468         }
00469         if ($aParents['oxrootid']) {
00470             unset($aParents['oxrootid']);
00471         }
00472         foreach (array_keys($aParents) as $sParent) {
00473             if (isset($this->_aArray[$sParent])) {
00474                 $this->_aArray[$sParent]->sortSubCats();
00475             }
00476         }
00477 
00478         // Sort root categories
00479         $oCategory = oxNew('oxcategory');
00480         $oCategory->setSortingIds( $aIds );
00481         uasort($aTree, array( $oCategory, 'cmpCat' ) );
00482 
00483         $this->assign($aTree);
00484     }
00485 
00491     public function sortCats()
00492     {
00493         $sViewName  = getViewName('oxcategories');
00494         $sSortSql = $this->_getSelectString(false, array('oxid', 'oxparentid', 'oxsort', 'oxtitle'), 'oxparentid, oxsort, oxtitle');
00495         $aIds = array();
00496         $oDB = oxDb::getDb(true);
00497         $rs = $oDB->execute($sSortSql);
00498         $cnt = 0;
00499         if ($rs != false && $rs->recordCount() > 0) {
00500             while (!$rs->EOF) {
00501                 $aIds[$rs->fields['oxid']] = $cnt;
00502                 $cnt++;
00503                 $rs->moveNext();
00504             }
00505         }
00506         return $aIds;
00507     }
00508 
00515     protected function _ppAddDepthInformation()
00516     {
00517 
00518         $aStack = array();
00519         $iDepth = 0;
00520         $sPrevParent = '';
00521 
00522         $aTree = array();
00523         foreach ($this->_aArray as $oCat) {
00524 
00525             $aTree[$oCat->getId()] = $oCat;
00526             $aSubCats = $oCat->getSubCats();
00527             if ( count($aSubCats) > 0 ) {
00528                 foreach ($aSubCats as $oSubCat) {
00529                     $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00530                 }
00531             }
00532         }
00533         $this->assign($aTree);
00534 
00535     }
00536 
00546     protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00547     {
00548         $sDepth .= "-";
00549         $oCat->oxcategories__oxtitle->setValue($sDepth.' '.$oCat->oxcategories__oxtitle->value);
00550         $aTree[$oCat->getId()] = $oCat;
00551         $aSubCats = $oCat->getSubCats();
00552         if ( count($aSubCats) > 0 ) {
00553             foreach ($aSubCats as $oSubCat) {
00554                 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00555             }
00556         }
00557         return $aTree;
00558     }
00567     public function updateCategoryTree($blVerbose = true, $sShopID = null)
00568     {
00569         $oDB = oxDb::getDb();
00570         $sWhere = '1';
00571 
00572 
00573         $oDB->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00574         $oDB->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00575 
00576         // Get all root categories
00577         $rs = $oDB->execute("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort");
00578         if ($rs != false && $rs->recordCount() > 0) {
00579             while (!$rs->EOF) {
00580                 $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
00581                 if ( $blVerbose ) {
00582                     echo next( $this->_aUpdateInfo );
00583                 }
00584                 $oxRootId = $rs->fields[0];
00585 
00586                 $updn = $this->_updateNodes($oxRootId, true, $oxRootId);
00587                 $rs->moveNext();
00588             }
00589         }
00590     }
00591 
00597     public function getUpdateInfo()
00598     {
00599         return $this->_aUpdateInfo;
00600     }
00601 
00611     protected function _updateNodes($oxRootId, $isroot, $thisRoot)
00612     {
00613         $oDB = oxDb::getDb();
00614 
00615         if ($isroot) {
00616             $thisRoot = $oxRootId;
00617         }
00618 
00619         // Get sub categories of root categorie
00620         $rs = $oDB->execute("update oxcategories set oxrootid = ".$oDB->quote($thisRoot)." where oxparentid = ".$oDB->quote($oxRootId));
00621         $rs = $oDB->execute("select oxid, oxparentid from oxcategories where oxparentid = ".$oDB->quote($oxRootId)." order by oxsort");
00622         // If there are sub categories
00623         if ($rs != false && $rs->recordCount() > 0) {
00624             while (!$rs->EOF) {
00625                 $parentId = $rs->fields[1];
00626                 $actOxid = $rs->fields[0];
00627                 $sActOxidQuoted = $oDB->quote($actOxid);
00628 
00629                 // Get the data of the parent category to the current Cat
00630                 $rs3 = $oDB->execute("select oxrootid, oxright from oxcategories where oxid = ".$oDB->quote($parentId));
00631                 while (!$rs3->EOF) {
00632                     $parentOxRootId = $rs3->fields[0];
00633                     $parentRight    = (int)$rs3->fields[1];
00634                     $rs3->moveNext();
00635                 }
00636                 $sParentOxRootIdQuoted = $oDB->quote($parentOxRootId);
00637                 $oDB->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00638                 $oDB->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00639                 $oDB->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00640                 $this->_updateNodes($actOxid, false, $thisRoot);
00641                 $rs->moveNext();
00642             }
00643         }
00644     }
00645 
00653     public function __get($sName)
00654     {
00655         switch ($sName) {
00656             case 'aPath':
00657             case 'aFullPath':
00658                 return $this->getPath();
00659                 break;
00660         }
00661         return parent::__get($sName);
00662     }
00663 
00664 }