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