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