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: abstract class Mage_Catalog_Model_Resource_Abstract extends Mage_Eav_Model_Entity_Abstract
36: {
37: 38: 39: 40: 41:
42: protected $_attributes = array();
43:
44: 45: 46: 47: 48:
49: protected function _getDefaultAttributeModel()
50: {
51: return 'catalog/resource_eav_attribute';
52: }
53:
54: 55: 56: 57: 58:
59: public function getDefaultStoreId()
60: {
61: return Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID;
62: }
63:
64: 65: 66: 67: 68: 69: 70:
71: protected function _isApplicableAttribute($object, $attribute)
72: {
73: $applyTo = $attribute->getApplyTo();
74: return count($applyTo) == 0 || in_array($object->getTypeId(), $applyTo);
75: }
76:
77: 78: 79: 80: 81: 82: 83: 84:
85: protected function _isCallableAttributeInstance($instance, $method, $args)
86: {
87: if ($instance instanceof Mage_Eav_Model_Entity_Attribute_Backend_Abstract
88: && ($method == 'beforeSave' || $method = 'afterSave')
89: ) {
90: $attributeCode = $instance->getAttribute()->getAttributeCode();
91: if (isset($args[0]) && $args[0] instanceof Varien_Object && $args[0]->getData($attributeCode) === false) {
92: return false;
93: }
94: }
95:
96: return parent::_isCallableAttributeInstance($instance, $method, $args);
97: }
98:
99:
100:
101: 102: 103: 104: 105: 106: 107: 108:
109: protected function _getLoadAttributesSelect($object, $table)
110: {
111: 112: 113: 114: 115:
116: if (Mage::app()->isSingleStoreMode()) {
117: $storeId = (int)Mage::app()->getStore(true)->getId();
118: } else {
119: $storeId = (int)$object->getStoreId();
120: }
121:
122: $setId = $object->getAttributeSetId();
123: $storeIds = array($this->getDefaultStoreId());
124: if ($storeId != $this->getDefaultStoreId()) {
125: $storeIds[] = $storeId;
126: }
127:
128: $select = $this->_getReadAdapter()->select()
129: ->from(array('attr_table' => $table), array())
130: ->where("attr_table.{$this->getEntityIdField()} = ?", $object->getId())
131: ->where('attr_table.store_id IN (?)', $storeIds);
132: if ($setId) {
133: $select->join(
134: array('set_table' => $this->getTable('eav/entity_attribute')),
135: $this->_getReadAdapter()->quoteInto('attr_table.attribute_id = set_table.attribute_id' .
136: ' AND set_table.attribute_set_id = ?', $setId),
137: array()
138: );
139: }
140: return $select;
141: }
142:
143: 144: 145: 146: 147: 148: 149: 150:
151: protected function _addLoadAttributesSelectFields($select, $table, $type)
152: {
153: $select->columns(
154: Mage::getResourceHelper('catalog')->attributeSelectFields('attr_table', $type)
155: );
156: return $select;
157: }
158:
159: 160: 161: 162: 163: 164:
165: protected function _prepareLoadSelect(array $selects)
166: {
167: $select = parent::_prepareLoadSelect($selects);
168: $select->order('store_id');
169: return $select;
170: }
171:
172: 173: 174: 175: 176: 177: 178:
179: protected function _setAttributeValue($object, $valueRow)
180: {
181: $attribute = $this->getAttribute($valueRow['attribute_id']);
182: if ($attribute) {
183: $attributeCode = $attribute->getAttributeCode();
184: $isDefaultStore = $valueRow['store_id'] == $this->getDefaultStoreId();
185: if (isset($this->_attributes[$valueRow['attribute_id']])) {
186: if ($isDefaultStore) {
187: $object->setAttributeDefaultValue($attributeCode, $valueRow['value']);
188: } else {
189: $object->setAttributeDefaultValue(
190: $attributeCode,
191: $this->_attributes[$valueRow['attribute_id']]['value']
192: );
193: }
194: } else {
195: $this->_attributes[$valueRow['attribute_id']] = $valueRow;
196: }
197:
198: $value = $valueRow['value'];
199: $valueId = $valueRow['value_id'];
200:
201: $object->setData($attributeCode, $value);
202: if (!$isDefaultStore) {
203: $object->setExistsStoreValueFlag($attributeCode);
204: }
205: $attribute->getBackend()->setEntityValueId($object, $valueId);
206: }
207:
208: return $this;
209: }
210:
211: 212: 213: 214: 215: 216: 217: 218:
219: protected function _saveAttributeValue($object, $attribute, $value)
220: {
221: $write = $this->_getWriteAdapter();
222: $storeId = (int)Mage::app()->getStore($object->getStoreId())->getId();
223: $table = $attribute->getBackend()->getTable();
224:
225: 226: 227: 228: 229:
230: if (Mage::app()->isSingleStoreMode()) {
231: $storeId = $this->getDefaultStoreId();
232: $write->delete($table, array(
233: 'attribute_id = ?' => $attribute->getAttributeId(),
234: 'entity_id = ?' => $object->getEntityId(),
235: 'store_id <> ?' => $storeId
236: ));
237: }
238:
239: $data = new Varien_Object(array(
240: 'entity_type_id' => $attribute->getEntityTypeId(),
241: 'attribute_id' => $attribute->getAttributeId(),
242: 'store_id' => $storeId,
243: 'entity_id' => $object->getEntityId(),
244: 'value' => $this->_prepareValueForSave($value, $attribute)
245: ));
246: $bind = $this->_prepareDataForTable($data, $table);
247:
248: if ($attribute->isScopeStore()) {
249: 250: 251:
252: $this->_attributeValuesToSave[$table][] = $bind;
253: } else if ($attribute->isScopeWebsite() && $storeId != $this->getDefaultStoreId()) {
254: 255: 256:
257: $storeIds = Mage::app()->getStore($storeId)->getWebsite()->getStoreIds(true);
258: foreach ($storeIds as $storeId) {
259: $bind['store_id'] = (int)$storeId;
260: $this->_attributeValuesToSave[$table][] = $bind;
261: }
262: } else {
263: 264: 265:
266: $bind['store_id'] = $this->getDefaultStoreId();
267: $this->_attributeValuesToSave[$table][] = $bind;
268: }
269:
270: return $this;
271: }
272:
273: 274: 275: 276: 277: 278: 279: 280:
281: protected function _insertAttribute($object, $attribute, $value)
282: {
283: 284: 285:
286: $storeId = (int)Mage::app()->getStore($object->getStoreId())->getId();
287: if ($attribute->getIsRequired() && $this->getDefaultStoreId() != $storeId) {
288: $table = $attribute->getBackend()->getTable();
289:
290: $select = $this->_getReadAdapter()->select()
291: ->from($table)
292: ->where('entity_type_id = ?', $attribute->getEntityTypeId())
293: ->where('attribute_id = ?', $attribute->getAttributeId())
294: ->where('store_id = ?', $this->getDefaultStoreId())
295: ->where('entity_id = ?', $object->getEntityId());
296: $row = $this->_getReadAdapter()->fetchOne($select);
297:
298: if (!$row) {
299: $data = new Varien_Object(array(
300: 'entity_type_id' => $attribute->getEntityTypeId(),
301: 'attribute_id' => $attribute->getAttributeId(),
302: 'store_id' => $this->getDefaultStoreId(),
303: 'entity_id' => $object->getEntityId(),
304: 'value' => $this->_prepareValueForSave($value, $attribute)
305: ));
306: $bind = $this->_prepareDataForTable($data, $table);
307: $this->_getWriteAdapter()->insertOnDuplicate($table, $bind, array('value'));
308: }
309: }
310:
311: return $this->_saveAttributeValue($object, $attribute, $value);
312: }
313:
314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325:
326: protected function _updateAttribute($object, $attribute, $valueId, $value)
327: {
328: return $this->_saveAttributeValue($object, $attribute, $value);
329: }
330:
331: 332: 333: 334: 335: 336: 337: 338: 339:
340: protected function _updateAttributeForStore($object, $attribute, $value, $storeId)
341: {
342: $adapter = $this->_getWriteAdapter();
343: $table = $attribute->getBackend()->getTable();
344: $entityIdField = $attribute->getBackend()->getEntityIdField();
345: $select = $adapter->select()
346: ->from($table, 'value_id')
347: ->where('entity_type_id = :entity_type_id')
348: ->where("$entityIdField = :entity_field_id")
349: ->where('store_id = :store_id')
350: ->where('attribute_id = :attribute_id');
351: $bind = array(
352: 'entity_type_id' => $object->getEntityTypeId(),
353: 'entity_field_id' => $object->getId(),
354: 'store_id' => $storeId,
355: 'attribute_id' => $attribute->getId()
356: );
357: $valueId = $adapter->fetchOne($select, $bind);
358: 359: 360:
361: if ($valueId) {
362: $bind = array('value' => $this->_prepareValueForSave($value, $attribute));
363: $where = array('value_id = ?' => (int)$valueId);
364:
365: $adapter->update($table, $bind, $where);
366: } else {
367: $bind = array(
368: $idField => (int)$object->getId(),
369: 'entity_type_id' => (int)$object->getEntityTypeId(),
370: 'attribute_id' => (int)$attribute->getId(),
371: 'value' => $this->_prepareValueForSave($value, $attribute),
372: 'store_id' => (int)$storeId
373: );
374:
375: $adapter->insert($table, $bind);
376: }
377:
378: return $this;
379: }
380:
381: 382: 383: 384: 385: 386: 387: 388:
389: protected function _deleteAttributes($object, $table, $info)
390: {
391: $adapter = $this->_getWriteAdapter();
392: $entityIdField = $this->getEntityIdField();
393: $globalValues = array();
394: $websiteAttributes = array();
395: $storeAttributes = array();
396:
397: 398: 399:
400: foreach ($info as $itemData) {
401: $attribute = $this->getAttribute($itemData['attribute_id']);
402: if ($attribute->isScopeStore()) {
403: $storeAttributes[] = (int)$itemData['attribute_id'];
404: } elseif ($attribute->isScopeWebsite()) {
405: $websiteAttributes[] = (int)$itemData['attribute_id'];
406: } else {
407: $globalValues[] = (int)$itemData['value_id'];
408: }
409: }
410:
411: 412: 413:
414: if (!empty($globalValues)) {
415: $adapter->delete($table, array('value_id IN (?)' => $globalValues));
416: }
417:
418: $condition = array(
419: $entityIdField . ' = ?' => $object->getId(),
420: 'entity_type_id = ?' => $object->getEntityTypeId()
421: );
422:
423: 424: 425:
426: if (!empty($websiteAttributes)) {
427: $storeIds = $object->getWebsiteStoreIds();
428: if (!empty($storeIds)) {
429: $delCondition = $condition;
430: $delCondition['attribute_id IN(?)'] = $websiteAttributes;
431: $delCondition['store_id IN(?)'] = $storeIds;
432:
433: $adapter->delete($table, $delCondition);
434: }
435: }
436:
437: 438: 439:
440: if (!empty($storeAttributes)) {
441: $delCondition = $condition;
442: $delCondition['attribute_id IN(?)'] = $storeAttributes;
443: $delCondition['store_id = ?'] = (int)$object->getStoreId();
444:
445: $adapter->delete($table, $delCondition);
446: }
447:
448: return $this;
449: }
450:
451: 452: 453: 454: 455: 456:
457: protected function _getOrigObject($object)
458: {
459: $className = get_class($object);
460: $origObject = new $className();
461: $origObject->setData(array());
462: $origObject->setStoreId($object->getStoreId());
463: $this->load($origObject, $object->getData($this->getEntityIdField()));
464:
465: return $origObject;
466: }
467:
468: 469: 470: 471: 472: 473: 474: 475:
476: protected function _collectOrigData($object)
477: {
478: $this->loadAllAttributes($object);
479:
480: if ($this->getUseDataSharing()) {
481: $storeId = $object->getStoreId();
482: } else {
483: $storeId = $this->getStoreId();
484: }
485:
486: $data = array();
487: foreach ($this->getAttributesByTable() as $table=>$attributes) {
488: $select = $this->_getReadAdapter()->select()
489: ->from($table)
490: ->where($this->getEntityIdField() . '=?', $object->getId());
491:
492: $where = $this->_getReadAdapter()->quoteInto('store_id=?', $storeId);
493:
494: $globalAttributeIds = array();
495: foreach ($attributes as $attr) {
496: if ($attr->getIsGlobal()) {
497: $globalAttributeIds[] = $attr->getId();
498: }
499: }
500: if (!empty($globalAttributeIds)) {
501: $where .= ' or '.$this->_getReadAdapter()->quoteInto('attribute_id in (?)', $globalAttributeIds);
502: }
503: $select->where($where);
504:
505: $values = $this->_getReadAdapter()->fetchAll($select);
506:
507: if (empty($values)) {
508: continue;
509: }
510:
511: foreach ($values as $row) {
512: $data[$this->getAttribute($row['attribute_id'])->getName()][$row['store_id']] = $row;
513: }
514: }
515: return $data;
516: }
517:
518: 519: 520: 521: 522: 523: 524:
525: protected function _isAttributeValueEmpty(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $value)
526: {
527: return $value === false;
528: }
529:
530: 531: 532: 533: 534: 535: 536: 537: 538: 539:
540: protected function _canUpdateAttribute(
541: Mage_Eav_Model_Entity_Attribute_Abstract $attribute,
542: $value,
543: array &$origData)
544: {
545: $result = parent::_canUpdateAttribute($attribute, $value, $origData);
546: if ($result &&
547: ($attribute->isScopeStore() || $attribute->isScopeWebsite()) &&
548: !$this->_isAttributeValueEmpty($attribute, $value) &&
549: $value == $origData[$attribute->getAttributeCode()] &&
550: isset($origData['store_id']) && $origData['store_id'] != $this->getDefaultStoreId()
551: ) {
552: return false;
553: }
554:
555: return $result;
556: }
557:
558: 559: 560: 561: 562: 563: 564:
565: protected function _prepareValueForSave($value, Mage_Eav_Model_Entity_Attribute_Abstract $attribute)
566: {
567: $type = $attribute->getBackendType();
568: if (($type == 'int' || $type == 'decimal' || $type == 'datetime') && $value === '') {
569: $value = null;
570: }
571:
572: return parent::_prepareValueForSave($value, $attribute);
573: }
574:
575: 576: 577: 578: 579: 580: 581: 582:
583: public function getAttributeRawValue($entityId, $attribute, $store)
584: {
585: if (!$entityId || empty($attribute)) {
586: return false;
587: }
588: if (!is_array($attribute)) {
589: $attribute = array($attribute);
590: }
591:
592: $attributesData = array();
593: $staticAttributes = array();
594: $typedAttributes = array();
595: $staticTable = null;
596: $adapter = $this->_getReadAdapter();
597:
598: foreach ($attribute as $_attribute) {
599:
600: $_attribute = $this->getAttribute($_attribute);
601: if (!$_attribute) {
602: continue;
603: }
604: $attributeCode = $_attribute->getAttributeCode();
605: $attrTable = $_attribute->getBackend()->getTable();
606: $isStatic = $_attribute->getBackend()->isStatic();
607:
608: if ($isStatic) {
609: $staticAttributes[] = $attributeCode;
610: $staticTable = $attrTable;
611: } else {
612: 613: 614:
615: $typedAttributes[$attrTable][$_attribute->getId()] = $attributeCode;
616: }
617: }
618:
619: 620: 621:
622: if ($staticAttributes) {
623: $select = $adapter->select()->from($staticTable, $staticAttributes)
624: ->where($this->getEntityIdField() . ' = :entity_id');
625: $attributesData = $adapter->fetchRow($select, array('entity_id' => $entityId));
626: }
627:
628: 629: 630:
631: if ($store instanceof Mage_Core_Model_Store) {
632: $store = $store->getId();
633: }
634:
635: $store = (int)$store;
636: if ($typedAttributes) {
637: foreach ($typedAttributes as $table => $_attributes) {
638: $select = $adapter->select()
639: ->from(array('default_value' => $table), array('attribute_id'))
640: ->where('default_value.attribute_id IN (?)', array_keys($_attributes))
641: ->where('default_value.entity_type_id = :entity_type_id')
642: ->where('default_value.entity_id = :entity_id')
643: ->where('default_value.store_id = ?', 0);
644: $bind = array(
645: 'entity_type_id' => $this->getTypeId(),
646: 'entity_id' => $entityId,
647: );
648:
649: if ($store != $this->getDefaultStoreId()) {
650: $valueExpr = $adapter->getCheckSql('store_value.value IS NULL',
651: 'default_value.value', 'store_value.value');
652: $joinCondition = array(
653: $adapter->quoteInto('store_value.attribute_id IN (?)', array_keys($_attributes)),
654: 'store_value.entity_type_id = :entity_type_id',
655: 'store_value.entity_id = :entity_id',
656: 'store_value.store_id = :store_id',
657: );
658:
659: $select->joinLeft(
660: array('store_value' => $table),
661: implode(' AND ', $joinCondition),
662: array('attr_value' => $valueExpr)
663: );
664:
665: $bind['store_id'] = $store;
666:
667: } else {
668: $select->columns(array('attr_value' => 'value'), 'default_value');
669: }
670:
671: $result = $adapter->fetchPairs($select, $bind);
672: foreach ($result as $attrId => $value) {
673: $attrCode = $typedAttributes[$table][$attrId];
674: $attributesData[$attrCode] = $value;
675: }
676: }
677: }
678:
679: if (sizeof($attributesData) == 1) {
680: $_data = each($attributesData);
681: $attributesData = $_data[1];
682: }
683:
684: return $attributesData ? $attributesData : false;
685: }
686:
687: 688: 689: 690: 691: 692: 693: 694:
695: public function load($object, $entityId, $attributes = array())
696: {
697: $this->_attributes = array();
698: return parent::load($object, $entityId, $attributes);
699: }
700: }
701: