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
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
00159 if ($oCat) {
00160
00161 $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00162 }
00163
00164
00165 if ($this->_iForceLevel >= 1) {
00166 $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00167 }
00168
00169
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
00229 if ( !$this->isAdmin() ) {
00230
00231 $this->_ppRemoveInactiveCategories();
00232
00233
00234 $this->_ppLoadFullCategory($sActCat);
00235
00236
00237 $this->_ppAddPathInfo();
00238
00239
00240 $this->_ppAddContentCategories();
00241
00242
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
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
00289 $this->_ppBuildTree();
00290
00291
00292
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
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
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
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
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
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
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
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
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
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
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 }