00001 <?php
00002
00003
00010 class oxCategoryList extends oxList
00011 {
00012
00018 protected $_sObjectsInListName = 'oxcategory';
00019
00025 protected $_blHideEmpty = false;
00026
00032 protected $_blForceFull = false;
00033
00039 protected $_iForceLevel = 2;
00040
00046 protected $_sActCat = null;
00047
00053 protected $_aPath = array();
00054
00060 protected $_aUpdateInfo = array();
00061
00069 public function __construct($sObjectsInListName = 'oxcategory')
00070 {
00071 $this->_blHideEmpty = $this->getConfig()->getConfigParam('blDontShowEmptyCategories');
00072 parent::__construct($sObjectsInListName);
00073 }
00074
00080 public function setLoadFull($blForceFull)
00081 {
00082 $this->_blForceFull = $blForceFull;
00083 }
00084
00090 public function getLoadFull()
00091 {
00092 return $this->_blForceFull;
00093 }
00094
00100 public function setLoadLevel($iForceLevel)
00101 {
00102 if ($iForceLevel > 2) {
00103 $iForceLevel = 2;
00104 } elseif ($iForceLevel < 1) {
00105 $iForceLevel = 0;
00106 }
00107 $this->_iForceLevel = $iForceLevel;
00108 }
00109
00115 public function getLoadLevel()
00116 {
00117 return $this->_iForceLevel;
00118 }
00119
00128 protected function _getSqlSelectFieldsForTree($sTable, $aColumns = null)
00129 {
00130 if ($aColumns && count($aColumns)) {
00131 foreach ($aColumns as $key => $val) {
00132 $aColumns[$key] .= ' as ' . $val;
00133 }
00134
00135 return "$sTable." . implode(", $sTable.", $aColumns);
00136 }
00137
00138 $sFieldList = "$sTable.oxid as oxid, $sTable.oxactive as oxactive,"
00139 . " $sTable.oxhidden as oxhidden, $sTable.oxparentid as oxparentid,"
00140 . " $sTable.oxdefsort as oxdefsort, $sTable.oxdefsortmode as oxdefsortmode,"
00141 . " $sTable.oxleft as oxleft, $sTable.oxright as oxright,"
00142 . " $sTable.oxrootid as oxrootid, $sTable.oxsort as oxsort,"
00143 . " $sTable.oxtitle as oxtitle, $sTable.oxdesc as oxdesc,"
00144 . " $sTable.oxpricefrom as oxpricefrom, $sTable.oxpriceto as oxpriceto,"
00145 . " $sTable.oxicon as oxicon, $sTable.oxextlink as oxextlink,"
00146 . " $sTable.oxthumb as oxthumb, $sTable.oxpromoicon as oxpromoicon";
00147
00148 $sFieldList .= ",not $sTable.oxactive as oxppremove";
00149
00150
00151 return $sFieldList;
00152 }
00153
00163 protected function _getSelectString($blReverse = false, $aColumns = null, $sOrder = null)
00164 {
00165 $sViewName = $this->getBaseObject()->getViewName();
00166 $sFieldList = $this->_getSqlSelectFieldsForTree($sViewName, $aColumns);
00167
00168
00169 if (!$this->isAdmin() && !$this->_blHideEmpty && !$this->getLoadFull()) {
00170 $oCat = oxNew('oxCategory');
00171 if (!($this->_sActCat && $oCat->load($this->_sActCat) && $oCat->oxcategories__oxrootid->value)) {
00172 $oCat = null;
00173 $this->_sActCat = null;
00174 }
00175
00176 $sUnion = $this->_getDepthSqlUnion($oCat, $aColumns);
00177 $sWhere = $this->_getDepthSqlSnippet($oCat);
00178 } else {
00179 $sUnion = '';
00180 $sWhere = '1';
00181 }
00182
00183 if (!$sOrder) {
00184 $sOrdDir = $blReverse ? 'desc' : 'asc';
00185 $sOrder = "oxrootid $sOrdDir, oxleft $sOrdDir";
00186 }
00187
00188 return "select $sFieldList from $sViewName where $sWhere $sUnion order by $sOrder";
00189 }
00190
00199 protected function _getDepthSqlSnippet($oCat)
00200 {
00201 $sViewName = $this->getBaseObject()->getViewName();
00202 $sDepthSnippet = ' ( 0';
00203
00204
00205 if ($oCat) {
00206
00207 $sDepthSnippet .= " or ($sViewName.oxparentid = " . oxDb::getDb()->quote($oCat->oxcategories__oxid->value) . ")";
00208 }
00209
00210
00211 if ($this->getLoadLevel() >= 1) {
00212 $sDepthSnippet .= " or $sViewName.oxparentid = 'oxrootid'";
00213 }
00214
00215
00216 if ($this->getLoadLevel() >= 2) {
00217 $sDepthSnippet .= " or $sViewName.oxrootid = $sViewName.oxparentid or $sViewName.oxid = $sViewName.oxrootid";
00218 }
00219
00220 $sDepthSnippet .= ' ) ';
00221
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
00269 public function load()
00270 {
00271
00272 $aData = $this->_loadFromDb();
00273
00274 $this->assignArray($aData);
00275 }
00276
00277
00285 public function buildTree($sActCat)
00286 {
00287 startProfile("buildTree");
00288
00289 $this->_sActCat = $sActCat;
00290 $this->load();
00291
00292
00293 if (!$this->isAdmin()) {
00294
00295
00296 $this->_ppRemoveInactiveCategories();
00297
00298
00299 $this->_ppLoadFullCategory($sActCat);
00300
00301
00302 $this->_ppAddPathInfo();
00303
00304
00305 $this->_ppAddContentCategories();
00306
00307
00308 $this->_ppBuildTree();
00309 }
00310
00311 stopProfile("buildTree");
00312 }
00313
00319 protected function _ppLoadFullCategory($sId)
00320 {
00321 if (isset($this->_aArray[$sId])) {
00322 $oNewCat = oxNew('oxCategory');
00323 if ($oNewCat->load($sId)) {
00324
00325 $this->_aArray[$sId] = $oNewCat;
00326 }
00327 } else {
00328 $this->_sActCat = null;
00329 }
00330 }
00331
00335 public function loadList()
00336 {
00337 startProfile('buildCategoryList');
00338
00339 $this->setLoadFull(true);
00340 $this->selectString($this->_getSelectString(false));
00341
00342
00343 $this->_ppBuildTree();
00344
00345
00346
00347 $this->_ppAddDepthInformation();
00348 stopProfile('buildCategoryList');
00349 }
00350
00356 public function setShopID($sShopID)
00357 {
00358 $this->_sShopID = $sShopID;
00359 }
00360
00366 public function getPath()
00367 {
00368 return $this->_aPath;
00369 }
00370
00376 public function getClickCat()
00377 {
00378 if (count($this->_aPath)) {
00379 return end($this->_aPath);
00380 }
00381 }
00382
00388 public function getClickRoot()
00389 {
00390 if (count($this->_aPath)) {
00391 return array(reset($this->_aPath));
00392 }
00393 }
00394
00398 protected function _ppRemoveInactiveCategories()
00399 {
00400
00401 $aRemoveList = array();
00402 foreach ($this->_aArray as $sId => $oCat) {
00403 if ($oCat->oxcategories__oxppremove->value) {
00404 if (!isset($aRemoveList[$oCat->oxcategories__oxrootid->value])) {
00405 $aRemoveList[$oCat->oxcategories__oxrootid->value] = array();
00406 }
00407 $aRemoveList[$oCat->oxcategories__oxrootid->value][$oCat->oxcategories__oxleft->value] = $oCat->oxcategories__oxright->value;
00408 unset($this->_aArray[$sId]);
00409 } else {
00410 unset($oCat->oxcategories__oxppremove);
00411 }
00412 }
00413
00414
00415 foreach ($this->_aArray as $sId => $oCat) {
00416 if (isset($aRemoveList[$oCat->oxcategories__oxrootid->value]) &&
00417 is_array($aRemoveList[$oCat->oxcategories__oxrootid->value])
00418 ) {
00419 foreach ($aRemoveList[$oCat->oxcategories__oxrootid->value] as $iLeft => $iRight) {
00420 if (
00421 ($iLeft <= $oCat->oxcategories__oxleft->value)
00422 && ($iRight >= $oCat->oxcategories__oxleft->value)
00423 ) {
00424
00425 unset($this->_aArray[$sId]);
00426 break 1;
00427 }
00428 }
00429 }
00430 }
00431 }
00432
00438 protected function _ppAddPathInfo()
00439 {
00440 if (is_null($this->_sActCat)) {
00441 return;
00442 }
00443
00444 $aPath = array();
00445 $sCurrentCat = $this->_sActCat;
00446
00447 while ($sCurrentCat != 'oxrootid' && isset($this[$sCurrentCat])) {
00448 $oCat = $this[$sCurrentCat];
00449 $oCat->setExpanded(true);
00450 $aPath[$sCurrentCat] = $oCat;
00451 $sCurrentCat = $oCat->oxcategories__oxparentid->value;
00452 }
00453
00454 $this->_aPath = array_reverse($aPath);
00455 }
00456
00460 protected function _ppAddContentCategories()
00461 {
00462
00463 $oContentList = oxNew("oxContentList");
00464 $oContentList->loadCatMenues();
00465
00466 foreach ($oContentList as $sCatId => $aContent) {
00467 if (array_key_exists($sCatId, $this->_aArray)) {
00468 $this[$sCatId]->setContentCats($aContent);
00469
00470 }
00471 }
00472 }
00473
00477 protected function _ppBuildTree()
00478 {
00479 $aTree = array();
00480 foreach ($this->_aArray as $oCat) {
00481 $sParentId = $oCat->oxcategories__oxparentid->value;
00482 if ($sParentId != 'oxrootid') {
00483 if (isset($this->_aArray[$sParentId])) {
00484 $this->_aArray[$sParentId]->setSubCat($oCat, $oCat->getId());
00485 }
00486 } else {
00487 $aTree[$oCat->getId()] = $oCat;
00488 }
00489 }
00490
00491 $this->assign($aTree);
00492 }
00493
00498 protected function _ppAddDepthInformation()
00499 {
00500 $aStack = array();
00501 $iDepth = 0;
00502 $sPrevParent = '';
00503
00504 $aTree = array();
00505 foreach ($this->_aArray as $oCat) {
00506
00507 $aTree[$oCat->getId()] = $oCat;
00508 $aSubCats = $oCat->getSubCats();
00509 if (count($aSubCats) > 0) {
00510 foreach ($aSubCats as $oSubCat) {
00511 $aTree = $this->_addDepthInfo($aTree, $oSubCat);
00512 }
00513 }
00514 }
00515 $this->assign($aTree);
00516 }
00517
00527 protected function _addDepthInfo($aTree, $oCat, $sDepth = "")
00528 {
00529 $sDepth .= "-";
00530 $oCat->oxcategories__oxtitle->setValue($sDepth . ' ' . $oCat->oxcategories__oxtitle->value);
00531 $aTree[$oCat->getId()] = $oCat;
00532 $aSubCats = $oCat->getSubCats();
00533 if (count($aSubCats) > 0) {
00534 foreach ($aSubCats as $oSubCat) {
00535 $aTree = $this->_addDepthInfo($aTree, $oSubCat, $sDepth);
00536 }
00537 }
00538
00539 return $aTree;
00540 }
00541
00548 public function updateCategoryTree($blVerbose = true, $sShopID = null)
00549 {
00550 $oDb = oxDb::getDb();
00551 $sWhere = '1';
00552
00553
00554 $oDb->execute("update oxcategories set oxleft = 0, oxright = 0 where $sWhere");
00555 $oDb->execute("update oxcategories set oxleft = 1, oxright = 2 where oxparentid = 'oxrootid' and $sWhere");
00556
00557
00558 $rs = $oDb->select("select oxid, oxtitle from oxcategories where oxparentid = 'oxrootid' and $sWhere order by oxsort", false, false);
00559 if ($rs != false && $rs->recordCount() > 0) {
00560 while (!$rs->EOF) {
00561 $this->_aUpdateInfo[] = "<b>Processing : " . $rs->fields[1] . "</b>(" . $rs->fields[0] . ")<br>";
00562 if ($blVerbose) {
00563 echo next($this->_aUpdateInfo);
00564 }
00565 $oxRootId = $rs->fields[0];
00566
00567 $this->_updateNodes($oxRootId, true, $oxRootId);
00568 $rs->moveNext();
00569 }
00570 }
00571 }
00572
00578 public function getUpdateInfo()
00579 {
00580 return $this->_aUpdateInfo;
00581 }
00582
00590 protected function _updateNodes($oxRootId, $isRoot, $thisRoot)
00591 {
00592 $oDb = oxDb::getDb();
00593
00594 if ($isRoot) {
00595 $thisRoot = $oxRootId;
00596 }
00597
00598
00599 $rs = $oDb->execute("update oxcategories set oxrootid = " . $oDb->quote($thisRoot) . " where oxparentid = " . $oDb->quote($oxRootId));
00600 $rs = $oDb->select("select oxid, oxparentid from oxcategories where oxparentid = " . $oDb->quote($oxRootId) . " order by oxsort", false, false);
00601
00602 if ($rs != false && $rs->recordCount() > 0) {
00603 while (!$rs->EOF) {
00604 $parentId = $rs->fields[1];
00605 $actOxid = $rs->fields[0];
00606 $sActOxidQuoted = $oDb->quote($actOxid);
00607
00608
00609 $rs3 = $oDb->select("select oxrootid, oxright from oxcategories where oxid = " . $oDb->quote($parentId), false, false);
00610 while (!$rs3->EOF) {
00611 $parentOxRootId = $rs3->fields[0];
00612 $parentRight = (int) $rs3->fields[1];
00613 $rs3->moveNext();
00614 }
00615 $sParentOxRootIdQuoted = $oDb->quote($parentOxRootId);
00616 $oDb->execute("update oxcategories set oxleft = oxleft + 2 where oxrootid = $sParentOxRootIdQuoted and oxleft > '$parentRight' and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00617 $oDb->execute("update oxcategories set oxright = oxright + 2 where oxrootid = $sParentOxRootIdQuoted and oxright >= '$parentRight' and oxid != $sActOxidQuoted");
00618 $oDb->execute("update oxcategories set oxleft = $parentRight, oxright = ($parentRight + 1) where oxid = $sActOxidQuoted");
00619 $this->_updateNodes($actOxid, false, $thisRoot);
00620 $rs->moveNext();
00621 }
00622 }
00623 }
00624
00632 public function __get($sName)
00633 {
00634 switch ($sName) {
00635 case 'aPath':
00636 case 'aFullPath':
00637 return $this->getPath();
00638 break;
00639 }
00640 return parent::__get($sName);
00641 }
00642 }