Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
All Data Structures Namespaces Files Functions Variables Pages
Config.php
Go to the documentation of this file.
1 <?php
6 namespace Magento\Eav\Model;
7 
12 
18 class Config
19 {
23  const ENTITIES_CACHE_ID = 'EAV_ENTITY_TYPES';
24  const ATTRIBUTES_CACHE_ID = 'EAV_ENTITY_ATTRIBUTES';
25  const ATTRIBUTES_CODES_CACHE_ID = 'EAV_ENTITY_ATTRIBUTES_CODES';
29  protected $_entityTypeData;
30 
36  protected $_attributeData;
37 
43  protected $_attributeCodes;
44 
52  protected $_objects;
53 
63  private $attributes;
64 
75  protected $_references;
76 
82  protected $_isCacheEnabled = null;
83 
87  protected $_cache;
88 
92  protected $_cacheState;
93 
98 
103 
108 
112  private $attributeProto = [];
113 
117  private $serializer;
118 
124  private $attributesPerSet = [];
125 
135  public function __construct(
136  \Magento\Framework\App\CacheInterface $cache,
137  \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory,
138  \Magento\Eav\Model\ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory,
139  \Magento\Framework\App\Cache\StateInterface $cacheState,
140  \Magento\Framework\Validator\UniversalFactory $universalFactory,
141  SerializerInterface $serializer = null
142  ) {
143  $this->_cache = $cache;
144  $this->_entityTypeFactory = $entityTypeFactory;
145  $this->entityTypeCollectionFactory = $entityTypeCollectionFactory;
146  $this->_cacheState = $cacheState;
147  $this->_universalFactory = $universalFactory;
148  $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class);
149  }
150 
157  public function getCache()
158  {
159  return $this->_cache;
160  }
161 
167  public function clear()
168  {
169  $this->_entityTypeData = null;
170  $this->_attributeData = null;
171  $this->_objects = null;
172  $this->attributes = null;
173  $this->_references = null;
174  $this->_attributeCodes = null;
175  $this->attributesPerSet = [];
176  $this->_cache->clean(
177  [
178  \Magento\Eav\Model\Cache\Type::CACHE_TAG,
180  ]
181  );
182  return $this;
183  }
184 
191  protected function _load($id)
192  {
193  return isset($this->_objects[$id]) ? $this->_objects[$id] : null;
194  }
195 
202  private function loadAttributes($entityTypeCode)
203  {
204  return isset($this->attributes[$entityTypeCode]) ? $this->attributes[$entityTypeCode] : [];
205  }
206 
215  protected function _save($obj, $id)
216  {
217  $this->_objects[$id] = $obj;
218  }
219 
228  private function saveAttribute(AbstractAttribute $attribute, $entityTypeCode, $attributeCode)
229  {
230  $this->attributes[$entityTypeCode][$attributeCode] = $attribute;
231  }
232 
241  protected function _addEntityTypeReference($id, $code)
242  {
243  $this->_references['entity'][$id] = $code;
244  return $this;
245  }
246 
253  protected function _getEntityTypeReference($id)
254  {
255  return isset($this->_references['entity'][$id]) ? $this->_references['entity'][$id] : null;
256  }
257 
267  {
268  $this->_references['attribute'][$entityTypeCode][$id] = $code;
269  return $this;
270  }
271 
280  {
281  if (isset($this->_references['attribute'][$entityTypeCode][$id])) {
282  return $this->_references['attribute'][$entityTypeCode][$id];
283  }
284  return null;
285  }
286 
294  protected function _getEntityKey($code)
295  {
296  return 'ENTITY/' . $code;
297  }
298 
308  {
309  $codeSegments = explode('.', $attributeCode);
310 
311  return 'ATTRIBUTE/' . $entityTypeCode . '/' . array_pop($codeSegments);
312  }
313 
319  public function isCacheEnabled()
320  {
321  if ($this->_isCacheEnabled === null) {
322  $this->_isCacheEnabled = $this->_cacheState->isEnabled(\Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER);
323  }
324  return $this->_isCacheEnabled;
325  }
326 
332  protected function _initEntityTypes()
333  {
334  if (is_array($this->_entityTypeData)) {
335  return $this;
336  }
337  \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]);
338 
339  if ($this->isCacheEnabled() && ($cache = $this->_cache->load(self::ENTITIES_CACHE_ID))) {
340  $this->_entityTypeData = $this->serializer->unserialize($cache);
341  foreach ($this->_entityTypeData as $typeCode => $data) {
342  $typeId = $data['entity_type_id'];
343  $this->_addEntityTypeReference($typeId, $typeCode);
344  }
345  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
346  return $this;
347  }
348 
349  $entityTypesData = $this->entityTypeCollectionFactory->create()->getData();
350  foreach ($entityTypesData as $typeData) {
351  if (!isset($typeData['attribute_model'])) {
352  $typeData['attribute_model'] = \Magento\Eav\Model\Entity\Attribute::class;
353  }
354 
355  $typeCode = $typeData['entity_type_code'];
356  $typeId = $typeData['entity_type_id'];
357 
358  $this->_addEntityTypeReference($typeId, $typeCode);
359  $this->_entityTypeData[$typeCode] = $typeData;
360  }
361 
362  if ($this->isCacheEnabled()) {
363  $this->_cache->save(
364  $this->serializer->serialize($this->_entityTypeData),
366  [
368  \Magento\Eav\Model\Entity\Attribute::CACHE_TAG
369  ]
370  );
371  }
372  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
373  return $this;
374  }
375 
383  public function getEntityType($code)
384  {
385  if ($code instanceof Type) {
386  return $code;
387  }
388  $this->_initEntityTypes();
389  \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]);
390 
391  if (is_numeric($code)) {
392  $entityCode = $this->_getEntityTypeReference($code);
393  if ($entityCode !== null) {
394  $code = $entityCode;
395  }
396  }
397 
398  $entityKey = $this->_getEntityKey($code);
399  $entityType = $this->_load($entityKey);
400  if ($entityType) {
401  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
402  return $entityType;
403  }
404 
405  $entityType = $this->_entityTypeFactory->create(
406  ['data' => isset($this->_entityTypeData[$code]) ? $this->_entityTypeData[$code] : []]
407  );
408  if (!$entityType->getId()) {
409  throw new \Magento\Framework\Exception\LocalizedException(__('Invalid entity_type specified: %1', $code));
410  }
411  $this->_addEntityTypeReference($entityType->getId(), $entityType->getEntityTypeCode());
412  $this->_save($entityType, $entityKey);
413 
414  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
415  return $entityType;
416  }
417 
424  protected function _initAttributes($entityType)
425  {
427  $entityTypeCode = $entityType->getEntityTypeCode();
428 
429  if (is_array($this->_attributeData) && isset($this->_attributeData[$entityTypeCode])) {
430  return $this;
431  }
432 
433  if ($this->initAttributesFromCache($entityType)) {
434  return $this;
435  }
436 
437  \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]);
438 
439  $attributes = $this->_universalFactory->create(
440  $entityType->getEntityAttributeCollection()
441  )->setEntityTypeFilter(
443  )->getData();
444 
445  $this->_attributeData[$entityTypeCode] = [];
446  foreach ($attributes as $attribute) {
447  if (empty($attribute['attribute_model'])) {
448  $attribute['attribute_model'] = $entityType->getAttributeModel();
449  }
450  $attributeObject = $this->_createAttribute($entityType, $attribute);
451  $this->saveAttribute($attributeObject, $entityTypeCode, $attributeObject->getAttributeCode());
452  $this->_attributeData[$entityTypeCode][$attribute['attribute_code']] = $attributeObject->toArray();
453  }
454  if ($this->isCacheEnabled()) {
455  $this->_cache->save(
456  $this->serializer->serialize($this->_attributeData[$entityTypeCode]),
457  self::ATTRIBUTES_CACHE_ID . $entityTypeCode,
458  [
460  \Magento\Eav\Model\Entity\Attribute::CACHE_TAG
461  ]
462  );
463  }
464 
465  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
466  return $this;
467  }
468 
479  public function getAttributes($entityType)
480  {
481  return $this->getEntityAttributes($entityType);
482  }
483 
492  public function getAttribute($entityType, $code)
493  {
494  if ($code instanceof \Magento\Eav\Model\Entity\Attribute\AttributeInterface) {
495  return $code;
496  }
497 
498  \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]);
499  $entityTypeCode = $this->getEntityType($entityType)->getEntityTypeCode();
500 
501  if (is_numeric($code)) { // if code is numeric, try to map attribute id to code
503  }
504 
505  if (isset($this->attributes[$entityTypeCode][$code])) {
506  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
507  return $this->attributes[$entityTypeCode][$code];
508  }
509 
510  $attributes = $this->loadAttributes($entityTypeCode);
511  $attribute = isset($attributes[$code]) ? $attributes[$code] : null;
512  if (!$attribute) {
513  $attribute = $this->createAttributeByAttributeCode($entityType, $code);
514  $this->_addAttributeReference(
515  $attribute->getAttributeId(),
516  $attribute->getAttributeCode(),
518  );
519  $this->saveAttribute($attribute, $entityTypeCode, $attribute->getAttributeCode());
520  }
521  \Magento\Framework\Profiler::stop('EAV: ' . __METHOD__);
522  return $attribute;
523  }
524 
531  private function createAttribute($model)
532  {
533  if (!isset($this->attributeProto[$model])) {
535  $this->attributeProto[$model] = $this->_universalFactory->create($model);
536  }
537  return clone $this->attributeProto[$model];
538  }
539 
550  public function getEntityAttributeCodes($entityType, $object = null)
551  {
552  return array_keys($this->getEntityAttributes($entityType, $object));
553  }
554 
566  public function getEntityAttributes($entityType, $object = null)
567  {
569  $attributeSetId = 0;
570  $storeId = 0;
571  if ($object instanceof \Magento\Framework\DataObject) {
572  $attributeSetId = $object->getAttributeSetId() ?: $attributeSetId;
573  $storeId = $object->getStoreId() ?: $storeId;
574  }
575  $cacheKey = self::ATTRIBUTES_CACHE_ID . '-' . $entityType->getId() . '-' . $storeId . '-' . $attributeSetId;
576 
577  if (isset($this->attributesPerSet[$cacheKey])) {
578  return $this->attributesPerSet[$cacheKey];
579  }
580 
581  $attributesData = $this->isCacheEnabled() && ($attributes = $this->_cache->load($cacheKey))
582  ? $this->serializer->unserialize($attributes)
583  : null;
584 
585  $attributes = [];
586  if ($attributesData === null) {
587  if ($attributeSetId) {
588  $attributesData = $this->_universalFactory->create(
589  $entityType->getEntityAttributeCollection()
590  )->setEntityTypeFilter(
592  )->setAttributeSetFilter(
594  )->addStoreLabel(
595  $storeId
596  )->getData();
597  } else {
599  $attributesData = $this->_attributeData[$entityType->getEntityTypeCode()];
600  }
601 
602  if ($this->isCacheEnabled()) {
603  $this->_cache->save(
604  $this->serializer->serialize($attributesData),
605  $cacheKey,
606  [
608  \Magento\Eav\Model\Entity\Attribute::CACHE_TAG
609  ]
610  );
611  }
612  }
613 
614  foreach ($attributesData as $attributeData) {
615  $attributes[$attributeData['attribute_code']] = $this->_createAttribute($entityType, $attributeData);
616  }
617 
618  $this->attributesPerSet[$cacheKey] = $attributes;
619 
620  return $attributes;
621  }
622 
630  protected function _createAttribute($entityType, $attributeData)
631  {
633  $entityTypeCode = $entityType->getEntityTypeCode();
634 
635  $code = $attributeData['attribute_code'];
636  $attributes = $this->loadAttributes($entityTypeCode);
637  $attribute = isset($attributes[$code]) ? $attributes[$code] : null;
638  if ($attribute) {
639  $existsFullAttribute = $attribute->hasIsRequired();
640  $fullAttributeData = array_key_exists('is_required', $attributeData);
641 
642  if ($existsFullAttribute || !$existsFullAttribute && !$fullAttributeData) {
643  return $attribute;
644  }
645  }
646 
647  if (!empty($attributeData['attribute_model'])) {
648  $model = $attributeData['attribute_model'];
649  } else {
650  $model = $entityType->getAttributeModel();
651  }
653  $attribute = $this->createAttribute($model)->setData($attributeData);
654  $this->_addAttributeReference(
655  $attributeData['attribute_id'],
656  $code,
658  );
659  $this->saveAttribute($attribute, $entityTypeCode, $code);
660 
661  return $attribute;
662  }
663 
670  protected function _validateAttributeData($attributeData = null)
671  {
672  if (!is_array($attributeData)) {
673  return false;
674  }
675  $requiredKeys = ['attribute_id', 'attribute_code', 'entity_type_id', 'attribute_model'];
676  foreach ($requiredKeys as $key) {
677  if (!array_key_exists($key, $attributeData)) {
678  return false;
679  }
680  }
681 
682  return true;
683  }
684 
692  public function importAttributesData($entityType, array $attributes)
693  {
695  foreach ($attributes as $attributeData) {
696  if (!$this->_validateAttributeData($attributeData)) {
697  continue;
698  }
699  $this->_createAttribute($entityType, $attributeData);
700  }
701 
702  return $this;
703  }
704 
712  private function createAttributeByAttributeCode($entityType, $attributeCode)
713  {
715  $attribute = $this->createAttribute($entityType->getAttributeModel());
716  if (is_numeric($attributeCode)) {
717  $attribute->load($attributeCode);
718  if ($attribute->getEntityTypeId() != $entityType->getId()) {
719  $attribute = $this->createAttribute($entityType->getAttributeModel());
720  }
721  } else {
722  $attribute->loadByCode($entityType->getEntityTypeId(), $attributeCode);
723  $attribute->setAttributeCode($attributeCode);
724  }
725 
726  $entity = $entityType->getEntity();
727  if ($entity instanceof \Magento\Eav\Model\ResourceModel\Attribute\DefaultEntityAttributes\ProviderInterface
728  && in_array($attribute->getAttributeCode(), $entity->getDefaultAttributes(), true)
729  ) {
730  $attribute->setBackendType(AbstractAttribute::TYPE_STATIC)->setIsGlobal(1);
731  }
732  $attribute->setEntityType($entityType)->setEntityTypeId($entityType->getId());
733  return $attribute;
734  }
735 
742  private function initAttributesFromCache(Type $entityType)
743  {
744  $entityTypeCode = $entityType->getEntityTypeCode();
745  $cacheKey = self::ATTRIBUTES_CACHE_ID . $entityTypeCode;
746  if ($this->isCacheEnabled() && ($attributes = $this->_cache->load($cacheKey))) {
747  $attributes = $this->serializer->unserialize($attributes);
748  if ($attributes) {
749  foreach ($attributes as $attribute) {
750  $this->_createAttribute($entityType, $attribute);
751  $this->_attributeData[$entityTypeCode][$attribute['attribute_code']] = $attribute;
752  }
753  return true;
754  }
755  }
756  return false;
757  }
758 }
_initAttributes($entityType)
Definition: Config.php:424
$id
Definition: fieldset.phtml:14
_getAttributeReference($id, $entityTypeCode)
Definition: Config.php:279
_addEntityTypeReference($id, $code)
Definition: Config.php:241
__()
Definition: __.php:13
_getAttributeKey($entityTypeCode, $attributeCode)
Definition: Config.php:307
getEntityAttributeCodes($entityType, $object=null)
Definition: Config.php:550
$attributesData
$attributeCode
Definition: extend.phtml:12
__construct(\Magento\Framework\App\CacheInterface $cache, \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory, \Magento\Eav\Model\ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory, \Magento\Framework\App\Cache\StateInterface $cacheState, \Magento\Framework\Validator\UniversalFactory $universalFactory, SerializerInterface $serializer=null)
Definition: Config.php:135
$entity
Definition: element.phtml:22
getAttribute($entityType, $code)
Definition: Config.php:492
const ATTRIBUTES_CODES_CACHE_ID
Definition: Config.php:25
_validateAttributeData($attributeData=null)
Definition: Config.php:670
_addAttributeReference($id, $code, $entityTypeCode)
Definition: Config.php:266
getAttributes($entityType)
Definition: Config.php:479
importAttributesData($entityType, array $attributes)
Definition: Config.php:692
getEntityAttributes($entityType, $object=null)
Definition: Config.php:566
$code
Definition: info.phtml:12