Index.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\AdvancedSearch\Model\ResourceModel;
  7. use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
  8. use Magento\Framework\Search\Request\IndexScopeResolverInterface;
  9. use Magento\Store\Model\StoreManagerInterface;
  10. use Magento\Framework\Model\ResourceModel\Db\Context;
  11. use Magento\Framework\EntityManager\MetadataPool;
  12. use Magento\Catalog\Api\Data\CategoryInterface;
  13. use Magento\Framework\App\ObjectManager;
  14. use Magento\Framework\Search\Request\Dimension;
  15. use Magento\Catalog\Model\Indexer\Category\Product\AbstractAction;
  16. use Magento\Framework\Search\Request\IndexScopeResolverInterface as TableResolver;
  17. use Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory;
  18. use Magento\Store\Model\Indexer\WebsiteDimensionProvider;
  19. /**
  20. * @api
  21. * @since 100.1.0
  22. *
  23. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  24. */
  25. class Index extends AbstractDb
  26. {
  27. /**
  28. * @var StoreManagerInterface
  29. * @since 100.1.0
  30. */
  31. protected $storeManager;
  32. /**
  33. * @var MetadataPool
  34. * @since 100.1.0
  35. */
  36. protected $metadataPool;
  37. /**
  38. * @var TableResolver
  39. */
  40. private $tableResolver;
  41. /**
  42. * @var DimensionCollectionFactory|null
  43. */
  44. private $dimensionCollectionFactory;
  45. /**
  46. * @var int|null
  47. */
  48. private $websiteId;
  49. /**
  50. * Index constructor.
  51. * @param Context $context
  52. * @param StoreManagerInterface $storeManager
  53. * @param MetadataPool $metadataPool
  54. * @param string|null $connectionName
  55. * @param TableResolver|null $tableResolver
  56. * @param DimensionCollectionFactory|null $dimensionCollectionFactory
  57. */
  58. public function __construct(
  59. Context $context,
  60. StoreManagerInterface $storeManager,
  61. MetadataPool $metadataPool,
  62. $connectionName = null,
  63. TableResolver $tableResolver = null,
  64. DimensionCollectionFactory $dimensionCollectionFactory = null
  65. ) {
  66. parent::__construct($context, $connectionName);
  67. $this->storeManager = $storeManager;
  68. $this->metadataPool = $metadataPool;
  69. $this->tableResolver = $tableResolver ?: ObjectManager::getInstance()->get(IndexScopeResolverInterface::class);
  70. $this->dimensionCollectionFactory = $dimensionCollectionFactory
  71. ?: ObjectManager::getInstance()->get(DimensionCollectionFactory::class);
  72. }
  73. /**
  74. * Implementation of abstract construct
  75. * @return void
  76. * @since 100.1.0
  77. */
  78. protected function _construct()
  79. {
  80. }
  81. /**
  82. * Return array of price data per customer and website by products
  83. *
  84. * @param null|array $productIds
  85. * @return array
  86. * @since 100.1.0
  87. */
  88. protected function _getCatalogProductPriceData($productIds = null)
  89. {
  90. $connection = $this->getConnection();
  91. $catalogProductIndexPriceSelect = [];
  92. foreach ($this->dimensionCollectionFactory->create() as $dimensions) {
  93. if (!isset($dimensions[WebsiteDimensionProvider::DIMENSION_NAME]) ||
  94. $this->websiteId === null ||
  95. $dimensions[WebsiteDimensionProvider::DIMENSION_NAME]->getValue() === $this->websiteId) {
  96. $select = $connection->select()->from(
  97. $this->tableResolver->resolve('catalog_product_index_price', $dimensions),
  98. ['entity_id', 'customer_group_id', 'website_id', 'min_price']
  99. );
  100. if ($productIds) {
  101. $select->where('entity_id IN (?)', $productIds);
  102. }
  103. $catalogProductIndexPriceSelect[] = $select;
  104. }
  105. }
  106. $catalogProductIndexPriceUnionSelect = $connection->select()->union($catalogProductIndexPriceSelect);
  107. $result = [];
  108. foreach ($connection->fetchAll($catalogProductIndexPriceUnionSelect) as $row) {
  109. $result[$row['website_id']][$row['entity_id']][$row['customer_group_id']] = round($row['min_price'], 2);
  110. }
  111. return $result;
  112. }
  113. /**
  114. * Retrieve price data for product
  115. *
  116. * @param null|array $productIds
  117. * @param int $storeId
  118. * @return array
  119. * @since 100.1.0
  120. */
  121. public function getPriceIndexData($productIds, $storeId)
  122. {
  123. $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId();
  124. $this->websiteId = $websiteId;
  125. $priceProductsIndexData = $this->_getCatalogProductPriceData($productIds);
  126. $this->websiteId = null;
  127. if (!isset($priceProductsIndexData[$websiteId])) {
  128. return [];
  129. }
  130. return $priceProductsIndexData[$websiteId];
  131. }
  132. /**
  133. * Prepare system index data for products.
  134. *
  135. * @param int $storeId
  136. * @param null|array $productIds
  137. * @return array
  138. * @since 100.1.0
  139. */
  140. public function getCategoryProductIndexData($storeId = null, $productIds = null)
  141. {
  142. $connection = $this->getConnection();
  143. $catalogCategoryProductDimension = new Dimension(\Magento\Store\Model\Store::ENTITY, $storeId);
  144. $catalogCategoryProductTableName = $this->tableResolver->resolve(
  145. AbstractAction::MAIN_INDEX_TABLE,
  146. [
  147. $catalogCategoryProductDimension
  148. ]
  149. );
  150. $select = $connection->select()->from(
  151. [$catalogCategoryProductTableName],
  152. ['category_id', 'product_id', 'position', 'store_id']
  153. )->where(
  154. 'store_id = ?',
  155. $storeId
  156. );
  157. if ($productIds) {
  158. $select->where('product_id IN (?)', $productIds);
  159. }
  160. $result = [];
  161. foreach ($connection->fetchAll($select) as $row) {
  162. $result[$row['product_id']][$row['category_id']] = $row['position'];
  163. }
  164. return $result;
  165. }
  166. /**
  167. * Retrieve moved categories product ids
  168. *
  169. * @param int $categoryId
  170. * @return array
  171. * @since 100.1.0
  172. */
  173. public function getMovedCategoryProductIds($categoryId)
  174. {
  175. $connection = $this->getConnection();
  176. $identifierField = $this->metadataPool->getMetadata(CategoryInterface::class)->getIdentifierField();
  177. $select = $connection->select()->distinct()->from(
  178. ['c_p' => $this->getTable('catalog_category_product')],
  179. ['product_id']
  180. )->join(
  181. ['c_e' => $this->getTable('catalog_category_entity')],
  182. 'c_p.category_id = c_e.' . $identifierField,
  183. []
  184. )->where(
  185. $connection->quoteInto('c_e.path LIKE ?', '%/' . $categoryId . '/%')
  186. )->orWhere(
  187. 'c_p.category_id = ?',
  188. $categoryId
  189. );
  190. return $connection->fetchCol($select);
  191. }
  192. }