55 */
66namespace Magento \Catalog \Model \Indexer \Category \Product \Action ;
77
8+ use Magento \Framework \DB \Query \Generator as QueryGenerator ;
9+ use Magento \Framework \App \ResourceConnection ;
10+
11+ /**
12+ * Class Full reindex action
13+ *
14+ * @package Magento\Catalog\Model\Indexer\Category\Product\Action
15+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
16+ */
817class Full extends \Magento \Catalog \Model \Indexer \Category \Product \AbstractAction
918{
19+ /**
20+ * @var \Magento\Framework\Indexer\BatchSizeManagementInterface
21+ */
22+ private $ batchSizeManagement ;
23+
24+ /**
25+ * @var \Magento\Framework\Indexer\BatchProviderInterface
26+ */
27+ private $ batchProvider ;
28+
29+ /**
30+ * @var \Magento\Indexer\Model\Indexer\StateFactory
31+ */
32+ private $ indexerStateFactory ;
33+
34+ /**
35+ * @var \Magento\Framework\EntityManager\MetadataPool
36+ */
37+ protected $ metadataPool ;
38+
39+ /**
40+ * Row count to process in a batch
41+ *
42+ * @var int
43+ */
44+ private $ batchRowsCount ;
45+
46+ /**
47+ * @param ResourceConnection $resource
48+ * @param \Magento\Store\Model\StoreManagerInterface $storeManager
49+ * @param \Magento\Catalog\Model\Config $config
50+ * @param QueryGenerator|null $queryGenerator
51+ * @param \Magento\Framework\Indexer\BatchSizeManagementInterface|null $batchSizeManagement
52+ * @param \Magento\Framework\Indexer\BatchProviderInterface|null $batchProvider
53+ * @param \Magento\Framework\EntityManager\MetadataPool|null $metadataPool
54+ * @param \Magento\Indexer\Model\Indexer\StateFactory|null $stateFactory
55+ * @param int|null $batchRowsCount
56+ */
57+ public function __construct (
58+ \Magento \Framework \App \ResourceConnection $ resource ,
59+ \Magento \Store \Model \StoreManagerInterface $ storeManager ,
60+ \Magento \Catalog \Model \Config $ config ,
61+ QueryGenerator $ queryGenerator = null ,
62+ \Magento \Framework \Indexer \BatchSizeManagementInterface $ batchSizeManagement = null ,
63+ \Magento \Framework \Indexer \BatchProviderInterface $ batchProvider = null ,
64+ \Magento \Framework \EntityManager \MetadataPool $ metadataPool = null ,
65+ \Magento \Indexer \Model \Indexer \StateFactory $ stateFactory = null ,
66+ $ batchRowsCount = null
67+ ) {
68+ parent ::__construct (
69+ $ resource ,
70+ $ storeManager ,
71+ $ config ,
72+ $ queryGenerator
73+ );
74+ $ objectManager = \Magento \Framework \App \ObjectManager::getInstance ();
75+ $ this ->batchSizeManagement = $ batchSizeManagement ?: $ objectManager ->get (
76+ \Magento \Framework \Indexer \BatchSizeManagementInterface::class
77+ );
78+ $ this ->batchProvider = $ batchProvider ?: $ objectManager ->get (
79+ \Magento \Framework \Indexer \BatchProviderInterface::class
80+ );
81+ $ this ->metadataPool = $ metadataPool ?: $ objectManager ->get (
82+ \Magento \Framework \EntityManager \MetadataPool::class
83+ );
84+ $ this ->indexerStateFactory = $ stateFactory ?: $ objectManager ->get (
85+ \Magento \Indexer \Model \Indexer \StateFactory::class
86+ );
87+ $ this ->batchRowsCount = $ batchRowsCount ;
88+ }
89+
1090 /**
1191 * Refresh entities index
1292 *
1393 * @return $this
1494 */
1595 public function execute ()
1696 {
17- $ this ->clearTmpData ();
18-
1997 $ this ->reindex ();
2098
21- $ this ->publishData ();
22- $ this ->removeUnnecessaryData ();
23-
2499 return $ this ;
25100 }
26101
@@ -35,7 +110,7 @@ protected function getSelectUnnecessaryData()
35110 $ this ->getMainTable (),
36111 []
37112 )->joinLeft (
38- ['t ' => $ this ->getMainTmpTable ()],
113+ ['t ' => $ this ->getMainTable ()],
39114 $ this ->getMainTable () .
40115 '.category_id = t.category_id AND ' .
41116 $ this ->getMainTable () .
@@ -69,27 +144,116 @@ protected function publishData()
69144 {
70145 $ select = $ this ->connection ->select ()->from ($ this ->getMainTmpTable ());
71146
72- $ queries = $ this ->prepareSelectsByRange ($ select , 'category_id ' );
147+ $ columns = array_keys ($ this ->connection ->describeTable ($ this ->getMainTable ()));
148+
149+ $ this ->connection ->query (
150+ $ this ->connection ->insertFromSelect (
151+ $ select ,
152+ $ this ->getMainTable (),
153+ $ columns ,
154+ \Magento \Framework \DB \Adapter \AdapterInterface::INSERT_ON_DUPLICATE
155+ )
156+ );
157+ }
158+
159+ /**
160+ * Clear all index data
161+ *
162+ * @return void
163+ */
164+ protected function clearTmpData ()
165+ {
166+ $ this ->connection ->delete ($ this ->getMainTmpTable ());
167+ }
168+
169+ /**
170+ * {@inheritdoc}
171+ */
172+ protected function reindexRootCategory (\Magento \Store \Model \Store $ store )
173+ {
174+ if ($ this ->isIndexRootCategoryNeeded ()) {
175+ $ this ->reindexCategoriesBySelect ($ this ->getAllProducts ($ store ), 'cp.entity_id IN (?) ' );
176+ }
177+ }
178+
179+ /**
180+ * Reindex products of anchor categories
181+ *
182+ * @param \Magento\Store\Model\Store $store
183+ * @return void
184+ */
185+ protected function reindexAnchorCategories (\Magento \Store \Model \Store $ store )
186+ {
187+ $ this ->reindexCategoriesBySelect ($ this ->getAnchorCategoriesSelect ($ store ), 'ccp.product_id IN (?) ' );
188+ }
189+
190+ /**
191+ * Reindex products of non anchor categories
192+ *
193+ * @param \Magento\Store\Model\Store $store
194+ * @return void
195+ */
196+ protected function reindexNonAnchorCategories (\Magento \Store \Model \Store $ store )
197+ {
198+ $ this ->reindexCategoriesBySelect ($ this ->getNonAnchorCategoriesSelect ($ store ), 'ccp.product_id IN (?) ' );
199+ }
73200
74- foreach ($ queries as $ query ) {
201+ /**
202+ * Reindex categories using given SQL select and condition.
203+ *
204+ * @param \Magento\Framework\DB\Select $basicSelect
205+ * @param string $whereCondition
206+ * @return void
207+ */
208+ private function reindexCategoriesBySelect (\Magento \Framework \DB \Select $ basicSelect , $ whereCondition )
209+ {
210+ $ entityMetadata = $ this ->metadataPool ->getMetadata (\Magento \Catalog \Api \Data \ProductInterface::class);
211+ $ columns = array_keys ($ this ->connection ->describeTable ($ this ->getMainTmpTable ()));
212+ $ this ->batchSizeManagement ->ensureBatchSize ($ this ->connection , $ this ->batchRowsCount );
213+ $ batches = $ this ->batchProvider ->getBatches (
214+ $ this ->connection ,
215+ $ entityMetadata ->getEntityTable (),
216+ $ entityMetadata ->getIdentifierField (),
217+ $ this ->batchRowsCount
218+ );
219+ foreach ($ batches as $ batch ) {
220+ $ this ->clearTmpData ();
221+ $ resultSelect = clone $ basicSelect ;
222+ $ select = $ this ->connection ->select ();
223+ $ select ->distinct (true );
224+ $ select ->from (['e ' => $ entityMetadata ->getEntityTable ()], $ entityMetadata ->getIdentifierField ());
225+ $ entityIds = $ this ->batchProvider ->getBatchIds ($ this ->connection , $ select , $ batch );
226+ $ resultSelect ->where ($ whereCondition , $ entityIds );
75227 $ this ->connection ->query (
76228 $ this ->connection ->insertFromSelect (
77- $ query ,
78- $ this ->getMainTable (),
79- [ ' category_id ' , ' product_id ' , ' position ' , ' is_parent ' , ' store_id ' , ' visibility ' ] ,
229+ $ resultSelect ,
230+ $ this ->getMainTmpTable (),
231+ $ columns ,
80232 \Magento \Framework \DB \Adapter \AdapterInterface::INSERT_ON_DUPLICATE
81233 )
82234 );
235+ $ this ->publishData ();
236+ $ this ->removeUnnecessaryData ();
83237 }
84238 }
85239
86240 /**
87- * Clear all index data
241+ * This overridden method returns ALTERNATIVE table name to work with.
88242 *
89- * @return void
243+ * When the table used on frontend is 'catalog_category_product_index' this indexer should work
244+ * with 'catalog_category_product_index_replica' and vice versa.
245+ *
246+ * @return string table name which is NOT used on frontend
90247 */
91- protected function clearTmpData ()
248+ protected function getMainTable ()
92249 {
93- $ this ->connection ->delete ($ this ->getMainTmpTable ());
250+ $ table = $ this ->getTable (self ::MAIN_INDEX_TABLE );
251+ $ indexerState = $ this ->indexerStateFactory ->create ()->loadByIndexer (
252+ \Magento \Catalog \Model \Indexer \Category \Product::INDEXER_ID
253+ );
254+ $ destinationTableSuffix = ($ indexerState ->getTableSuffix () === '' )
255+ ? \Magento \Framework \Indexer \StateInterface::ADDITIONAL_TABLE_SUFFIX
256+ : '' ;
257+ return $ table . $ destinationTableSuffix ;
94258 }
95259}
0 commit comments