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: class Mage_Eav_Model_Config
29: {
30: const ENTITIES_CACHE_ID = 'EAV_ENTITY_TYPES';
31: const ATTRIBUTES_CACHE_ID = 'EAV_ENTITY_ATTRIBUTES';
32:
33: 34: 35: 36: 37:
38: protected $_entityData;
39:
40: 41: 42: 43: 44:
45: protected $_attributeData;
46:
47: 48: 49: 50: 51:
52: protected $_preloadedAttributes = array();
53:
54: 55: 56: 57: 58:
59: protected $_initializedAttributes = array();
60:
61: 62: 63: 64: 65:
66: protected $_attributeCodes = array();
67:
68: 69: 70: 71: 72: 73: 74:
75: protected $_objects;
76:
77: 78: 79: 80: 81: 82: 83: 84: 85: 86:
87: protected $_references;
88:
89: 90: 91: 92: 93:
94: protected $_isCacheEnabled = null;
95:
96: 97: 98: 99: 100:
101: protected $_collectionAttributes = array();
102:
103: 104: 105: 106: 107: 108:
109: public function clear()
110: {
111: $this->_entityData = null;
112: $this->_attributeData = null;
113: $this->_objects = null;
114: $this->_references = null;
115: $this->_preloadedAttributes = array();
116: $this->_initializedAttributes = array();
117: return $this;
118: }
119:
120: 121: 122: 123: 124: 125:
126: protected function _load($id)
127: {
128: return isset($this->_objects[$id]) ? $this->_objects[$id] : null;
129: }
130:
131: 132: 133: 134: 135: 136: 137:
138: protected function _save($obj, $id)
139: {
140: $this->_objects[$id] = $obj;
141: return $this;
142: }
143:
144: 145: 146: 147: 148: 149: 150:
151: protected function _addEntityTypeReference($id, $code)
152: {
153: $this->_references['entity'][$id] = $code;
154: return $this;
155: }
156:
157: 158: 159: 160: 161: 162:
163: protected function _getEntityTypeReference($id)
164: {
165: return isset($this->_references['entity'][$id]) ? $this->_references['entity'][$id] : null;
166: }
167:
168: 169: 170: 171: 172: 173: 174: 175:
176: protected function _addAttributeReference($id, $code, $entityTypeCode)
177: {
178: $this->_references['attribute'][$entityTypeCode][$id] = $code;
179: return $this;
180: }
181:
182: 183: 184: 185: 186: 187: 188:
189: protected function _getAttributeReference($id, $entityTypeCode)
190: {
191: if (isset($this->_references['attribute'][$entityTypeCode][$id])) {
192: return $this->_references['attribute'][$entityTypeCode][$id];
193: }
194: return null;
195: }
196:
197: 198: 199: 200: 201: 202:
203: protected function _getEntityKey($code)
204: {
205: return 'ENTITY/' . $code;
206: }
207:
208: 209: 210: 211: 212: 213: 214:
215: protected function _getAttributeKey($entityTypeCode, $attributeCode)
216: {
217: return 'ATTRIBUTE/' . $entityTypeCode . '/' . $attributeCode;
218: }
219:
220: 221: 222: 223: 224:
225: protected function _isCacheEnabled()
226: {
227: if ($this->_isCacheEnabled === null) {
228: $this->_isCacheEnabled = Mage::app()->useCache('eav');
229: }
230: return $this->_isCacheEnabled;
231: }
232:
233: 234: 235: 236: 237:
238: protected function _initEntityTypes()
239: {
240: if (is_array($this->_entityData)) {
241: return $this;
242: }
243: Varien_Profiler::start('EAV: '.__METHOD__);
244:
245: 246: 247:
248: if ($this->_isCacheEnabled()
249: && ($cache = Mage::app()->loadCache(self::ENTITIES_CACHE_ID))) {
250:
251: $this->_entityData = unserialize($cache);
252: foreach ($this->_entityData as $typeCode => $data) {
253: $typeId = $data['entity_type_id'];
254: $this->_addEntityTypeReference($typeId, $typeCode);
255: }
256: Varien_Profiler::stop('EAV: '.__METHOD__);
257: return $this;
258: }
259:
260: $entityTypesData = Mage::getModel('eav/entity_type')->getCollection()->getData();
261: $types = array();
262:
263: 264: 265:
266: foreach ($entityTypesData as $typeData) {
267: if (!isset($typeData['attribute_model'])) {
268: $typeData['attribute_model'] = 'eav/entity_attribute';
269: }
270:
271: $typeCode = $typeData['entity_type_code'];
272: $typeId = $typeData['entity_type_id'];
273:
274: $this->_addEntityTypeReference($typeId, $typeCode);
275: $types[$typeCode] = $typeData;
276: }
277:
278: $this->_entityData = $types;
279:
280: if ($this->_isCacheEnabled()) {
281: Mage::app()->saveCache(serialize($this->_entityData), self::ENTITIES_CACHE_ID,
282: array('eav', Mage_Eav_Model_Entity_Attribute::CACHE_TAG)
283: );
284: }
285: Varien_Profiler::stop('EAV: '.__METHOD__);
286: return $this;
287: }
288:
289: 290: 291: 292: 293: 294:
295: public function getEntityType($code)
296: {
297: if ($code instanceof Mage_Eav_Model_Entity_Type) {
298: return $code;
299: }
300: Varien_Profiler::start('EAV: '.__METHOD__);
301:
302: if (is_numeric($code)) {
303: $entityCode = $this->_getEntityTypeReference($code);
304: if ($entityCode !== null) {
305: $code = $entityCode;
306: }
307: }
308:
309: $entityKey = $this->_getEntityKey($code);
310: $entityType = $this->_load($entityKey);
311: if ($entityType) {
312: Varien_Profiler::stop('EAV: '.__METHOD__);
313: return $entityType;
314: }
315:
316:
317: $entityType = Mage::getModel('eav/entity_type');
318: if (isset($this->_entityData[$code])) {
319: $entityType->setData($this->_entityData[$code]);
320: } else {
321: if (is_numeric($code)) {
322: $entityType->load($code);
323: } else {
324: $entityType->loadByCode($code);
325: }
326:
327: if (!$entityType->getId()) {
328: Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code));
329: }
330: }
331: $this->_addEntityTypeReference($entityType->getId(), $entityType->getEntityTypeCode());
332: $this->_save($entityType, $entityKey);
333:
334: Varien_Profiler::stop('EAV: '.__METHOD__);
335: return $entityType;
336: }
337:
338: 339: 340: 341: 342: 343:
344: protected function _initAttributes($entityType)
345: {
346: $entityType = $this->getEntityType($entityType);
347: $entityTypeCode = $entityType->getEntityTypeCode();
348:
349: if (isset($this->_initializedAttributes[$entityTypeCode])) {
350: return $this;
351: }
352: Varien_Profiler::start('EAV: '.__METHOD__);
353:
354: $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection())
355: ->setEntityTypeFilter($entityType)
356: ->getData();
357:
358: $codes = array();
359: foreach ($attributesInfo as $attribute) {
360: $this->_createAttribute($entityType, $attribute);
361: $codes[] = $attribute['attribute_code'];
362: }
363:
364: $entityType->setAttributeCodes($codes);
365: $this->_initializedAttributes[$entityTypeCode] = true;
366:
367: Varien_Profiler::stop('EAV: '.__METHOD__);
368: return $this;
369: }
370:
371: 372: 373: 374: 375: 376: 377:
378: public function getAttribute($entityType, $code)
379: {
380: if ($code instanceof Mage_Eav_Model_Entity_Attribute_Interface) {
381: return $code;
382: }
383:
384: Varien_Profiler::start('EAV: '.__METHOD__);
385:
386: $entityTypeCode = $this->getEntityType($entityType)->getEntityTypeCode();
387: $entityType = $this->getEntityType($entityType);
388:
389: 390: 391:
392: if (is_numeric($code)) {
393: $attributeCode = $this->_getAttributeReference($code, $entityTypeCode);
394: if ($attributeCode) {
395: $code = $attributeCode;
396: }
397: }
398: $attributeKey = $this->_getAttributeKey($entityTypeCode, $code);
399:
400: 401: 402:
403: $attribute = $this->_load($attributeKey);
404: if ($attribute) {
405: Varien_Profiler::stop('EAV: '.__METHOD__);
406: return $attribute;
407: }
408:
409: if (isset($this->_attributeData[$entityTypeCode][$code])) {
410: $data = $this->_attributeData[$entityTypeCode][$code];
411: unset($this->_attributeData[$entityTypeCode][$code]);
412: $attribute = Mage::getModel($data['attribute_model'], $data);
413: } else {
414: if (is_numeric($code)) {
415: $attribute = Mage::getModel($entityType->getAttributeModel())->load($code);
416: if ($attribute->getEntityTypeId() != $entityType->getId()) {
417: return false;
418: }
419: $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute->getAttributeCode());
420: } else {
421: $attribute = Mage::getModel($entityType->getAttributeModel())
422: ->loadByCode($entityType, $code)
423: ->setAttributeCode($code);
424: }
425: }
426:
427: if ($attribute) {
428: $entity = $entityType->getEntity();
429: if ($entity && in_array($attribute->getAttributeCode(), $entity->getDefaultAttributes())) {
430: $attribute->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC)
431: ->setIsGlobal(1);
432: }
433: $attribute->setEntityType($entityType)
434: ->setEntityTypeId($entityType->getId());
435: $this->_addAttributeReference($attribute->getId(), $attribute->getAttributeCode(), $entityTypeCode);
436: $this->_save($attribute, $attributeKey);
437: }
438: Varien_Profiler::stop('EAV: '.__METHOD__);
439:
440: return $attribute;
441: }
442:
443: 444: 445: 446: 447: 448: 449:
450: public function getEntityAttributeCodes($entityType, $object = null)
451: {
452: $entityType = $this->getEntityType($entityType);
453: $attributeSetId = 0;
454: if (($object instanceof Varien_Object) && $object->getAttributeSetId()) {
455: $attributeSetId = $object->getAttributeSetId();
456: }
457: $storeId = 0;
458: if (($object instanceof Varien_Object) && $object->getStoreId()) {
459: $storeId = $object->getStoreId();
460: }
461: $cacheKey = sprintf('%d-%d', $entityType->getId(), $attributeSetId);
462: if (isset($this->_attributeCodes[$cacheKey])) {
463: return $this->_attributeCodes[$cacheKey];
464: }
465:
466: if ($attributeSetId) {
467: $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection())
468: ->setEntityTypeFilter($entityType)
469: ->setAttributeSetFilter($attributeSetId)
470: ->addStoreLabel($storeId)
471: ->getData();
472: $attributes = array();
473: foreach ($attributesInfo as $attributeData) {
474: $attributes[] = $attributeData['attribute_code'];
475: $this->_createAttribute($entityType, $attributeData);
476: }
477: } else {
478: $this->_initAttributes($entityType);
479: $attributes = $this->getEntityType($entityType)->getAttributeCodes();
480: }
481:
482: $this->_attributeCodes[$cacheKey] = $attributes;
483:
484: return $attributes;
485: }
486:
487: 488: 489: 490: 491: 492: 493:
494: public function preloadAttributes($entityType, $attributes)
495: {
496: if (is_string($attributes)) {
497: $attributes = array($attributes);
498: }
499:
500: $entityType = $this->getEntityType($entityType);
501: $entityTypeCode = $entityType->getEntityTypeCode();
502:
503: if (!isset($this->_preloadedAttributes[$entityTypeCode])) {
504: $this->_preloadedAttributes[$entityTypeCode] = $attributes;
505: } else {
506: $attributes = array_diff($attributes, $this->_preloadedAttributes[$entityTypeCode]);
507: $this->_preloadedAttributes[$entityTypeCode] = array_merge($this->_preloadedAttributes[$entityTypeCode],
508: $attributes
509: );
510: }
511:
512: if (empty($attributes)) {
513: return $this;
514: }
515: Varien_Profiler::start('EAV: '.__METHOD__ . ':'.$entityTypeCode);
516:
517: $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection())
518: ->setEntityTypeFilter($entityType)
519: ->setCodeFilter($attributes)
520: ->getData();
521:
522: if (!$attributesInfo) {
523: Varien_Profiler::stop('EAV: '.__METHOD__ . ':'.$entityTypeCode);
524: return $this;
525: }
526:
527: $attributesData = $codes = array();
528:
529: foreach ($attributesInfo as $attribute) {
530: if (empty($attribute['attribute_model'])) {
531: $attribute['attribute_model'] = $entityType->getAttributeModel();
532: }
533:
534: $attributeCode = $attribute['attribute_code'];
535: $attributeId = $attribute['attribute_id'];
536:
537: $this->_addAttributeReference($attributeId, $attributeCode, $entityTypeCode);
538: $attributesData[$attributeCode] = $attribute;
539: $codes[] = $attributeCode;
540: }
541:
542: $this->_attributeData[$entityTypeCode] = $attributesData;
543:
544: Varien_Profiler::stop('EAV: '.__METHOD__ . ':'.$entityTypeCode);
545:
546: return $this;
547: }
548:
549: 550: 551: 552: 553: 554: 555:
556: public function getCollectionAttribute($entityType, $attribute)
557: {
558: $entityType = $this->getEntityType($entityType);
559: $entityTypeCode = $entityType->getEntityTypeCode();
560:
561: if (is_numeric($attribute)) {
562: $attribute = $this->_getAttributeReference($attribute, $entityTypeCode);
563: if (!$attribute) {
564: return null;
565: }
566: }
567:
568: $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute);
569: $attributeObject = $this->_load($attributeKey);
570: if ($attributeObject) {
571: return $attributeObject;
572: }
573:
574: return $this->getAttribute($entityType, $attribute);
575: }
576:
577: 578: 579: 580: 581: 582: 583:
584: public function loadCollectionAttributes($entityType, $attributes)
585: {
586: $entityType = $this->getEntityType($entityType);
587: $entityTypeCode = $entityType->getEntityTypeCode();
588:
589: if (!isset($this->_collectionAttributes[$entityTypeCode])) {
590: $this->_collectionAttributes[$entityTypeCode] = array();
591: }
592: $loadedAttributes = array_keys($this->_collectionAttributes[$entityTypeCode]);
593: $attributes = array_diff($attributes, $loadedAttributes);
594:
595: foreach ($attributes as $k => $attribute) {
596: if (is_numeric($attribute)) {
597: $attribute = $this->_getAttributeReference($attribute, $entityTypeCode);
598: }
599: $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute);
600: if ($this->_load($attributeKey)) {
601: unset($attributes[$k]);
602: }
603: }
604:
605: if (empty($attributes)) {
606: return $this;
607: }
608: $attributeCollection = $entityType->getEntityAttributeCollection();
609: $attributesInfo = Mage::getResourceModel($attributeCollection)
610: ->useLoadDataFields()
611: ->setEntityTypeFilter($entityType)
612: ->setCodeFilter($attributes)
613: ->getData();
614:
615: foreach ($attributesInfo as $attributeData) {
616: $attribute = $this->_createAttribute($entityType, $attributeData);
617: $this->_collectionAttributes[$entityTypeCode][$attribute->getAttributeCode()] =$attribute;
618: }
619:
620: return $this;
621: }
622:
623: 624: 625: 626: 627: 628: 629:
630: protected function _createAttribute($entityType, $attributeData)
631: {
632: $entityType = $this->getEntityType($entityType);
633: $entityTypeCode = $entityType->getEntityTypeCode();
634:
635: $attributeKey = $this->_getAttributeKey($entityTypeCode, $attributeData['attribute_code']);
636: $attribute = $this->_load($attributeKey);
637: if ($attribute) {
638: $existsFullAttribute = $attribute->hasIsRequired();
639: $fullAttributeData = array_key_exists('is_required', $attributeData);
640:
641: if ($existsFullAttribute || (!$existsFullAttribute && !$fullAttributeData)) {
642: return $attribute;
643: }
644: }
645:
646: if (!empty($attributeData['attribute_model'])) {
647: $model = $attributeData['attribute_model'];
648: } else {
649: $model = $entityType->getAttributeModel();
650: }
651: $attribute = Mage::getModel($model)->setData($attributeData);
652: $this->_addAttributeReference(
653: $attributeData['attribute_id'],
654: $attributeData['attribute_code'],
655: $entityTypeCode
656: );
657: $attributeKey = $this->_getAttributeKey($entityTypeCode, $attributeData['attribute_code']);
658: $this->_save($attribute, $attributeKey);
659:
660: return $attribute;
661: }
662:
663: 664: 665: 666: 667: 668:
669: protected function _validateAttributeData($attributeData = null)
670: {
671: if (!is_array($attributeData)) {
672: return false;
673: }
674: $requiredKeys = array(
675: 'attribute_id',
676: 'attribute_code',
677: 'entity_type_id',
678: 'attribute_model'
679: );
680: foreach ($requiredKeys as $key) {
681: if (!array_key_exists($key, $attributeData)) {
682: return false;
683: }
684: }
685:
686: return true;
687: }
688:
689: 690: 691: 692: 693: 694: 695:
696: public function importAttributesData($entityType, array $attributes)
697: {
698: $entityType = $this->getEntityType($entityType);
699: foreach ($attributes as $attributeData) {
700: if (!$this->_validateAttributeData($attributeData)) {
701: continue;
702: }
703: $this->_createAttribute($entityType, $attributeData);
704: }
705:
706: return $this;
707: }
708: }
709: