diff --git a/vendor/magento/module-catalog-staging/Model/Product/Gallery/CreateHandler.php b/vendor/magento/module-catalog-staging/Model/Product/Gallery/CreateHandler.php index 3ba3dc8f6c8..5ece9d934be 100644 --- a/vendor/magento/module-catalog-staging/Model/Product/Gallery/CreateHandler.php +++ b/vendor/magento/module-catalog-staging/Model/Product/Gallery/CreateHandler.php @@ -5,30 +5,52 @@ */ namespace Magento\CatalogStaging\Model\Product\Gallery; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Gallery\CopyHandler; use Magento\Catalog\Model\Product\Gallery\CreateHandler as ProductGalleryCreateHandler; use Magento\Catalog\Model\Product\Gallery\UpdateHandler; use Magento\Catalog\Model\Product\Media\Config; use Magento\Catalog\Model\ResourceModel\Product\Gallery; +use Magento\Framework\App\ObjectManager; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\EntityManager\Operation\ExtensionInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; use Magento\Framework\Json\Helper\Data; use Magento\MediaStorage\Helper\File\Storage\Database; +use Magento\Staging\Model\ResourceModel\Db\ReadEntityVersion; +use Magento\Staging\Model\VersionHistoryInterface; +use Magento\Staging\Model\VersionManager; /** * Create handler for staging catalog product gallery + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CreateHandler extends ProductGalleryCreateHandler implements ExtensionInterface { - /** * @var UpdateHandler */ private $updateHandler; + /** + * @var CopyHandler + */ + private $copyHandler; + + /** + * @var VersionHistoryInterface + */ + private $versionHistory; + + /** + * @var ReadEntityVersion + */ + private $readEntityVersion; + /** * @param MetadataPool $metadataPool * @param ProductAttributeRepositoryInterface $attributeRepository @@ -38,6 +60,10 @@ class CreateHandler extends ProductGalleryCreateHandler implements ExtensionInte * @param Filesystem $filesystem * @param Database $fileStorageDb * @param UpdateHandler $updateHandler + * @param CopyHandler|null $copyHandler + * @param VersionHistoryInterface|null $versionHistory + * @param ReadEntityVersion|null $readEntityVersion + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( MetadataPool $metadataPool, @@ -47,7 +73,10 @@ class CreateHandler extends ProductGalleryCreateHandler implements ExtensionInte Config $mediaConfig, Filesystem $filesystem, Database $fileStorageDb, - UpdateHandler $updateHandler + UpdateHandler $updateHandler, + ?CopyHandler $copyHandler = null, + ?VersionHistoryInterface $versionHistory = null, + ?ReadEntityVersion $readEntityVersion = null ) { $this->updateHandler = $updateHandler; @@ -60,6 +89,9 @@ class CreateHandler extends ProductGalleryCreateHandler implements ExtensionInte $filesystem, $fileStorageDb ); + $this->copyHandler = $copyHandler ?? ObjectManager::getInstance()->get(CopyHandler::class); + $this->versionHistory = $versionHistory ?? ObjectManager::getInstance()->get(VersionHistoryInterface::class); + $this->readEntityVersion = $readEntityVersion ?? ObjectManager::getInstance()->get(ReadEntityVersion::class); } /** @@ -72,6 +104,25 @@ class CreateHandler extends ProductGalleryCreateHandler implements ExtensionInte */ public function execute($product, $arguments = []) { + if (isset($arguments['origin_in'])) { + $originId = $arguments['origin_in']; + } elseif (isset($arguments['copy_origin_in'])) { + $originId = $arguments['copy_origin_in']; + } else { + $originId = $this->versionHistory->getCurrentId(); + } + + if (!in_array($product->getData('created_in'), [VersionManager::MIN_VERSION, $originId], true)) { + $arguments['original_link_id'] = $this->readEntityVersion->getVersionRowId( + ProductInterface::class, + $product->getData($this->metadata->getIdentifierField()), + $originId + ); + $this->copyHandler->execute($product, $arguments); + if (!empty($arguments['is_rollback'])) { + return $product; + } + } return $product->isObjectNew() ? parent::execute($product, $arguments) : $this->updateHandler->execute($product, $arguments); diff --git a/vendor/magento/module-catalog-staging/Model/Product/Gallery/UpdateHandler.php b/vendor/magento/module-catalog-staging/Model/Product/Gallery/UpdateHandler.php new file mode 100644 index 00000000000..9e6906fc908 --- /dev/null +++ b/vendor/magento/module-catalog-staging/Model/Product/Gallery/UpdateHandler.php @@ -0,0 +1,151 @@ +copyHandler = $copyHandler; + $this->deleteHandler = $deleteHandler; + $this->readHandler = $readHandler; + $this->readEntityVersion = $readEntityVersion; + } + + /** + * Update product media gallery + * + * @param Product $product + * @param array $arguments + * @return object + */ + public function execute($product, $arguments = []) + { + if (!empty($arguments['is_rollback']) && !empty($arguments['copy_origin_in'])) { + $arguments['media_attribute_codes'] = $this->getMediaAttributeCodes(); + $arguments['original_link_id'] = $this->readEntityVersion->getVersionRowId( + ProductInterface::class, + $product->getData($this->metadata->getIdentifierField()), + $arguments['copy_origin_in'] + ); + $this->deleteHandler->execute($product, $arguments); + $this->copyHandler->execute($product, $arguments); + // reload gallery data as new value IDs are auto generated + $this->readHandler->execute($product, $arguments); + return $product; + } + return parent::execute($product, $arguments); + } + + /** + * Get all media attributes codes including their corresponding labels + * + * @return array + */ + private function getMediaAttributeCodes(): array + { + $attributeCodes = []; + foreach ($this->mediaConfig->getMediaAttributeCodes() as $attributeCode) { + $attributeCodes[] = $attributeCode; + if (in_array($attributeCode, $this->mediaAttributesWithLabels)) { + $attributeCodes[] = $attributeCode . '_label'; + } + } + return $attributeCodes; + } +} diff --git a/vendor/magento/module-catalog-staging/Model/ResourceModel/AttributeCopier.php b/vendor/magento/module-catalog-staging/Model/ResourceModel/AttributeCopier.php index a052f7fbe3b..3660f2dd3b4 100644 --- a/vendor/magento/module-catalog-staging/Model/ResourceModel/AttributeCopier.php +++ b/vendor/magento/module-catalog-staging/Model/ResourceModel/AttributeCopier.php @@ -6,12 +6,9 @@ namespace Magento\CatalogStaging\Model\ResourceModel; -use Magento\Catalog\Api\Data\ProductAttributeInterface; -use Magento\Catalog\Model\ResourceModel\Product\Gallery; use Magento\Eav\Api\AttributeRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\ResourceConnection; -use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\EntityManager\EntityMetadataInterface; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Model\Entity\ScopeResolver; @@ -149,65 +146,7 @@ class AttributeCopier $query = $select->insertFromSelect($attributeTable, array_keys($insertColumns)); $connection->query($query); } - if ($metadata->getEavEntityType() === ProductAttributeInterface::ENTITY_TYPE_CODE) { - $this->copyMediaGalleryRecords($connection, $metadata, $fromRowId, $toRowId); - } return true; } - - /** - * Copy existing gallery items for staging - * - * @param AdapterInterface $connection - * @param EntityMetadataInterface $metadata - * @param int $fromRowId - * @param int $toRowId - */ - private function copyMediaGalleryRecords( - AdapterInterface $connection, - EntityMetadataInterface $metadata, - int $fromRowId, - int $toRowId - ): void { - $select = $connection->select(); - - $galleryValueToEntityTable = $this->resourceConnection->getTableName(Gallery::GALLERY_VALUE_TO_ENTITY_TABLE); - $galleryTable = $this->resourceConnection->getTableName(Gallery::GALLERY_TABLE); - $galleryValueTable = $this->resourceConnection->getTableName(Gallery::GALLERY_VALUE_TABLE); - - $select->from($galleryValueToEntityTable) - ->where($metadata->getLinkField() . ' = ?', $fromRowId); - $ids = $connection->fetchCol($select); - - $select = $connection->select(); - $select->from($galleryTable) - ->where('value_id IN (?)', $ids); - - $rows = $connection->fetchAll($select); - foreach ($rows as $row) { - $oldValueId = $row['value_id']; - unset($row['value_id']); - $connection->insert($galleryTable, $row); - $newValueId = $connection->lastInsertId(); - $connection->insert( - $galleryValueToEntityTable, - [ - 'value_id' => $newValueId, - $metadata->getLinkField() => $toRowId, - ] - ); - $select = $connection->select(); - $select->from($galleryValueTable) - ->where($metadata->getLinkField() . ' = ?', $fromRowId) - ->where('value_id = ?', $oldValueId); - $rows2 = $connection->fetchAll($select); - foreach ($rows2 as $row2) { - unset($row2['record_id']); - $row2['row_id'] = $toRowId; - $row2['value_id'] = $newValueId; - $connection->insert($galleryValueTable, $row2); - } - } - } } diff --git a/vendor/magento/module-catalog-staging/etc/adminhtml/di.xml b/vendor/magento/module-catalog-staging/etc/adminhtml/di.xml index afc290c806b..83c85ea33cc 100644 --- a/vendor/magento/module-catalog-staging/etc/adminhtml/di.xml +++ b/vendor/magento/module-catalog-staging/etc/adminhtml/di.xml @@ -140,7 +140,6 @@ - diff --git a/vendor/magento/module-catalog-staging/etc/di.xml b/vendor/magento/module-catalog-staging/etc/di.xml index 5b1842d8266..181a3177789 100644 --- a/vendor/magento/module-catalog-staging/etc/di.xml +++ b/vendor/magento/module-catalog-staging/etc/di.xml @@ -384,4 +384,18 @@ + + + + + + Magento\CatalogStaging\Model\Product\Gallery\CreateHandler + + + Magento\CatalogStaging\Model\Product\Gallery\UpdateHandler + + + + + diff --git a/vendor/magento/module-staging/Model/Operation/Delete/UpdateIntersectedRollbacks.php b/vendor/magento/module-staging/Model/Operation/Delete/UpdateIntersectedRollbacks.php index f50912d20aa..5998cd3f4e8 100644 --- a/vendor/magento/module-staging/Model/Operation/Delete/UpdateIntersectedRollbacks.php +++ b/vendor/magento/module-staging/Model/Operation/Delete/UpdateIntersectedRollbacks.php @@ -99,6 +99,8 @@ class UpdateIntersectedRollbacks $metadata->getLinkField() => $this->readEntityVersion->getCurrentVersionRowId($entityType, $entityId), 'created_in' => $rollbackId, 'updated_in' => $this->readEntityVersion->getNextVersionId($entityType, $rollbackId, $entityId), + 'is_rollback' => true, + 'copy_origin_in' => $createdIn ]; $this->updateEntityVersion->execute($originEntity, $arguments); } diff --git a/vendor/magento/module-staging/Model/ResourceModel/Db/ReadEntityVersion.php b/vendor/magento/module-staging/Model/ResourceModel/Db/ReadEntityVersion.php index bf8a960c48f..0c87ba42b8b 100644 --- a/vendor/magento/module-staging/Model/ResourceModel/Db/ReadEntityVersion.php +++ b/vendor/magento/module-staging/Model/ResourceModel/Db/ReadEntityVersion.php @@ -327,4 +327,31 @@ class ReadEntityVersion } return $currentRowId; } + + /** + * Get entity row id by version id + * + * @param string $entityType + * @param int $identifier + * @param int $versionId + * @return string + */ + public function getVersionRowId($entityType, $identifier, $versionId) + { + $metadata = $this->metadataPool->getMetadata($entityType); + $identifierField = $metadata->getIdentifierField(); + $select = $metadata->getEntityConnection() + ->select() + ->from( + ['entity_table' => $metadata->getEntityTable()], + [$metadata->getLinkField()] + ) + ->where($identifierField . ' = ?', $identifier) + ->where('created_in <= ?', $versionId) + ->order('created_in DESC') + ->limit(1) + ->setPart('disable_staging_preview', true); + + return $metadata->getEntityConnection()->fetchOne($select); + } }