|
| 1 | +<?php |
| 2 | +/* |
| 3 | + * Copyright (c) Aligent Consulting. All rights reserved. |
| 4 | + */ |
| 5 | + |
| 6 | +declare(strict_types=1); |
| 7 | + |
| 8 | +namespace Aligent\PrerenderIo\Model\Indexer\Category; |
| 9 | + |
| 10 | +use Aligent\PrerenderIo\Api\PrerenderClientInterface; |
| 11 | +use Aligent\PrerenderIo\Helper\Config; |
| 12 | +use Aligent\PrerenderIo\Model\Indexer\DataProvider\ProductCategories; |
| 13 | +use Aligent\PrerenderIo\Model\Url\GetUrlsForCategories; |
| 14 | +use Magento\Framework\App\DeploymentConfig; |
| 15 | +use Magento\Framework\Exception\FileSystemException; |
| 16 | +use Magento\Framework\Exception\LocalizedException; |
| 17 | +use Magento\Framework\Exception\RuntimeException; |
| 18 | +use Magento\Framework\Indexer\ActionInterface as IndexerActionInterface; |
| 19 | +use Magento\Framework\Indexer\DimensionalIndexerInterface; |
| 20 | +use Magento\Framework\Indexer\DimensionProviderInterface; |
| 21 | +use Magento\Framework\Mview\ActionInterface as MviewActionInterface; |
| 22 | +use Magento\Store\Model\StoreDimensionProvider; |
| 23 | + |
| 24 | +class ProductIndexer implements IndexerActionInterface, MviewActionInterface, DimensionalIndexerInterface |
| 25 | +{ |
| 26 | + private const INDEXER_ID = 'prerender_io_category_product'; |
| 27 | + private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/'; |
| 28 | + |
| 29 | + /** @var DimensionProviderInterface */ |
| 30 | + private DimensionProviderInterface $dimensionProvider; |
| 31 | + /** @var ProductCategories */ |
| 32 | + private ProductCategories $productCategoriesDataProvider; |
| 33 | + /** @var GetUrlsForCategories */ |
| 34 | + private GetUrlsForCategories $getUrlsForCategories; |
| 35 | + /** @var PrerenderClientInterface */ |
| 36 | + private PrerenderClientInterface $prerenderClient; |
| 37 | + /** @var DeploymentConfig */ |
| 38 | + private DeploymentConfig $eploymentConfig; |
| 39 | + /** @var Config */ |
| 40 | + private Config $prerenderConfigHelper; |
| 41 | + /** @var int|null */ |
| 42 | + private ?int $batchSize; |
| 43 | + |
| 44 | + /** |
| 45 | + * |
| 46 | + * @param DimensionProviderInterface $dimensionProvider |
| 47 | + * @param ProductCategories $productCategoriesDataProvider |
| 48 | + * @param GetUrlsForCategories $getUrlsForCategories |
| 49 | + * @param PrerenderClientInterface $prerenderClient |
| 50 | + * @param DeploymentConfig $deploymentConfig |
| 51 | + * @param Config $prerenderConfigHelper |
| 52 | + * @param int|null $batchSize |
| 53 | + */ |
| 54 | + public function __construct( |
| 55 | + DimensionProviderInterface $dimensionProvider, |
| 56 | + ProductCategories $productCategoriesDataProvider, |
| 57 | + GetUrlsForCategories $getUrlsForCategories, |
| 58 | + PrerenderClientInterface $prerenderClient, |
| 59 | + DeploymentConfig $deploymentConfig, |
| 60 | + Config $prerenderConfigHelper, |
| 61 | + ?int $batchSize = 1000 |
| 62 | + ) { |
| 63 | + $this->dimensionProvider = $dimensionProvider; |
| 64 | + $this->productCategoriesDataProvider = $productCategoriesDataProvider; |
| 65 | + $this->getUrlsForCategories = $getUrlsForCategories; |
| 66 | + $this->prerenderClient = $prerenderClient; |
| 67 | + $this->deploymentConfig = $deploymentConfig; |
| 68 | + $this->batchSize = $batchSize; |
| 69 | + $this->prerenderConfigHelper = $prerenderConfigHelper; |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * Execute full indexation |
| 74 | + * |
| 75 | + * @return void |
| 76 | + */ |
| 77 | + public function executeFull(): void |
| 78 | + { |
| 79 | + $this->executeList([]); |
| 80 | + } |
| 81 | + |
| 82 | + /** |
| 83 | + * Execute partial indexation by ID list |
| 84 | + * |
| 85 | + * @param int[] $ids |
| 86 | + * @return void |
| 87 | + */ |
| 88 | + public function executeList(array $ids): void |
| 89 | + { |
| 90 | + foreach ($this->dimensionProvider->getIterator() as $dimension) { |
| 91 | + try { |
| 92 | + $this->executeByDimensions($dimension, new \ArrayIterator($ids)); |
| 93 | + } catch (FileSystemException|RuntimeException $e) { |
| 94 | + continue; |
| 95 | + } |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + /** |
| 100 | + * Execute partial indexation by ID |
| 101 | + * |
| 102 | + * @param int $id |
| 103 | + * @return void |
| 104 | + * @throws LocalizedException |
| 105 | + */ |
| 106 | + public function executeRow($id): void |
| 107 | + { |
| 108 | + if (!$id) { |
| 109 | + throw new LocalizedException( |
| 110 | + __('Cannot recache url for an undefined product.') |
| 111 | + ); |
| 112 | + } |
| 113 | + $this->executeList([$id]); |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * Execute materialization on ids entities |
| 118 | + * |
| 119 | + * @param int[] $ids |
| 120 | + * @return void |
| 121 | + */ |
| 122 | + public function execute($ids): void |
| 123 | + { |
| 124 | + $this->executeList($ids); |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * Execute indexing per dimension (store) |
| 129 | + * |
| 130 | + * @param arry $dimensions |
| 131 | + * @param \Traversable $entityIds |
| 132 | + * @throws FileSystemException |
| 133 | + * @throws RuntimeException |
| 134 | + */ |
| 135 | + public function executeByDimensions(array $dimensions, \Traversable $entityIds): void |
| 136 | + { |
| 137 | + if (count($dimensions) > 1 || !isset($dimensions[StoreDimensionProvider::DIMENSION_NAME])) { |
| 138 | + throw new \InvalidArgumentException('Indexer "' . self::INDEXER_ID . '" supports only Store dimension'); |
| 139 | + } |
| 140 | + $storeId = (int)$dimensions[StoreDimensionProvider::DIMENSION_NAME]->getValue(); |
| 141 | + |
| 142 | + if (!$this->prerenderConfigHelper->isRecacheEnabled($storeId)) { |
| 143 | + return; |
| 144 | + } |
| 145 | + |
| 146 | + $entityIds = iterator_to_array($entityIds); |
| 147 | + // get list of category ids for the products |
| 148 | + $categoryIds = $this->productCategoriesDataProvider->getCategoryIdsForProducts($entityIds, $storeId); |
| 149 | + |
| 150 | + // get urls for the products |
| 151 | + $urls = $this->getUrlsForCategories->execute($categoryIds, $storeId); |
| 152 | + |
| 153 | + $this->batchSize = $this->deploymentConfig->get( |
| 154 | + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . self::INDEXER_ID . '/partial_reindex' |
| 155 | + ) ?? $this->batchSize; |
| 156 | + |
| 157 | + $urlBatches = array_chunk($urls, $this->batchSize); |
| 158 | + foreach ($urlBatches as $batchUrls) { |
| 159 | + $this->prerenderClient->recacheUrls($batchUrls, $storeId); |
| 160 | + } |
| 161 | + } |
| 162 | +} |
0 commit comments