From becc5a10808b889cc0c7e2dfb32c08229e844c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Niederges=C3=A4=C3=9F?= Date: Fri, 21 Sep 2018 11:30:12 +0200 Subject: [PATCH] implemented EAV Cache --- app/code/core/Mage/Catalog/Helper/Data.php | 3 +- app/code/core/Mage/Catalog/Model/Config.php | 4 +- app/code/core/Mage/Catalog/Model/Layer.php | 25 +- .../Product/Attribute/Backend/Media.php | 3 +- .../Model/Indexer/Minimalprice.php | 4 +- .../Product/Edit/Tab/Downloadable/Links.php | 3 +- app/code/core/Mage/Eav/Model/Config.php | 658 ++++++++++-------- .../core/Mage/Eav/Model/Entity/Abstract.php | 14 + .../core/Mage/Eav/Model/Entity/Attribute.php | 2 +- app/code/core/Mage/Tax/Helper/Data.php | 3 +- 10 files changed, 413 insertions(+), 306 deletions(-) diff --git a/app/code/core/Mage/Catalog/Helper/Data.php b/app/code/core/Mage/Catalog/Helper/Data.php index 0d65dd75791..2a971cbc226 100644 --- a/app/code/core/Mage/Catalog/Helper/Data.php +++ b/app/code/core/Mage/Catalog/Helper/Data.php @@ -422,8 +422,7 @@ public function canApplyMsrpToProductType($product) { if($this->_mapApplyToProductType === null) { /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - $attribute = Mage::getModel('catalog/resource_eav_attribute') - ->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'msrp_enabled'); + $attribute = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY,'msrp_enabled'); $this->_mapApplyToProductType = $attribute->getApplyTo(); } return empty($this->_mapApplyToProductType) || in_array($product->getTypeId(), $this->_mapApplyToProductType); diff --git a/app/code/core/Mage/Catalog/Model/Config.php b/app/code/core/Mage/Catalog/Model/Config.php index 1850b22f4fa..ea184d24895 100644 --- a/app/code/core/Mage/Catalog/Model/Config.php +++ b/app/code/core/Mage/Catalog/Model/Config.php @@ -256,8 +256,8 @@ public function getSourceOptionId($source, $value) */ public function getProductAttributes() { - if (is_null($this->_productAttributes)) { - $this->_productAttributes = array_keys($this->getAttributesUsedInProductListing()); + if (null === $this->_usedInProductListing) { + $this->_usedInProductListing = Mage::getSingleton('eav/config')->getAttributesUsedInProductListing(); } return $this->_productAttributes; } diff --git a/app/code/core/Mage/Catalog/Model/Layer.php b/app/code/core/Mage/Catalog/Model/Layer.php index ea4fa1d3d89..bb5bc8ffc98 100644 --- a/app/code/core/Mage/Catalog/Model/Layer.php +++ b/app/code/core/Mage/Catalog/Model/Layer.php @@ -214,24 +214,19 @@ public function getCurrentStore() */ public function getFilterableAttributes() { -// $entity = Mage::getSingleton('eav/config') -// ->getEntityType('catalog_product'); - $setIds = $this->_getSetIds(); - if (!$setIds) { + if (false === is_array($setIds) || count($setIds) === 0) { return array(); } - /** @var $collection Mage_Catalog_Model_Resource_Product_Attribute_Collection */ - $collection = Mage::getResourceModel('catalog/product_attribute_collection'); - $collection - ->setItemObjectClass('catalog/resource_eav_attribute') - ->setAttributeSetFilter($setIds) - ->addStoreLabel(Mage::app()->getStore()->getId()) - ->setOrder('position', 'ASC'); - $collection = $this->_prepareAttributeCollection($collection); - $collection->load(); - - return $collection; + /** @var Mage_Eav_Model_Config $eavConfig */ + $attributes = Mage::getSingleton('eav/config')->getFilterableProductAttributesUsedInSets($setIds); + usort($attributes, function ($attributeA, $attributeB){ + if ((int)$attributeA->getPosition() == (int)$attributeB->getPosition()) { + return 0; + } + return ((int)$attributeA->getPosition() < (int)$attributeB->getPosition()) ? -1 : 1; + }); + return $attributes; } /** diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Attribute/Backend/Media.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Attribute/Backend/Media.php index 02724f9a0ae..5534b96a879 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Product/Attribute/Backend/Media.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Attribute/Backend/Media.php @@ -270,8 +270,7 @@ protected function _getLoadGallerySelect(array $productIds, $storeId, $attribute */ protected function _getAttributeId() { if(is_null($this->_attributeId)) { - $attribute = Mage::getModel('eav/entity_attribute') - ->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'media_gallery'); + $attribute = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'media_gallery'); $this->_attributeId = $attribute->getId(); } diff --git a/app/code/core/Mage/CatalogIndex/Model/Indexer/Minimalprice.php b/app/code/core/Mage/CatalogIndex/Model/Indexer/Minimalprice.php index 0ee8fba484c..1cf38cc60d3 100644 --- a/app/code/core/Mage/CatalogIndex/Model/Indexer/Minimalprice.php +++ b/app/code/core/Mage/CatalogIndex/Model/Indexer/Minimalprice.php @@ -65,7 +65,7 @@ public function getTierPriceAttribute() { $data = $this->getData('tier_price_attribute'); if (is_null($data)) { - $data = Mage::getModel('eav/entity_attribute')->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'tier_price'); + $data = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'tier_price'); $this->setData('tier_price_attribute', $data); } return $data; @@ -75,7 +75,7 @@ public function getPriceAttribute() { $data = $this->getData('price_attribute'); if (is_null($data)) { - $data = Mage::getModel('eav/entity_attribute')->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'price'); + $data = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'price'); $this->setData('price_attribute', $data); } return $data; diff --git a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php index 661908f810b..a0498ea8357 100644 --- a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php +++ b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php @@ -73,8 +73,7 @@ public function getPurchasedSeparatelyAttribute() if (is_null($this->_purchasedSeparatelyAttribute)) { $_attributeCode = 'links_purchased_separately'; - $this->_purchasedSeparatelyAttribute = Mage::getModel('eav/entity_attribute') - ->loadByCode(Mage_Catalog_Model_Product::ENTITY, $_attributeCode); + $this->_purchasedSeparatelyAttribute = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, $_attributeCode); } return $this->_purchasedSeparatelyAttribute; diff --git a/app/code/core/Mage/Eav/Model/Config.php b/app/code/core/Mage/Eav/Model/Config.php index f4428006ff6..9c191882685 100644 --- a/app/code/core/Mage/Eav/Model/Config.php +++ b/app/code/core/Mage/Eav/Model/Config.php @@ -29,6 +29,14 @@ class Mage_Eav_Model_Config { const ENTITIES_CACHE_ID = 'EAV_ENTITY_TYPES'; const ATTRIBUTES_CACHE_ID = 'EAV_ENTITY_ATTRIBUTES'; + const CACHE_TAG = 'EAV'; + + /** + * Entity types cache + * + * @var Mage_Eav_Model_Entity_Type[] + */ + protected $_entityTypes = null; /** * Entity types data @@ -37,6 +45,20 @@ class Mage_Eav_Model_Config */ protected $_entityData; + /** + * Attributes cache + * + * @var Mage_Eav_Model_Entity_Attribute_Abstract[] + */ + protected $_attributes = null; + + /** + * Attribute sets cache + * + * @var Mage_Eav_Model_Entity_Attribute_Set[] + */ + protected $_attributeSets = null; + /** * Attributes data * @@ -58,6 +80,27 @@ class Mage_Eav_Model_Config */ protected $_initializedAttributes = array(); + /** + * Product Attributes used in product listing + * + * @var array + */ + protected $_attributesUsedInProductListing; + + /** + * Product Attributes For Sort By + * + * @var array + */ + protected $_attributesUsedForSortInProductListing; + + /** + * filtered product attributes in sets for layered navigation + * + * @var array + */ + protected $_filteredAttributeSetsUsedInProductListing; + /** * Attribute codes cache array * @@ -89,7 +132,7 @@ class Mage_Eav_Model_Config /** * Cache flag * - * @var unknown_type + * @var boolean */ protected $_isCacheEnabled = null; @@ -100,6 +143,50 @@ class Mage_Eav_Model_Config */ protected $_collectionAttributes = array(); + /** + * Check EAV cache availability + * + * @return bool + */ + protected function _isCacheEnabled() + { + if ($this->_isCacheEnabled === null) { + if (false === Mage::isInstalled() || Mage::app()->getUpdateMode() == true) { + $this->_isCacheEnabled = false; + } else { + $this->_isCacheEnabled = Mage::app()->useCache('eav'); + } + } + return $this->_isCacheEnabled; + } + + /** + * Load data from cache + * + * @param string $cacheId + * + * @return bool|string + */ + protected function _loadDataFromCache($cacheId) + { + if (true === $this->_isCacheEnabled()) { + return Mage::app()->loadCache($cacheId); + } + return false; + } + + /** + * save data to cache + * + * @param string $cacheId + * @param string $data + */ + protected function _saveDataToCache($cacheId, $data) + { + Mage::app()->saveCache($data, $cacheId, array(self::CACHE_TAG, Mage_Eav_Model_Entity_Attribute::CACHE_TAG)); + } + + /** * Reset object state * @@ -108,12 +195,13 @@ class Mage_Eav_Model_Config */ public function clear() { - $this->_entityData = null; - $this->_attributeData = null; - $this->_objects = null; - $this->_references = null; - $this->_preloadedAttributes = array(); - $this->_initializedAttributes = array(); + $this->_references = null; + $this->_entityTypes = null; + $this->_attributeSets = null; + $this->_attributes = null; + $this->_attributesUsedForSortInProductListing = null; + $this->_attributesUsedInProductListing = null; + $this->_filteredAttributeSetsUsedInProductListing = null; return $this; } @@ -218,74 +306,215 @@ protected function _getAttributeKey($entityTypeCode, $attributeCode) } /** - * Check EAV cache availability + * Initialize all entity types data * - * @return bool + * @return Mage_Eav_Model_Config */ - protected function _isCacheEnabled() + protected function _initEntityTypes() { - if ($this->_isCacheEnabled === null) { - $this->_isCacheEnabled = Mage::app()->useCache('eav'); + if (true === is_array($this->_entityTypes)) { + return $this; } - return $this->_isCacheEnabled; + Varien_Profiler::start('EAV: ' . __METHOD__); + //try load information about entity types from cache + $cache = $this->_loadDataFromCache(self::ENTITIES_CACHE_ID); + if ($cache) { + list($this->_entityTypes, $this->_references['entity']) = unserialize($cache); + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $this; + } + $this->_entityTypes = array(); + $entityTypeCollection = Mage::getResourceModel('eav/entity_type_collection'); + if ($entityTypeCollection->count() > 0) { + /** @var $entityType Mage_Eav_Model_Entity_Type */ + foreach ($entityTypeCollection as $entityType) { + $entityTypeCode = $entityType->getData('entity_type_code'); + $this->_entityTypes[$entityTypeCode] = $entityType; + $this->_addEntityTypeReference($entityType->getData('entity_type_id'), $entityTypeCode); + } + } + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $this; } /** - * Initialize all entity types data + * Initialize all attribute sets * * @return Mage_Eav_Model_Config */ - protected function _initEntityTypes() + protected function _initAllAttributeSets() { - if (is_array($this->_entityData)) { + if (true === is_array($this->_attributeSets)) { return $this; } - Varien_Profiler::start('EAV: '.__METHOD__); - - /** - * try load information about entity types from cache - */ - if ($this->_isCacheEnabled() - && ($cache = Mage::app()->loadCache(self::ENTITIES_CACHE_ID))) { - - $this->_entityData = unserialize($cache); - foreach ($this->_entityData as $typeCode => $data) { - $typeId = $data['entity_type_id']; - $this->_addEntityTypeReference($typeId, $typeCode); + Varien_Profiler::start('EAV: ' . __METHOD__); + $this->_attributeSets = array(); + $attributeSetCollection = Mage::getResourceModel('eav/entity_attribute_set_collection'); + if ($attributeSetCollection->count() > 0) { + /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */ + foreach ($attributeSetCollection as $attributeSet) { + $this->_attributeSets[$attributeSet->getData('attribute_set_id')] = $attributeSet; } - Varien_Profiler::stop('EAV: '.__METHOD__); - return $this; } + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $this; + } - $entityTypesData = Mage::getModel('eav/entity_type')->getCollection()->getData(); - $types = array(); + /** + * preload all attributes used for sort in product listing + * + * @return Mage_Eav_Model_Config + */ + protected function _initFilterableAttributesInAttributeSetsUsedInProductListing() + { + $productEntityType = Mage_Catalog_Model_Product::ENTITY; + $productEntityTypeId = $this->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getEntityTypeId(); + $productAttributeSets = array_filter($this->_attributeSets, function ($attributeSet) use ($productEntityTypeId) { + /** @var Mage_Eav_Model_Entity_Attribute_Set $attributeSet */ + return (int)$attributeSet->getEntityTypeId() == $productEntityTypeId; + }); + $this->_filteredAttributeSetsUsedInProductListing = array(); + foreach ($productAttributeSets as $attributeSet) { + /** @var Mage_Eav_Model_Entity_Attribute_Set $attributeSet */ + $this->_filteredAttributeSetsUsedInProductListing[$attributeSet->getAttributeSetId()] = array(); + $this->_filteredAttributeSetsUsedInProductListing[$attributeSet->getAttributeSetId()] = array_filter( + $this->_attributeSets[$attributeSet->getAttributeSetId()]->getAttributeCodes(), function ($attribute) use ($productEntityType) { + return (int)$this->_attributes[$productEntityType][$attribute]->getIsFilterable() == 1; + }); + } + return $this; + } - /** - * prepare entity type data - */ - foreach ($entityTypesData as $typeData) { - if (!isset($typeData['attribute_model'])) { - $typeData['attribute_model'] = 'eav/entity_attribute'; - } + /** + * preload all attributes used for sort in product listing + * + * @return Mage_Eav_Model_Config + */ + protected function _initAttributesUsedForSortInProductListing() + { + $this->_attributesUsedForSortInProductListing = array_filter($this->_attributes[Mage_Catalog_Model_Product::ENTITY], function ($attribute) { + /** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */ + return (int)$attribute->getUsedForSortBy() == 1; + }); + return $this; + } - $typeCode = $typeData['entity_type_code']; - $typeId = $typeData['entity_type_id']; + /** + * preload all attributes used in product listing + * + * @return Mage_Eav_Model_Config + */ + protected function _initAttributesUsedInProductListing() + { + $this->_attributesUsedInProductListing = array_filter($this->_attributes[Mage_Catalog_Model_Product::ENTITY], function ($attribute) { + /** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */ + return (int)$attribute->getUsedInProductListing() == 1; + }); + return $this; + } - $this->_addEntityTypeReference($typeId, $typeCode); - $types[$typeCode] = $typeData; + /** + * Initialize all attributes for all entity types + * + * @return Mage_Eav_Model_Config + */ + protected function _initAllAttributes() + { + if (true === is_array($this->_attributes)) { + return $this; + } + Varien_Profiler::start('EAV: ' . __METHOD__); + $this->_initEntityTypes(); + //try load information about attributes and attribute sets from cache + $cache = $this->_loadDataFromCache(self::ATTRIBUTES_CACHE_ID); + if ($cache) { + list( + $this->_attributeSets, + $this->_attributes, + $this->_references['attribute'], + $this->_attributesUsedInProductListing, + $this->_attributesUsedForSortInProductListing, + $this->_filteredAttributeSetsUsedInProductListing + ) = unserialize($cache); + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $this; + } + $this->_initAllAttributeSets(); + if (true === is_array($this->_entityTypes) && count($this->_entityTypes) > 0) { + foreach ($this->_entityTypes as $entityType) { + $this->_initAttributes($entityType); + } } - $this->_entityData = $types; - - if ($this->_isCacheEnabled()) { - Mage::app()->saveCache(serialize($this->_entityData), self::ENTITIES_CACHE_ID, - array('eav', Mage_Eav_Model_Entity_Attribute::CACHE_TAG) + try { + // try Catch around init for product attributes is needed during setup scripts + $this->_initAttributesUsedForSortInProductListing(); + $this->_initAttributesUsedInProductListing(); + $this->_initFilterableAttributesInAttributeSetsUsedInProductListing(); + } catch (Exception $e) {} + + if (true === $this->_isCacheEnabled()) { + $this->_saveDataToCache(self::ATTRIBUTES_CACHE_ID, + serialize(array( + $this->_attributeSets, + $this->_attributes, + $this->_references['attribute'], + $this->_attributesUsedInProductListing, + $this->_attributesUsedForSortInProductListing, + $this->_filteredAttributeSetsUsedInProductListing + )) + ); + // save entities types to cache because they are fully set now + // (we've just added attribute_codes to each entity type object) + $this->_saveDataToCache(self::ENTITIES_CACHE_ID, + serialize(array($this->_entityTypes, $this->_references['entity'])) ); } - Varien_Profiler::stop('EAV: '.__METHOD__); + Varien_Profiler::stop('EAV: ' . __METHOD__); return $this; } + + /** + * Init attribute store labels + * + * @param Mage_Eav_Model_Entity_Attribute $attribute + * @param array $attributeData + */ + protected function _initAttributeStoreLabels(Mage_Eav_Model_Entity_Attribute $attribute){ + if(true === method_exists($attribute, 'getStoreLabels')){ + $attribute->setData('store_labels', $attribute->getStoreLabels()); + }else{ + $attribute->setData('store_labels', array()); + } + } + + /** + * Init attribute from attribute data array + * + * @param Mage_Eav_Model_Entity_Type $entityType + * @param array $attributeData + */ + protected function _initAttribute($entityType, $attributeData) + { + $entityTypeCode = $entityType->getEntityTypeCode(); + if (false === empty($attributeData['attribute_model'])) { + $model = $attributeData['attribute_model']; + } else { + $model = $entityType->getAttributeModel(); + } + $attributeCode = $attributeData['attribute_code']; + $attribute = Mage::getModel($model)->setData($attributeData); + $this->_initAttributeStoreLabels($attribute); + $entity = $entityType->getEntity(); + $isFlatTableEntity = false === method_exists($entity, 'getDefaultAttributes'); + if ($entity && (true === $isFlatTableEntity || true === in_array($attributeCode, $entity->getDefaultAttributes()))) { + $attribute->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC)->setIsGlobal(1); + } + $this->_attributes[$entityTypeCode][$attributeCode] = $attribute; + $this->_addAttributeReference($attributeData['attribute_id'], $attributeCode, $entityTypeCode); + } + /** * Get entity type object by entity type code/identifier * @@ -297,42 +526,19 @@ public function getEntityType($code) if ($code instanceof Mage_Eav_Model_Entity_Type) { return $code; } - Varien_Profiler::start('EAV: '.__METHOD__); - - if (is_numeric($code)) { + Varien_Profiler::start('EAV: ' . __METHOD__); + $this->_initEntityTypes(); + if (true === is_numeric($code)) { $entityCode = $this->_getEntityTypeReference($code); if ($entityCode !== null) { $code = $entityCode; } } - - $entityKey = $this->_getEntityKey($code); - $entityType = $this->_load($entityKey); - if ($entityType) { - Varien_Profiler::stop('EAV: '.__METHOD__); - return $entityType; + if (false === isset($this->_entityTypes[$code])) { + Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code)); } - - - $entityType = Mage::getModel('eav/entity_type'); - if (isset($this->_entityData[$code])) { - $entityType->setData($this->_entityData[$code]); - } else { - if (is_numeric($code)) { - $entityType->load($code); - } else { - $entityType->loadByCode($code); - } - - if (!$entityType->getId()) { - Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code)); - } - } - $this->_addEntityTypeReference($entityType->getId(), $entityType->getEntityTypeCode()); - $this->_save($entityType, $entityKey); - - Varien_Profiler::stop('EAV: '.__METHOD__); - return $entityType; + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $this->_entityTypes[$code]; } /** @@ -343,28 +549,35 @@ public function getEntityType($code) */ protected function _initAttributes($entityType) { - $entityType = $this->getEntityType($entityType); - $entityTypeCode = $entityType->getEntityTypeCode(); - - if (isset($this->_initializedAttributes[$entityTypeCode])) { - return $this; - } - Varien_Profiler::start('EAV: '.__METHOD__); - - $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection()) - ->setEntityTypeFilter($entityType) - ->getData(); - - $codes = array(); - foreach ($attributesInfo as $attribute) { - $this->_createAttribute($entityType, $attribute); - $codes[] = $attribute['attribute_code']; + Varien_Profiler::start('EAV: ' . __METHOD__); + /** @var Mage_Eav_Model_Resource_Entity_Attribute_Collection $attributesCollection */ + $attributesCollection = Mage::getResourceModel($entityType->getEntityAttributeCollection()); + if ($attributesCollection) { + $attributesData = $attributesCollection->setEntityTypeFilter($entityType)->addSetInfo()->getData(); + $entityTypeAttributeCodes = array(); + $attributeSetsAttributeCodes = array(); + foreach ($attributesData as $attributeData) { + $this->_initAttribute($entityType, $attributeData); + $entityTypeAttributeCodes[] = $attributeData['attribute_code']; + $attributeSetIds = array_keys($attributeData['attribute_set_info']); + unset($attributeData['attribute_set_info']); + foreach ($attributeSetIds as $attributeSetId) { + if (false === isset($attributeSetsAttributeCodes[$attributeSetId])) { + $attributeSetsAttributeCodes[$attributeSetId] = array(); + } + $attributeSetsAttributeCodes[$attributeSetId][] = $attributeData['attribute_code']; + } + } + $entityType->setData('attribute_codes', $entityTypeAttributeCodes); + if (count($attributeSetsAttributeCodes) > 0) { + foreach ($attributeSetsAttributeCodes as $attributeSetId => $attributeCodes) { + if (true === isset($this->_attributeSets[$attributeSetId])) { + $this->_attributeSets[$attributeSetId]->setData('attribute_codes', $attributeCodes); + } + } + } } - - $entityType->setAttributeCodes($codes); - $this->_initializedAttributes[$entityTypeCode] = true; - - Varien_Profiler::stop('EAV: '.__METHOD__); + Varien_Profiler::stop('EAV: ' . __METHOD__); return $this; } @@ -380,63 +593,28 @@ public function getAttribute($entityType, $code) if ($code instanceof Mage_Eav_Model_Entity_Attribute_Interface) { return $code; } - - Varien_Profiler::start('EAV: '.__METHOD__); - - $entityTypeCode = $this->getEntityType($entityType)->getEntityTypeCode(); + Varien_Profiler::start('EAV: ' . __METHOD__); + $this->_initAllAttributes(); $entityType = $this->getEntityType($entityType); - + $entityTypeCode = $entityType->getEntityTypeCode(); /** * Validate attribute code */ - if (is_numeric($code)) { + if (true === is_numeric($code)) { $attributeCode = $this->_getAttributeReference($code, $entityTypeCode); if ($attributeCode) { $code = $attributeCode; } } - $attributeKey = $this->_getAttributeKey($entityTypeCode, $code); - - /** - * Try use loaded attribute - */ - $attribute = $this->_load($attributeKey); - if ($attribute) { - Varien_Profiler::stop('EAV: '.__METHOD__); - return $attribute; - } - - if (isset($this->_attributeData[$entityTypeCode][$code])) { - $data = $this->_attributeData[$entityTypeCode][$code]; - unset($this->_attributeData[$entityTypeCode][$code]); - $attribute = Mage::getModel($data['attribute_model'], $data); + if (false === isset($this->_attributes[$entityTypeCode][$code])) { + // backward compatibility with attributes which are absent in db but present in xml config for some reason + // for example type_id attribute in app/code/core/Mage/Sales/etc/config.xml + $attribute = Mage::getModel($entityType->getAttributeModel())->setAttributeCode($code); } else { - if (is_numeric($code)) { - $attribute = Mage::getModel($entityType->getAttributeModel())->load($code); - if ($attribute->getEntityTypeId() != $entityType->getId()) { - return false; - } - $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute->getAttributeCode()); - } else { - $attribute = Mage::getModel($entityType->getAttributeModel()) - ->loadByCode($entityType, $code) - ->setAttributeCode($code); - } - } - - if ($attribute) { - $entity = $entityType->getEntity(); - if ($entity && in_array($attribute->getAttributeCode(), $entity->getDefaultAttributes())) { - $attribute->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC) - ->setIsGlobal(1); - } - $attribute->setEntityType($entityType) - ->setEntityTypeId($entityType->getId()); - $this->_addAttributeReference($attribute->getId(), $attribute->getAttributeCode(), $entityTypeCode); - $this->_save($attribute, $attributeKey); + $attribute = $this->_attributes[$entityTypeCode][$code]; + $attribute->setEntityType($entityType); } - Varien_Profiler::stop('EAV: '.__METHOD__); - + Varien_Profiler::stop('EAV: ' . __METHOD__); return $attribute; } @@ -449,39 +627,68 @@ public function getAttribute($entityType, $code) */ public function getEntityAttributeCodes($entityType, $object = null) { - $entityType = $this->getEntityType($entityType); + Varien_Profiler::start('EAV: ' . __METHOD__); + $this->_initAllAttributes(); $attributeSetId = 0; if (($object instanceof Varien_Object) && $object->getAttributeSetId()) { - $attributeSetId = $object->getAttributeSetId(); + $attributeSetId = $object->getAttributeSetId(); } - $storeId = 0; - if (($object instanceof Varien_Object) && $object->getStoreId()) { - $storeId = $object->getStoreId(); - } - $cacheKey = sprintf('%d-%d', $entityType->getId(), $attributeSetId); - if (isset($this->_attributeCodes[$cacheKey])) { - return $this->_attributeCodes[$cacheKey]; + if ($attributeSetId && isset($this->_attributeSets[$attributeSetId])) { + $attributes = $this->_attributeSets[$attributeSetId]->getData('attribute_codes'); + } else { + $entityType = $this->getEntityType($entityType); + $attributes = $entityType->getAttributeCodes(); } + Varien_Profiler::stop('EAV: ' . __METHOD__); + // it might happen that entity type doesn't have attributes (some custom one) or + // there are no attributes in attribute set + return empty($attributes) ? array() : $attributes; + } - if ($attributeSetId) { - $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection()) - ->setEntityTypeFilter($entityType) - ->setAttributeSetFilter($attributeSetId) - ->addStoreLabel($storeId) - ->getData(); - $attributes = array(); - foreach ($attributesInfo as $attributeData) { - $attributes[] = $attributeData['attribute_code']; - $this->_createAttribute($entityType, $attributeData); + /** + * return a list of all attributes used in given attribute sets + * + * @return array + */ + public function getFilterableProductAttributesUsedInSets(array $setIds) + { + $this->_initAllAttributes(); + Varien_Profiler::start('EAV: ' . __METHOD__); + $out = array(); + foreach ($setIds as $setId) { + if (true === isset($this->_filteredAttributeSetsUsedInProductListing[$setId])) { + $out = array_merge($out, $this->_filteredAttributeSetsUsedInProductListing[$setId]); } - } else { - $this->_initAttributes($entityType); - $attributes = $this->getEntityType($entityType)->getAttributeCodes(); } + $out = array_unique($out); + $return = array(); + foreach ($out as $attributeCode) { + $return[$attributeCode] = $this->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode); + } + Varien_Profiler::stop('EAV: ' . __METHOD__); + return $return; + } - $this->_attributeCodes[$cacheKey] = $attributes; + /** + * return a list of all attributes used for sort by + * + * @return array + */ + public function getProductAttributesUsedForSortBy() + { + $this->_initAllAttributes(); + return $this->_attributesUsedForSortInProductListing; + } - return $attributes; + /** + * return a list of all attributes used in product listing + * + * @return array + */ + public function getAttributesUsedInProductListing() + { + $this->_initAllAttributes(); + return $this->_attributesUsedInProductListing; } /** @@ -493,56 +700,7 @@ public function getEntityAttributeCodes($entityType, $object = null) */ public function preloadAttributes($entityType, $attributes) { - if (is_string($attributes)) { - $attributes = array($attributes); - } - - $entityType = $this->getEntityType($entityType); - $entityTypeCode = $entityType->getEntityTypeCode(); - - if (!isset($this->_preloadedAttributes[$entityTypeCode])) { - $this->_preloadedAttributes[$entityTypeCode] = $attributes; - } else { - $attributes = array_diff($attributes, $this->_preloadedAttributes[$entityTypeCode]); - $this->_preloadedAttributes[$entityTypeCode] = array_merge($this->_preloadedAttributes[$entityTypeCode], - $attributes - ); - } - - if (empty($attributes)) { - return $this; - } - Varien_Profiler::start('EAV: '.__METHOD__ . ':'.$entityTypeCode); - - $attributesInfo = Mage::getResourceModel($entityType->getEntityAttributeCollection()) - ->setEntityTypeFilter($entityType) - ->setCodeFilter($attributes) - ->getData(); - - if (!$attributesInfo) { - Varien_Profiler::stop('EAV: '.__METHOD__ . ':'.$entityTypeCode); - return $this; - } - - $attributesData = $codes = array(); - - foreach ($attributesInfo as $attribute) { - if (empty($attribute['attribute_model'])) { - $attribute['attribute_model'] = $entityType->getAttributeModel(); - } - - $attributeCode = $attribute['attribute_code']; - $attributeId = $attribute['attribute_id']; - - $this->_addAttributeReference($attributeId, $attributeCode, $entityTypeCode); - $attributesData[$attributeCode] = $attribute; - $codes[] = $attributeCode; - } - - $this->_attributeData[$entityTypeCode] = $attributesData; - - Varien_Profiler::stop('EAV: '.__METHOD__ . ':'.$entityTypeCode); - + // with fixed cached eav attributes this method is obsolete return $this; } @@ -555,22 +713,6 @@ public function preloadAttributes($entityType, $attributes) */ public function getCollectionAttribute($entityType, $attribute) { - $entityType = $this->getEntityType($entityType); - $entityTypeCode = $entityType->getEntityTypeCode(); - - if (is_numeric($attribute)) { - $attribute = $this->_getAttributeReference($attribute, $entityTypeCode); - if (!$attribute) { - return null; - } - } - - $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute); - $attributeObject = $this->_load($attributeKey); - if ($attributeObject) { - return $attributeObject; - } - return $this->getAttribute($entityType, $attribute); } @@ -583,40 +725,7 @@ public function getCollectionAttribute($entityType, $attribute) */ public function loadCollectionAttributes($entityType, $attributes) { - $entityType = $this->getEntityType($entityType); - $entityTypeCode = $entityType->getEntityTypeCode(); - - if (!isset($this->_collectionAttributes[$entityTypeCode])) { - $this->_collectionAttributes[$entityTypeCode] = array(); - } - $loadedAttributes = array_keys($this->_collectionAttributes[$entityTypeCode]); - $attributes = array_diff($attributes, $loadedAttributes); - - foreach ($attributes as $k => $attribute) { - if (is_numeric($attribute)) { - $attribute = $this->_getAttributeReference($attribute, $entityTypeCode); - } - $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute); - if ($this->_load($attributeKey)) { - unset($attributes[$k]); - } - } - - if (empty($attributes)) { - return $this; - } - $attributeCollection = $entityType->getEntityAttributeCollection(); - $attributesInfo = Mage::getResourceModel($attributeCollection) - ->useLoadDataFields() - ->setEntityTypeFilter($entityType) - ->setCodeFilter($attributes) - ->getData(); - - foreach ($attributesInfo as $attributeData) { - $attribute = $this->_createAttribute($entityType, $attributeData); - $this->_collectionAttributes[$entityTypeCode][$attribute->getAttributeCode()] =$attribute; - } - + // with cached eav attributes we don't need this method return $this; } @@ -695,14 +804,7 @@ protected function _validateAttributeData($attributeData = null) */ public function importAttributesData($entityType, array $attributes) { - $entityType = $this->getEntityType($entityType); - foreach ($attributes as $attributeData) { - if (!$this->_validateAttributeData($attributeData)) { - continue; - } - $this->_createAttribute($entityType, $attributeData); - } - + // with cached eav attributes we don't need this method return $this; } } diff --git a/app/code/core/Mage/Eav/Model/Entity/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Abstract.php index 6fbd9ae857e..4e232bb22fd 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Abstract.php @@ -35,6 +35,14 @@ abstract class Mage_Eav_Model_Entity_Abstract extends Mage_Core_Model_Resource_Abstract implements Mage_Eav_Model_Entity_Interface { + + /** + * sorted attributes by attribute Set Id (static cache) + * + * @var array + */ + protected static $_sortedAttributesByAttributeSetId = array(); + /** * Read connection * @@ -540,6 +548,9 @@ public function loadAllAttributes($object=null) */ public function getSortedAttributes($setId = null) { + if (null !== $setId && true === isset(self::$_sortedAttributesByAttributeSetId[$setId])) { + return self::$_sortedAttributesByAttributeSetId[$setId]; + } $attributes = $this->getAttributesByCode(); if ($setId === null) { $setId = $this->getEntityType()->getDefaultAttributeSetId(); @@ -558,6 +569,9 @@ public function getSortedAttributes($setId = null) $this->_sortingSetId = $setId; uasort($attributes, array($this, 'attributesCompare')); + if (null !== $setId) { + self::$_sortedAttributesByAttributeSetId[$setId] = $attributes; + } return $attributes; } diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute.php b/app/code/core/Mage/Eav/Model/Entity/Attribute.php index b291fd1a9f4..e8212a9f058 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute.php @@ -310,7 +310,7 @@ public function getAttributeCodesByFrontendType($type) */ public function getStoreLabels() { - if (!$this->getData('store_labels')) { + if (false === is_array($this->getData('store_labels'))) { $storeLabel = $this->getResource()->getStoreLabelsByAttributeId($this->getId()); $this->setData('store_labels', $storeLabel); } diff --git a/app/code/core/Mage/Tax/Helper/Data.php b/app/code/core/Mage/Tax/Helper/Data.php index 867496b4a58..eb7cc10b1ee 100644 --- a/app/code/core/Mage/Tax/Helper/Data.php +++ b/app/code/core/Mage/Tax/Helper/Data.php @@ -871,8 +871,7 @@ public function getPriceTaxSql($priceField, $taxClassField) */ public function joinTaxClass($select, $storeId, $priceTable = 'main_table') { - $taxClassAttribute = Mage::getModel('eav/entity_attribute') - ->loadByCode(Mage_Catalog_Model_Product::ENTITY, 'tax_class_id'); + $taxClassAttribute = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'tax_class_id'); $joinConditionD = implode(' AND ', array( "tax_class_d.entity_id = {$priceTable}.entity_id", $select->getAdapter()->quoteInto('tax_class_d.attribute_id = ?', (int)$taxClassAttribute->getId()),