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 
00149             $sFieldList.= ",not $sTable.oxactive as oxppremove";
00150 
00151 
00152         return $sFieldList;
00153     }
00154 
00164     protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00165     {
00166         $sViewName  = $this->getBaseObject()->getViewName();
00167         $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00168 
00169         //excluding long desc
00170         if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
00171             $oCat = oxNew( 'oxCategory' );
00172             if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00173                 $oCat = null;
00174                 $this->_sActCat = null;
00175             }
00176 
00177             $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00178             $sWhere = $this->_getDepthSqlSnippet($oCat);
00179         } else {
00180             $sUnion = '';
00181             $sWhere = '1';
00182         }
00183 
00184         if (!$sOrder) {
00185             $sOrdDir    = $blReverse?'desc':'asc';
00186             $sOrder     = "oxrootid $sOrdDir, oxleft $sOrdDir";
00187         }
00188 
00189         return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00190     }
00191 
00200     protected function _getDepthSqlSnippet($oCat)
00201     {
00202         $sViewName  = $this->getBaseObject()->getViewName();
00203         $sDepthSnippet = ' ( 0';
00204 
00205         // load complete tree of active category, if it exists
00206         if ($oCat) {
00207             // select children here, siblings will be selected from union
00208             $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00209         }
00210 
00211         // load 1'st category level (roots)
00212         if ($this->getLoadLevel() >= 1) {
00213             $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00214         }
00215 
00216         // load 2'nd category level ()
00217         if ($this->getLoadLevel() >= 2) {
00218             $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00219         }
00220 
00221         $sDepthSnippet .= ' ) ';
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 
00271     public function load()
00272     {
00273 
00274            $aData = $this->_loadFromDb();
00275 
00276         $this->assignArray( $aData );
00277     }
00278 
00279 
00289     public function buildTree( $sActCat  )
00290     {
00291         startProfile("buildTree");
00292 
00293         $this->_sActCat = $sActCat;
00294         $this->load();
00295 
00296         // PostProcessing
00297         if ( !$this->isAdmin() ) {
00298 
00299             // remove inactive categories
00300             $this->_ppRemoveInactiveCategories();
00301 
00302             // add active cat as full object
00303             $this->_ppLoadFullCategory( $sActCat );
00304 
00305             // builds navigation path
00306             $this->_ppAddPathInfo();
00307 
00308             // add content categories
00309             $this->_ppAddContentCategories();
00310 
00311             // build tree structure
00312             $this->_ppBuildTree();
00313         }
00314 
00315         stopProfile("buildTree");
00316     }
00317 
00325     protected function _ppLoadFullCategory( $sId )
00326     {
00327         if ( isset($this->_aArray[$sId])) {
00328             $oNewCat = oxNew( 'oxCategory' );
00329             if ( $oNewCat->load($sId)) {
00330                 // replace aArray object with fully loaded category
00331                 $this->_aArray[$sId] = $oNewCat;
00332             }
00333         } else {
00334             $this->_sActCat = null;
00335         }
00336     }
00337 
00343     public function loadList()
00344     {
00345         startProfile('buildCategoryList');
00346 
00347         $this->setLoadFull(true);
00348         $this->selectString($this->_getSelectString(false));
00349 
00350         // build tree structure
00351         $this->_ppBuildTree();
00352 
00353         // PostProcessing
00354         // add tree depth info
00355         $this->_ppAddDepthInformation();
00356         stopProfile('buildCategoryList');
00357     }
00358 
00359 
00369     public function buildList( $blLoad )
00370     {
00371         if (!$blLoad) {
00372             return;
00373         }
00374 
00375         $this->loadList();
00376     }
00377 
00385     public function setShopID($sShopID)
00386     {
00387         $this->_sShopID = $sShopID;
00388     }
00389 
00395     public function getPath()
00396     {
00397         return $this->_aPath;
00398     }
00399 
00405     public function getClickCat()
00406     {
00407         if (count($this->_aPath)) {
00408             return end($this->_aPath);
00409         }
00410     }
00411 
00417     public function getClickRoot()
00418     {
00419         if (count($this->_aPath)) {
00420             return array(reset($this->_aPath));
00421         }
00422     }
00423 
00429     protected function _ppRemoveInactiveCategories()
00430     {
00431         // Collect all items which must be remove
00432         $aRemoveList = array();
00433         foreach ($this->_aArray as $sId => $oCat) {
00434             if ($oCat->oxcategories__oxppremove->value) {
00435                 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00436                     $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00437                 }
00438                 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00439                 unset( $this->_aArray[$sId] );
00440             } else {
00441                 unset($oCat->oxcategories__oxppremove);
00442             }
00443         }
00444 
00445         // Remove collected item's children from the list too (in the ranges).
00446         foreach ($this->_aArray as $sId => $oCat) {
00447             if ( isset( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) &&
00448                  is_array( $aRemoveList[$oCat->oxcategories__oxrootid->value] ) ) {
00449                 foreach ( $aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight ) {
00450                     if (
00451                             ($iLeft  <= $oCat->oxcategories__oxleft->value)
00452                          && ($iRight >= $oCat->oxcategories__oxleft->value)
00453                        ) {
00454                         // this is a child in an inactive range (parent already gone)
00455                         unset( $this->_aArray[$sId] );
00456                         break 1;
00457                     }
00458                 }
00459             }
00460         }
00461     }
00462 
00468     protected function _ppAddPathInfo()
00469     {
00470         if (is_null($this->_sActCat)) {
00471             return;
00472         }
00473 
00474         $aPath = array();
00475         $sCurrentCat  = $this->_sActCat;
00476 
00477         while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00478             $oCat = $this[$sCurrentCat];
00479             $oCat->setExpanded( true );
00480             $aPath[$sCurrentCat] = $oCat;
00481             $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00482         }
00483 
00484         $this->_aPath = array_reverse($aPath);
00485     }
00486 
00492     protected function _ppAddContentCategories()
00493     {
00494         // load content pages for adding them into menu tree
00495         $oContentList = oxNew( "oxContentList" );
00496         $oContentList->loadCatMenues();
00497 
00498         foreach ($oContentList as $sCatId => $aContent) {
00499             if (array_key_exists($sCatId, $this->_aArray)) {
00500                 $this[$sCatId]->setContentCats($aContent);
00501 
00502             }
00503         }
00504     }
00505 
00511     protected function _ppBuildTree()
00512     {
00513         $aTree = array();
00514         foreach ($this->_aArray as $oCat) {
00515             $sParentId = $oCat->oxcategories__oxparentid->value;
00516             if ( $sParentId != 'oxrootid') {
00517                 if (isset($this->_aArray[$sParentId])) {
00518                     $this->_aArray[$sParentId]->setSubCat( $oCat, $oCat->getId() );
00519                 }
00520             } else {
00521                 $aTree[$oCat->getId()] = $oCat;
00522             }
00523         }
00524 
00525         $this->assign($aTree);
00526     }
00527 
00534     protected function _ppAddDepthInformation()
00535     {
00536         $aStack = array();
00537         $iDepth = 0;
00538         $sPrevParent = '';
00539 
00540         $aTree = array();
00541         foreach ($this->_aArray as $oCat) {
00542 
00543             $aTree[$oCat->getId()] = $oCat;
00544             $aSubCats = $oCat->getSubCats();
00545             if ( count($aSubCats) > 0 ) {
00546                 foreach ($aSubCats as $oSubCat) {
00547                     $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00548                 }
00549             }
00550         }
00551         $this->assign($aTree);
00552     }
00553 
00563     protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00564     {
00565         $sDepth .= "-";
00566         $oCat->oxcategories__oxtitle->setValue($sDepth.' '.$oCat->oxcategories__oxtitle->value);
00567         $aTree[$oCat->getId()] = $oCat;
00568         $aSubCats = $oCat->getSubCats();
00569         if ( count($aSubCats) > 0 ) {
00570             foreach ($aSubCats as $oSubCat) {
00571                 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00572             }
00573         }
00574         return $aTree;
00575     }
00584     public function updateCategoryTree($blVerbose = true, $sShopID = null)
00585     {
00586         $oDb = oxDb::getDb();
00587         $sWhere = '1';
00588 
00589 
00590         $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00591         $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00592 
00593         // Get all root categories
00594         $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false );
00595         if ($rs != false && $rs->recordCount() > 0) {
00596             while (!$rs->EOF) {
00597                 $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
00598                 if ( $blVerbose ) {
00599                     echo next( $this->_aUpdateInfo );
00600                 }
00601                 $oxRootId = $rs->fields[0];
00602 
00603                 $this->_updateNodes($oxRootId, true, $oxRootId);
00604                 $rs->moveNext();
00605             }
00606         }
00607     }
00608 
00614     public function getUpdateInfo()
00615     {
00616         return $this->_aUpdateInfo;
00617     }
00618 
00628     protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
00629     {
00630         $oDb = oxDb::getDb();
00631 
00632         if ($isRoot) {
00633             $thisRoot = $oxRootId;
00634         }
00635 
00636         // Get sub categories of root categories
00637         $rs = $oDb->execute("update oxcategories set oxrootid = ".$oDb->quote($thisRoot)." where oxparentid = ".$oDb->quote($oxRootId));
00638         $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = ".$oDb->quote($oxRootId)." order by oxsort", false, false);
00639         // If there are sub categories
00640         if ($rs != false && $rs->recordCount() > 0) {
00641             while (!$rs->EOF) {
00642                 $parentId = $rs->fields[1];
00643                 $actOxid = $rs->fields[0];
00644                 $sActOxidQuoted = $oDb->quote($actOxid);
00645 
00646                 // Get the data of the parent category to the current Cat
00647                 $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = ".$oDb->quote($parentId), false, false );
00648                 while (!$rs3->EOF) {
00649                     $parentOxRootId = $rs3->fields[0];
00650                     $parentRight    = (int)$rs3->fields[1];
00651                     $rs3->moveNext();
00652                 }
00653                 $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
00654                 $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00655                 $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00656                 $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00657                 $this->_updateNodes($actOxid, false, $thisRoot);
00658                 $rs->moveNext();
00659             }
00660         }
00661     }
00662 
00670     public function __get($sName)
00671     {
00672         switch ($sName) {
00673             case 'aPath':
00674             case 'aFullPath':
00675                 return $this->getPath();
00676                 break;
00677         }
00678         return parent::__get($sName);
00679     }
00680 
00681 }