Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
IndexBuilder.php
Go to the documentation of this file.
1 <?php
8 
10 use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory as RuleCollectionFactory;
16 
25 {
26  const SECONDS_IN_DAY = 86400;
27 
33  protected $metadataPool;
34 
43  protected $_catalogRuleGroupWebsiteColumnsList = ['rule_id', 'customer_group_id', 'website_id'];
44 
48  protected $resource;
49 
53  protected $storeManager;
54 
59 
63  protected $logger;
64 
68  protected $priceCurrency;
69 
73  protected $eavConfig;
74 
78  protected $dateFormat;
79 
83  protected $dateTime;
84 
88  protected $productFactory;
89 
93  protected $loadedProducts;
94 
98  protected $batchCount;
99 
103  protected $connection;
104 
108  private $productPriceCalculator;
109 
113  private $reindexRuleProduct;
114 
118  private $reindexRuleGroupWebsite;
119 
123  private $ruleProductsSelectBuilder;
124 
128  private $reindexRuleProductPrice;
129 
133  private $pricesPersistor;
134 
138  private $activeTableSwitcher;
139 
143  private $tableSwapper;
144 
148  private $productLoader;
149 
172  public function __construct(
173  RuleCollectionFactory $ruleCollectionFactory,
177  \Psr\Log\LoggerInterface $logger,
178  \Magento\Eav\Model\Config $eavConfig,
179  \Magento\Framework\Stdlib\DateTime $dateFormat,
180  \Magento\Framework\Stdlib\DateTime\DateTime $dateTime,
181  \Magento\Catalog\Model\ProductFactory $productFactory,
182  $batchCount = 1000,
183  ProductPriceCalculator $productPriceCalculator = null,
184  ReindexRuleProduct $reindexRuleProduct = null,
185  ReindexRuleGroupWebsite $reindexRuleGroupWebsite = null,
186  RuleProductsSelectBuilder $ruleProductsSelectBuilder = null,
187  ReindexRuleProductPrice $reindexRuleProductPrice = null,
188  RuleProductPricesPersistor $pricesPersistor = null,
189  \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher $activeTableSwitcher = null,
190  ProductLoader $productLoader = null,
191  TableSwapper $tableSwapper = null
192  ) {
193  $this->resource = $resource;
194  $this->connection = $resource->getConnection();
195  $this->storeManager = $storeManager;
196  $this->ruleCollectionFactory = $ruleCollectionFactory;
197  $this->logger = $logger;
198  $this->priceCurrency = $priceCurrency;
199  $this->eavConfig = $eavConfig;
200  $this->dateFormat = $dateFormat;
201  $this->dateTime = $dateTime;
202  $this->productFactory = $productFactory;
203  $this->batchCount = $batchCount;
204 
205  $this->productPriceCalculator = $productPriceCalculator ?? ObjectManager::getInstance()->get(
206  ProductPriceCalculator::class
207  );
208  $this->reindexRuleProduct = $reindexRuleProduct ?? ObjectManager::getInstance()->get(
209  ReindexRuleProduct::class
210  );
211  $this->reindexRuleGroupWebsite = $reindexRuleGroupWebsite ?? ObjectManager::getInstance()->get(
212  ReindexRuleGroupWebsite::class
213  );
214  $this->ruleProductsSelectBuilder = $ruleProductsSelectBuilder ?? ObjectManager::getInstance()->get(
215  RuleProductsSelectBuilder::class
216  );
217  $this->reindexRuleProductPrice = $reindexRuleProductPrice ?? ObjectManager::getInstance()->get(
218  ReindexRuleProductPrice::class
219  );
220  $this->pricesPersistor = $pricesPersistor ?? ObjectManager::getInstance()->get(
221  RuleProductPricesPersistor::class
222  );
223  $this->activeTableSwitcher = $activeTableSwitcher ?? ObjectManager::getInstance()->get(
224  \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher::class
225  );
226  $this->productLoader = $productLoader ?? ObjectManager::getInstance()->get(
227  ProductLoader::class
228  );
229  $this->tableSwapper = $tableSwapper ??
230  ObjectManager::getInstance()->get(TableSwapper::class);
231  }
232 
240  public function reindexById($id)
241  {
242  $this->reindexByIds([$id]);
243  }
244 
253  public function reindexByIds(array $ids)
254  {
255  try {
256  $this->doReindexByIds($ids);
257  } catch (\Exception $e) {
258  $this->critical($e);
259  throw new \Magento\Framework\Exception\LocalizedException(
260  __("Catalog rule indexing failed. See details in exception log.")
261  );
262  }
263  }
264 
271  protected function doReindexByIds($ids)
272  {
273  $this->cleanByIds($ids);
274 
275  $products = $this->productLoader->getProducts($ids);
276  foreach ($this->getActiveRules() as $rule) {
277  foreach ($products as $product) {
278  $this->applyRule($rule, $product);
279  }
280  }
281  }
282 
290  public function reindexFull()
291  {
292  try {
293  $this->doReindexFull();
294  } catch (\Exception $e) {
295  $this->critical($e);
296  throw new \Magento\Framework\Exception\LocalizedException(
297  __("Catalog rule indexing failed. See details in exception log.")
298  );
299  }
300  }
301 
307  protected function doReindexFull()
308  {
309  foreach ($this->getAllRules() as $rule) {
310  $this->reindexRuleProduct->execute($rule, $this->batchCount, true);
311  }
312 
313  $this->reindexRuleProductPrice->execute($this->batchCount, null, true);
314  $this->reindexRuleGroupWebsite->execute(true);
315 
316  $this->tableSwapper->swapIndexTables(
317  [
318  $this->getTable('catalogrule_product'),
319  $this->getTable('catalogrule_product_price'),
320  $this->getTable('catalogrule_group_website')
321  ]
322  );
323  }
324 
331  protected function cleanByIds($productIds)
332  {
333  $query = $this->connection->deleteFromSelect(
334  $this->connection
335  ->select()
336  ->from($this->resource->getTableName('catalogrule_product'), 'product_id')
337  ->distinct()
338  ->where('product_id IN (?)', $productIds),
339  $this->resource->getTableName('catalogrule_product')
340  );
341  $this->connection->query($query);
342 
343  $query = $this->connection->deleteFromSelect(
344  $this->connection->select()
345  ->from($this->resource->getTableName('catalogrule_product_price'), 'product_id')
346  ->distinct()
347  ->where('product_id IN (?)', $productIds),
348  $this->resource->getTableName('catalogrule_product_price')
349  );
350  $this->connection->query($query);
351  }
352 
360  protected function applyRule(Rule $rule, $product)
361  {
362  $ruleId = $rule->getId();
363  $productEntityId = $product->getId();
364  $websiteIds = array_intersect($product->getWebsiteIds(), $rule->getWebsiteIds());
365 
366  if (!$rule->validate($product)) {
367  return $this;
368  }
369 
370  $this->connection->delete(
371  $this->resource->getTableName('catalogrule_product'),
372  [
373  $this->connection->quoteInto('rule_id = ?', $ruleId),
374  $this->connection->quoteInto('product_id = ?', $productEntityId)
375  ]
376  );
377 
378  $customerGroupIds = $rule->getCustomerGroupIds();
379  $fromTime = strtotime($rule->getFromDate());
380  $toTime = strtotime($rule->getToDate());
381  $toTime = $toTime ? $toTime + self::SECONDS_IN_DAY - 1 : 0;
382  $sortOrder = (int)$rule->getSortOrder();
383  $actionOperator = $rule->getSimpleAction();
384  $actionAmount = $rule->getDiscountAmount();
385  $actionStop = $rule->getStopRulesProcessing();
386 
387  $rows = [];
388  try {
389  foreach ($websiteIds as $websiteId) {
390  foreach ($customerGroupIds as $customerGroupId) {
391  $rows[] = [
392  'rule_id' => $ruleId,
393  'from_time' => $fromTime,
394  'to_time' => $toTime,
395  'website_id' => $websiteId,
396  'customer_group_id' => $customerGroupId,
397  'product_id' => $productEntityId,
398  'action_operator' => $actionOperator,
399  'action_amount' => $actionAmount,
400  'action_stop' => $actionStop,
401  'sort_order' => $sortOrder,
402  ];
403 
404  if (count($rows) == $this->batchCount) {
405  $this->connection->insertMultiple($this->getTable('catalogrule_product'), $rows);
406  $rows = [];
407  }
408  }
409  }
410 
411  if (!empty($rows)) {
412  $this->connection->insertMultiple($this->resource->getTableName('catalogrule_product'), $rows);
413  }
414  } catch (\Exception $e) {
415  throw $e;
416  }
417 
418  $this->reindexRuleProductPrice->execute($this->batchCount, $product);
419  $this->reindexRuleGroupWebsite->execute();
420 
421  return $this;
422  }
423 
428  protected function getTable($tableName)
429  {
430  return $this->resource->getTableName($tableName);
431  }
432 
439  protected function updateRuleProductData(Rule $rule)
440  {
441  $ruleId = $rule->getId();
442  if ($rule->getProductsFilter()) {
443  $this->connection->delete(
444  $this->getTable('catalogrule_product'),
445  ['rule_id=?' => $ruleId, 'product_id IN (?)' => $rule->getProductsFilter()]
446  );
447  } else {
448  $this->connection->delete(
449  $this->getTable('catalogrule_product'),
450  $this->connection->quoteInto('rule_id=?', $ruleId)
451  );
452  }
453 
454  $this->reindexRuleProduct->execute($rule, $this->batchCount);
455  return $this;
456  }
457 
466  protected function applyAllRules(Product $product = null)
467  {
468  $this->reindexRuleProductPrice->execute($this->batchCount, $product);
469  $this->reindexRuleGroupWebsite->execute();
470  return $this;
471  }
472 
481  {
482  $this->reindexRuleGroupWebsite->execute();
483  return $this;
484  }
485 
491  protected function deleteOldData()
492  {
493  $this->connection->delete($this->getTable('catalogrule_product_price'));
494  return $this;
495  }
496 
504  protected function calcRuleProductPrice($ruleData, $productData = null)
505  {
506  return $this->productPriceCalculator->calculate($ruleData, $productData);
507  }
508 
517  protected function getRuleProductsStmt($websiteId, Product $product = null)
518  {
519  return $this->ruleProductsSelectBuilder->build($websiteId, $product);
520  }
521 
529  protected function saveRuleProductPrices($arrData)
530  {
531  $this->pricesPersistor->execute($arrData);
532  return $this;
533  }
534 
540  protected function getActiveRules()
541  {
542  return $this->ruleCollectionFactory->create()->addFieldToFilter('is_active', 1);
543  }
544 
550  protected function getAllRules()
551  {
552  return $this->ruleCollectionFactory->create();
553  }
554 
559  protected function getProduct($productId)
560  {
561  if (!isset($this->loadedProducts[$productId])) {
562  $this->loadedProducts[$productId] = $this->productFactory->create()->load($productId);
563  }
564  return $this->loadedProducts[$productId];
565  }
566 
571  protected function critical($e)
572  {
573  $this->logger->critical($e);
574  }
575 }
$tableName
Definition: trigger.php:13
__construct(RuleCollectionFactory $ruleCollectionFactory, PriceCurrencyInterface $priceCurrency, \Magento\Framework\App\ResourceConnection $resource, \Magento\Store\Model\StoreManagerInterface $storeManager, \Psr\Log\LoggerInterface $logger, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Stdlib\DateTime $dateFormat, \Magento\Framework\Stdlib\DateTime\DateTime $dateTime, \Magento\Catalog\Model\ProductFactory $productFactory, $batchCount=1000, ProductPriceCalculator $productPriceCalculator=null, ReindexRuleProduct $reindexRuleProduct=null, ReindexRuleGroupWebsite $reindexRuleGroupWebsite=null, RuleProductsSelectBuilder $ruleProductsSelectBuilder=null, ReindexRuleProductPrice $reindexRuleProductPrice=null, RuleProductPricesPersistor $pricesPersistor=null, \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher $activeTableSwitcher=null, ProductLoader $productLoader=null, TableSwapper $tableSwapper=null)
$id
Definition: fieldset.phtml:14
__()
Definition: __.php:13
calcRuleProductPrice($ruleData, $productData=null)
$ruleData
Definition: tax_rule.php:26
$productData
getRuleProductsStmt($websiteId, Product $product=null)