1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27:
28: 29: 30: 31: 32: 33: 34:
35: class Mage_Catalog_Model_Resource_Url extends Mage_Core_Model_Resource_Db_Abstract
36: {
37: 38: 39: 40: 41:
42: protected $_stores;
43:
44: 45: 46: 47: 48:
49: protected $_categoryAttributes = array();
50:
51: 52: 53: 54: 55:
56: protected $_productAttributes = array();
57:
58: 59: 60: 61: 62:
63: protected $_productLimit = 250;
64:
65: 66: 67: 68: 69:
70: protected $_rootChildrenIds = array();
71:
72: 73: 74: 75:
76: protected function _construct()
77: {
78: $this->_init('core/url_rewrite', 'url_rewrite_id');
79: }
80:
81: 82: 83: 84: 85: 86:
87: public function getStores($storeId = null)
88: {
89: if ($this->_stores === null) {
90: $this->_stores = $this->_prepareStoreRootCategories(Mage::app()->getStores());
91: }
92: if ($storeId && isset($this->_stores[$storeId])) {
93: return $this->_stores[$storeId];
94: }
95: return $this->_stores;
96: }
97:
98: 99: 100: 101: 102:
103: public function getCategoryModel()
104: {
105: return Mage::getSingleton('catalog/category');
106: }
107:
108: 109: 110: 111: 112:
113: public function getProductModel()
114: {
115: return Mage::getSingleton('catalog/product');
116: }
117:
118: 119: 120: 121: 122: 123: 124:
125: public function getRewriteByIdPath($idPath, $storeId)
126: {
127: $adapter = $this->_getReadAdapter();
128: $select = $adapter->select()
129: ->from($this->getMainTable())
130: ->where('store_id = :store_id')
131: ->where('id_path = :id_path');
132: $bind = array(
133: 'store_id' => (int)$storeId,
134: 'id_path' => $idPath
135: );
136: $row = $adapter->fetchRow($select, $bind);
137:
138: if (!$row) {
139: return false;
140: }
141: $rewrite = new Varien_Object($row);
142: $rewrite->setIdFieldName($this->getIdFieldName());
143:
144: return $rewrite;
145: }
146:
147: 148: 149: 150: 151: 152: 153:
154: public function getRewriteByRequestPath($requestPath, $storeId)
155: {
156: $adapter = $this->_getWriteAdapter();
157: $select = $adapter->select()
158: ->from($this->getMainTable())
159: ->where('store_id = :store_id')
160: ->where('request_path = :request_path');
161: $bind = array(
162: 'request_path' => $requestPath,
163: 'store_id' => (int)$storeId
164: );
165: $row = $adapter->fetchRow($select, $bind);
166:
167: if (!$row) {
168: return false;
169: }
170: $rewrite = new Varien_Object($row);
171: $rewrite->setIdFieldName($this->getIdFieldName());
172:
173: return $rewrite;
174: }
175:
176: 177: 178: 179: 180: 181: 182: 183:
184: public function getLastUsedRewriteRequestIncrement($prefix, $suffix, $storeId)
185: {
186: $adapter = $this->_getWriteAdapter();
187: $requestPathField = new Zend_Db_Expr($adapter->quoteIdentifier('request_path'));
188:
189: $urlIncrementPartExpression = Mage::getResourceHelper('eav')
190: ->getCastToIntExpression($adapter->getSubstringSql(
191: $requestPathField,
192: strlen($prefix) + 1,
193: $adapter->getLengthSql($requestPathField) . ' - ' . strlen($prefix) . ' - ' . strlen($suffix)
194: ));
195: $select = $adapter->select()
196: ->from($this->getMainTable(), new Zend_Db_Expr('MAX(' . $urlIncrementPartExpression . ')'))
197: ->where('store_id = :store_id')
198: ->where('request_path LIKE :request_path')
199: ->where($adapter->prepareSqlCondition('request_path', array(
200: 'regexp' => '^' . preg_quote($prefix) . '[0-9]*' . preg_quote($suffix) . '$'
201: )));
202: $bind = array(
203: 'store_id' => (int)$storeId,
204: 'request_path' => $prefix . '%' . $suffix,
205: );
206:
207: return (int)$adapter->fetchOne($select, $bind);
208: }
209:
210: 211: 212: 213: 214: 215: 216:
217: public function checkRequestPaths($paths, $storeId)
218: {
219: $adapter = $this->_getWriteAdapter();
220: $select = $adapter->select()
221: ->from($this->getMainTable(), 'request_path')
222: ->where('store_id = :store_id')
223: ->where('request_path IN (?)', $paths);
224: $data = $adapter->fetchCol($select, array('store_id' => $storeId));
225: $paths = array_diff($paths, $data);
226: if (empty($paths)) {
227: return false;
228: }
229: reset($paths);
230:
231: return current($paths);
232: }
233:
234: 235: 236: 237: 238: 239: 240: 241:
242: public function prepareRewrites($storeId, $categoryIds = null, $productIds = null)
243: {
244: $rewrites = array();
245: $adapter = $this->_getWriteAdapter();
246: $select = $adapter->select()
247: ->from($this->getMainTable())
248: ->where('store_id = :store_id')
249: ->where('is_system = ?', 1);
250: $bind = array('store_id' => $storeId);
251: if ($categoryIds === null) {
252: $select->where('category_id IS NULL');
253: } elseif ($categoryIds) {
254: $catIds = is_array($categoryIds) ? $categoryIds : array($categoryIds);
255:
256:
257:
258: if ($productIds) {
259: $addNullCategory = in_array($this->getStores($storeId)->getRootCategoryId(), $catIds);
260: } else {
261: $addNullCategory = false;
262: }
263:
264:
265: if ($addNullCategory) {
266: $select->where('category_id IN(?) OR category_id IS NULL', $catIds);
267: } else {
268: $select->where('category_id IN(?)', $catIds);
269: }
270: }
271:
272: if ($productIds === null) {
273: $select->where('product_id IS NULL');
274: } elseif ($productIds) {
275: $select->where('product_id IN(?)', $productIds);
276: }
277:
278: $rowSet = $adapter->fetchAll($select, $bind);
279:
280: foreach ($rowSet as $row) {
281: $rewrite = new Varien_Object($row);
282: $rewrite->setIdFieldName($this->getIdFieldName());
283: $rewrites[$rewrite->getIdPath()] = $rewrite;
284: }
285:
286: return $rewrites;
287: }
288:
289: 290: 291: 292: 293: 294: 295:
296: public function saveRewrite($rewriteData, $rewrite)
297: {
298: $adapter = $this->_getWriteAdapter();
299: try {
300: $adapter->insertOnDuplicate($this->getMainTable(), $rewriteData);
301: } catch (Exception $e) {
302: Mage::logException($e);
303: Mage::throwException(Mage::helper('catalog')->__('An error occurred while saving the URL rewrite'));
304: }
305:
306: if ($rewrite && $rewrite->getId()) {
307: if ($rewriteData['request_path'] != $rewrite->getRequestPath()) {
308:
309: $where = array('target_path = ?' => $rewrite->getRequestPath());
310: if ($rewrite->getStoreId()) {
311: $where['store_id = ?'] = (int)$rewrite->getStoreId();
312: }
313: $adapter->update(
314: $this->getMainTable(),
315: array('target_path' => $rewriteData['request_path']),
316: $where
317: );
318: }
319: }
320: unset($rewriteData);
321:
322: return $this;
323: }
324:
325: 326: 327: 328: 329: 330:
331: public function saveRewriteHistory($rewriteData)
332: {
333: $rewriteData = new Varien_Object($rewriteData);
334:
335: $rewrite = $this->getRewriteByRequestPath($rewriteData->getRequestPath(), $rewriteData->getStoreId());
336: if ($rewrite === false) {
337:
338: $this->_getWriteAdapter()->insert($this->getMainTable(), $rewriteData->getData());
339: }
340:
341: return $this;
342: }
343:
344: 345: 346: 347: 348: 349: 350:
351: public function saveCategoryAttribute(Varien_Object $category, $attributeCode)
352: {
353: $adapter = $this->_getWriteAdapter();
354: if (!isset($this->_categoryAttributes[$attributeCode])) {
355: $attribute = $this->getCategoryModel()->getResource()->getAttribute($attributeCode);
356:
357: $this->_categoryAttributes[$attributeCode] = array(
358: 'entity_type_id' => $attribute->getEntityTypeId(),
359: 'attribute_id' => $attribute->getId(),
360: 'table' => $attribute->getBackend()->getTable(),
361: 'is_global' => $attribute->getIsGlobal()
362: );
363: unset($attribute);
364: }
365:
366: $attributeTable = $this->_categoryAttributes[$attributeCode]['table'];
367:
368: $attributeData = array(
369: 'entity_type_id' => $this->_categoryAttributes[$attributeCode]['entity_type_id'],
370: 'attribute_id' => $this->_categoryAttributes[$attributeCode]['attribute_id'],
371: 'store_id' => $category->getStoreId(),
372: 'entity_id' => $category->getId(),
373: 'value' => $category->getData($attributeCode)
374: );
375:
376: if ($this->_categoryAttributes[$attributeCode]['is_global'] || $category->getStoreId() == 0) {
377: $attributeData['store_id'] = 0;
378: }
379:
380: $select = $adapter->select()
381: ->from($attributeTable)
382: ->where('entity_type_id = ?', (int)$attributeData['entity_type_id'])
383: ->where('attribute_id = ?', (int)$attributeData['attribute_id'])
384: ->where('store_id = ?', (int)$attributeData['store_id'])
385: ->where('entity_id = ?', (int)$attributeData['entity_id']);
386:
387: $row = $adapter->fetchRow($select);
388: $whereCond = array('value_id = ?' => $row['value_id']);
389: if ($row) {
390: $adapter->update($attributeTable, $attributeData, $whereCond);
391: } else {
392: $adapter->insert($attributeTable, $attributeData);
393: }
394:
395: if ($attributeData['store_id'] != 0) {
396: $attributeData['store_id'] = 0;
397: $select = $adapter->select()
398: ->from($attributeTable)
399: ->where('entity_type_id = ?', (int)$attributeData['entity_type_id'])
400: ->where('attribute_id = ?', (int)$attributeData['attribute_id'])
401: ->where('store_id = ?', (int)$attributeData['store_id'])
402: ->where('entity_id = ?', (int)$attributeData['entity_id']);
403:
404: $row = $adapter->fetchRow($select);
405: if ($row) {
406: $whereCond = array('value_id = ?' => $row['value_id']);
407: $adapter->update($attributeTable, $attributeData, $whereCond);
408: } else {
409: $adapter->insert($attributeTable, $attributeData);
410: }
411: }
412: unset($attributeData);
413:
414: return $this;
415: }
416:
417: 418: 419: 420: 421: 422: 423: 424:
425: protected function _getCategoryAttribute($attributeCode, $categoryIds, $storeId)
426: {
427: $adapter = $this->_getWriteAdapter();
428: if (!isset($this->_categoryAttributes[$attributeCode])) {
429: $attribute = $this->getCategoryModel()->getResource()->getAttribute($attributeCode);
430:
431: $this->_categoryAttributes[$attributeCode] = array(
432: 'entity_type_id' => $attribute->getEntityTypeId(),
433: 'attribute_id' => $attribute->getId(),
434: 'table' => $attribute->getBackend()->getTable(),
435: 'is_global' => $attribute->getIsGlobal(),
436: 'is_static' => $attribute->isStatic()
437: );
438: unset($attribute);
439: }
440:
441: if (!is_array($categoryIds)) {
442: $categoryIds = array($categoryIds);
443: }
444:
445: $attributeTable = $this->_categoryAttributes[$attributeCode]['table'];
446: $select = $adapter->select();
447: $bind = array();
448: if ($this->_categoryAttributes[$attributeCode]['is_static']) {
449: $select
450: ->from(
451: $this->getTable('catalog/category'),
452: array('value' => $attributeCode, 'entity_id' => 'entity_id')
453: )
454: ->where('entity_id IN(?)', $categoryIds);
455: } elseif ($this->_categoryAttributes[$attributeCode]['is_global'] || $storeId == 0) {
456: $select
457: ->from($attributeTable, array('entity_id', 'value'))
458: ->where('attribute_id = :attribute_id')
459: ->where('store_id = ?', 0)
460: ->where('entity_id IN(?)', $categoryIds);
461: $bind['attribute_id'] = $this->_categoryAttributes[$attributeCode]['attribute_id'];
462: } else {
463: $valueExpr = $adapter->getCheckSql('t2.value_id > 0', 't2.value', 't1.value');
464: $select
465: ->from(
466: array('t1' => $attributeTable),
467: array('entity_id', 'value' => $valueExpr)
468: )
469: ->joinLeft(
470: array('t2' => $attributeTable),
471: 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = :store_id',
472: array()
473: )
474: ->where('t1.store_id = ?', 0)
475: ->where('t1.attribute_id = :attribute_id')
476: ->where('t1.entity_id IN(?)', $categoryIds);
477:
478: $bind['attribute_id'] = $this->_categoryAttributes[$attributeCode]['attribute_id'];
479: $bind['store_id'] = $storeId;
480: }
481:
482: $rowSet = $adapter->fetchAll($select, $bind);
483:
484: $attributes = array();
485: foreach ($rowSet as $row) {
486: $attributes[$row['entity_id']] = $row['value'];
487: }
488: unset($rowSet);
489: foreach ($categoryIds as $categoryId) {
490: if (!isset($attributes[$categoryId])) {
491: $attributes[$categoryId] = null;
492: }
493: }
494:
495: return $attributes;
496: }
497:
498: 499: 500: 501: 502: 503: 504:
505: public function saveProductAttribute(Varien_Object $product, $attributeCode)
506: {
507: $adapter = $this->_getWriteAdapter();
508: if (!isset($this->_productAttributes[$attributeCode])) {
509: $attribute = $this->getProductModel()->getResource()->getAttribute($attributeCode);
510:
511: $this->_productAttributes[$attributeCode] = array(
512: 'entity_type_id' => $attribute->getEntityTypeId(),
513: 'attribute_id' => $attribute->getId(),
514: 'table' => $attribute->getBackend()->getTable(),
515: 'is_global' => $attribute->getIsGlobal()
516: );
517: unset($attribute);
518: }
519:
520: $attributeTable = $this->_productAttributes[$attributeCode]['table'];
521:
522: $attributeData = array(
523: 'entity_type_id' => $this->_productAttributes[$attributeCode]['entity_type_id'],
524: 'attribute_id' => $this->_productAttributes[$attributeCode]['attribute_id'],
525: 'store_id' => $product->getStoreId(),
526: 'entity_id' => $product->getId(),
527: 'value' => $product->getData($attributeCode)
528: );
529:
530: if ($this->_productAttributes[$attributeCode]['is_global'] || $product->getStoreId() == 0) {
531: $attributeData['store_id'] = 0;
532: }
533:
534: $select = $adapter->select()
535: ->from($attributeTable)
536: ->where('entity_type_id = ?', (int)$attributeData['entity_type_id'])
537: ->where('attribute_id = ?', (int)$attributeData['attribute_id'])
538: ->where('store_id = ?', (int)$attributeData['store_id'])
539: ->where('entity_id = ?', (int)$attributeData['entity_id']);
540:
541: $row = $adapter->fetchRow($select);
542: if ($row) {
543: $whereCond = array('value_id = ?' => $row['value_id']);
544: $adapter->update($attributeTable, $attributeData, $whereCond);
545: } else {
546: $adapter->insert($attributeTable, $attributeData);
547: }
548:
549: if ($attributeData['store_id'] != 0) {
550: $attributeData['store_id'] = 0;
551: $select = $adapter->select()
552: ->from($attributeTable)
553: ->where('entity_type_id = ?', (int)$attributeData['entity_type_id'])
554: ->where('attribute_id = ?', (int)$attributeData['attribute_id'])
555: ->where('store_id = ?', (int)$attributeData['store_id'])
556: ->where('entity_id = ?', (int)$attributeData['entity_id']);
557:
558: $row = $adapter->fetchRow($select);
559: if ($row) {
560: $whereCond = array('value_id = ?' => $row['value_id']);
561: $adapter->update($attributeTable, $attributeData, $whereCond);
562: } else {
563: $adapter->insert($attributeTable, $attributeData);
564: }
565: }
566: unset($attributeData);
567:
568: return $this;
569: }
570:
571: 572: 573: 574: 575: 576: 577: 578:
579: public function _getProductAttribute($attributeCode, $productIds, $storeId)
580: {
581: $adapter = $this->_getReadAdapter();
582: if (!isset($this->_productAttributes[$attributeCode])) {
583: $attribute = $this->getProductModel()->getResource()->getAttribute($attributeCode);
584:
585: $this->_productAttributes[$attributeCode] = array(
586: 'entity_type_id' => $attribute->getEntityTypeId(),
587: 'attribute_id' => $attribute->getId(),
588: 'table' => $attribute->getBackend()->getTable(),
589: 'is_global' => $attribute->getIsGlobal()
590: );
591: unset($attribute);
592: }
593:
594: if (!is_array($productIds)) {
595: $productIds = array($productIds);
596: }
597: $bind = array('attribute_id' => $this->_productAttributes[$attributeCode]['attribute_id']);
598: $select = $adapter->select();
599: $attributeTable = $this->_productAttributes[$attributeCode]['table'];
600: if ($this->_productAttributes[$attributeCode]['is_global'] || $storeId == 0) {
601: $select
602: ->from($attributeTable, array('entity_id', 'value'))
603: ->where('attribute_id = :attribute_id')
604: ->where('store_id = ?', 0)
605: ->where('entity_id IN(?)', $productIds);
606: } else {
607: $valueExpr = $adapter->getCheckSql('t2.value_id > 0', 't2.value', 't1.value');
608: $select
609: ->from(
610: array('t1' => $attributeTable),
611: array('entity_id', 'value' => $valueExpr)
612: )
613: ->joinLeft(
614: array('t2' => $attributeTable),
615: 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id=:store_id',
616: array()
617: )
618: ->where('t1.store_id = ?', 0)
619: ->where('t1.attribute_id = :attribute_id')
620: ->where('t1.entity_id IN(?)', $productIds);
621: $bind['store_id'] = $storeId;
622: }
623:
624: $rowSet = $adapter->fetchAll($select, $bind);
625:
626: $attributes = array();
627: foreach ($rowSet as $row) {
628: $attributes[$row['entity_id']] = $row['value'];
629: }
630: unset($rowSet);
631: foreach ($productIds as $productIds) {
632: if (!isset($attributes[$productIds])) {
633: $attributes[$productIds] = null;
634: }
635: }
636:
637: return $attributes;
638: }
639:
640: 641: 642: 643: 644: 645:
646: protected function _prepareCategoryParentId(Varien_Object $category)
647: {
648: if ($category->getPath() != $category->getId()) {
649: $split = explode('/', $category->getPath());
650: $category->setParentId($split[(count($split) - 2)]);
651: } else {
652: $category->setParentId(0);
653: }
654: return $this;
655: }
656:
657: 658: 659: 660: 661: 662:
663: protected function _prepareStoreRootCategories($stores)
664: {
665: $rootCategoryIds = array();
666: foreach ($stores as $store) {
667:
668: $rootCategoryIds[$store->getRootCategoryId()] = $store->getRootCategoryId();
669: }
670: if ($rootCategoryIds) {
671: $categories = $this->_getCategories($rootCategoryIds);
672: }
673: foreach ($stores as $store) {
674:
675: $rootCategoryId = $store->getRootCategoryId();
676: if (isset($categories[$rootCategoryId])) {
677: $store->setRootCategoryPath($categories[$rootCategoryId]->getPath());
678: $store->setRootCategory($categories[$rootCategoryId]);
679: } else {
680: unset($stores[$store->getId()]);
681: }
682: }
683: return $stores;
684: }
685:
686: 687: 688: 689: 690: 691: 692: 693: 694:
695: protected function _getCategories($categoryIds, $storeId = null, $path = null)
696: {
697: $isActiveAttribute = Mage::getSingleton('eav/config')
698: ->getAttribute(Mage_Catalog_Model_Category::ENTITY, 'is_active');
699: $categories = array();
700: $adapter = $this->_getReadAdapter();
701:
702: if (!is_array($categoryIds)) {
703: $categoryIds = array($categoryIds);
704: }
705: $isActiveExpr = $adapter->getCheckSql('c.value_id > 0', 'c.value', 'c.value');
706: $select = $adapter->select()
707: ->from(array('main_table' => $this->getTable('catalog/category')), array(
708: 'main_table.entity_id',
709: 'main_table.parent_id',
710: 'main_table.level',
711: 'is_active' => $isActiveExpr,
712: 'main_table.path'));
713:
714:
715: if ($path === null) {
716: $select->where('main_table.entity_id IN(?)', $categoryIds);
717: } else {
718:
719: if (substr($path, -1) != '/') {
720: $path .= '/';
721: }
722:
723: $select
724: ->where('main_table.path LIKE ?', $path . '%')
725: ->order('main_table.path');
726: }
727: $table = $this->getTable(array('catalog/category', 'int'));
728: $select->joinLeft(array('d' => $table),
729: 'd.attribute_id = :attribute_id AND d.store_id = 0 AND d.entity_id = main_table.entity_id',
730: array()
731: )
732: ->joinLeft(array('c' => $table),
733: 'c.attribute_id = :attribute_id AND c.store_id = :store_id AND c.entity_id = main_table.entity_id',
734: array()
735: );
736:
737: if ($storeId !== null) {
738: $rootCategoryPath = $this->getStores($storeId)->getRootCategoryPath();
739: $rootCategoryPathLength = strlen($rootCategoryPath);
740: }
741: $bind = array(
742: 'attribute_id' => (int)$isActiveAttribute->getId(),
743: 'store_id' => (int)$storeId
744: );
745:
746: $rowSet = $adapter->fetchAll($select, $bind);
747: foreach ($rowSet as $row) {
748: if ($storeId !== null) {
749:
750:
751: if (substr($row['path'], 0, $rootCategoryPathLength) != $rootCategoryPath) {
752: continue;
753: }
754:
755: if ((strlen($row['path']) > $rootCategoryPathLength)
756: && ($row['path'][$rootCategoryPathLength] != '/')) {
757: continue;
758: }
759: }
760:
761: $category = new Varien_Object($row);
762: $category->setIdFieldName('entity_id');
763: $category->setStoreId($storeId);
764: $this->_prepareCategoryParentId($category);
765:
766: $categories[$category->getId()] = $category;
767: }
768: unset($rowSet);
769:
770: if ($storeId !== null && $categories) {
771: foreach (array('name', 'url_key', 'url_path') as $attributeCode) {
772: $attributes = $this->_getCategoryAttribute($attributeCode, array_keys($categories),
773: $category->getStoreId());
774: foreach ($attributes as $categoryId => $attributeValue) {
775: $categories[$categoryId]->setData($attributeCode, $attributeValue);
776: }
777: }
778: }
779:
780: return $categories;
781: }
782:
783: 784: 785: 786: 787: 788: 789:
790: public function getCategory($categoryId, $storeId)
791: {
792: if (!$categoryId || !$storeId) {
793: return false;
794: }
795:
796: $categories = $this->_getCategories($categoryId, $storeId);
797: if (isset($categories[$categoryId])) {
798: return $categories[$categoryId];
799: }
800: return false;
801: }
802:
803: 804: 805: 806: 807: 808: 809:
810: public function getCategories($categoryIds, $storeId)
811: {
812: if (!$categoryIds || !$storeId) {
813: return false;
814: }
815:
816: return $this->_getCategories($categoryIds, $storeId);
817: }
818:
819: 820: 821: 822: 823: 824:
825: public function loadCategoryChilds(Varien_Object $category)
826: {
827: if ($category->getId() === null || $category->getStoreId() === null) {
828: return $category;
829: }
830:
831: $categories = $this->_getCategories(null, $category->getStoreId(), $category->getPath() . '/');
832: $category->setChilds(array());
833: foreach ($categories as $child) {
834: if (!is_array($child->getChilds())) {
835: $child->setChilds(array());
836: }
837: if ($child->getParentId() == $category->getId()) {
838: $category->setChilds($category->getChilds() + array($child->getId() => $child));
839: } else {
840: if (isset($categories[$child->getParentId()])) {
841: if (!is_array($categories[$child->getParentId()]->getChilds())) {
842: $categories[$child->getParentId()]->setChilds(array());
843: }
844: $categories[$child->getParentId()]->setChilds(
845: $categories[$child->getParentId()]->getChilds() + array($child->getId() => $child)
846: );
847: }
848: }
849: }
850: $category->setAllChilds($categories);
851:
852: return $category;
853: }
854:
855: 856: 857: 858: 859: 860: 861: 862:
863: public function getRootChildrenIds($categoryId, $categoryPath, $includeStart = true)
864: {
865: if (!isset($this->_rootChildrenIds[$categoryId])) {
866:
867: $adapter = $this->_getReadAdapter();
868: $select = $adapter->select()
869: ->from(array($this->getTable('catalog/category')), array('entity_id'))
870: ->where('path LIKE ?', $categoryPath . '/%');
871:
872: $categoryIds = array();
873: $rowSet = $adapter->fetchAll($select);
874: foreach ($rowSet as $row) {
875: $categoryIds[$row['entity_id']] = $row['entity_id'];
876: }
877: $this->_rootChildrenIds[$categoryId] = $categoryIds;
878: }
879:
880: $categoryIds = $this->_rootChildrenIds[$categoryId];
881: if ($includeStart) {
882: $categoryIds[$categoryId] = $categoryId;
883: }
884: return $categoryIds;
885: }
886:
887: 888: 889: 890: 891: 892:
893: public function getCategoryParentPath(Varien_Object $category)
894: {
895: $store = Mage::app()->getStore($category->getStoreId());
896:
897: if ($category->getId() == $store->getRootCategoryId()) {
898: return '';
899: } elseif ($category->getParentId() == 1 || $category->getParentId() == $store->getRootCategoryId()) {
900: return '';
901: }
902:
903: $parentCategory = $this->getCategory($category->getParentId(), $store->getId());
904: return $parentCategory->getUrlPath() . '/';
905: }
906:
907: 908: 909: 910: 911: 912:
913: public function getProductIdsByCategory($category)
914: {
915: if ($category instanceof Varien_Object) {
916: $categoryId = $category->getId();
917: } else {
918: $categoryId = $category;
919: }
920: $adapter = $this->_getReadAdapter();
921: $select = $adapter->select()
922: ->from($this->getTable('catalog/category_product'), array('product_id'))
923: ->where('category_id = :category_id')
924: ->order('product_id');
925: $bind = array('category_id' => $categoryId);
926:
927: return $adapter->fetchCol($select, $bind);
928: }
929:
930: 931: 932: 933: 934: 935: 936: 937: 938:
939: protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId)
940: {
941: $products = array();
942: $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
943: $adapter = $this->_getReadAdapter();
944: if ($productIds !== null) {
945: if (!is_array($productIds)) {
946: $productIds = array($productIds);
947: }
948: }
949: $bind = array(
950: 'website_id' => (int)$websiteId,
951: 'entity_id' => (int)$entityId,
952: );
953: $select = $adapter->select()
954: ->useStraightJoin(true)
955: ->from(array('e' => $this->getTable('catalog/product')), array('entity_id'))
956: ->join(
957: array('w' => $this->getTable('catalog/product_website')),
958: 'e.entity_id = w.product_id AND w.website_id = :website_id',
959: array()
960: )
961: ->where('e.entity_id > :entity_id')
962: ->order('e.entity_id')
963: ->limit($this->_productLimit);
964: if ($productIds !== null) {
965: $select->where('e.entity_id IN(?)', $productIds);
966: }
967:
968: $rowSet = $adapter->fetchAll($select, $bind);
969: foreach ($rowSet as $row) {
970: $product = new Varien_Object($row);
971: $product->setIdFieldName('entity_id');
972: $product->setCategoryIds(array());
973: $product->setStoreId($storeId);
974: $products[$product->getId()] = $product;
975: $lastEntityId = $product->getId();
976: }
977:
978: unset($rowSet);
979:
980: if ($products) {
981: $select = $adapter->select()
982: ->from(
983: $this->getTable('catalog/category_product'),
984: array('product_id', 'category_id')
985: )
986: ->where('product_id IN(?)', array_keys($products));
987: $categories = $adapter->fetchAll($select);
988: foreach ($categories as $category) {
989: $productId = $category['product_id'];
990: $categoryIds = $products[$productId]->getCategoryIds();
991: $categoryIds[] = $category['category_id'];
992: $products[$productId]->setCategoryIds($categoryIds);
993: }
994:
995: foreach (array('name', 'url_key', 'url_path') as $attributeCode) {
996: $attributes = $this->_getProductAttribute($attributeCode, array_keys($products), $storeId);
997: foreach ($attributes as $productId => $attributeValue) {
998: $products[$productId]->setData($attributeCode, $attributeValue);
999: }
1000: }
1001: }
1002:
1003: return $products;
1004: }
1005:
1006: 1007: 1008: 1009: 1010: 1011: 1012:
1013: public function getProduct($productId, $storeId)
1014: {
1015: $entityId = 0;
1016: $products = $this->_getProducts($productId, $storeId, 0, $entityId);
1017: if (isset($products[$productId])) {
1018: return $products[$productId];
1019: }
1020: return false;
1021: }
1022:
1023: 1024: 1025: 1026: 1027: 1028: 1029:
1030: public function getProductsByStore($storeId, &$lastEntityId)
1031: {
1032: return $this->_getProducts(null, $storeId, $lastEntityId, $lastEntityId);
1033: }
1034:
1035: 1036: 1037: 1038: 1039: 1040: 1041:
1042: public function getProductsByCategory(Varien_Object $category, &$lastEntityId)
1043: {
1044: $productIds = $this->getProductIdsByCategory($category);
1045: if (!$productIds) {
1046: return array();
1047: }
1048: return $this->_getProducts($productIds, $category->getStoreId(), $lastEntityId, $lastEntityId);
1049: }
1050:
1051: 1052: 1053: 1054: 1055: 1056: 1057:
1058: public function clearCategoryProduct($storeId)
1059: {
1060: $adapter = $this->_getWriteAdapter();
1061: $select = $adapter->select()
1062: ->from(array('tur' => $this->getMainTable()), $this->getIdFieldName())
1063: ->joinLeft(
1064: array('tcp' => $this->getTable('catalog/category_product')),
1065: 'tur.category_id = tcp.category_id AND tur.product_id = tcp.product_id',
1066: array()
1067: )
1068: ->where('tur.store_id = :store_id')
1069: ->where('tur.category_id IS NOT NULL')
1070: ->where('tur.product_id IS NOT NULL')
1071: ->where('tcp.category_id IS NULL');
1072: $rewriteIds = $adapter->fetchCol($select, array('store_id' => $storeId));
1073: if ($rewriteIds) {
1074: $where = array($this->getIdFieldName() . ' IN(?)' => $rewriteIds);
1075: $adapter->delete($this->getMainTable(), $where);
1076: }
1077:
1078: return $this;
1079: }
1080:
1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092:
1093: public function clearProductRewrites($productId, $storeId, $excludeCategoryIds = array())
1094: {
1095: $where = array(
1096: 'product_id = ?' => $productId,
1097: 'store_id = ?' => $storeId
1098: );
1099:
1100: if (!empty($excludeCategoryIds)) {
1101: $where['category_id NOT IN (?)'] = $excludeCategoryIds;
1102:
1103: $where[] = 'category_id IS NOT NULL';
1104: }
1105:
1106: $this->_getWriteAdapter()->delete($this->getMainTable(), $where);
1107:
1108: return $this;
1109: }
1110:
1111: 1112: 1113: 1114: 1115: 1116: 1117:
1118: public function clearStoreCategoriesInvalidRewrites($storeId)
1119: {
1120:
1121: $store = $this->getStores($storeId);
1122: $rootCategoryId = $store->getRootCategoryId();
1123: if (!$rootCategoryId) {
1124: return $this;
1125: }
1126: $categoryIds = $this->getRootChildrenIds($rootCategoryId, $store->getRootCategoryPath());
1127:
1128:
1129: $where = array(
1130: 'store_id = ?' => $storeId,
1131: 'category_id IS NOT NULL',
1132: 'category_id NOT IN (?)' => $categoryIds
1133: );
1134:
1135: $this->_getWriteAdapter()->delete($this->getMainTable(), $where);
1136:
1137: return $this;
1138: }
1139:
1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151:
1152: public function clearStoreProductsInvalidRewrites($storeId, $productId = null)
1153: {
1154: $store = $this->getStores($storeId);
1155: $adapter = $this->_getReadAdapter();
1156: $bind = array(
1157: 'website_id' => (int)$store->getWebsiteId(),
1158: 'store_id' => (int)$storeId
1159: );
1160: $select = $adapter->select()
1161: ->from(array('rewrite' => $this->getMainTable()), $this->getIdFieldName())
1162: ->joinLeft(
1163: array('website' => $this->getTable('catalog/product_website')),
1164: 'rewrite.product_id = website.product_id AND website.website_id = :website_id',
1165: array()
1166: )->where('rewrite.store_id = :store_id')
1167: ->where('rewrite.category_id IS NULL');
1168: if ($productId) {
1169: $select->where('rewrite.product_id IN (?)', $productId);
1170: } else {
1171: $select->where('rewrite.product_id IS NOT NULL');
1172: }
1173: $select->where('website.website_id IS NULL');
1174:
1175: $rewriteIds = $adapter->fetchCol($select, $bind);
1176: if ($rewriteIds) {
1177: $where = array($this->getIdFieldName() . ' IN(?)' => $rewriteIds);
1178: $this->_getWriteAdapter()->delete($this->getMainTable(), $where);
1179: }
1180:
1181: return $this;
1182: }
1183:
1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191:
1192: public function clearStoreInvalidRewrites($storeId)
1193: {
1194: $this->clearStoreCategoriesInvalidRewrites($storeId);
1195: $this->clearStoreProductsInvalidRewrites($storeId);
1196: return $this;
1197: }
1198:
1199: 1200: 1201: 1202: 1203: 1204: 1205:
1206: public function deleteCategoryProductRewrites($categoryId, $productIds)
1207: {
1208: $this->deleteCategoryProductStoreRewrites($categoryId, $productIds);
1209: return $this;
1210: }
1211:
1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219:
1220: public function deleteCategoryProductStoreRewrites($categoryId, $productIds = null, $storeId = null)
1221: {
1222:
1223:
1224:
1225: $condition = array('category_id = ?' => $categoryId);
1226: if (empty($productIds)) {
1227: $condition[] = 'product_id IS NOT NULL';
1228: } else {
1229: $condition['product_id IN (?)'] = $productIds;
1230: }
1231:
1232: if ($storeId !== null) {
1233: $condition['store_id IN(?)'] = $storeId;
1234: }
1235:
1236: $this->_getWriteAdapter()->delete($this->getMainTable(), $condition);
1237: return $this;
1238: }
1239:
1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251:
1252: public function getRewriteByProductStore(array $products)
1253: {
1254: $result = array();
1255:
1256: if (empty($products)) {
1257: return $result;
1258: }
1259: $adapter = $this->_getReadAdapter();
1260:
1261: $select = $adapter->select()
1262: ->from(
1263: array('i' => $this->getTable('catalog/category_product_index')),
1264: array('product_id', 'store_id', 'visibility')
1265: )
1266: ->joinLeft(
1267: array('r' => $this->getMainTable()),
1268: 'i.product_id = r.product_id AND i.store_id=r.store_id AND r.category_id IS NULL',
1269: array('request_path')
1270: );
1271:
1272: $bind = array();
1273: foreach ($products as $productId => $storeId) {
1274: $catId = Mage::app()->getStore($storeId)->getRootCategoryId();
1275: $productBind = 'product_id' . $productId;
1276: $storeBind = 'store_id' . $storeId;
1277: $catBind = 'category_id' . $catId;
1278: $cond = '(' . implode(' AND ', array(
1279: 'i.product_id = :' . $productBind,
1280: 'i.store_id = :' . $storeBind,
1281: 'i.category_id = :' . $catBind,
1282: )) . ')';
1283: $bind[$productBind] = $productId;
1284: $bind[$storeBind] = $storeId;
1285: $bind[$catBind] = $catId;
1286: $select->orWhere($cond);
1287: }
1288:
1289: $rowSet = $adapter->fetchAll($select, $bind);
1290: foreach ($rowSet as $row) {
1291: $result[$row['product_id']] = array(
1292: 'store_id' => $row['store_id'],
1293: 'visibility' => $row['visibility'],
1294: 'url_rewrite' => $row['request_path'],
1295: );
1296: }
1297:
1298: return $result;
1299: }
1300:
1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309:
1310: public function findFinalTargetPath($requestPath, $storeId, &$_checkedPaths = array())
1311: {
1312: if (in_array($requestPath, $_checkedPaths)) {
1313: return false;
1314: }
1315:
1316: $_checkedPaths[] = $requestPath;
1317:
1318: $select = $this->_getWriteAdapter()->select()
1319: ->from($this->getMainTable(), array('target_path', 'id_path'))
1320: ->where('store_id = ?', $storeId)
1321: ->where('request_path = ?', $requestPath);
1322:
1323: if ($row = $this->_getWriteAdapter()->fetchRow($select)) {
1324: $idPath = $this->findFinalTargetPath($row['target_path'], $storeId, $_checkedPaths);
1325: if (!$idPath) {
1326: return $row['id_path'];
1327: } else {
1328: return $idPath;
1329: }
1330: }
1331:
1332: return false;
1333: }
1334:
1335: 1336: 1337: 1338: 1339: 1340: 1341:
1342: public function deleteRewrite($requestPath, $storeId)
1343: {
1344: $this->deleteRewriteRecord($requestPath, $storeId);
1345: }
1346:
1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354:
1355: public function deleteRewriteRecord($requestPath, $storeId, $rp = false)
1356: {
1357: $conditions = array(
1358: 'store_id = ?' => $storeId,
1359: 'request_path = ?' => $requestPath,
1360: );
1361: if ($rp) {
1362: $conditions['options = ?'] = 'RP';
1363: }
1364: $this->_getWriteAdapter()->delete($this->getMainTable(), $conditions);
1365: }
1366: }
1367: