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
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
00156 if ($oCat) {
00157
00158 $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00159 }
00160
00161
00162 if ($this->_iForceLevel >= 1) {
00163 $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00164 }
00165
00166
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
00225 if ( !$this->isAdmin() ) {
00226
00227 $this->_ppRemoveInactiveCategories();
00228
00229
00230 $this->_ppLoadFullCategory($sActCat);
00231
00232
00233 $this->_ppAddPathInfo();
00234
00235
00236 $this->_ppAddContentCategories();
00237
00238
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
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
00285 $this->_ppBuildTree();
00286
00287
00288
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
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
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
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
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
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
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
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
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 }