diff --git a/vendor/magento/module-catalog/Model/Product/Gallery/CopyHandler.php b/vendor/magento/module-catalog/Model/Product/Gallery/CopyHandler.php new file mode 100644 index 00000000000..5e4d3e39161 --- /dev/null +++ b/vendor/magento/module-catalog/Model/Product/Gallery/CopyHandler.php @@ -0,0 +1,173 @@ +metadata = $metadataPool->getMetadata(ProductInterface::class); + $this->galleryResourceModel = $galleryResourceModel; + $this->attributeRepository = $attributeRepository; + $this->attributeValue = $attributeValue; + $this->json = $json; + } + + /** + * Copy gallery data from one product to another + * + * @param Product $product + * @param array $arguments + * @return void + */ + public function execute($product, $arguments = []): void + { + $fromId = (int) $arguments['original_link_id']; + $toId = $product->getData($this->metadata->getLinkField()); + $attributeId = $this->getAttribute()->getAttributeId(); + $valueIdMap = $this->galleryResourceModel->duplicate($attributeId, [], $fromId, $toId); + $gallery = $this->getMediaGalleryCollection($product); + + if (!empty($gallery['images'])) { + $images = []; + foreach ($gallery['images'] as $key => $image) { + $valueId = $image['value_id'] ?? null; + $newKey = $key; + if ($valueId !== null) { + $newValueId = $valueId; + if (isset($valueIdMap[$valueId])) { + $newValueId = $valueIdMap[$valueId]; + } + if (((int) $valueId) === $key) { + $newKey = $newValueId; + } + $image['value_id'] = $newValueId; + } + $images[$newKey] = $image; + } + $gallery['images'] = $images; + $attrCode = $this->getAttribute()->getAttributeCode(); + $product->setData($attrCode, $gallery); + } + + //Copy media attribute values from one product to another + if (isset($arguments['media_attribute_codes'])) { + $values = $this->attributeValue->getValues( + ProductInterface::class, + $fromId, + $arguments['media_attribute_codes'] + ); + if ($values) { + foreach (array_keys($values) as $key) { + $values[$key][$this->metadata->getLinkField()] = $product->getData($this->metadata->getLinkField()); + unset($values[$key]['value_id']); + } + $this->attributeValue->insertValues( + ProductInterface::class, + $values + ); + } + } + } + + /** + * Get product media gallery collection + * + * @param Product $product + * @return array + */ + private function getMediaGalleryCollection(Product $product): array + { + $attrCode = $this->getAttribute()->getAttributeCode(); + $value = $product->getData($attrCode); + + if (is_array($value) && isset($value['images'])) { + if (!is_array($value['images']) && strlen($value['images']) > 0) { + $value['images'] = $this->json->unserialize($value['images']); + } + + if (!is_array($value['images'])) { + $value['images'] = []; + } + } + + return $value; + } + + /** + * Returns media gallery attribute instance + * + * @return ProductAttributeInterface + */ + private function getAttribute(): ProductAttributeInterface + { + if (!$this->attribute) { + $this->attribute = $this->attributeRepository->get( + ProductInterface::MEDIA_GALLERY + ); + } + + return $this->attribute; + } +} diff --git a/vendor/magento/module-catalog/Model/Product/Gallery/DeleteHandler.php b/vendor/magento/module-catalog/Model/Product/Gallery/DeleteHandler.php new file mode 100644 index 00000000000..16adccb29b2 --- /dev/null +++ b/vendor/magento/module-catalog/Model/Product/Gallery/DeleteHandler.php @@ -0,0 +1,99 @@ +metadata = $metadataPool->getMetadata(ProductInterface::class); + $this->galleryResourceModel = $galleryResourceModel; + $this->attributeValue = $attributeValue; + } + + /** + * Delete all media gallery records for provided product + * + * @param Product $product + * @param array $arguments + * @return void + */ + public function execute($product, $arguments = []): void + { + $valuesId = $this->getMediaGalleryValuesId($product); + if ($valuesId) { + $this->galleryResourceModel->deleteGallery($valuesId); + } + if (isset($arguments['media_attribute_codes'])) { + $values = $this->attributeValue->getValues( + ProductInterface::class, + (int) $product->getData($this->metadata->getLinkField()), + $arguments['media_attribute_codes'] + ); + if ($values) { + $this->attributeValue->deleteValues( + ProductInterface::class, + $values + ); + } + } + } + + /** + * Get product media gallery values IDs + * + * @param Product $product + * @return array + */ + private function getMediaGalleryValuesId(Product $product): array + { + $connection = $this->galleryResourceModel->getConnection(); + $select = $connection->select() + ->from($this->galleryResourceModel->getTable(Gallery::GALLERY_VALUE_TO_ENTITY_TABLE)) + ->where( + $this->metadata->getLinkField() . '=?', + $product->getData($this->metadata->getLinkField()), + \Zend_Db::INT_TYPE + ); + return $connection->fetchCol($select); + } +} diff --git a/vendor/magento/module-catalog/Model/ResourceModel/Product/Gallery.php b/vendor/magento/module-catalog/Model/ResourceModel/Product/Gallery.php index 5ff6207074b..28e637ad056 100644 --- a/vendor/magento/module-catalog/Model/ResourceModel/Product/Gallery.php +++ b/vendor/magento/module-catalog/Model/ResourceModel/Product/Gallery.php @@ -452,6 +452,9 @@ class Gallery extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb // Duplicate per store gallery values $select = $this->getConnection()->select()->from( $this->getTable(self::GALLERY_VALUE_TABLE) + )->where( + $linkField . ' = ?', + $originalProductId )->where( 'value_id IN(?)', array_keys($valueIdMap) diff --git a/vendor/magento/module-eav/Model/ResourceModel/AttributeValue.php b/vendor/magento/module-eav/Model/ResourceModel/AttributeValue.php index 305ed202ff2..66404c3ef38 100644 --- a/vendor/magento/module-eav/Model/ResourceModel/AttributeValue.php +++ b/vendor/magento/module-eav/Model/ResourceModel/AttributeValue.php @@ -117,7 +117,7 @@ class AttributeValue * Delete attribute values * * @param string $entityType - * @param array[][] $values + * @param array[] $values * Format: * array( * 0 => array( @@ -159,12 +159,64 @@ class AttributeValue } } + /** + * Insert attribute values + * + * @param string $entityType + * @param array[] $values + * Format: + * array( + * 0 => array( + * attribute_id => 11, + * value => 'some long text', + * ... + * ), + * 1 => array( + * attribute_id => 22, + * value => 'some short text', + * ... + * ) + * ) + */ + public function insertValues(string $entityType, array $values): void + { + $metadata = $this->metadataPool->getMetadata($entityType); + $connection = $metadata->getEntityConnection(); + $attributeTables = []; + $allAttributes = []; + + foreach ($this->getEntityAttributes($entityType) as $attribute) { + $allAttributes[(int) $attribute->getAttributeId()] = $attribute; + } + + foreach ($values as $value) { + $attribute = $allAttributes[(int) $value['attribute_id']] ?? null; + if ($attribute && !$attribute->isStatic()) { + $columns = array_keys($value); + $columnsHash = implode(',', $columns); + $attributeTable = $attribute->getBackend()->getTable(); + $attributeTables[$attributeTable][$columnsHash][] = array_values($value); + } + } + + foreach ($attributeTables as $table => $tableData) { + foreach ($tableData as $columns => $data) { + $connection->insertArray( + $table, + explode(',', $columns), + $data + ); + } + } + } + /** * Get attribute of given entity type * * @param string $entityType + * @return array */ - private function getEntityAttributes(string $entityType) + private function getEntityAttributes(string $entityType): array { $metadata = $this->metadataPool->getMetadata($entityType); $eavEntityType = $metadata->getEavEntityType();