oxcategorylist.php

Go to the documentation of this file.
00001 <?php
00002 
00003 
00010 class oxCategoryList extends oxList
00011 {
00017     protected $_sObjectsInListName = 'oxcategory';
00018 
00024     protected $_blHideEmpty = false;
00025 
00031     protected $_blForceFull = false;
00032 
00038     protected $_iForceLevel = 2;
00039 
00045     protected $_sActCat     = null;
00046 
00052     protected $_aPath = array();
00053 
00059     protected $_aUpdateInfo = array();
00060 
00068     public function __construct( $sObjectsInListName = 'oxcategory')
00069     {
00070         $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
00071         parent::__construct( $sObjectsInListName );
00072     }
00073 
00081     public function setLoadFull( $blForceFull )
00082     {
00083         $this->_blForceFull = $blForceFull;
00084     }
00085 
00091     public function getLoadFull()
00092     {
00093         return $this->_blForceFull;
00094     }
00095 
00103     public function setLoadLevel( $iForceLevel )
00104     {
00105         if ( $iForceLevel > 2 ) {
00106             $iForceLevel = 2;
00107         } elseif ( $iForceLevel < 1 ) {
00108             $iForceLevel = 0;
00109         }
00110         $this->_iForceLevel = $iForceLevel;
00111     }
00112 
00118     public function getLoadLevel()
00119     {
00120         return $this->_iForceLevel;
00121     }
00122 
00131     protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
00132     {
00133         if ($aColumns && count($aColumns)) {
00134             foreach ($aColumns as $key=>$val) {
00135                 $aColumns[$key].=' as '.$val;
00136             }
00137             return "$sTable.".implode(", $sTable.", $aColumns);
00138         }
00139 
00140         $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
00141             ." $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
00142             ." $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
00143             ." $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
00144             ." $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
00145             ." $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
00146             ." $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
00147             ." $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink,"
00148             ." $sTable.oxthumb as oxthumb, $sTable.oxpromoicon as oxpromoicon";
00149 
00150             $sFieldList.= ",not $sTable.oxactive as oxppremove";
00151 
00152 
00153         return $sFieldList;
00154     }
00155 
00165     protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00166     {
00167         $sViewName  = $this->getBaseObject()->getViewName();
00168         $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00169 
00170         //excluding long desc
00171         if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
00172             $oCat = oxNew( 'oxCategory' );
00173             if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00174                 $oCat = null;
00175                 $this->_sActCat = null;
00176             }
00177 
00178             $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00179             $sWhere = $this->_getDepthSqlSnippet($oCat);
00180         } else {
00181             $sUnion = '';
00182             $sWhere = '1';
00183         }
00184 
00185         if (!$sOrder) {
00186             $sOrdDir    = $blReverse?'desc':'asc';
00187             $sOrder     = "oxrootid $sOrdDir, oxleft $sOrdDir";
00188         }
00189 
00190         return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00191     }
00192 
00201     protected function _getDepthSqlSnippet($oCat)
00202     {
00203         $sViewName  = $this->getBaseObject()->getViewName();
00204         $sDepthSnippet = ' ( 0';
00205 
00206         // load complete tree of active category, if it exists
00207         if ($oCat) {
00208             // select children here, siblings will be selected from union
00209             $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00210         }
00211 
00212         // load 1'st category level (roots)
00213         if ($this->getLoadLevel() >= 1) {
00214             $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00215         }
00216 
00217         // load 2'nd category level ()
00218         if ($this->getLoadLevel() >= 2) {
00219             $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00220         }
00221 
00222         $sDepthSnippet .= ' ) ';
00223         return $sDepthSnippet;
00224     }
00225 
00236     protected function _getDepthSqlUnion($oCat, $aColumns = null)
00237     {
00238         if (!$oCat) {
00239             return '';
00240         }
00241 
00242         $sViewName = $this->getBaseObject()->getViewName();
00243 
00244         return "UNION SELECT ".$this->_getSqlSelectFieldsForTree('maincats', $aColumns)
00245                 ." FROM oxcategories AS subcats"
00246                 ." LEFT JOIN $sViewName AS maincats on maincats.oxparentid = subcats.oxparentid"
00247                 ." WHERE subcats.oxrootid = ".oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
00248                 ." AND subcats.oxleft <= ". (int)$oCat->oxcategories__oxleft->value
00249                 ." AND subcats.oxright >= ".(int)$oCat->oxcategories__oxright->value;
00250     }
00251 
00252 
00253 
00259     protected function _loadFromDb()
00260     {
00261         $sSql = $this->_getSelectString(false, null, 'oxparentid, oxsort, oxtitle');
00262         $aData = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->getAll( $sSql );
00263 
00264         return $aData;
00265     }
00266 
00272     public function load()
00273     {
00274 
00275            $aData = $this->_loadFromDb();
00276 
00277         $this->assignArray( $aData );
00278     }
00279 
00280 
00290     public function buildTree( $sActCat  )
00291     {
00292         startProfile("buildTree");
00293 
00294         $this->_sActCat = $sActCat;
00295         $this->load();
00296 
00297         // PostProcessing
00298         if ( !$this->isAdmin() ) {
00299 
00300             // remove inactive categories
00301             $this->_ppRemoveInactiveCategories();
00302 
00303             // add active cat as full object
00304             $this->_ppLoadFullCategory( $sActCat );
00305 
00306             // builds navigation path
00307             $this->_ppAddPathInfo();
00308 
00309             // add content categories
00310             $this->_ppAddContentCategories();
00311 
00312             // build tree structure
00313             $this->_ppBuildTree();
00314         }
00315 
00316         stopProfile("buildTree");
00317     }
00318 
00326     protected function _ppLoadFullCategory( $sId )
00327     {
00328         if ( isset($this->_aArray[$sId])) {
00329             $oNewCat = oxNew( 'oxCategory' );
00330             if ( $oNewCat->load($sId)) {
00331                 // replace aArray object with fully loaded category
00332                 $this->_aArray[$sId] = $oNewCat;
00333             }
00334         } else {
00335             $this->_sActCat = null;
00336         }
00337     }
00338 
00344     public function loadList()
00345     {
00346         startProfile('buildCategoryList');
00347 
00348         $this->setLoadFull(true);
00349         $this->selectString($this->_getSelectString(false));
00350 
00351         // build tree structure
00352         $this->_ppBuildTree();
00353 
00354         // PostProcessing
00355         // add tree depth info
00356         $this->_ppAddDepthInformation();
00357         stopProfile('buildCategoryList');
00358     }
00359 
00360 
00370     public function buildList( $blLoad )
00371     {
00372         if (!$blLoad) {
00373             return;
00374         }
00375 
00376         $this->loadList();
00377     }
00378 
00386     public function setShopID($sShopID)
00387     {
00388         $this->_sShopID = $sShopID;
00389     }
00390 
00396     public function getPath()
00397     {
00398         return $this->_aPath;
00399     }
00400 
00406     public function getClickCat()
00407     {
00408         if (count($this->_aPath)) {
00409             return end($this->_aPath);
00410         }
00411     }
00412 
00418     public function getClickRoot()
00419     {
00420         if (count($this->_aPath)) {
00421             return array(reset($this->_aPath));
00422         }
00423     }
00424 
00430     protected function _ppRemoveInactiveCategories()
00431     {
00432         // Collect all items which must be remove
00433         $aRemoveList = array();
00434         foreach ($this->_aArray as $sId => $oCat) {
00435             if ($oCat->oxcategories__oxppremove->value) {
00436                 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00437                     $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00438                 }
00439                 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00440                 unset( $this->_aArray[$sId] );
00441             } else {
00442                 unset($oCat->oxcategories__oxppremove);
00443             }
00444         }
00445 
00446         // Remove collected item's children from the list too (in the ranges).
00447         foreach ($this->_aArray as $sId => $oCat) {
00448             if ( isset( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) &&
00449                  is_array( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) ) {
00450                 foreach ( $aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight ) {
00451                     if (
00452                             ($iLeft  <= $oCat->oxcategories__oxleft->value)
00453                          && ($iRight >= $oCat->oxcategories__oxleft->value)
00454                        ) {
00455                         // this is a child in an inactive range (parent already gone)
00456                         unset( $this->_aArray[$sId] );
00457                         break 1;
00458                     }
00459                 }
00460             }
00461         }
00462     }
00463 
00469     protected function _ppAddPathInfo()
00470     {
00471         if (is_null($this->_sActCat)) {
00472             return;
00473         }
00474 
00475         $aPath = array();
00476         $sCurrentCat  = $this->_sActCat;
00477 
00478         while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00479             $oCat = $this[$sCurrentCat];
00480             $oCat->setExpanded( true );
00481             $aPath[$sCurrentCat] = $oCat;
00482             $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00483         }
00484 
00485         $this->_aPath = array_reverse($aPath);
00486     }
00487 
00493     protected function _ppAddContentCategories()
00494     {
00495         // load content pages for adding them into menu tree
00496         $oContentList = oxNew( "oxContentList" );
00497         $oContentList->loadCatMenues();
00498 
00499         foreach ($oContentList as $sCatId => $aContent) {
00500             if (array_key_exists($sCatId, $this->_aArray)) {
00501                 $this[$sCatId]->setContentCats($aContent);
00502 
00503             }
00504         }
00505     }
00506 
00512     protected function _ppBuildTree()
00513     {
00514         $aTree = array();
00515         foreach ($this->_aArray as $oCat) {
00516             $sParentId = $oCat->oxcategories__oxparentid->value;
00517             if ( $sParentId != 'oxrootid') {
00518                 if (isset($this->_aArray[$sParentId])) {
00519                     $this->_aArray[$sParentId]->setSubCat( $oCat, $oCat->getId() );
00520                 }
00521             } else {
00522                 $aTree[$oCat->getId()] = $oCat;
00523             }
00524         }
00525 
00526         $this->assign($aTree);
00527     }
00528 
00535     protected function _ppAddDepthInformation()
00536     {
00537         $aStack = array();
00538         $iDepth = 0;
00539         $sPrevParent = '';
00540 
00541         $aTree = array();
00542         foreach ($this->_aArray as $oCat) {
00543 
00544             $aTree[$oCat->getId()] = $oCat;
00545             $aSubCats = $oCat->getSubCats();
00546             if ( count($aSubCats) > 0 ) {
00547                 foreach ($aSubCats as $oSubCat) {
00548                     $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00549                 }
00550             }
00551         }
00552         $this->assign($aTree);
00553     }
00554 
00564     protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00565     {
00566         $sDepth .= "-";
00567         $oCat->oxcategories__oxtitle->setValue($sDepth.' '.$oCat->oxcategories__oxtitle->value);
00568         $aTree[$oCat->getId()] = $oCat;
00569         $aSubCats = $oCat->getSubCats();
00570         if ( count($aSubCats) > 0 ) {
00571             foreach ($aSubCats as $oSubCat) {
00572                 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00573             }
00574         }
00575         return $aTree;
00576     }
00585     public function updateCategoryTree($blVerbose = true, $sShopID = null)
00586     {
00587         $oDb = oxDb::getDb();
00588         $sWhere = '1';
00589 
00590 
00591         $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00592         $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00593 
00594         // Get all root categories
00595         $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false );
00596         if ($rs != false && $rs->recordCount() > 0) {
00597             while (!$rs->EOF) {
00598                 $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
00599                 if ( $blVerbose ) {
00600                     echo next( $this->_aUpdateInfo );
00601                 }
00602                 $oxRootId = $rs->fields[0];
00603 
00604                 $this->_updateNodes($oxRootId, true, $oxRootId);
00605                 $rs->moveNext();
00606             }
00607         }
00608     }
00609 
00615     public function getUpdateInfo()
00616     {
00617         return $this->_aUpdateInfo;
00618     }
00619 
00629     protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
00630     {
00631         $oDb = oxDb::getDb();
00632 
00633         if ($isRoot) {
00634             $thisRoot = $oxRootId;
00635         }
00636 
00637         // Get sub categories of root categories
00638         $rs = $oDb->execute("update oxcategories set oxrootid = ".$oDb->quote($thisRoot)." where oxparentid = ".$oDb->quote($oxRootId));
00639         $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = ".$oDb->quote($oxRootId)." order by oxsort", false, false);
00640         // If there are sub categories
00641         if ($rs != false && $rs->recordCount() > 0) {
00642             while (!$rs->EOF) {
00643                 $parentId = $rs->fields[1];
00644                 $actOxid = $rs->fields[0];
00645                 $sActOxidQuoted = $oDb->quote($actOxid);
00646 
00647                 // Get the data of the parent category to the current Cat
00648                 $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = ".$oDb->quote($parentId), false, false );
00649                 while (!$rs3->EOF) {
00650                     $parentOxRootId = $rs3->fields[0];
00651                     $parentRight    = (int)$rs3->fields[1];
00652                     $rs3->moveNext();
00653                 }
00654                 $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
00655                 $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00656                 $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00657                 $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00658                 $this->_updateNodes($actOxid, false, $thisRoot);
00659                 $rs->moveNext();
00660             }
00661         }
00662     }
00663 
00671     public function __get($sName)
00672     {
00673         switch ($sName) {
00674             case 'aPath':
00675             case 'aFullPath':
00676                 return $this->getPath();
00677                 break;
00678         }
00679         return parent::__get($sName);
00680     }
00681 
00682 }