diff --git a/app/code/Magento/CatalogExport/etc/di.xml b/app/code/Magento/CatalogExport/etc/di.xml index f47d80e14..d8154d560 100644 --- a/app/code/Magento/CatalogExport/etc/di.xml +++ b/app/code/Magento/CatalogExport/etc/di.xml @@ -11,7 +11,6 @@ - @@ -33,16 +32,6 @@ - - - Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantFeedIndexMetadata - catalog.export.product.variants.data - product_variants_updated - product_variants_deleted - - - diff --git a/app/code/Magento/CatalogExport/etc/module.xml b/app/code/Magento/CatalogExport/etc/module.xml index 2d50f0efc..ea9727a2c 100644 --- a/app/code/Magento/CatalogExport/etc/module.xml +++ b/app/code/Magento/CatalogExport/etc/module.xml @@ -6,10 +6,5 @@ */ --> - - - - - - + diff --git a/app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariants.php b/app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariantsAfterSave.php similarity index 67% rename from app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariants.php rename to app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariantsAfterSave.php index e8b2c2774..6da3b94f4 100644 --- a/app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariants.php +++ b/app/code/Magento/ConfigurableProductDataExporter/Plugin/ReindexVariantsAfterSave.php @@ -11,13 +11,15 @@ use Magento\Catalog\Model\ResourceModel\Product as ResourceProduct; use Magento\ConfigurableProductDataExporter\Model\Query\LinkedAttributesQuery; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Indexer\IndexerRegistry; use Magento\Framework\Model\AbstractModel; use Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantFeedIndexer; +use Magento\ProductVariantDataExporter\Model\Indexer\UpdateChangeLog; /** * Plugin to trigger reindex on parent products, when a super attribute value is changed on a child product */ -class ReindexVariants +class ReindexVariantsAfterSave { /** * @var ResourceConnection @@ -30,27 +32,35 @@ class ReindexVariants private $linkedAttributesQuery; /** - * @var ProductVariantFeedIndexer + * @var IndexerRegistry */ - private $feedIndexer; + private $indexerRegistry; + + /** + * @var UpdateChangeLog + */ + private $updateChangeLog; /** * @param ResourceConnection $resourceConnection * @param LinkedAttributesQuery $linkedAttributesQuery - * @param ProductVariantFeedIndexer $feedIndexer + * @param IndexerRegistry $indexerRegistry + * @param UpdateChangeLog $updateChangeLog */ public function __construct( ResourceConnection $resourceConnection, LinkedAttributesQuery $linkedAttributesQuery, - ProductVariantFeedIndexer $feedIndexer + IndexerRegistry $indexerRegistry, + UpdateChangeLog $updateChangeLog ) { $this->resourceConnection = $resourceConnection; $this->linkedAttributesQuery = $linkedAttributesQuery; - $this->feedIndexer = $feedIndexer; + $this->indexerRegistry = $indexerRegistry; + $this->updateChangeLog = $updateChangeLog; } /** - * Reindex parent product on change of super attribute value. + * Reindex parent products on change of child product attribute value * * @param ResourceProduct $subject * @param ResourceProduct $result @@ -75,9 +85,26 @@ public function afterSave( } } if (!empty($changedConfigurableIds)) { - $this->feedIndexer->executeList(array_filter($changedConfigurableIds)); + $this->reindexVariants($changedConfigurableIds); } } return $result; } + + /** + * Reindex product variants + * + * @param int[] $ids + * @return void + */ + private function reindexVariants(array $ids): void + { + $indexer = $this->indexerRegistry->get(ProductVariantFeedIndexer::INDEXER_ID); + + if ($indexer->isScheduled()) { + $this->updateChangeLog->execute($indexer->getViewId(), $ids); + } else { + $indexer->reindexList($ids); + } + } } diff --git a/app/code/Magento/ConfigurableProductDataExporter/etc/di.xml b/app/code/Magento/ConfigurableProductDataExporter/etc/di.xml index 4a40b3b93..c6e1e33e3 100755 --- a/app/code/Magento/ConfigurableProductDataExporter/etc/di.xml +++ b/app/code/Magento/ConfigurableProductDataExporter/etc/di.xml @@ -48,7 +48,7 @@ - + diff --git a/app/code/Magento/ProductVariantDataExporter/Model/Indexer/ProductVariantFeedIndexer.php b/app/code/Magento/ProductVariantDataExporter/Model/Indexer/ProductVariantFeedIndexer.php index 65aba3ecc..8b62c4f91 100644 --- a/app/code/Magento/ProductVariantDataExporter/Model/Indexer/ProductVariantFeedIndexer.php +++ b/app/code/Magento/ProductVariantDataExporter/Model/Indexer/ProductVariantFeedIndexer.php @@ -15,6 +15,11 @@ */ class ProductVariantFeedIndexer extends FeedIndexer { + /** + * Product variant feed indexer id + */ + public const INDEXER_ID = 'catalog_data_exporter_product_variants'; + /** * Get Ids select * @@ -122,8 +127,6 @@ public function execute($ids): void /** * Indexer feed data processor * - * TODO: currently reindexAll is going reindex all the products, should base that on catalog_product_relation - * * @param array $indexData * @return void */ diff --git a/app/code/Magento/ProductVariantDataExporter/Model/Indexer/UpdateChangeLog.php b/app/code/Magento/ProductVariantDataExporter/Model/Indexer/UpdateChangeLog.php new file mode 100644 index 000000000..8c59d2ae4 --- /dev/null +++ b/app/code/Magento/ProductVariantDataExporter/Model/Indexer/UpdateChangeLog.php @@ -0,0 +1,66 @@ +resourceConnection = $resourceConnection; + $this->logger = $logger; + } + + /** + * Update indexer change log + * + * @param string $viewId + * @param array $ids + */ + public function execute(string $viewId, array $ids): void + { + $connection = $this->resourceConnection->getConnection(); + $connection->beginTransaction(); + try { + foreach ($ids as $id) { + $connection->insert($viewId . '_cl', ['entity_id' => $id]); + } + $connection->commit(); + } catch (\Exception $e) { + $connection->rollBack(); + $this->logger->error( + sprintf( + 'Failed to update change log of indexer %s. %s', + $viewId, + $e->getMessage() + ) + ); + } + } +} diff --git a/app/code/Magento/ProductVariantDataExporter/Model/Query/ProductRelationsQuery.php b/app/code/Magento/ProductVariantDataExporter/Model/Query/ProductRelationsQuery.php new file mode 100644 index 000000000..7347dd7c9 --- /dev/null +++ b/app/code/Magento/ProductVariantDataExporter/Model/Query/ProductRelationsQuery.php @@ -0,0 +1,55 @@ +resourceConnection = $resourceConnection; + } + + /** + * Return the parent ids of product relations + * + * @param int[] $ids + * @return array + */ + public function getRelationsParentIds(array $ids): array + { + $connection = $this->resourceConnection->getConnection(); + $select = $connection->select()->from( + ['cpr' => $this->resourceConnection->getTableName('catalog_product_relation')], + [] + )->join( + ['cpe' => $catalogProductTable = $this->resourceConnection->getTableName('catalog_product_entity')], + \sprintf('cpe.%1$s = cpr.parent_id', $connection->getAutoIncrementField($catalogProductTable)), + ['entity_id'] + )->where( + sprintf( + 'cpe.entity_id IN ("%1$s") OR cpr.child_id IN ("%1$s")', + \implode(",", $ids) + ) + ); + return array_filter($connection->fetchCol($select)); + } +} diff --git a/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnDelete.php b/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnDelete.php new file mode 100644 index 000000000..95789efad --- /dev/null +++ b/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnDelete.php @@ -0,0 +1,89 @@ +indexerRegistry = $indexerRegistry; + $this->updateChangeLog = $updateChangeLog; + $this->productRelationsQuery = $productRelationsQuery; + } + + /** + * Reindex product variants on product deletion + * + * @param ResourceProduct $subject + * @param \Closure $proceed + * @param AbstractModel $product + * @return ResourceProduct + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundDelete( + ResourceProduct $subject, + \Closure $proceed, + AbstractModel $product + ): ResourceProduct { + $ids = $this->productRelationsQuery->getRelationsParentIds([$product->getId()]); + $result = $proceed($product); + if (!empty($ids)) { + $this->reindexVariants($ids); + } + return $result; + } + + /** + * Reindex product variants + * + * @param int[] $ids + * @return void + */ + private function reindexVariants(array $ids): void + { + $indexer = $this->indexerRegistry->get(ProductVariantFeedIndexer::INDEXER_ID); + if ($indexer->isScheduled()) { + $this->updateChangeLog->execute($indexer->getViewId(), $ids); + } else { + $indexer->reindexList($ids); + } + } +} diff --git a/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnRelationsChange.php b/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnRelationsChange.php new file mode 100644 index 000000000..e8cdc8e81 --- /dev/null +++ b/app/code/Magento/ProductVariantDataExporter/Plugin/ReindexVariantsOnRelationsChange.php @@ -0,0 +1,186 @@ +indexerRegistry = $indexerRegistry; + $this->updateChangeLog = $updateChangeLog; + $this->metadataPool = $metadataPool; + $this->resourceConnection = $resourceConnection; + $this->logger = $logger; + } + + /** + * Reindex variants after addition of new relations + * + * @param Relation $subject + * @param Relation $result + * @param int $parentLinkId + * @param int[] $childIds + * @return Relation + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterAddRelations( + Relation $subject, + Relation $result, + int $parentLinkId, + array $childIds + ): Relation { + if (!empty($childIds)) { + try { + $parentId = $this->getProductEntityId($parentLinkId); + $this->addCommitCallback($subject, (int)$parentId); + } catch (\Exception $e) { + $this->logger->error(sprintf( + 'Failed to reindex product variants after product relation addition: "%s"', + $e->getMessage() + )); + } + } + return $result; + } + + /** + * Reindex variants after removal of relations + * + * @param Relation $subject + * @param Relation $result + * @param int $parentLinkId + * @param int[] $childIds + * @return Relation + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterRemoveRelations( + Relation $subject, + Relation $result, + int $parentLinkId, + array $childIds + ): Relation { + if (!empty($childIds)) { + try { + $parentId = $this->getProductEntityId($parentLinkId); + $this->addCommitCallback($subject, (int)$parentId); + } catch (\Exception $e) { + $this->logger->error(sprintf( + 'Failed to reindex product variants after product relation removal: "%s"', + $e->getMessage() + )); + } + } + return $result; + } + + /** + * Reindex product variants after commit + * + * @param Relation $subject + * @param int $id + * @return void + */ + private function addCommitCallback(Relation $subject, int $id): void + { + $indexer = $this->indexerRegistry->get(ProductVariantFeedIndexer::INDEXER_ID); + $viewId = $indexer->getViewId(); + + if ($indexer->isScheduled()) { + $subject->addCommitCallback(function () use ($viewId, $id) { + $this->updateChangeLog->execute($viewId, [$id]); + }); + } else { + $subject->addCommitCallback(function () use ($indexer, $id) { + $indexer->reindexRow($id); + }); + } + } + + /** + * Get product entity id from product link id + * + * @param int $linkId + * @return int + * @throws \Exception + */ + private function getProductEntityId(int $linkId): int + { + if (($linkField = $this->getProductEntityLinkField()) !== 'entity_id') { + $connection = $this->resourceConnection->getConnection(); + $select = $connection->select()->from( + ['cpe' => $this->resourceConnection->getTableName('catalog_product_entity')], + ['entity_id'] + )->where( + sprintf('%1$s = ?', $linkField), + $linkId + ); + return (int)$connection->fetchOne($select); + } + return $linkId; + } + + /** + * Get product entity link field + * + * @return string + * @throws \Exception + */ + private function getProductEntityLinkField(): string + { + return $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + } +} diff --git a/app/code/Magento/ProductVariantDataExporter/composer.json b/app/code/Magento/ProductVariantDataExporter/composer.json index db5517b00..ac698cb3b 100644 --- a/app/code/Magento/ProductVariantDataExporter/composer.json +++ b/app/code/Magento/ProductVariantDataExporter/composer.json @@ -22,6 +22,7 @@ "guzzlehttp/guzzle": "*", "guzzlehttp/psr7": "~1.0", "magento/framework": "*", - "magento/module-data-exporter": "*" + "magento/module-data-exporter": "*", + "magento/module-catalog": "*" } } diff --git a/app/code/Magento/ProductVariantDataExporter/etc/di.xml b/app/code/Magento/ProductVariantDataExporter/etc/di.xml index 2371528b9..15c659688 100644 --- a/app/code/Magento/ProductVariantDataExporter/etc/di.xml +++ b/app/code/Magento/ProductVariantDataExporter/etc/di.xml @@ -31,17 +31,21 @@ - - - + + + Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantFeedIndexMetadata + catalog.export.product.variants.data + product_variants_updated + product_variants_deleted + + Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantFeedIndexMetadata Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantDataSerializer - Magento\ProductVariantDataExporter\Model\Indexer\ProductVariantIndexerCallbackInterface + Magento\CatalogExport\Model\Indexer\ProductVariantIndexerCallback @@ -58,4 +62,12 @@ + + + + + + diff --git a/app/code/Magento/ProductVariantDataExporter/etc/indexer.xml b/app/code/Magento/ProductVariantDataExporter/etc/indexer.xml index 774175ede..c8d22dd88 100644 --- a/app/code/Magento/ProductVariantDataExporter/etc/indexer.xml +++ b/app/code/Magento/ProductVariantDataExporter/etc/indexer.xml @@ -13,8 +13,5 @@ > Product Variant Feed Collects data for a Product Variants Feed - - - diff --git a/app/code/Magento/ProductVariantDataExporter/etc/mview.xml b/app/code/Magento/ProductVariantDataExporter/etc/mview.xml index 83ad31221..9c3f4acf3 100644 --- a/app/code/Magento/ProductVariantDataExporter/etc/mview.xml +++ b/app/code/Magento/ProductVariantDataExporter/etc/mview.xml @@ -6,9 +6,5 @@ */ --> - - - - - +