From 943a30ac9b85f4170e7bf31156b7c4dccd9025c4 Mon Sep 17 00:00:00 2001 From: Richard BAYET Date: Thu, 28 Feb 2019 16:47:32 +0100 Subject: [PATCH] Fixes #1322 Support price index dimensions/segmentation --- .../Indexer/Fulltext/Datasource/PriceData.php | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/PriceData.php b/src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/PriceData.php index 844a88802..36f95fd51 100644 --- a/src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/PriceData.php +++ b/src/module-elasticsuite-catalog/Model/ResourceModel/Product/Indexer/Fulltext/Datasource/PriceData.php @@ -15,6 +15,12 @@ namespace Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource; use Smile\ElasticsuiteCatalog\Model\ResourceModel\Eav\Indexer\Indexer; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory; +use Magento\Store\Model\Indexer\WebsiteDimensionProvider; +use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; /** * Prices data datasource resource model. @@ -25,6 +31,52 @@ */ class PriceData extends Indexer { + /** + * @var DimensionCollectionFactory + */ + private $dimensionCollectionFactory; + + /** + * @var array + */ + private $dimensions; + + /** + * @var array + */ + private $dimensionsByWebsite; + + /** + * @var PriceTableResolver + */ + private $priceTableResolver; + + /** + * PriceData constructor. + * + * @param ResourceConnection $resource Database adapter. + * @param StoreManagerInterface $storeManager Store Manager. + * @param MetadataPool $metadataPool Metadata Pool. + * @param DimensionCollectionFactory $dimensionCollectionFactory Dimension collection factory. + * @param PriceTableResolver $priceTableResolver Price index table resolver. + */ + public function __construct( + ResourceConnection $resource, + StoreManagerInterface $storeManager, + MetadataPool $metadataPool, + DimensionCollectionFactory $dimensionCollectionFactory, + PriceTableResolver $priceTableResolver + ) { + // \Smile\ElasticsuiteCatalog\Model\ResourceModel\Product\Indexer\Fulltext\Datasource\CategoryData::getCategoryProductIndexTable + + $this->dimensionCollectionFactory = $dimensionCollectionFactory; + $this->dimensions = null; + $this->dimensionsByWebsite = []; + $this->priceTableResolver = $priceTableResolver; + + parent::__construct($resource, $storeManager, $metadataPool); + } + /** * Load prices data for a list of product ids and a given store. * @@ -37,11 +89,130 @@ public function loadPriceData($storeId, $productIds) { $websiteId = $this->getStore($storeId)->getWebsiteId(); + /* $select = $this->getConnection()->select() ->from(['p' => $this->getTable('catalog_product_index_price')]) ->where('p.website_id = ?', $websiteId) ->where('p.entity_id IN(?)', $productIds); + */ + $baseQueries = []; + foreach ($this->getPriceIndexDimensionsTables($websiteId) as $dimensionsTable) { + $baseQueries[] = $this->getLoadPriceDataSelect($dimensionsTable, $websiteId, $productIds); + } + $select = $this->getConnection()->select()->union($baseQueries); + + $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/index-select.log'); + $logger = new \Zend\Log\Logger(); + $logger->addWriter($writer); + $logger->info('--- UNION SELECT ---'); + $logger->info((string) $select); return $this->getConnection()->fetchAll($select); } + + /** + * Return a single price loading query against a specific price index table. + * + * @param string $indexTable Price index table. + * @param integer $websiteId Website id. + * @param array $productIds Product ids list. + * + * @return \Magento\Framework\DB\Select + */ + private function getLoadPriceDataSelect($indexTable, $websiteId, $productIds) + { + $select = $this->getConnection()->select() + ->from(['p' => $indexTable]) + ->where('p.website_id = ?', $websiteId) + ->where('p.entity_id IN(?)', $productIds); + + $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/index-select.log'); + $logger = new \Zend\Log\Logger(); + $logger->addWriter($writer); + $logger->info('--- SINGLE SELECT ---'); + $logger->info((string) $select); + + return $select; + } + + /** + * Return the price index tables according to the price index dimensions for the given website. + * + * @param integer $websiteId Website id. + * + * @return array + */ + private function getPriceIndexDimensionsTables($websiteId) + { + $tables = []; + + $indexDimensions = $this->getPriceIndexDimensions($websiteId); + foreach ($indexDimensions as $dimensions) { + $tables[] = $this->priceTableResolver->resolve('catalog_product_index_price', $dimensions); + } + + return $tables; + } + + /** + * Return price index dimensions applicable for the given website. + * + * @param integer $websiteId Website id. + * + * @return array + */ + private function getPriceIndexDimensions($websiteId) + { + if (!array_key_exists($websiteId, $this->dimensionsByWebsite)) { + $indexDimensions = $this->getAllPriceIndexDimensions(); + + $relevantDimensions = []; + foreach ($indexDimensions as $dimensions) { + if (array_key_exists(WebsiteDimensionProvider::DIMENSION_NAME, $dimensions)) { + $websiteDimension = $dimensions[WebsiteDimensionProvider::DIMENSION_NAME]; + if ((string) $websiteDimension->getValue() == $websiteId) { + $relevantDimensions[] = $dimensions; + } + } else { + $relevantDimensions[] = $dimensions; + } + } + + $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/dimensions.log'); + $logger = new \Zend\Log\Logger(); + $logger->addWriter($writer); + $logger->info('--- RELEVANT DIMENSIONS ---'); + foreach ($relevantDimensions as $currentDimension) { + $logger->info(print_r($currentDimension, true)); + } + + $this->dimensionsByWebsite[$websiteId] = $relevantDimensions; + } + + return $this->dimensionsByWebsite[$websiteId]; + } + + /** + * Return all price index dimensions. + * + * @return array + */ + private function getAllPriceIndexDimensions() + { + if ($this->dimensions === null) { + $dimensions = $this->dimensionCollectionFactory->create(); + + $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/dimensions.log'); + $logger = new \Zend\Log\Logger(); + $logger->addWriter($writer); + $logger->info('--- DIMENSIONS ---'); + foreach ($dimensions as $currentDimension) { + $logger->info(print_r($currentDimension, true)); + } + + $this->dimensions = $dimensions; + } + + return $this->dimensions; + } }