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 remove";
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
00124 if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->_blForceFull) {
00125 $oCat = oxNew('oxcategory');
00126 if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00127 $oCat = null;
00128 $this->_sActCat = null;
00129 }
00130 $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00131 $sWhere = $this->_getDepthSqlSnippet($oCat);
00132 } else {
00133 $sUnion = '';
00134 $sWhere = '1';
00135 }
00136
00137 if (!$sOrder) {
00138 $sOrdDir = $blReverse?'desc':'asc';
00139 $sOrder = "oxrootid $sOrdDir, oxleft $sOrdDir";
00140 }
00141
00142 return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00143 }
00144
00154 protected function _getDepthSqlSnippet($oCat)
00155 {
00156 $sViewName = $this->getBaseObject()->getViewName();
00157 $sDepthSnippet = ' ( 0';
00158
00159
00160 if ($oCat) {
00161
00162 $sDepthSnippet .= " or ($sViewName.oxparentid = ".oxDb::getDb()->quote($oCat->oxcategories__oxid->value).")";
00163 }
00164
00165
00166 if ($this->_iForceLevel >= 1) {
00167 $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00168 }
00169
00170
00171 if ($this->_iForceLevel >= 2) {
00172 $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00173 }
00174
00175 $sDepthSnippet .= ' ) ';
00176 return $sDepthSnippet;
00177 }
00178
00189 protected function _getDepthSqlUnion($oCat, $aColumns = null)
00190 {
00191 if (!$oCat) {
00192 return '';
00193 }
00194 return "UNION SELECT ".$this->_getSqlSelectFieldsForTree('maincats', $aColumns)
00195 ." FROM oxcategories AS subcats"
00196 ." LEFT JOIN oxcategories AS maincats on maincats.oxparentid = subcats.oxparentid"
00197 ." WHERE subcats.oxrootid = ".oxDb::getDb()->quote($oCat->oxcategories__oxrootid->value)
00198 ." AND subcats.oxleft <= ". (int)$oCat->oxcategories__oxleft->value
00199 ." AND subcats.oxright >= ".(int)$oCat->oxcategories__oxright->value;
00200 }
00201
00202
00215 public function buildTree($sActCat, $blLoadFullTree, $blPerfLoadTreeForSearch, $blTopNaviLayout)
00216 {
00217 startProfile("buildTree");
00218
00219 $this->_sActCat = $sActCat;
00220 $this->_blForceFull = $blLoadFullTree || $blPerfLoadTreeForSearch;
00221 $this->_iForceLevel = $blTopNaviLayout?2:1;
00222
00223 $sSelect = $this->_getSelectString(true);
00224 $this->selectString($sSelect);
00225
00226
00227 if ( !$this->isAdmin() ) {
00228
00229 $this->_ppRemoveInactiveCategories();
00230
00231
00232 $this->_ppLoadFullCategory($sActCat);
00233
00234
00235 $this->_ppAddPathInfo();
00236
00237
00238 $this->_ppAddContentCategories();
00239
00240
00241 $this->_ppBuildTree();
00242 }
00243
00244 stopProfile("buildTree");
00245 }
00246
00254 protected function _ppLoadFullCategory( $sId )
00255 {
00256 $oNewCat = oxNew('oxcategory');
00257 if ($oNewCat->load($sId)) {
00258
00259 $this->_aArray[$sId] = $oNewCat;
00260 }
00261 }
00262
00270 public function buildList($blLoad)
00271 {
00272
00273 if (!$blLoad) {
00274 return;
00275 }
00276
00277 startProfile('buildCategoryList');
00278
00279 $this->_blForceFull = true;
00280 $this->selectString($this->_getSelectString(false));
00281
00282
00283
00284 $this->_ppAddDepthInformation();
00285 stopProfile('buildCategoryList');
00286 }
00287
00295 public function setShopID($sShopID)
00296 {
00297 $this->_sShopID = $sShopID;
00298 }
00299
00305 public function getPath()
00306 {
00307 return $this->_aPath;
00308 }
00309
00315 public function getHtmlPath()
00316 {
00317 $sHtmlCatTree = '';
00318 $sSep = '';
00319 foreach ( $this->_aPath as $oCategory ) {
00320 $sHtmlCatTree .= " $sSep<a href='".$oCategory->getLink()."'>".$oCategory->oxcategories__oxtitle->value."</a>";
00321 $sSep = '/ ';
00322 }
00323 return $sHtmlCatTree;
00324 }
00325
00331 public function getClickCat()
00332 {
00333 if (count($this->_aPath)) {
00334 return end($this->_aPath);
00335 }
00336 }
00337
00343 public function getClickRoot()
00344 {
00345 if (count($this->_aPath)) {
00346 return array(reset($this->_aPath));
00347 }
00348 }
00349
00355 protected function _ppRemoveInactiveCategories()
00356 {
00357
00358 $aRemoveList = array();
00359 foreach ($this->_aArray as $oCat) {
00360 if ($oCat->oxcategories__remove->value) {
00361 if (isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00362 $aRemoveRange = $aRemoveList[$oCat->oxcategories__oxrootid->value];
00363 } else {
00364 $aRemoveRange = array();
00365 }
00366 $aRemoveList[$oCat->oxcategories__oxrootid->value] = array_merge(range($oCat->oxcategories__oxleft->value, $oCat->oxcategories__oxright->value), $aRemoveRange);
00367 }
00368 unset($oCat->oxcategories__remove);
00369 }
00370
00371
00372 foreach ($this->_aArray as $oCat) {
00373 if (isset($aRemoveList[$oCat->oxcategories__oxrootid->value]) && in_array($oCat->oxcategories__oxleft->value, $aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00374 unset( $this->_aArray[$oCat->oxcategories__oxid->value] );
00375 }
00376 }
00377 }
00378
00384 protected function _ppAddPathInfo()
00385 {
00386
00387 if (is_null($this->_sActCat)) {
00388 return;
00389 }
00390
00391 $aPath = array();
00392 $sCurrentCat = $this->_sActCat;
00393
00394 while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00395 $oCat = $this[$sCurrentCat];
00396 $oCat->setExpanded(true);
00397 $aPath[$sCurrentCat] = $oCat;
00398 $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00399 }
00400
00401 $this->_aPath = array_reverse($aPath);
00402 }
00403
00409 protected function _ppAddContentCategories()
00410 {
00411
00412 $oContentList = oxNew( "oxcontentlist" );
00413 $oContentList->loadCatMenues();
00414
00415 foreach ($oContentList as $sCatId => $aContent) {
00416 if (array_key_exists($sCatId, $this->_aArray)) {
00417 $this[$sCatId]->setContentCats($aContent);
00418
00419 }
00420 }
00421 }
00422
00428 protected function _ppBuildTree()
00429 {
00430 startProfile("_sortCats");
00431 $aIds = $this->sortCats();
00432 stopProfile("_sortCats");
00433 $aTree = array();
00434 foreach ($this->_aArray as $oCat) {
00435 $sParentId = $oCat->oxcategories__oxparentid->value;
00436 if ( $sParentId != 'oxrootid') {
00437 $this->_aArray[$sParentId]->setSortingIds( $aIds );
00438 $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId(), true);
00439 } else {
00440 $aTree[$oCat->getId()] = $oCat;
00441 }
00442 }
00443
00444
00445 $aParents = array();
00446 foreach ($this->_aArray as $oCat) {
00447 $aParents[$oCat->oxcategories__oxparentid->value] = true;
00448 }
00449 if ($aParents['oxrootid']) {
00450 unset($aParents['oxrootid']);
00451 }
00452 foreach (array_keys($aParents) as $sParent) {
00453 $this->_aArray[$sParent]->sortSubCats();
00454 }
00455
00456
00457 $oCategory = oxNew('oxcategory');
00458 $oCategory->setSortingIds( $aIds );
00459 uasort($aTree, array( $oCategory, 'cmpCat' ) );
00460
00461 $this->assign($aTree);
00462 }
00463
00469 public function sortCats()
00470 {
00471 $sViewName = getViewName('oxcategories');
00472 $sSortSql = $this->_getSelectString(false, array('oxid', 'oxparentid', 'oxsort', 'oxtitle'), 'oxparentid, oxsort, oxtitle');
00473 $aIds = array();
00474 $oDB = oxDb::getDb();
00475 $rs = $oDB->execute($sSortSql);
00476 $cnt = 0;
00477 if ($rs != false && $rs->recordCount() > 0) {
00478 while (!$rs->EOF) {
00479 $aIds[$rs->fields[0]] = $cnt;
00480 $cnt++;
00481 $rs->moveNext();
00482 }
00483 }
00484 return $aIds;
00485 }
00486
00493 protected function _ppAddDepthInformation()
00494 {
00495
00496 $aStack = array();
00497 $iDepth = 0;
00498 $sPrevParent = '';
00499
00500 foreach ($this->_aArray as $oCat) {
00501
00502 $sParentId = $oCat->oxcategories__oxparentid->value;
00503 if ( $oCat->oxcategories__oxparentid->value == 'oxrootid' ) {
00504 $iDepth = 1;
00505 $aStack = array($sParentId => '0');
00506 }
00507
00508 if ($sPrevParent != $sParentId && isset($aStack[$sParentId]) ) {
00509 $iDepth -= count($aStack)- $aStack[$sParentId];
00510 $aStack = array_slice($aStack, 0, $iDepth-1, true);
00511 }
00512
00513 if ( !isset($aStack[$sParentId])) {
00514 $aStack[$sParentId] = $iDepth;
00515 $iDepth++;
00516 }
00517
00518 $oCat->oxcategories__oxtitle->setValue(str_repeat('-', $iDepth-1).' '.$oCat->oxcategories__oxtitle->value);
00519 $sPrevParent = $sParentId;
00520 }
00521
00522 }
00523
00532 public function updateCategoryTree($blVerbose = true, $sShopID = null)
00533 {
00534 $oDB = oxDb::getDb();
00535 $sWhere = '1';
00536
00537
00538 $oDB->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00539 $oDB->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00540
00541
00542 $rs = $oDB->execute("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort");
00543 if ($rs != false && $rs->recordCount() > 0) {
00544 while (!$rs->EOF) {
00545 $this->_aUpdateInfo[] = "<b>Processing : ".$rs->fields[1]."</b>(".$rs->fields[0].")<br>";
00546 if ( $blVerbose ) {
00547 echo next( $this->_aUpdateInfo );
00548 }
00549 $oxRootId = $rs->fields[0];
00550
00551 $updn = $this->_updateNodes($oxRootId, true, $oxRootId);
00552 $rs->moveNext();
00553 }
00554 }
00555 }
00556
00562 public function getUpdateInfo()
00563 {
00564 return $this->_aUpdateInfo;
00565 }
00566
00576 protected function _updateNodes($oxRootId, $isroot, $thisRoot)
00577 {
00578 $oDB = oxDb::getDb();
00579
00580 if ($isroot) {
00581 $thisRoot = $oxRootId;
00582 }
00583
00584
00585 $rs = $oDB->execute("update oxcategories set oxrootid = ".$oDB->quote($thisRoot)." where oxparentid = ".$oDB->quote($oxRootId));
00586 $rs = $oDB->execute("select oxid, oxparentid from oxcategories where oxparentid = ".$oDB->quote($oxRootId)." order by oxsort");
00587
00588 if ($rs != false && $rs->recordCount() > 0) {
00589 while (!$rs->EOF) {
00590 $parentId = $rs->fields[1];
00591 $actOxid = $rs->fields[0];
00592 $sActOxidQuoted = $oDB->quote($actOxid);
00593
00594
00595 $rs3 = $oDB->execute("select oxrootid, oxright from oxcategories where oxid = ".$oDB->quote($parentId));
00596 while (!$rs3->EOF) {
00597 $parentOxRootId = $rs3->fields[0];
00598 $parentRight = (int)$rs3->fields[1];
00599 $rs3->moveNext();
00600 }
00601 $sParentOxRootIdQuoted = $oDB->quote($parentOxRootId);
00602 $oDB->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00603 $oDB->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00604 $oDB->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00605 $this->_updateNodes($actOxid, false, $thisRoot);
00606 $rs->moveNext();
00607 }
00608 }
00609 }
00610
00618 public function __get($sName)
00619 {
00620 switch ($sName) {
00621 case 'aPath':
00622 case 'aFullPath':
00623 return $this->getPath();
00624 break;
00625 }
00626 return parent::__get($sName);
00627 }
00628
00629 }