Collection.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Reports\Model\ResourceModel\Quote\Item;
  7. use Magento\Framework\App\ResourceConnection;
  8. /**
  9. * Collection of Magento\Quote\Model\Quote\Item
  10. *
  11. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  12. * @api
  13. * @since 100.0.2
  14. */
  15. class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
  16. {
  17. /**
  18. * Join fields
  19. *
  20. * @var array
  21. */
  22. protected $_joinedFields = [];
  23. /**
  24. * Fields map for correlation names & real selected fields
  25. *
  26. * @var array
  27. */
  28. protected $_map = ['fields' => ['store_id' => 'main_table.store_id']];
  29. /**
  30. * @var \Magento\Catalog\Model\ResourceModel\Product\Collection
  31. */
  32. protected $productResource;
  33. /**
  34. * @var \Magento\Customer\Model\ResourceModel\Customer
  35. */
  36. protected $customerResource;
  37. /**
  38. * @var \Magento\Sales\Model\ResourceModel\Order\Collection
  39. */
  40. protected $orderResource;
  41. /**
  42. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
  43. * @param \Psr\Log\LoggerInterface $logger
  44. * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
  45. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  46. * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $productResource
  47. * @param \Magento\Customer\Model\ResourceModel\Customer $customerResource
  48. * @param \Magento\Sales\Model\ResourceModel\Order\Collection $orderResource
  49. * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
  50. * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource
  51. */
  52. public function __construct(
  53. \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
  54. \Psr\Log\LoggerInterface $logger,
  55. \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
  56. \Magento\Framework\Event\ManagerInterface $eventManager,
  57. \Magento\Catalog\Model\ResourceModel\Product\Collection $productResource,
  58. \Magento\Customer\Model\ResourceModel\Customer $customerResource,
  59. \Magento\Sales\Model\ResourceModel\Order\Collection $orderResource,
  60. \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
  61. \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
  62. ) {
  63. parent::__construct(
  64. $entityFactory,
  65. $logger,
  66. $fetchStrategy,
  67. $eventManager,
  68. $connection,
  69. $resource
  70. );
  71. $this->productResource = $productResource;
  72. $this->customerResource = $customerResource;
  73. $this->orderResource = $orderResource;
  74. }
  75. /**
  76. * Resource initialization
  77. *
  78. * @return void
  79. */
  80. protected function _construct()
  81. {
  82. $this->_init(\Magento\Quote\Model\Quote\Item::class, \Magento\Quote\Model\ResourceModel\Quote\Item::class);
  83. }
  84. /**
  85. * Prepare select query for products in carts report
  86. *
  87. * @return \Magento\Framework\DB\Select
  88. */
  89. public function prepareActiveCartItems()
  90. {
  91. $quoteItemsSelect = $this->getSelect();
  92. $quoteItemsSelect->reset()
  93. ->from(['main_table' => $this->getTable('quote_item')], '')
  94. ->columns('main_table.product_id')
  95. ->columns(['carts' => new \Zend_Db_Expr('COUNT(main_table.item_id)')])
  96. ->columns('quote.base_to_global_rate')
  97. ->joinInner(
  98. ['quote' => $this->getTable('quote')],
  99. 'main_table.quote_id = quote.entity_id',
  100. null
  101. )->where(
  102. 'quote.is_active = ?',
  103. 1
  104. )->group(
  105. 'main_table.product_id'
  106. );
  107. return $quoteItemsSelect;
  108. }
  109. /**
  110. * Orders quantity data
  111. *
  112. * @param array $productIds
  113. * @return array
  114. */
  115. protected function getOrdersData(array $productIds)
  116. {
  117. $ordersSubSelect = clone $this->orderResource->getSelect();
  118. $ordersSubSelect->reset()->from(
  119. ['oi' => $this->getTable('sales_order_item')],
  120. ['product_id', 'orders' => new \Zend_Db_Expr('COUNT(1)')]
  121. )->where('oi.product_id IN (?)', $productIds)->group(
  122. 'oi.product_id'
  123. );
  124. return $this->orderResource->getConnection()->fetchAssoc($ordersSubSelect);
  125. }
  126. /**
  127. * Add store ids to filter
  128. *
  129. * @param array $storeIds
  130. * @return $this
  131. */
  132. public function addStoreFilter($storeIds)
  133. {
  134. $this->addFieldToFilter('store_id', ['in' => $storeIds]);
  135. return $this;
  136. }
  137. /**
  138. * Get select count sql
  139. *
  140. * @return \Magento\Framework\DB\Select
  141. */
  142. public function getSelectCountSql()
  143. {
  144. $countSelect = clone $this->prepareActiveCartItems();
  145. $countSelect->reset(\Magento\Framework\DB\Select::COLUMNS)
  146. ->reset(\Magento\Framework\DB\Select::GROUP)
  147. ->columns('COUNT(DISTINCT main_table.product_id)');
  148. return $countSelect;
  149. }
  150. /**
  151. * Separate query for product and order data
  152. *
  153. * @param array $productIds
  154. * @return array
  155. * @throws \Magento\Framework\Exception\LocalizedException
  156. */
  157. protected function getProductData(array $productIds)
  158. {
  159. $productConnection = $this->productResource->getConnection();
  160. $productAttrName = $this->productResource->getAttribute('name');
  161. $productAttrNameId = (int)$productAttrName->getAttributeId();
  162. $productAttrPrice = $this->productResource->getAttribute('price');
  163. $productAttrPriceId = (int)$productAttrPrice->getAttributeId();
  164. $linkField = $this->productResource->getEntity()->getLinkField();
  165. $select = clone $this->productResource->getSelect();
  166. $select->reset();
  167. $select->from(
  168. ['main_table' => $this->getTable('catalog_product_entity')],
  169. ['main_table.entity_id', 'main_table.*']
  170. )->useStraightJoin(
  171. true
  172. )->joinInner(
  173. ['product_name' => $productAttrName->getBackend()->getTable()],
  174. "product_name.{$linkField} = main_table.{$linkField}"
  175. . ' AND product_name.attribute_id = ' . $productAttrNameId
  176. . ' AND product_name.store_id = ' . \Magento\Store\Model\Store::DEFAULT_STORE_ID,
  177. ['name' => 'product_name.value']
  178. )->joinLeft(
  179. ['product_price' => $productAttrPrice->getBackend()->getTable()],
  180. "product_price.{$linkField} = main_table.{$linkField}"
  181. ." AND product_price.attribute_id = {$productAttrPriceId}",
  182. ['price' => new \Zend_Db_Expr('product_price.value')]
  183. )->where("main_table.entity_id IN (?)", $productIds);
  184. $productData = $productConnection->fetchAssoc($select);
  185. return $productData;
  186. }
  187. /**
  188. * Add data fetched from another database
  189. *
  190. * @return $this
  191. */
  192. protected function _afterLoad()
  193. {
  194. parent::_afterLoad();
  195. $items = $this->getItems();
  196. $productIds = [];
  197. foreach ($items as $item) {
  198. $productIds[] = $item->getProductId();
  199. }
  200. $productData = $this->getProductData($productIds);
  201. $orderData = $this->getOrdersData($productIds);
  202. foreach ($items as $item) {
  203. $item->setId($item->getProductId());
  204. if (isset($productData[$item->getProductId()])) {
  205. $item->setPrice($productData[$item->getProductId()]['price'] * $item->getBaseToGlobalRate());
  206. $item->setName($productData[$item->getProductId()]['name']);
  207. }
  208. $item->setOrders(0);
  209. if (isset($orderData[$item->getProductId()])) {
  210. $item->setOrders($orderData[$item->getProductId()]['orders']);
  211. }
  212. }
  213. return $this;
  214. }
  215. }