Attribute.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Eav\Model\ResourceModel\Entity;
  7. use Magento\Eav\Model\Config;
  8. use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
  9. use Magento\Eav\Model\Entity\Attribute as EntityAttribute;
  10. use Magento\Framework\App\ObjectManager;
  11. use Magento\Framework\DB\Select;
  12. use Magento\Framework\Model\AbstractModel;
  13. /**
  14. * EAV attribute resource model
  15. *
  16. * @api
  17. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  18. * @since 100.0.2
  19. */
  20. class Attribute extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
  21. {
  22. /**
  23. * Eav Entity attributes cache
  24. *
  25. * @var array
  26. */
  27. protected static $_entityAttributes = [];
  28. /**
  29. * @var \Magento\Store\Model\StoreManagerInterface
  30. */
  31. protected $_storeManager;
  32. /**
  33. * @var Type
  34. */
  35. protected $_eavEntityType;
  36. /**
  37. * @var Config
  38. */
  39. private $config;
  40. /**
  41. * Class constructor
  42. *
  43. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  44. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  45. * @param Type $eavEntityType
  46. * @param string $connectionName
  47. * @codeCoverageIgnore
  48. */
  49. public function __construct(
  50. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  51. \Magento\Store\Model\StoreManagerInterface $storeManager,
  52. Type $eavEntityType,
  53. $connectionName = null
  54. ) {
  55. $this->_storeManager = $storeManager;
  56. $this->_eavEntityType = $eavEntityType;
  57. parent::__construct($context, $connectionName);
  58. }
  59. /**
  60. * Define main table
  61. *
  62. * @return void
  63. * @codeCoverageIgnore
  64. */
  65. protected function _construct()
  66. {
  67. $this->_init('eav_attribute', 'attribute_id');
  68. }
  69. /**
  70. * Initialize unique fields
  71. *
  72. * @return $this
  73. * @codeCoverageIgnore
  74. */
  75. protected function _initUniqueFields()
  76. {
  77. $this->_uniqueFields = [
  78. ['field' => ['attribute_code', 'entity_type_id'], 'title' => __('Attribute with the same code')],
  79. ];
  80. return $this;
  81. }
  82. /**
  83. * Load attribute data by attribute code
  84. *
  85. * @param EntityAttribute|\Magento\Framework\Model\AbstractModel $object
  86. * @param int $entityTypeId
  87. * @param string $code
  88. * @return bool
  89. */
  90. public function loadByCode(AbstractModel $object, $entityTypeId, $code)
  91. {
  92. $bind = [':entity_type_id' => $entityTypeId];
  93. $select = $this->_getLoadSelect('attribute_code', $code, $object)->where('entity_type_id = :entity_type_id');
  94. $data = $this->getConnection()->fetchRow($select, $bind);
  95. if ($data) {
  96. $object->setData($data);
  97. $this->_afterLoad($object);
  98. return true;
  99. }
  100. return false;
  101. }
  102. /**
  103. * Retrieve Max Sort order for attribute in group
  104. *
  105. * @param AbstractModel $object
  106. * @return int
  107. */
  108. private function _getMaxSortOrder(AbstractModel $object)
  109. {
  110. if ((int)$object->getAttributeGroupId() > 0) {
  111. $connection = $this->getConnection();
  112. $bind = [
  113. ':attribute_set_id' => $object->getAttributeSetId(),
  114. ':attribute_group_id' => $object->getAttributeGroupId(),
  115. ];
  116. $select = $connection->select()->from(
  117. $this->getTable('eav_entity_attribute'),
  118. new \Zend_Db_Expr("MAX(sort_order)")
  119. )->where(
  120. 'attribute_set_id = :attribute_set_id'
  121. )->where(
  122. 'attribute_group_id = :attribute_group_id'
  123. );
  124. return $connection->fetchOne($select, $bind);
  125. }
  126. return 0;
  127. }
  128. /**
  129. * Delete entity
  130. *
  131. * @param \Magento\Framework\Model\AbstractMode $object
  132. * @return $this
  133. */
  134. public function deleteEntity(\Magento\Framework\Model\AbstractModel $object)
  135. {
  136. if (!$object->getEntityAttributeId()) {
  137. return $this;
  138. }
  139. $this->getConnection()->delete(
  140. $this->getTable('eav_entity_attribute'),
  141. ['entity_attribute_id = ?' => $object->getEntityAttributeId()]
  142. );
  143. return $this;
  144. }
  145. /**
  146. * Validate attribute data before save
  147. *
  148. * @param EntityAttribute|AbstractModel $object
  149. * @return $this
  150. * @throws \Magento\Framework\Exception\LocalizedException
  151. */
  152. protected function _beforeSave(AbstractModel $object)
  153. {
  154. $frontendLabel = $object->getFrontendLabel();
  155. if (is_array($frontendLabel)) {
  156. $this->checkDefaultFrontendLabelExists($frontendLabel, $frontendLabel);
  157. $object->setFrontendLabel($frontendLabel[0])->setStoreLabels($frontendLabel);
  158. } else {
  159. $this->setStoreLabels($object, $frontendLabel);
  160. }
  161. /**
  162. * @todo need use default source model of entity type !!!
  163. */
  164. if (!$object->getId()) {
  165. if ($object->getFrontendInput() == 'select') {
  166. $object->setSourceModel(\Magento\Eav\Model\Entity\Attribute\Source\Table::class);
  167. }
  168. }
  169. return parent::_beforeSave($object);
  170. }
  171. /**
  172. * Save additional attribute data after save attribute
  173. *
  174. * @param EntityAttribute|AbstractModel $object
  175. * @return $this
  176. */
  177. protected function _afterSave(AbstractModel $object)
  178. {
  179. $this->_saveStoreLabels(
  180. $object
  181. )->_saveAdditionalAttributeData(
  182. $object
  183. )->saveInSetIncluding(
  184. $object
  185. )->_saveOption(
  186. $object
  187. );
  188. $this->getConfig()->clear();
  189. return parent::_afterSave($object);
  190. }
  191. /**
  192. * Perform actions after object delete
  193. *
  194. * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
  195. * @return $this
  196. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  197. * @since 100.0.7
  198. */
  199. protected function _afterDelete(\Magento\Framework\Model\AbstractModel $object)
  200. {
  201. $this->getConfig()->clear();
  202. return $this;
  203. }
  204. /**
  205. * Returns config instance
  206. *
  207. * @return Config
  208. * @deprecated 100.0.7
  209. */
  210. private function getConfig()
  211. {
  212. if (!$this->config) {
  213. $this->config = ObjectManager::getInstance()->get(Config::class);
  214. }
  215. return $this->config;
  216. }
  217. /**
  218. * Save store labels
  219. *
  220. * @param EntityAttribute|\Magento\Framework\Model\AbstractModel $object
  221. * @return $this
  222. */
  223. protected function _saveStoreLabels(AbstractModel $object)
  224. {
  225. $storeLabels = $object->getStoreLabels();
  226. if (is_array($storeLabels)) {
  227. $connection = $this->getConnection();
  228. if ($object->getId()) {
  229. $condition = ['attribute_id =?' => $object->getId()];
  230. $connection->delete($this->getTable('eav_attribute_label'), $condition);
  231. }
  232. foreach ($storeLabels as $storeId => $label) {
  233. if ($storeId == 0 || !strlen($label)) {
  234. continue;
  235. }
  236. $bind = ['attribute_id' => $object->getId(), 'store_id' => $storeId, 'value' => $label];
  237. $connection->insert($this->getTable('eav_attribute_label'), $bind);
  238. }
  239. }
  240. return $this;
  241. }
  242. /**
  243. * Save additional data of attribute
  244. *
  245. * @param EntityAttribute|\Magento\Framework\Model\AbstractModel $object
  246. * @return $this
  247. */
  248. protected function _saveAdditionalAttributeData(AbstractModel $object)
  249. {
  250. $additionalTable = $this->getAdditionalAttributeTable($object->getEntityTypeId());
  251. if ($additionalTable) {
  252. $connection = $this->getConnection();
  253. $data = $this->_prepareDataForTable($object, $this->getTable($additionalTable));
  254. $bind = [':attribute_id' => $object->getId()];
  255. $select = $connection->select()->from(
  256. $this->getTable($additionalTable),
  257. ['attribute_id']
  258. )->where(
  259. 'attribute_id = :attribute_id'
  260. );
  261. $result = $connection->fetchOne($select, $bind);
  262. if ($result) {
  263. $where = ['attribute_id = ?' => $object->getId()];
  264. $connection->update($this->getTable($additionalTable), $data, $where);
  265. } else {
  266. $connection->insert($this->getTable($additionalTable), $data);
  267. }
  268. }
  269. return $this;
  270. }
  271. /**
  272. * Save in set including
  273. *
  274. * @param AbstractModel $object
  275. * @param int|null $attributeEntityId
  276. * @param int|null $attributeSetId
  277. * @param int|null $attributeGroupId
  278. * @param int|null $attributeSortOrder
  279. * @return $this
  280. * @SuppressWarnings(PHPMD.NPathComplexity)
  281. */
  282. public function saveInSetIncluding(
  283. AbstractModel $object,
  284. $attributeEntityId = null,
  285. $attributeSetId = null,
  286. $attributeGroupId = null,
  287. $attributeSortOrder = null
  288. ) {
  289. $attributeId = $attributeEntityId === null ? (int)$object->getId() : (int)$attributeEntityId;
  290. $setId = $attributeSetId === null ? (int)$object->getAttributeSetId() : (int)$attributeSetId;
  291. $groupId = $attributeGroupId === null ? (int)$object->getAttributeGroupId() : (int)$attributeGroupId;
  292. $attributeSortOrder = $attributeSortOrder === null ? (int)$object->getSortOrder() : (int)$attributeSortOrder;
  293. if ($setId && $groupId && $object->getEntityTypeId()) {
  294. $connection = $this->getConnection();
  295. $table = $this->getTable('eav_entity_attribute');
  296. $sortOrder = $attributeSortOrder ?: $this->_getMaxSortOrder($object) + 1;
  297. $data = [
  298. 'entity_type_id' => $object->getEntityTypeId(),
  299. 'attribute_set_id' => $setId,
  300. 'attribute_group_id' => $groupId,
  301. 'attribute_id' => $attributeId,
  302. 'sort_order' => $sortOrder,
  303. ];
  304. $where = ['attribute_id =?' => $attributeId, 'attribute_set_id =?' => $setId];
  305. $connection->delete($table, $where);
  306. $connection->insert($table, $data);
  307. }
  308. return $this;
  309. }
  310. /**
  311. * Save attribute options
  312. *
  313. * @param EntityAttribute|AbstractModel $object
  314. * @return $this
  315. */
  316. protected function _saveOption(AbstractModel $object)
  317. {
  318. $option = $object->getOption();
  319. if (!is_array($option)) {
  320. return $this;
  321. }
  322. $defaultValue = $object->getDefault() ?: [];
  323. if (isset($option['value'])) {
  324. if (!is_array($object->getDefault())) {
  325. $object->setDefault([]);
  326. }
  327. $defaultValue = $this->_processAttributeOptions($object, $option);
  328. }
  329. $this->_saveDefaultValue($object, $defaultValue);
  330. return $this;
  331. }
  332. /**
  333. * Save changes of attribute options, return obtained default value
  334. *
  335. * @param EntityAttribute|AbstractModel $object
  336. * @param array $option
  337. * @return array
  338. */
  339. protected function _processAttributeOptions($object, $option)
  340. {
  341. $defaultValue = [];
  342. foreach ($option['value'] as $optionId => $values) {
  343. $intOptionId = $this->_updateAttributeOption($object, $optionId, $option);
  344. if ($intOptionId === false) {
  345. continue;
  346. }
  347. $this->_updateDefaultValue($object, $optionId, $intOptionId, $defaultValue);
  348. $this->_checkDefaultOptionValue($values);
  349. $this->_updateAttributeOptionValues($intOptionId, $values);
  350. }
  351. return $defaultValue;
  352. }
  353. /**
  354. * Check default option value presence
  355. *
  356. * @param array $values
  357. * @return void
  358. * @throws \Magento\Framework\Exception\LocalizedException
  359. */
  360. protected function _checkDefaultOptionValue($values)
  361. {
  362. if (!isset($values[0])) {
  363. throw new \Magento\Framework\Exception\LocalizedException(
  364. __("The default option isn't defined. Set the option and try again.")
  365. );
  366. }
  367. }
  368. /**
  369. * Update attribute default value
  370. *
  371. * @param EntityAttribute|AbstractModel $object
  372. * @param int|string $optionId
  373. * @param int $intOptionId
  374. * @param array $defaultValue
  375. * @return void
  376. */
  377. protected function _updateDefaultValue($object, $optionId, $intOptionId, &$defaultValue)
  378. {
  379. if (in_array($optionId, $object->getDefault())) {
  380. $frontendInput = $object->getFrontendInput();
  381. if ($frontendInput === 'multiselect') {
  382. $defaultValue[] = $intOptionId;
  383. } elseif ($frontendInput === 'select') {
  384. $defaultValue = [$intOptionId];
  385. }
  386. }
  387. }
  388. /**
  389. * Save attribute default value
  390. *
  391. * @param AbstractModel $object
  392. * @param array $defaultValue
  393. * @return void
  394. */
  395. protected function _saveDefaultValue($object, $defaultValue)
  396. {
  397. if ($defaultValue !== null) {
  398. $bind = ['default_value' => implode(',', $defaultValue)];
  399. $where = ['attribute_id = ?' => $object->getId()];
  400. $this->getConnection()->update($this->getMainTable(), $bind, $where);
  401. }
  402. }
  403. /**
  404. * Save option records
  405. *
  406. * @param AbstractModel $object
  407. * @param int $optionId
  408. * @param array $option
  409. * @return int|bool
  410. */
  411. protected function _updateAttributeOption($object, $optionId, $option)
  412. {
  413. $connection = $this->getConnection();
  414. $table = $this->getTable('eav_attribute_option');
  415. // ignore strings that start with a number
  416. $intOptionId = is_numeric($optionId) ? (int)$optionId : 0;
  417. if (!empty($option['delete'][$optionId])) {
  418. if ($intOptionId) {
  419. $connection->delete($table, ['option_id = ?' => $intOptionId]);
  420. }
  421. return false;
  422. }
  423. $sortOrder = empty($option['order'][$optionId]) ? 0 : $option['order'][$optionId];
  424. if (!$intOptionId) {
  425. $data = ['attribute_id' => $object->getId(), 'sort_order' => $sortOrder];
  426. $connection->insert($table, $data);
  427. $intOptionId = $connection->lastInsertId($table);
  428. } else {
  429. $data = ['sort_order' => $sortOrder];
  430. $where = ['option_id = ?' => $intOptionId];
  431. $connection->update($table, $data, $where);
  432. }
  433. return $intOptionId;
  434. }
  435. /**
  436. * Save option values records per store
  437. *
  438. * @param int $optionId
  439. * @param array $values
  440. * @return void
  441. */
  442. protected function _updateAttributeOptionValues($optionId, $values)
  443. {
  444. $connection = $this->getConnection();
  445. $table = $this->getTable('eav_attribute_option_value');
  446. $connection->delete($table, ['option_id = ?' => $optionId]);
  447. $stores = $this->_storeManager->getStores(true);
  448. foreach ($stores as $store) {
  449. $storeId = $store->getId();
  450. if (!empty($values[$storeId]) || isset($values[$storeId]) && $values[$storeId] == '0') {
  451. $data = ['option_id' => $optionId, 'store_id' => $storeId, 'value' => $values[$storeId]];
  452. $connection->insert($table, $data);
  453. }
  454. }
  455. }
  456. /**
  457. * Retrieve attribute id by entity type code and attribute code
  458. *
  459. * @param string $entityType
  460. * @param string $code
  461. * @return int
  462. */
  463. public function getIdByCode($entityType, $code)
  464. {
  465. $connection = $this->getConnection();
  466. $bind = [':entity_type_code' => $entityType, ':attribute_code' => $code];
  467. $select = $connection->select()->from(
  468. ['a' => $this->getTable('eav_attribute')],
  469. ['a.attribute_id']
  470. )->join(
  471. ['t' => $this->getTable('eav_entity_type')],
  472. 'a.entity_type_id = t.entity_type_id',
  473. []
  474. )->where(
  475. 't.entity_type_code = :entity_type_code'
  476. )->where(
  477. 'a.attribute_code = :attribute_code'
  478. );
  479. return $connection->fetchOne($select, $bind);
  480. }
  481. /**
  482. * Get entity attribute
  483. *
  484. * @param int|string $entityAttributeId
  485. * @return array
  486. * @since 100.1.0
  487. */
  488. public function getEntityAttribute($entityAttributeId)
  489. {
  490. $select = $this->getConnection()->select()->from(
  491. $this->getTable('eav_entity_attribute')
  492. )->where(
  493. 'entity_attribute_id = ?',
  494. (int)$entityAttributeId
  495. );
  496. return $this->getConnection()->fetchRow($select);
  497. }
  498. /**
  499. * Retrieve attribute codes by front-end type
  500. *
  501. * @param string $frontendType
  502. * @return array
  503. */
  504. public function getAttributeCodesByFrontendType($frontendType)
  505. {
  506. $connection = $this->getConnection();
  507. $bind = [':frontend_input' => $frontendType];
  508. $select = $connection->select()->from(
  509. $this->getTable('eav_attribute'),
  510. 'attribute_code'
  511. )->where(
  512. 'frontend_input = :frontend_input'
  513. );
  514. return $connection->fetchCol($select, $bind);
  515. }
  516. /**
  517. * Retrieve Select For Flat Attribute update
  518. *
  519. * @param AbstractAttribute $attribute
  520. * @param int $storeId
  521. * @return Select
  522. */
  523. public function getFlatUpdateSelect(AbstractAttribute $attribute, $storeId)
  524. {
  525. $connection = $this->getConnection();
  526. $joinConditionTemplate = "%s.entity_id=%s.entity_id" .
  527. " AND %s.entity_type_id = " .
  528. $attribute->getEntityTypeId() .
  529. " AND %s.attribute_id = " .
  530. $attribute->getId() .
  531. " AND %s.store_id = %d";
  532. $joinCondition = sprintf(
  533. $joinConditionTemplate,
  534. 'e',
  535. 't1',
  536. 't1',
  537. 't1',
  538. 't1',
  539. \Magento\Store\Model\Store::DEFAULT_STORE_ID
  540. );
  541. if ($attribute->getFlatAddChildData()) {
  542. $joinCondition .= ' AND e.child_id = t1.entity_id';
  543. }
  544. $valueExpr = $connection->getCheckSql('t2.value_id > 0', 't2.value', 't1.value');
  545. /** @var $select Select */
  546. $select = $connection->select()->joinLeft(
  547. ['t1' => $attribute->getBackend()->getTable()],
  548. $joinCondition,
  549. []
  550. )->joinLeft(
  551. ['t2' => $attribute->getBackend()->getTable()],
  552. sprintf($joinConditionTemplate, 't1', 't2', 't2', 't2', 't2', $storeId),
  553. [$attribute->getAttributeCode() => $valueExpr]
  554. );
  555. if ($attribute->getFlatAddChildData()) {
  556. $select->where("e.is_child = ?", 0);
  557. }
  558. return $select;
  559. }
  560. /**
  561. * Returns the column descriptions for a table
  562. *
  563. * @param string $table
  564. * @return array
  565. * @codeCoverageIgnore
  566. */
  567. public function describeTable($table)
  568. {
  569. return $this->getConnection()->describeTable($table);
  570. }
  571. /**
  572. * Retrieve additional attribute table name for specified entity type
  573. *
  574. * @param int $entityTypeId
  575. * @return string
  576. * @codeCoverageIgnore
  577. */
  578. public function getAdditionalAttributeTable($entityTypeId)
  579. {
  580. return $this->_eavEntityType->getAdditionalAttributeTable($entityTypeId);
  581. }
  582. /**
  583. * Load additional attribute data.
  584. *
  585. * Load label of current active store
  586. *
  587. * @param EntityAttribute|AbstractModel $object
  588. * @return $this
  589. */
  590. protected function _afterLoad(AbstractModel $object)
  591. {
  592. /** @var $entityType \Magento\Eav\Model\Entity\Type */
  593. $entityType = $object->getData('entity_type');
  594. if ($entityType) {
  595. $additionalTable = $entityType->getAdditionalAttributeTable();
  596. } else {
  597. $additionalTable = $this->getAdditionalAttributeTable($object->getEntityTypeId());
  598. }
  599. if ($additionalTable) {
  600. $connection = $this->getConnection();
  601. $bind = [':attribute_id' => $object->getId()];
  602. $select = $connection->select()->from(
  603. $this->getTable($additionalTable)
  604. )->where(
  605. 'attribute_id = :attribute_id'
  606. );
  607. $result = $connection->fetchRow($select, $bind);
  608. if ($result) {
  609. $object->addData($result);
  610. }
  611. }
  612. return $this;
  613. }
  614. /**
  615. * @var array
  616. */
  617. private $storeLabelsCache = [];
  618. /**
  619. * Retrieve store labels by given attribute id
  620. *
  621. * @param int $attributeId
  622. * @return array
  623. */
  624. public function getStoreLabelsByAttributeId($attributeId)
  625. {
  626. if (!isset($this->storeLabelsCache[$attributeId])) {
  627. $connection = $this->getConnection();
  628. $bind = [':attribute_id' => $attributeId];
  629. $select = $connection->select()->from(
  630. $this->getTable('eav_attribute_label'),
  631. ['store_id', 'value']
  632. )->where(
  633. 'attribute_id = :attribute_id'
  634. );
  635. $this->storeLabelsCache[$attributeId] = $connection->fetchPairs($select, $bind);
  636. }
  637. return $this->storeLabelsCache[$attributeId];
  638. }
  639. /**
  640. * Load by given attributes ids and return only exist attribute ids
  641. *
  642. * @param array $attributeIds
  643. * @return array
  644. */
  645. public function getValidAttributeIds($attributeIds)
  646. {
  647. $connection = $this->getConnection();
  648. $select = $connection->select()->from(
  649. $this->getMainTable(),
  650. ['attribute_id']
  651. )->where(
  652. 'attribute_id IN (?)',
  653. $attributeIds
  654. );
  655. return $connection->fetchCol($select);
  656. }
  657. /**
  658. * Provide variables to serialize
  659. *
  660. * @return array
  661. * @since 100.0.7
  662. */
  663. public function __sleep()
  664. {
  665. $properties = parent::__sleep();
  666. $properties = array_diff($properties, ['_storeManager']);
  667. return $properties;
  668. }
  669. /**
  670. * Restore global dependencies
  671. *
  672. * @return void
  673. * @since 100.0.7
  674. */
  675. public function __wakeup()
  676. {
  677. parent::__wakeup();
  678. $this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance()
  679. ->get(\Magento\Store\Model\StoreManagerInterface::class);
  680. }
  681. /**
  682. * This method extracts frontend labels into array and sets array values as storeLabels into an object.
  683. *
  684. * @param AbstractModel $object
  685. * @param string|null $frontendLabel
  686. * @return void
  687. * @throws \Magento\Framework\Exception\LocalizedException
  688. */
  689. private function setStoreLabels(AbstractModel $object, $frontendLabel)
  690. {
  691. $resultLabel = [];
  692. $frontendLabels = $object->getFrontendLabels();
  693. if (isset($frontendLabels[0])
  694. && $frontendLabels[0] instanceof \Magento\Eav\Model\Entity\Attribute\FrontendLabel
  695. ) {
  696. foreach ($frontendLabels as $label) {
  697. $resultLabel[$label->getStoreId()] = $label->getLabel();
  698. }
  699. $this->checkDefaultFrontendLabelExists($frontendLabel, $resultLabel);
  700. $object->setStoreLabels($resultLabel);
  701. }
  702. }
  703. /**
  704. * This method checks whether value for default frontend label exists in attribute data.
  705. *
  706. * @param array|string|null $frontendLabel
  707. * @param array $resultLabels
  708. * @return void
  709. * @throws \Magento\Framework\Exception\LocalizedException
  710. */
  711. private function checkDefaultFrontendLabelExists($frontendLabel, $resultLabels)
  712. {
  713. $isAdminStoreLabel = (isset($resultLabels[0]) && !empty($resultLabels[0]));
  714. if (empty($frontendLabel) && !$isAdminStoreLabel) {
  715. throw new \Magento\Framework\Exception\LocalizedException(__('The storefront label is not defined.'));
  716. }
  717. }
  718. }