![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-eav/Setup/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Eav\Setup; use Magento\Eav\Model\AttributeFactory; use Magento\Eav\Model\Config; use Magento\Eav\Model\Entity\Attribute; use Magento\Eav\Model\Entity\Setup\Context; use Magento\Eav\Model\Entity\Setup\PropertyMapperInterface; use Magento\Eav\Model\ReservedAttributeCheckerInterface; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory; use Magento\Eav\Model\Validator\Attribute\Code; use Magento\Framework\App\CacheInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Validator\ValidateException; /** * Base eav setup class. * * @api * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @codeCoverageIgnore * @since 100.0.2 */ class EavSetup { /** * @var CacheInterface */ private $cache; /** * @var CollectionFactory */ private $attrGroupCollectionFactory; /** * @var PropertyMapperInterface */ private $attributeMapper; /** * @var ModuleDataSetupInterface */ private $setup; /** * @var string */ private $_generalGroupName = 'General'; /** * @var array */ private $defaultGroupIdAssociations = ['general' => 1]; /** * @var string */ private $_defaultGroupName = 'Default'; /** * @var string */ private $_defaultAttributeSetName = 'Default'; /** * @var AddOptionToAttribute */ private $addAttributeOption; /** * @var Code */ private $attributeCodeValidator; /** * @var ReservedAttributeCheckerInterface */ private $reservedAttributeChecker; /** * @var AttributeFactory */ private $attributeFactory; /** * @var Config|null */ private $eavConfig; /** * Init * * @param ModuleDataSetupInterface $setup * @param Context $context * @param CacheInterface $cache * @param CollectionFactory $attrGroupCollectionFactory * @param Code|null $attributeCodeValidator * @param AddOptionToAttribute|null $addAttributeOption * @param ReservedAttributeCheckerInterface|null $reservedAttributeChecker * @param AttributeFactory|null $attributeFactory * @param Config|null $eavConfig * @SuppressWarnings(PHPMD.LongVariable) */ public function __construct( ModuleDataSetupInterface $setup, Context $context, CacheInterface $cache, CollectionFactory $attrGroupCollectionFactory, Code $attributeCodeValidator = null, AddOptionToAttribute $addAttributeOption = null, ReservedAttributeCheckerInterface $reservedAttributeChecker = null, AttributeFactory $attributeFactory = null, Config $eavConfig = null ) { $this->cache = $cache; $this->attrGroupCollectionFactory = $attrGroupCollectionFactory; $this->attributeMapper = $context->getAttributeMapper(); $this->setup = $setup; $this->addAttributeOption = $addAttributeOption ?? ObjectManager::getInstance()->get(AddOptionToAttribute::class); $this->attributeCodeValidator = $attributeCodeValidator ?? ObjectManager::getInstance()->get(Code::class); $this->reservedAttributeChecker = $reservedAttributeChecker ?? ObjectManager::getInstance()->get(ReservedAttributeCheckerInterface::class); $this->attributeFactory = $attributeFactory ?? ObjectManager::getInstance()->get(AttributeFactory::class); $this->eavConfig = $eavConfig ?? ObjectManager::getInstance()->get(Config::class); } /** * Gets setup model. * * @deprecated 102.0.0 * @see we don't recommend this approach anymore * @return ModuleDataSetupInterface */ public function getSetup() { return $this->setup; } /** * Gets attribute group collection factory * * @return \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\Collection */ public function getAttributeGroupCollectionFactory() { return $this->attrGroupCollectionFactory->create(); } /** * Clean cache * * @return $this */ public function cleanCache() { $this->cache->clean([\Magento\Eav\Model\Cache\Type::CACHE_TAG]); return $this; } /** * Install Default Group Ids * * @return $this */ public function installDefaultGroupIds() { $setIds = $this->getAllAttributeSetIds(); foreach ($this->defaultGroupIdAssociations as $defaultGroupCode => $defaultGroupId) { foreach ($setIds as $set) { $groupId = $this->setup->getTableRow( 'eav_attribute_group', 'attribute_group_code', $defaultGroupCode, 'attribute_group_id', 'attribute_set_id', $set ); if (!$groupId) { $groupId = $this->setup->getTableRow( 'eav_attribute_group', 'attribute_set_id', $set, 'attribute_group_id' ); } $this->setup->updateTableRow( 'eav_attribute_group', 'attribute_group_id', $groupId, 'default_id', $defaultGroupId ); } } return $this; } /******************* ENTITY TYPES *****************/ /** * Add an entity type * * If already exists updates the entity type with params data * * @param string $code * @param array $params * @return $this */ public function addEntityType($code, array $params) { $data = [ 'entity_type_code' => $code, 'entity_model' => $params['entity_model'], 'attribute_model' => $this->_getValue($params, 'attribute_model'), 'entity_table' => $this->_getValue($params, 'table', 'eav_entity'), 'value_table_prefix' => $this->_getValue($params, 'table_prefix'), 'entity_id_field' => $this->_getValue($params, 'id_field'), 'increment_model' => $this->_getValue($params, 'increment_model'), 'increment_per_store' => $this->_getValue($params, 'increment_per_store', 0), 'increment_pad_length' => $this->_getValue($params, 'increment_pad_length', 8), 'increment_pad_char' => $this->_getValue($params, 'increment_pad_char', 0), 'additional_attribute_table' => $this->_getValue($params, 'additional_attribute_table'), 'entity_attribute_collection' => $this->_getValue($params, 'entity_attribute_collection'), ]; if (isset($params['entity_type_id'])) { $data['entity_type_id'] = $params['entity_type_id']; } if ($this->getEntityType($code, 'entity_type_id')) { $this->updateEntityType($code, $data); } else { $this->setup->getConnection()->insert( $this->setup->getTable('eav_entity_type'), $data ); } if (isset($params['entity_type_id'])) { $this->addAttributeSet($code, $this->_defaultAttributeSetName, null, $params['entity_type_id']); } else { $this->addAttributeSet($code, $this->_defaultAttributeSetName); } $this->addAttributeGroup($code, $this->_defaultGroupName, $this->_generalGroupName); $this->eavConfig->clear(); return $this; } /** * Update entity row * * @param string $code * @param string $field * @param string $value * @return $this */ public function updateEntityType($code, $field, $value = null) { $this->setup->updateTableRow( 'eav_entity_type', 'entity_type_id', $this->getEntityTypeId($code), $field, $value ); return $this; } /** * Retrieve Entity Type Data * * @param int|string $id * @param string $field * @return mixed */ public function getEntityType($id, $field = null) { return $this->setup->getTableRow( 'eav_entity_type', is_numeric($id) ? 'entity_type_id' : 'entity_type_code', $id, $field ); } /** * Retrieve Entity Type Id By Id or Code * * @param int|string $entityTypeId * @return int * @throws LocalizedException */ public function getEntityTypeId($entityTypeId) { if (!is_numeric($entityTypeId)) { $entityTypeId = $this->getEntityType($entityTypeId, 'entity_type_id'); } if (!is_numeric($entityTypeId)) { throw new LocalizedException(__('The entity ID is incorrect. Verify the ID and try again.')); } return $entityTypeId; } /** * Remove entity type by Id or Code * * @param int|string $id * @return $this */ public function removeEntityType($id) { if (is_numeric($id)) { $this->setup->deleteTableRow('eav_entity_type', 'entity_type_id', $id); } else { $this->setup->deleteTableRow('eav_entity_type', 'entity_type_code', (string)$id); } return $this; } /******************* ATTRIBUTE SETS *****************/ /** * Retrieve Attribute Set Sort order * * @param int|string $entityTypeId * @param int $sortOrder * @return int */ public function getAttributeSetSortOrder($entityTypeId, $sortOrder = null) { if (!is_numeric($sortOrder)) { $bind = ['entity_type_id' => $this->getEntityTypeId($entityTypeId)]; $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_attribute_set'), 'MAX(sort_order)' )->where( 'entity_type_id = :entity_type_id' ); $sortOrder = $this->setup->getConnection()->fetchOne($select, $bind) + 1; } return $sortOrder; } /** * Add Attribute Set * * @param int|string $entityTypeId * @param string $name * @param int $sortOrder * @param int $setId * @return $this */ public function addAttributeSet($entityTypeId, $name, $sortOrder = null, $setId = null) { $data = [ 'entity_type_id' => $this->getEntityTypeId($entityTypeId), 'attribute_set_name' => $name, 'sort_order' => $this->getAttributeSetSortOrder($entityTypeId, $sortOrder), ]; if ($setId !== null) { $data['attribute_set_id'] = $setId; } $setId = $this->getAttributeSet($entityTypeId, $name, 'attribute_set_id'); if ($setId) { $this->updateAttributeSet($entityTypeId, $setId, $data); } else { $this->setup->getConnection()->insert( $this->setup->getTable('eav_attribute_set'), $data ); $this->addAttributeGroup($entityTypeId, $name, $this->_generalGroupName); } return $this; } /** * Update attribute set data * * @param int|string $entityTypeId * @param int $id * @param string $field * @param mixed $value * @return $this */ public function updateAttributeSet($entityTypeId, $id, $field, $value = null) { $this->setup->updateTableRow( 'eav_attribute_set', 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $id), $field, $value, 'entity_type_id', $this->getEntityTypeId($entityTypeId) ); return $this; } /** * Retrieve Attribute set data by id or name * * @param int|string $entityTypeId * @param int|string $id * @param string $field * @return mixed */ public function getAttributeSet($entityTypeId, $id, $field = null) { return $this->setup->getTableRow( 'eav_attribute_set', is_numeric($id) ? 'attribute_set_id' : 'attribute_set_name', $id, $field, 'entity_type_id', $this->getEntityTypeId($entityTypeId) ); } /** * Retrieve Attribute Set Id By Id or Name * * @param int|string $entityTypeId * @param int|string $setId * @return int * @throws LocalizedException */ public function getAttributeSetId($entityTypeId, $setId) { if (!is_numeric($setId)) { $setId = $this->getAttributeSet($entityTypeId, $setId, 'attribute_set_id'); } if (!is_numeric($setId)) { throw new LocalizedException(__('The attribute set ID is incorrect. Verify the ID and try again.')); } return $setId; } /** * Remove Attribute Set * * @param int|string $entityTypeId * @param int|string $id * @return $this */ public function removeAttributeSet($entityTypeId, $id) { $this->setup->deleteTableRow( 'eav_attribute_set', 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $id) ); return $this; } /** * Set Default Attribute Set to Entity Type * * @param int|string $entityType * @param string $attributeSet * @return $this */ public function setDefaultSetToEntityType($entityType, $attributeSet = 'Default') { $entityTypeId = $this->getEntityTypeId($entityType); $setId = $this->getAttributeSetId($entityTypeId, $attributeSet); $this->updateEntityType($entityTypeId, 'default_attribute_set_id', $setId); return $this; } /** * Get identifiers of all attribute sets * * @param int|string|null $entityTypeId * @return array */ public function getAllAttributeSetIds($entityTypeId = null) { $select = $this->setup->getConnection()->select() ->from($this->setup->getTable('eav_attribute_set'), 'attribute_set_id'); $bind = []; if ($entityTypeId !== null) { $bind['entity_type_id'] = $this->getEntityTypeId($entityTypeId); $select->where('entity_type_id = :entity_type_id'); } return $this->setup->getConnection()->fetchCol($select, $bind); } /** * Retrieve Default Attribute Set for Entity Type * * @param string|int $entityType * @return int */ public function getDefaultAttributeSetId($entityType) { $bind = ['entity_type' => $entityType]; if (is_numeric($entityType)) { $where = 'entity_type_id = :entity_type'; } else { $where = 'entity_type_code = :entity_type'; } $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_entity_type'), 'default_attribute_set_id' )->where( $where ); return $this->setup->getConnection()->fetchOne($select, $bind); } /******************* ATTRIBUTE GROUPS *****************/ /** * Retrieve Attribute Group Sort order * * @param int|string $entityTypeId * @param int|string $setId * @param int $sortOrder * @return int */ public function getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder = null) { if (!is_numeric($sortOrder)) { $bind = ['attribute_set_id' => $this->getAttributeSetId($entityTypeId, $setId)]; $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_attribute_group'), 'MAX(sort_order)' )->where( 'attribute_set_id = :attribute_set_id' ); $sortOrder = $this->setup->getConnection()->fetchOne($select, $bind) + 1; } return $sortOrder; } /** * Add Attribute Group * * @param int|string $entityTypeId * @param int|string $setId * @param string $name * @param int $sortOrder * @return $this */ public function addAttributeGroup($entityTypeId, $setId, $name, $sortOrder = null) { $setId = $this->getAttributeSetId($entityTypeId, $setId); $data = ['attribute_set_id' => $setId, 'attribute_group_name' => $name]; $attributeGroupCode = $this->convertToAttributeGroupCode($name); if (isset($this->defaultGroupIdAssociations[$attributeGroupCode])) { $data['default_id'] = $this->defaultGroupIdAssociations[$attributeGroupCode]; } if ($sortOrder !== null) { $data['sort_order'] = $sortOrder; } $groupId = $this->getAttributeGroup($entityTypeId, $setId, $attributeGroupCode, 'attribute_group_id'); if ($groupId) { $this->updateAttributeGroup($entityTypeId, $setId, $groupId, $data); } else { if ($sortOrder === null) { $data['sort_order'] = $this->getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder); } if (empty($data['attribute_group_code'])) { if (empty($attributeGroupCode)) { // in the following code md5 is not used for security purposes // phpcs:disable Magento2.Security.InsecureFunction $attributeGroupCode = md5($name); } $data['attribute_group_code'] = $attributeGroupCode; } $this->setup->getConnection()->insert( $this->setup->getTable('eav_attribute_group'), $data ); } return $this; } /** * Convert group name to attribute group code. * * @param string $groupName * @return string * @since 100.1.0 */ public function convertToAttributeGroupCode($groupName) { return trim(preg_replace('/[^a-z0-9]+/', '-', strtolower((string)$groupName)), '-'); } /** * Update Attribute Group Data * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $id * @param string $field * @param mixed $value * @return $this */ public function updateAttributeGroup($entityTypeId, $setId, $id, $field, $value = null) { $this->setup->updateTableRow( 'eav_attribute_group', 'attribute_group_id', $this->getAttributeGroupId($entityTypeId, $setId, $id), $field, $value, 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $setId) ); return $this; } /** * Retrieve Attribute Group Data * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $id * @param string $field * @return mixed */ public function getAttributeGroup($entityTypeId, $setId, $id, $field = null) { if (is_numeric($id)) { $searchField = 'attribute_group_id'; } else { $id = $this->convertToAttributeGroupCode($id); if (isset($this->defaultGroupIdAssociations[$id])) { $searchField = 'default_id'; $id = $this->defaultGroupIdAssociations[$id]; } else { $searchField = 'attribute_group_code'; } } return $this->setup->getTableRow( 'eav_attribute_group', $searchField, $id, $field, 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $setId) ); } /** * Retrieve Attribute Group Data by Code * * @param int|string $entityTypeId * @param int|string $setId * @param string $code * @param string $field * @return mixed * @since 100.1.0 */ public function getAttributeGroupByCode($entityTypeId, $setId, $code, $field = null) { return $this->setup->getTableRow( 'eav_attribute_group', 'attribute_group_code', $code, $field, 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $setId) ); } /** * Retrieve Attribute Group Id by Id or Name * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $groupId * @return $this * @throws LocalizedException */ public function getAttributeGroupId($entityTypeId, $setId, $groupId) { if (!is_numeric($groupId)) { $groupId = $this->getAttributeGroup($entityTypeId, $setId, $groupId, 'attribute_group_id'); } if (!is_numeric($groupId)) { $groupId = $this->getDefaultAttributeGroupId($entityTypeId, $setId); } if (!is_numeric($groupId)) { throw new LocalizedException(__('The attribute group ID is incorrect. Verify the ID and try again.')); } return $groupId; } /** * Remove Attribute Group By Id or Name * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $id * @return $this */ public function removeAttributeGroup($entityTypeId, $setId, $id) { $this->setup->deleteTableRow( 'eav_attribute_group', 'attribute_group_id', $this->getAttributeGroupId($entityTypeId, $setId, $id) ); return $this; } /** * Retrieve Default Attribute Group Id By Entity Type and Attribute Set * * @param string|int $entityType * @param int $attributeSetId * @return int */ public function getDefaultAttributeGroupId($entityType, $attributeSetId = null) { $entityType = $this->getEntityTypeId($entityType); if (!is_numeric($attributeSetId)) { $attributeSetId = $this->getDefaultAttributeSetId($entityType); } $bind = ['attribute_set_id' => $attributeSetId]; $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_attribute_group'), 'attribute_group_id' )->where( 'attribute_set_id = :attribute_set_id' )->order( ['default_id ' . \Magento\Framework\DB\Select::SQL_DESC, 'sort_order'] )->limit( 1 ); return $this->setup->getConnection()->fetchOne($select, $bind); } /** * Get number of all attributes in group * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $groupId * * @return string */ public function getAttributesNumberInGroup($entityTypeId, $setId, $groupId) { $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_entity_attribute'), ['count' => 'COUNT(*)'] )->where( 'attribute_group_id = ?', $this->getAttributeGroupId($entityTypeId, $setId, $groupId) )->where( 'entity_type_id = ?', $entityTypeId )->where( 'attribute_set_id = ?', $setId ); return $this->setup->getConnection()->fetchOne($select); } /******************* ATTRIBUTES *****************/ /** * Retrieve value from array by key or return default value * * @param array $array * @param string $key * @param string $default * @return string */ private function _getValue($array, $key, $default = null) { if (isset($array[$key]) && is_bool($array[$key])) { $array[$key] = (int)$array[$key]; } return isset($array[$key]) ? $array[$key] : $default; } /** * Add attribute to an entity type * * If attribute is system will add to all existing attribute sets * * @param string|integer $entityTypeId * @param string $code * @param array $attr * @return $this * @throws LocalizedException|ValidateException */ public function addAttribute($entityTypeId, $code, array $attr) { $entityTypeId = $this->getEntityTypeId($entityTypeId); $data = array_replace( ['entity_type_id' => $entityTypeId, 'attribute_code' => $code], $this->attributeMapper->map($attr, $entityTypeId) ); $this->validateAttributeCode($data); $sortOrder = isset($attr['sort_order']) ? $attr['sort_order'] : null; $attributeId = $this->getAttribute($entityTypeId, $code, 'attribute_id'); if ($attributeId) { $this->updateAttribute($entityTypeId, $attributeId, $data, null, $sortOrder); } else { $this->_insertAttribute($data); } if (!empty($attr['group']) || empty($attr['user_defined'])) { $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_attribute_set') )->where( 'entity_type_id = :entity_type_id' ); $sets = $this->setup->getConnection()->fetchAll($select, ['entity_type_id' => $entityTypeId]); foreach ($sets as $set) { if (!empty($attr['group'])) { $this->addAttributeGroup($entityTypeId, $set['attribute_set_id'], $attr['group']); $this->addAttributeToSet( $entityTypeId, $set['attribute_set_id'], $attr['group'], $code, $sortOrder ); } else { $this->addAttributeToSet( $entityTypeId, $set['attribute_set_id'], $this->_generalGroupName, $code, $sortOrder ); } } } if (isset($attr['option']) && is_array($attr['option'])) { $option = $attr['option']; $option['attribute_id'] = $this->getAttributeId($entityTypeId, $code); $this->addAttributeOption($option); } return $this; } /** * Add Attribute Option * * @param array $option * @return void * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function addAttributeOption($option) { $this->addAttributeOption->execute($option); } /** * Update Attribute data and Attribute additional data * * @param int|string $entityTypeId * @param int|string $id * @param string|array $field * @param mixed $value * @param int $sortOrder * @return $this */ public function updateAttribute($entityTypeId, $id, $field, $value = null, $sortOrder = null) { $this->_updateAttribute($entityTypeId, $id, $field, $value, $sortOrder); $this->_updateAttributeAdditionalData($entityTypeId, $id, $field, $value); return $this; } /** * Update Attribute data * * @param int|string $entityTypeId * @param int|string $id * @param string $field * @param mixed $value * @param int $sortOrder * @return $this * @throws LocalizedException */ private function _updateAttribute($entityTypeId, $id, $field, $value = null, $sortOrder = null) { if ($sortOrder !== null) { $this->setup->updateTableRow( 'eav_entity_attribute', 'attribute_id', $this->getAttributeId($entityTypeId, $id), 'sort_order', $sortOrder ); } $attributeFields = $this->_getAttributeTableFields(); if (is_array($field)) { $bind = []; foreach ($field as $k => $v) { if (isset($attributeFields[$k])) { $bind[$k] = $this->setup->getConnection()->prepareColumnValue( $attributeFields[$k], $v ); } } if (!$bind) { return $this; } $field = $bind; } else { if (!isset($attributeFields[$field])) { return $this; } } $attributeId = $this->getAttributeId($entityTypeId, $id); if (false === $attributeId) { throw new LocalizedException(__('Attribute with ID: "%1" does not exist', $id)); } $this->setup->updateTableRow( 'eav_attribute', 'attribute_id', $attributeId, $field, $value, 'entity_type_id', $this->getEntityTypeId($entityTypeId) ); return $this; } /** * Update Attribute Additional data * * @param int|string $entityTypeId * @param int|string $id * @param string|array $field * @param mixed $value * @return $this * @throws LocalizedException */ private function _updateAttributeAdditionalData($entityTypeId, $id, $field, $value = null) { $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table'); if (!$additionalTable) { return $this; } $additionalTableExists = $this->setup->getConnection()->isTableExists( $this->setup->getTable($additionalTable) ); if (!$additionalTableExists) { return $this; } $attributeFields = $this->setup->getConnection()->describeTable( $this->setup->getTable($additionalTable) ); if (is_array($field)) { $bind = []; foreach ($field as $k => $v) { if (isset($attributeFields[$k])) { $bind[$k] = $this->setup->getConnection()->prepareColumnValue( $attributeFields[$k], $v ); } } if (!$bind) { return $this; } $field = $bind; } else { if (!isset($attributeFields[$field])) { return $this; } } $attributeId = $this->getAttributeId($entityTypeId, $id); if (false === $attributeId) { throw new LocalizedException(__('Attribute with ID: "%1" does not exist', $id)); } $this->setup->updateTableRow( $this->setup->getTable($additionalTable), 'attribute_id', $this->getAttributeId($entityTypeId, $id), $field, $value ); $attribute = $this->getAttribute($entityTypeId, $id); $this->updateCachedRow($field, $value, $attribute); return $this; } /** * Updates cache for the row * * @param string|array $field * @param mixed $value * @param array $attribute * * @return void */ private function updateCachedRow($field, $value, $attribute) { $setupCache = $this->setup->getSetupCache(); $mainTable = $this->setup->getTable('eav_attribute'); if (is_array($field)) { $oldRow = $setupCache->has($mainTable, $attribute['entity_type_id'], $attribute['attribute_code']) ? $setupCache->get($mainTable, $attribute['entity_type_id'], $attribute['attribute_code']) : []; $newRowData = array_merge($oldRow, $field); $setupCache->setRow( $mainTable, $attribute['entity_type_id'], $attribute['attribute_code'], $newRowData ); } else { $setupCache->setField( $mainTable, $attribute['entity_type_id'], $attribute['attribute_code'], $field, $value ); } } /** * Retrieve Attribute Data By Id or Code * * @param int|string $entityTypeId * @param int|string $id * @param string $field * @return mixed */ public function getAttribute($entityTypeId, $id, $field = null) { $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table'); $entityTypeId = $this->getEntityTypeId($entityTypeId); $idField = is_numeric($id) ? 'attribute_id' : 'attribute_code'; if (!$additionalTable) { return $this->setup->getTableRow('eav_attribute', $idField, $id, $field, 'entity_type_id', $entityTypeId); } $mainTable = $this->setup->getTable('eav_attribute'); $setupCache = $this->setup->getSetupCache(); if (!$setupCache->has($mainTable, $entityTypeId, $id)) { $additionalTable = $this->setup->getTable($additionalTable); $bind = ['id' => $id, 'entity_type_id' => $entityTypeId]; $select = $this->setup->getConnection()->select()->from( ['main' => $mainTable] )->join( ['additional' => $additionalTable], 'main.attribute_id = additional.attribute_id' )->where( "main.{$idField} = :id" )->where( 'main.entity_type_id = :entity_type_id' ); $row = $this->setup->getConnection()->fetchRow($select, $bind); if (!$row) { $setupCache->setRow($mainTable, $entityTypeId, $id, []); } else { $setupCache->setRow($mainTable, $entityTypeId, $row['attribute_id'], $row); $setupCache->setRow($mainTable, $entityTypeId, $row['attribute_code'], $row); } } $row = $setupCache->get($mainTable, $entityTypeId, $id); if ($field !== null) { return isset($row[$field]) ? $row[$field] : false; } return $row; } /** * Retrieve Attribute Id Data By Id or Code * * @param int|string $entityTypeId * @param int|string $id * @return int */ public function getAttributeId($entityTypeId, $id) { if (!is_numeric($id)) { $id = $this->getAttribute($entityTypeId, $id, 'attribute_id'); } if (!is_numeric($id)) { return false; } return $id; } /** * Return table name for eav attribute * * @param int|string $entityTypeId Entity Type id or Entity Type code * @param int|string $id Attribute id or Attribute code * @return string */ public function getAttributeTable($entityTypeId, $id) { $entityKeyName = is_numeric($entityTypeId) ? 'entity_type_id' : 'entity_type_code'; $attributeKeyName = is_numeric($id) ? 'attribute_id' : 'attribute_code'; $bind = ['id' => $id, 'entity_type_id' => $entityTypeId]; $select = $this->setup->getConnection()->select()->from( ['entity_type' => $this->setup->getTable('eav_entity_type')], ['entity_table'] )->join( ['attribute' => $this->setup->getTable('eav_attribute')], 'attribute.entity_type_id = entity_type.entity_type_id', ['backend_type'] )->where( "entity_type.{$entityKeyName} = :entity_type_id" )->where( "attribute.{$attributeKeyName} = :id" )->limit( 1 ); $result = $this->setup->getConnection()->fetchRow($select, $bind); if ($result) { $table = $this->setup->getTable($result['entity_table']); if ($result['backend_type'] != 'static') { $table .= '_' . $result['backend_type']; } return $table; } return false; } /** * Remove Attribute * * @param int|string $entityTypeId * @param int|string $code * @return $this */ public function removeAttribute($entityTypeId, $code) { $mainTable = $this->setup->getTable('eav_attribute'); $attribute = $this->getAttribute($entityTypeId, $code); if ($attribute) { $this->setup->deleteTableRow('eav_attribute', 'attribute_id', $attribute['attribute_id']); $setupCache = $this->setup->getSetupCache(); if ($setupCache->has($mainTable, $attribute['entity_type_id'], $attribute['attribute_code'])) { $setupCache->remove($mainTable, $attribute['entity_type_id'], $attribute['attribute_code']); } } return $this; } /** * Retrieve Attribute Sort Order * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $groupId * @param int $sortOrder * @return $this */ public function getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder = null) { if (!is_numeric($sortOrder)) { $bind = ['attribute_group_id' => $this->getAttributeGroupId($entityTypeId, $setId, $groupId)]; $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_entity_attribute'), 'MAX(sort_order)' )->where( 'attribute_group_id = :attribute_group_id' ); $sortOrder = $this->setup->getConnection()->fetchOne($select, $bind) + 1; } return $sortOrder; } /** * Add Attribute to All Groups on Attribute Set * * @param int|string $entityTypeId * @param int|string $setId * @param int|string $groupId * @param int|string $attributeId * @param int $sortOrder * @return $this */ public function addAttributeToSet($entityTypeId, $setId, $groupId, $attributeId, $sortOrder = null) { $entityTypeId = $this->getEntityTypeId($entityTypeId); $setId = $this->getAttributeSetId($entityTypeId, $setId); $groupId = $this->getAttributeGroupId($entityTypeId, $setId, $groupId); $attributeId = $this->getAttributeId($entityTypeId, $attributeId); $table = $this->setup->getTable('eav_entity_attribute'); $bind = ['attribute_set_id' => $setId, 'attribute_id' => $attributeId]; $select = $this->setup->getConnection()->select()->from( $table )->where( 'attribute_set_id = :attribute_set_id' )->where( 'attribute_id = :attribute_id' ); $result = $this->setup->getConnection()->fetchRow($select, $bind); if ($result) { if ($result['attribute_group_id'] != $groupId) { $where = ['entity_attribute_id =?' => $result['entity_attribute_id']]; $data = ['attribute_group_id' => $groupId]; $this->setup->getConnection()->update($table, $data, $where); } } else { $data = [ 'entity_type_id' => $entityTypeId, 'attribute_set_id' => $setId, 'attribute_group_id' => $groupId, 'attribute_id' => $attributeId, 'sort_order' => $this->getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder), ]; $this->setup->getConnection()->insert($table, $data); } return $this; } /** * Add or update attribute to group * * @param int|string $entityType * @param int|string $setId * @param int|string $groupId * @param int|string $attributeId * @param int $sortOrder * @return $this */ public function addAttributeToGroup($entityType, $setId, $groupId, $attributeId, $sortOrder = null) { $entityType = $this->getEntityTypeId($entityType); $setId = $this->getAttributeSetId($entityType, $setId); $groupId = $this->getAttributeGroupId($entityType, $setId, $groupId); $attributeId = $this->getAttributeId($entityType, $attributeId); $data = [ 'entity_type_id' => $entityType, 'attribute_set_id' => $setId, 'attribute_group_id' => $groupId, 'attribute_id' => $attributeId, ]; $bind = ['entity_type_id' => $entityType, 'attribute_set_id' => $setId, 'attribute_id' => $attributeId]; $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_entity_attribute') )->where( 'entity_type_id = :entity_type_id' )->where( 'attribute_set_id = :attribute_set_id' )->where( 'attribute_id = :attribute_id' ); $row = $this->setup->getConnection()->fetchRow($select, $bind); if ($row) { // update if ($sortOrder !== null) { $data['sort_order'] = $sortOrder; } $this->setup->getConnection()->update( $this->setup->getTable('eav_entity_attribute'), $data, $this->setup->getConnection()->quoteInto('entity_attribute_id=?', $row['entity_attribute_id']) ); } else { if ($sortOrder === null) { $select = $this->setup->getConnection()->select()->from( $this->setup->getTable('eav_entity_attribute'), 'MAX(sort_order)' )->where( 'entity_type_id = :entity_type_id' )->where( 'attribute_set_id = :attribute_set_id' )->where( 'attribute_id = :attribute_id' ); $sortOrder = $this->setup->getConnection()->fetchOne($select, $bind) + 10; } $sortOrder = is_numeric($sortOrder) ? $sortOrder : 1; $data['sort_order'] = $sortOrder; $this->setup->getConnection()->insert( $this->setup->getTable('eav_entity_attribute'), $data ); } return $this; } /******************* BULK INSTALL *****************/ /** * Gets default entities and attributes * * @return array */ public function getDefaultEntities() { return []; } /** * Install entities * * @param array $entities * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function installEntities($entities = null) { $this->cleanCache(); if ($entities === null) { $entities = $this->getDefaultEntities(); } foreach ($entities as $entityName => $entity) { $this->addEntityType($entityName, $entity); $frontendPrefix = isset($entity['frontend_prefix']) ? $entity['frontend_prefix'] : ''; $backendPrefix = isset($entity['backend_prefix']) ? $entity['backend_prefix'] : ''; $sourcePrefix = isset($entity['source_prefix']) ? $entity['source_prefix'] : ''; if (is_array($entity['attributes']) && !empty($entity['attributes'])) { foreach ($entity['attributes'] as $attrCode => $attr) { if (!empty($attr['backend'])) { if ('_' === $attr['backend']) { $attr['backend'] = $backendPrefix; } elseif ('_' === $attr['backend'][0]) { $attr['backend'] = $backendPrefix . $attr['backend']; } } if (!empty($attr['frontend'])) { if ('_' === $attr['frontend']) { $attr['frontend'] = $frontendPrefix; } elseif ('_' === $attr['frontend'][0]) { $attr['frontend'] = $frontendPrefix . $attr['frontend']; } } if (!empty($attr['source'])) { if ('_' === $attr['source']) { $attr['source'] = $sourcePrefix; } elseif ('_' === $attr['source'][0]) { $attr['source'] = $sourcePrefix . $attr['source']; } } $this->addAttribute($entityName, $attrCode, $attr); } } $this->setDefaultSetToEntityType($entityName); } return $this; } /** * Retrieve attribute table fields * * @return array */ private function _getAttributeTableFields() { return $this->setup->getConnection()->describeTable( $this->setup->getTable('eav_attribute') ); } /** * Insert attribute and filter data * * @param array $data * @return $this */ private function _insertAttribute(array $data) { $bind = []; $fields = $this->_getAttributeTableFields(); foreach ($data as $k => $v) { if (isset($fields[$k])) { $bind[$k] = $this->setup->getConnection()->prepareColumnValue($fields[$k], $v); } } if (!$bind) { return $this; } $this->setup->getConnection()->insert( $this->setup->getTable('eav_attribute'), $bind ); $attributeId = $this->setup->getConnection()->lastInsertId( $this->setup->getTable('eav_attribute') ); $this->_insertAttributeAdditionalData( $data['entity_type_id'], array_merge(['attribute_id' => $attributeId], $data) ); return $this; } /** * Insert attribute additional data * * @param int|string $entityTypeId * @param array $data * @return $this */ private function _insertAttributeAdditionalData($entityTypeId, array $data) { $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table'); if (!$additionalTable) { return $this; } $additionalTableExists = $this->setup->getConnection()->isTableExists( $this->setup->getTable($additionalTable) ); if ($additionalTable && $additionalTableExists) { $bind = []; $fields = $this->setup->getConnection()->describeTable( $this->setup->getTable($additionalTable) ); foreach ($data as $k => $v) { if (isset($fields[$k])) { $bind[$k] = $this->setup->getConnection()->prepareColumnValue($fields[$k], $v); } } if (!$bind) { return $this; } $this->setup->getConnection()->insert( $this->setup->getTable($additionalTable), $bind ); } return $this; } /** * Validate attribute code. * * @param array $data * @throws LocalizedException * @throws ValidateException */ private function validateAttributeCode(array $data): void { $attributeCode = $data['attribute_code'] ?? ''; if (!$this->attributeCodeValidator->isValid($attributeCode)) { $errorMessage = implode('\n', $this->attributeCodeValidator->getMessages()); throw new LocalizedException(__($errorMessage)); } /* Actual attribute is created from data array for compatibility with reserved attribute validator logic */ $attribute = $this->attributeFactory->createAttribute(Attribute::class, $data); if ($this->reservedAttributeChecker->isReservedAttribute($attribute)) { throw new LocalizedException( __( 'The attribute code \'%1\' is reserved by system. Please try another attribute code', $attributeCode ) ); } } }