UpdateHandler.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Eav\Model\ResourceModel;
  7. use Magento\Framework\App\ObjectManager;
  8. use Magento\Framework\EntityManager\MetadataPool;
  9. use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository;
  10. use Magento\Framework\Api\SearchCriteriaBuilder;
  11. use Magento\Framework\Model\Entity\ScopeResolver;
  12. use Magento\Framework\EntityManager\Operation\AttributeInterface;
  13. /**
  14. * Class UpdateHandler
  15. *
  16. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  17. */
  18. class UpdateHandler implements AttributeInterface
  19. {
  20. /**
  21. * @var AttributeRepository
  22. */
  23. private $attributeRepository;
  24. /**
  25. * @var MetadataPool
  26. */
  27. private $metadataPool;
  28. /**
  29. * @var SearchCriteriaBuilder
  30. */
  31. private $searchCriteriaBuilder;
  32. /**
  33. * @var AttributePersistor
  34. */
  35. private $attributePersistor;
  36. /**
  37. * @var ReadSnapshot
  38. */
  39. private $readSnapshot;
  40. /**
  41. * @var ScopeResolver
  42. */
  43. private $scopeResolver;
  44. /**
  45. * @var ReadHandler
  46. */
  47. private $readHandler;
  48. /**
  49. * @var AttributeLoader
  50. */
  51. private $attributeLoader;
  52. /**
  53. * UpdateHandler constructor.
  54. * @param AttributeRepository $attributeRepository
  55. * @param MetadataPool $metadataPool
  56. * @param SearchCriteriaBuilder $searchCriteriaBuilder
  57. * @param AttributePersistor $attributePersistor
  58. * @param ReadSnapshot $readSnapshot
  59. * @param ScopeResolver $scopeResolver
  60. * @param AttributeLoader $attributeLoader
  61. */
  62. public function __construct(
  63. AttributeRepository $attributeRepository,
  64. MetadataPool $metadataPool,
  65. SearchCriteriaBuilder $searchCriteriaBuilder,
  66. AttributePersistor $attributePersistor,
  67. ReadSnapshot $readSnapshot,
  68. ScopeResolver $scopeResolver,
  69. AttributeLoader $attributeLoader = null
  70. ) {
  71. $this->attributeRepository = $attributeRepository;
  72. $this->metadataPool = $metadataPool;
  73. $this->searchCriteriaBuilder = $searchCriteriaBuilder;
  74. $this->attributePersistor = $attributePersistor;
  75. $this->readSnapshot = $readSnapshot;
  76. $this->scopeResolver = $scopeResolver;
  77. $this->attributeLoader = $attributeLoader ?: ObjectManager::getInstance()->get(AttributeLoader::class);
  78. }
  79. /**
  80. * @param string $entityType
  81. * @param int $attributeSetId
  82. * @return \Magento\Eav\Api\Data\AttributeInterface[]
  83. */
  84. protected function getAttributes($entityType, $attributeSetId = null)
  85. {
  86. return $this->attributeLoader->getAttributes($entityType, $attributeSetId);
  87. }
  88. /**
  89. * @param string $entityType
  90. * @param array $entityData
  91. * @param array $arguments
  92. * @return array
  93. * @throws \Exception
  94. * @throws \Magento\Framework\Exception\ConfigurationMismatchException
  95. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  96. * @SuppressWarnings(PHPMD.NPathComplexity)
  97. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  98. */
  99. public function execute($entityType, $entityData, $arguments = [])
  100. {
  101. /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */
  102. $metadata = $this->metadataPool->getMetadata($entityType);
  103. if ($metadata->getEavEntityType()) {
  104. $context = $this->scopeResolver->getEntityContext($entityType, $entityData);
  105. $entityDataForSnapshot = [$metadata->getLinkField() => $entityData[$metadata->getLinkField()]];
  106. foreach ($context as $scope) {
  107. if (isset($entityData[$scope->getIdentifier()])) {
  108. $entityDataForSnapshot[$scope->getIdentifier()] = $entityData[$scope->getIdentifier()];
  109. }
  110. }
  111. $attributeSetId = isset($entityData[AttributeLoader::ATTRIBUTE_SET_ID])
  112. ? $entityData[AttributeLoader::ATTRIBUTE_SET_ID]
  113. : null; // @todo verify is it normal to not have attribute_set_id
  114. if (!isset($entityDataForSnapshot['attribute_set_id'])) {
  115. $entityDataForSnapshot['attribute_set_id'] = $attributeSetId;
  116. }
  117. $snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot);
  118. foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) {
  119. $code = $attribute->getAttributeCode();
  120. $isAllowedValueType = array_key_exists($code, $entityData)
  121. && (is_scalar($entityData[$code]) || $entityData[$code] === null);
  122. if ($attribute->isStatic() || !$isAllowedValueType) {
  123. continue;
  124. }
  125. $newValue = $entityData[$code];
  126. $isValueEmpty = $attribute->isValueEmpty($newValue);
  127. $isAllowedEmptyStringValue = $attribute->isAllowedEmptyTextValue($newValue);
  128. if (array_key_exists($code, $snapshot)) {
  129. $snapshotValue = $snapshot[$code];
  130. /**
  131. * 'FALSE' value for attributes can't be update or delete
  132. */
  133. if ($snapshotValue === false) {
  134. continue;
  135. }
  136. if (!$isValueEmpty || $isAllowedEmptyStringValue) {
  137. /**
  138. * NOT Updated value for attributes not need to update
  139. */
  140. if ($snapshotValue === $newValue) {
  141. continue;
  142. }
  143. $this->attributePersistor->registerUpdate(
  144. $entityType,
  145. $entityData[$metadata->getLinkField()],
  146. $code,
  147. $newValue
  148. );
  149. } else {
  150. $this->attributePersistor->registerDelete(
  151. $entityType,
  152. $entityData[$metadata->getLinkField()],
  153. $code
  154. );
  155. }
  156. } else {
  157. /**
  158. * Only not empty value of attribute is insertable
  159. */
  160. if (!$isValueEmpty || $isAllowedEmptyStringValue) {
  161. $this->attributePersistor->registerInsert(
  162. $entityType,
  163. $entityData[$metadata->getLinkField()],
  164. $code,
  165. $newValue
  166. );
  167. }
  168. }
  169. }
  170. $this->attributePersistor->flush($entityType, $context);
  171. }
  172. return $this->getReadHandler()->execute($entityType, $entityData, $arguments);
  173. }
  174. /**
  175. * Get read handler
  176. *
  177. * @deprecated 100.1.0
  178. *
  179. * @return ReadHandler
  180. */
  181. protected function getReadHandler()
  182. {
  183. if (!$this->readHandler) {
  184. $this->readHandler = ObjectManager::getInstance()->get(ReadHandler::class);
  185. }
  186. return $this->readHandler;
  187. }
  188. }