5
5
*/
6
6
namespace Magento \Catalog \Model \Indexer \Category \Product \Action ;
7
7
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
+ */
8
17
class Full extends \Magento \Catalog \Model \Indexer \Category \Product \AbstractAction
9
18
{
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
+
10
90
/**
11
91
* Refresh entities index
12
92
*
13
93
* @return $this
14
94
*/
15
95
public function execute ()
16
96
{
17
- $ this ->clearTmpData ();
18
-
19
97
$ this ->reindex ();
20
98
21
- $ this ->publishData ();
22
- $ this ->removeUnnecessaryData ();
23
-
24
99
return $ this ;
25
100
}
26
101
@@ -35,7 +110,7 @@ protected function getSelectUnnecessaryData()
35
110
$ this ->getMainTable (),
36
111
[]
37
112
)->joinLeft (
38
- ['t ' => $ this ->getMainTmpTable ()],
113
+ ['t ' => $ this ->getMainTable ()],
39
114
$ this ->getMainTable () .
40
115
'.category_id = t.category_id AND ' .
41
116
$ this ->getMainTable () .
@@ -69,27 +144,116 @@ protected function publishData()
69
144
{
70
145
$ select = $ this ->connection ->select ()->from ($ this ->getMainTmpTable ());
71
146
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
+ }
73
200
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 );
75
227
$ this ->connection ->query (
76
228
$ 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 ,
80
232
\Magento \Framework \DB \Adapter \AdapterInterface::INSERT_ON_DUPLICATE
81
233
)
82
234
);
235
+ $ this ->publishData ();
236
+ $ this ->removeUnnecessaryData ();
83
237
}
84
238
}
85
239
86
240
/**
87
- * Clear all index data
241
+ * This overridden method returns ALTERNATIVE table name to work with.
88
242
*
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
90
247
*/
91
- protected function clearTmpData ()
248
+ protected function getMainTable ()
92
249
{
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 ;
94
258
}
95
259
}
0 commit comments