Stock.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Bundle\Model\ResourceModel\Indexer;
  7. use Magento\CatalogInventory\Model\Indexer\Stock\Action\Full;
  8. use Magento\Framework\App\ObjectManager;
  9. /**
  10. * Bundle Stock Status Indexer Resource Model
  11. *
  12. * @author Magento Core Team <core@magentocommerce.com>
  13. */
  14. class Stock extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\DefaultStock
  15. {
  16. /**
  17. * @var \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher
  18. */
  19. private $activeTableSwitcher;
  20. /**
  21. * @var \Magento\Bundle\Model\ResourceModel\Indexer\StockStatusSelectBuilder
  22. */
  23. private $stockStatusSelectBuilder;
  24. /**
  25. * @var \Magento\Bundle\Model\ResourceModel\Indexer\BundleOptionStockDataSelectBuilder
  26. */
  27. private $bundleOptionStockDataSelectBuilder;
  28. /**
  29. * Class constructor
  30. *
  31. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  32. * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy
  33. * @param \Magento\Eav\Model\Config $eavConfig
  34. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  35. * @param null $connectionName
  36. * @param \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher|null $activeTableSwitcher
  37. * @param StockStatusSelectBuilder|null $stockStatusSelectBuilder
  38. * @param BundleOptionStockDataSelectBuilder|null $bundleOptionStockDataSelectBuilder
  39. */
  40. public function __construct(
  41. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  42. \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
  43. \Magento\Eav\Model\Config $eavConfig,
  44. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  45. $connectionName = null,
  46. \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher $activeTableSwitcher = null,
  47. StockStatusSelectBuilder $stockStatusSelectBuilder = null,
  48. BundleOptionStockDataSelectBuilder $bundleOptionStockDataSelectBuilder = null
  49. ) {
  50. parent::__construct($context, $tableStrategy, $eavConfig, $scopeConfig, $connectionName);
  51. $this->activeTableSwitcher = $activeTableSwitcher ?: ObjectManager::getInstance()
  52. ->get(\Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher::class);
  53. $this->stockStatusSelectBuilder = $stockStatusSelectBuilder ?: ObjectManager::getInstance()
  54. ->get(StockStatusSelectBuilder::class);
  55. $this->bundleOptionStockDataSelectBuilder = $bundleOptionStockDataSelectBuilder ?: ObjectManager::getInstance()
  56. ->get(BundleOptionStockDataSelectBuilder::class);
  57. }
  58. /**
  59. * Retrieve table name for temporary bundle option stock index
  60. *
  61. * @return string
  62. */
  63. protected function _getBundleOptionTable()
  64. {
  65. return $this->getTable('catalog_product_bundle_stock_index');
  66. }
  67. /**
  68. * Prepare stock status per Bundle options, website and stock
  69. *
  70. * @param int|array $entityIds
  71. * @param bool $usePrimaryTable use primary or temporary index table
  72. * @return $this
  73. */
  74. protected function _prepareBundleOptionStockData($entityIds = null, $usePrimaryTable = false)
  75. {
  76. $this->_cleanBundleOptionStockData();
  77. $connection = $this->getConnection();
  78. $table = $this->getActionType() === Full::ACTION_TYPE
  79. ? $this->activeTableSwitcher->getAdditionalTableName($this->getMainTable())
  80. : $this->getMainTable();
  81. $idxTable = $usePrimaryTable ? $table : $this->getIdxTable();
  82. $select = $this->bundleOptionStockDataSelectBuilder->buildSelect($idxTable);
  83. $status = new \Zend_Db_Expr(
  84. 'MAX('
  85. . $connection->getCheckSql('e.required_options = 0', 'i.stock_status', '0')
  86. . ')'
  87. );
  88. $select->columns(['status' => $status]);
  89. if ($entityIds !== null) {
  90. $select->where('product.entity_id IN(?)', $entityIds);
  91. }
  92. // clone select for bundle product without required bundle options
  93. $selectNonRequired = clone $select;
  94. $select->where('bo.required = ?', 1);
  95. $selectNonRequired->where('bo.required = ?', 0)->having($status . ' = 1');
  96. $query = $select->insertFromSelect($this->_getBundleOptionTable());
  97. $connection->query($query);
  98. $query = $selectNonRequired->insertFromSelect($this->_getBundleOptionTable());
  99. $connection->query($query);
  100. return $this;
  101. }
  102. /**
  103. * Get the select object for get stock status by product ids
  104. *
  105. * @param int|array $entityIds
  106. * @param bool $usePrimaryTable use primary or temporary index table
  107. * @return \Magento\Framework\DB\Select
  108. */
  109. protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false)
  110. {
  111. $this->_prepareBundleOptionStockData($entityIds, $usePrimaryTable);
  112. $connection = $this->getConnection();
  113. $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable);
  114. $select = $this->stockStatusSelectBuilder->buildSelect($select);
  115. $statusNotNullExpr = $connection->getCheckSql('o.stock_status IS NOT NULL', 'o.stock_status', '0');
  116. $statusExpr = $this->getStatusExpression($connection);
  117. $select->columns(
  118. [
  119. 'status' => $connection->getLeastSql(
  120. [
  121. new \Zend_Db_Expr('MIN(' . $statusNotNullExpr . ')'),
  122. new \Zend_Db_Expr('MIN(' . $statusExpr . ')'),
  123. ]
  124. ),
  125. ]
  126. );
  127. if ($entityIds !== null) {
  128. $select->where('e.entity_id IN(?)', $entityIds);
  129. }
  130. return $select;
  131. }
  132. /**
  133. * Prepare stock status data in temporary index table
  134. *
  135. * @param int|array $entityIds the product limitation
  136. * @return $this
  137. */
  138. protected function _prepareIndexTable($entityIds = null)
  139. {
  140. parent::_prepareIndexTable($entityIds);
  141. $this->_cleanBundleOptionStockData();
  142. return $this;
  143. }
  144. /**
  145. * Update Stock status index by product ids
  146. *
  147. * @param array|int $entityIds
  148. * @return $this
  149. */
  150. protected function _updateIndex($entityIds)
  151. {
  152. parent::_updateIndex($entityIds);
  153. $this->_cleanBundleOptionStockData();
  154. return $this;
  155. }
  156. /**
  157. * Clean temporary bundle options stock data
  158. *
  159. * @return $this
  160. */
  161. protected function _cleanBundleOptionStockData()
  162. {
  163. $this->getConnection()->delete($this->_getBundleOptionTable());
  164. return $this;
  165. }
  166. }