PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/magento/module-catalog-inventory/Model/Indexer/Stock/AbstractAction.php

https://gitlab.com/yousafsyed/easternglamor
PHP | 300 lines | 143 code | 39 blank | 118 comment | 6 complexity | a08fef5db052e6dc1d7a279471b09940 MD5 | raw file
  1. <?php
  2. /**
  3. * @category Magento
  4. * @package Magento_CatalogInventory
  5. * Copyright © 2016 Magento. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\CatalogInventory\Model\Indexer\Stock;
  9. use Magento\Catalog\Model\Category;
  10. use Magento\Framework\App\ResourceConnection;
  11. /**
  12. * Abstract action reindex class
  13. *
  14. * @package Magento\CatalogInventory\Model\Indexer\Stock
  15. */
  16. abstract class AbstractAction
  17. {
  18. /**
  19. * Resource instance
  20. *
  21. * @var Resource
  22. */
  23. protected $_resource;
  24. /**
  25. * @var \Magento\CatalogInventory\Model\ResourceModel\Indexer\StockFactory
  26. */
  27. protected $_indexerFactory;
  28. /**
  29. * @var \Magento\Catalog\Model\Product\Type
  30. */
  31. protected $_catalogProductType;
  32. /**
  33. * @var \Magento\Framework\DB\Adapter\AdapterInterface
  34. */
  35. protected $_connection;
  36. /**
  37. * Stock Indexer models per product type
  38. * Sorted by priority
  39. *
  40. * @var array
  41. */
  42. protected $_indexers = [];
  43. /**
  44. * Flag that defines if need to use "_idx" index table suffix instead of "_tmp"
  45. *
  46. * @var bool
  47. */
  48. protected $_isNeedUseIdxTable = false;
  49. /**
  50. * @var \Magento\Framework\Indexer\CacheContext
  51. */
  52. private $cacheContext;
  53. /**
  54. * @var \Magento\Framework\Event\ManagerInterface
  55. */
  56. private $eventManager;
  57. /**
  58. * @param ResourceConnection $resource
  59. * @param \Magento\CatalogInventory\Model\ResourceModel\Indexer\StockFactory $indexerFactory
  60. * @param \Magento\Catalog\Model\Product\Type $catalogProductType
  61. * @param \Magento\Framework\Indexer\CacheContext $cacheContext
  62. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  63. */
  64. public function __construct(
  65. ResourceConnection $resource,
  66. \Magento\CatalogInventory\Model\ResourceModel\Indexer\StockFactory $indexerFactory,
  67. \Magento\Catalog\Model\Product\Type $catalogProductType,
  68. \Magento\Framework\Indexer\CacheContext $cacheContext,
  69. \Magento\Framework\Event\ManagerInterface $eventManager
  70. ) {
  71. $this->_resource = $resource;
  72. $this->_indexerFactory = $indexerFactory;
  73. $this->_catalogProductType = $catalogProductType;
  74. $this->cacheContext = $cacheContext;
  75. $this->eventManager = $eventManager;
  76. }
  77. /**
  78. * Execute action for given ids
  79. *
  80. * @param array|int $ids
  81. *
  82. * @return void
  83. */
  84. abstract public function execute($ids);
  85. /**
  86. * Retrieve connection instance
  87. *
  88. * @return bool|\Magento\Framework\DB\Adapter\AdapterInterface
  89. */
  90. protected function _getConnection()
  91. {
  92. if (null === $this->_connection) {
  93. $this->_connection = $this->_resource->getConnection();
  94. }
  95. return $this->_connection;
  96. }
  97. /**
  98. * Retrieve Stock Indexer Models per Product Type
  99. *
  100. * @return \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StockInterface[]
  101. */
  102. protected function _getTypeIndexers()
  103. {
  104. if (empty($this->_indexers)) {
  105. foreach ($this->_catalogProductType->getTypesByPriority() as $typeId => $typeInfo) {
  106. $indexerClassName = isset($typeInfo['stock_indexer']) ? $typeInfo['stock_indexer'] : '';
  107. $indexer = $this->_indexerFactory->create($indexerClassName)
  108. ->setTypeId($typeId)
  109. ->setIsComposite(!empty($typeInfo['composite']));
  110. $this->_indexers[$typeId] = $indexer;
  111. }
  112. }
  113. return $this->_indexers;
  114. }
  115. /**
  116. * Returns table name for given entity
  117. *
  118. * @param string $entityName
  119. * @return string
  120. */
  121. protected function _getTable($entityName)
  122. {
  123. return $this->_resource->getTableName($entityName);
  124. }
  125. /**
  126. * Retrieve product relations by children
  127. *
  128. * @param int|array $childIds
  129. * @return array
  130. */
  131. public function getRelationsByChild($childIds)
  132. {
  133. $connection = $this->_getConnection();
  134. $select = $connection->select()
  135. ->from($this->_getTable('catalog_product_relation'), 'parent_id')
  136. ->where('child_id IN(?)', $childIds);
  137. return $connection->fetchCol($select);
  138. }
  139. /**
  140. * Reindex all
  141. *
  142. * @return void
  143. */
  144. public function reindexAll()
  145. {
  146. $this->useIdxTable(true);
  147. $this->clearTemporaryIndexTable();
  148. foreach ($this->_getTypeIndexers() as $indexer) {
  149. $indexer->reindexAll();
  150. }
  151. $this->_syncData();
  152. }
  153. /**
  154. * Synchronize data between index storage and original storage
  155. *
  156. * @return $this
  157. */
  158. protected function _syncData()
  159. {
  160. $idxTableName = $this->_getIdxTable();
  161. $tableName = $this->_getTable('cataloginventory_stock_status');
  162. $this->_deleteOldRelations($tableName);
  163. $columns = array_keys($this->_connection->describeTable($idxTableName));
  164. $select = $this->_connection->select()->from($idxTableName, $columns);
  165. $query = $select->insertFromSelect($tableName, $columns);
  166. $this->_connection->query($query);
  167. return $this;
  168. }
  169. /**
  170. * Delete old relations
  171. *
  172. * @param string $tableName
  173. *
  174. * @return void
  175. */
  176. protected function _deleteOldRelations($tableName)
  177. {
  178. $select = $this->_connection->select()
  179. ->from(['s' => $tableName])
  180. ->joinLeft(
  181. ['w' => $this->_getTable('catalog_product_website')],
  182. 's.product_id = w.product_id AND s.website_id = w.website_id',
  183. []
  184. )
  185. ->where('w.product_id IS NULL');
  186. $sql = $select->deleteFromSelect('s');
  187. $this->_connection->query($sql);
  188. }
  189. /**
  190. * Refresh entities index
  191. *
  192. * @param array $productIds
  193. * @return array Affected ids
  194. */
  195. protected function _reindexRows($productIds = [])
  196. {
  197. $connection = $this->_getConnection();
  198. if (!is_array($productIds)) {
  199. $productIds = [$productIds];
  200. }
  201. $parentIds = $this->getRelationsByChild($productIds);
  202. $processIds = $parentIds ? array_merge($parentIds, $productIds) : $productIds;
  203. // retrieve product types by processIds
  204. $select = $connection->select()
  205. ->from($this->_getTable('catalog_product_entity'), ['entity_id', 'type_id'])
  206. ->where('entity_id IN(?)', $processIds);
  207. $pairs = $connection->fetchPairs($select);
  208. $byType = [];
  209. foreach ($pairs as $productId => $typeId) {
  210. $byType[$typeId][$productId] = $productId;
  211. }
  212. $indexers = $this->_getTypeIndexers();
  213. foreach ($indexers as $indexer) {
  214. if (isset($byType[$indexer->getTypeId()])) {
  215. $indexer->reindexEntity($byType[$indexer->getTypeId()]);
  216. }
  217. }
  218. $select = $connection->select()
  219. ->distinct(true)
  220. ->from($this->_getTable('catalog_category_product'), ['category_id'])
  221. ->where('product_id IN(?)', $processIds);
  222. $affectedCategories = $connection->fetchCol($select);
  223. $this->cacheContext->registerEntities(Category::CACHE_TAG, $affectedCategories);
  224. $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
  225. return $this;
  226. }
  227. /**
  228. * Set or get what either "_idx" or "_tmp" suffixed temporary index table need to use
  229. *
  230. * @param bool|null $value
  231. * @return bool
  232. */
  233. public function useIdxTable($value = null)
  234. {
  235. if ($value !== null) {
  236. $this->_isNeedUseIdxTable = (bool)$value;
  237. }
  238. return $this->_isNeedUseIdxTable;
  239. }
  240. /**
  241. * Retrieve temporary index table name
  242. *
  243. * @return string
  244. */
  245. protected function _getIdxTable()
  246. {
  247. if ($this->useIdxTable()) {
  248. return $this->_getTable('cataloginventory_stock_status_idx');
  249. }
  250. return $this->_getTable('cataloginventory_stock_status_tmp');
  251. }
  252. /**
  253. * Clean up temporary index table
  254. *
  255. * @return void
  256. */
  257. public function clearTemporaryIndexTable()
  258. {
  259. $this->_getConnection()->delete($this->_getIdxTable());
  260. }
  261. }