AbstractCollection.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Catalog\Model\ResourceModel\Collection;
  7. /**
  8. * Catalog EAV collection resource abstract model
  9. * Implement using different stores for retrieve attribute values
  10. *
  11. * @api
  12. * @author Magento Core Team <core@magentocommerce.com>
  13. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  14. * @since 100.0.2
  15. */
  16. class AbstractCollection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
  17. {
  18. /**
  19. * Current scope (store Id)
  20. *
  21. * @var int
  22. */
  23. protected $_storeId;
  24. /**
  25. * Store manager
  26. *
  27. * @var \Magento\Store\Model\StoreManagerInterface
  28. */
  29. protected $_storeManager;
  30. /**
  31. * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
  32. * @param \Psr\Log\LoggerInterface $logger
  33. * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
  34. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  35. * @param \Magento\Eav\Model\Config $eavConfig
  36. * @param \Magento\Framework\App\ResourceConnection $resource
  37. * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
  38. * @param \Magento\Eav\Model\ResourceModel\Helper $resourceHelper
  39. * @param \Magento\Framework\Validator\UniversalFactory $universalFactory
  40. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  41. * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
  42. *
  43. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  44. */
  45. public function __construct(
  46. \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
  47. \Psr\Log\LoggerInterface $logger,
  48. \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
  49. \Magento\Framework\Event\ManagerInterface $eventManager,
  50. \Magento\Eav\Model\Config $eavConfig,
  51. \Magento\Framework\App\ResourceConnection $resource,
  52. \Magento\Eav\Model\EntityFactory $eavEntityFactory,
  53. \Magento\Eav\Model\ResourceModel\Helper $resourceHelper,
  54. \Magento\Framework\Validator\UniversalFactory $universalFactory,
  55. \Magento\Store\Model\StoreManagerInterface $storeManager,
  56. \Magento\Framework\DB\Adapter\AdapterInterface $connection = null
  57. ) {
  58. $this->_storeManager = $storeManager;
  59. parent::__construct(
  60. $entityFactory,
  61. $logger,
  62. $fetchStrategy,
  63. $eventManager,
  64. $eavConfig,
  65. $resource,
  66. $eavEntityFactory,
  67. $resourceHelper,
  68. $universalFactory,
  69. $connection
  70. );
  71. }
  72. /**
  73. * Retrieve Entity Primary Key
  74. *
  75. * @param \Magento\Eav\Model\Entity\AbstractEntity $entity
  76. * @return string
  77. * @since 101.0.0
  78. */
  79. protected function getEntityPkName(\Magento\Eav\Model\Entity\AbstractEntity $entity)
  80. {
  81. return $entity->getLinkField();
  82. }
  83. /**
  84. * Set store scope
  85. *
  86. * @param int|string|\Magento\Store\Model\Store $store
  87. * @return $this
  88. */
  89. public function setStore($store)
  90. {
  91. $this->setStoreId($this->_storeManager->getStore($store)->getId());
  92. return $this;
  93. }
  94. /**
  95. * Set store scope
  96. *
  97. * @param int|string|\Magento\Store\Api\Data\StoreInterface $storeId
  98. * @return $this
  99. */
  100. public function setStoreId($storeId)
  101. {
  102. if ($storeId instanceof \Magento\Store\Api\Data\StoreInterface) {
  103. $storeId = $storeId->getId();
  104. }
  105. $this->_storeId = (int)$storeId;
  106. return $this;
  107. }
  108. /**
  109. * Return current store id
  110. *
  111. * @return int
  112. */
  113. public function getStoreId()
  114. {
  115. if ($this->_storeId === null) {
  116. $this->setStoreId($this->_storeManager->getStore()->getId());
  117. }
  118. return $this->_storeId;
  119. }
  120. /**
  121. * Retrieve default store id
  122. *
  123. * @return int
  124. */
  125. public function getDefaultStoreId()
  126. {
  127. return \Magento\Store\Model\Store::DEFAULT_STORE_ID;
  128. }
  129. /**
  130. * Retrieve attributes load select
  131. *
  132. * @param string $table
  133. * @param array|int $attributeIds
  134. * @return \Magento\Framework\DB\Select
  135. */
  136. protected function _getLoadAttributesSelect($table, $attributeIds = [])
  137. {
  138. if (empty($attributeIds)) {
  139. $attributeIds = $this->_selectAttributes;
  140. }
  141. $storeId = $this->getStoreId();
  142. $connection = $this->getConnection();
  143. $entityTable = $this->getEntity()->getEntityTable();
  144. $indexList = $connection->getIndexList($entityTable);
  145. $entityIdField = $indexList[$connection->getPrimaryKeyName($entityTable)]['COLUMNS_LIST'][0];
  146. if ($storeId) {
  147. $joinCondition = [
  148. 't_s.attribute_id = t_d.attribute_id',
  149. "t_s.{$entityIdField} = t_d.{$entityIdField}",
  150. $connection->quoteInto('t_s.store_id = ?', $storeId),
  151. ];
  152. $select = $connection->select()->from(
  153. ['t_d' => $table],
  154. ['attribute_id']
  155. )->join(
  156. ['e' => $entityTable],
  157. "e.{$entityIdField} = t_d.{$entityIdField}",
  158. ['e.entity_id']
  159. )->where(
  160. "e.entity_id IN (?)",
  161. array_keys($this->_itemsById)
  162. )->where(
  163. 't_d.attribute_id IN (?)',
  164. $attributeIds
  165. )->joinLeft(
  166. ['t_s' => $table],
  167. implode(' AND ', $joinCondition),
  168. []
  169. )->where(
  170. 't_d.store_id = ?',
  171. $connection->getIfNullSql('t_s.store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID)
  172. );
  173. } else {
  174. $select = $connection->select()->from(
  175. ['t_d' => $table],
  176. ['attribute_id']
  177. )->join(
  178. ['e' => $entityTable],
  179. "e.{$entityIdField} = t_d.{$entityIdField}",
  180. ['e.entity_id']
  181. )->where(
  182. "e.entity_id IN (?)",
  183. array_keys($this->_itemsById)
  184. )->where(
  185. 'attribute_id IN (?)',
  186. $attributeIds
  187. )->where(
  188. 'store_id = ?',
  189. $this->getDefaultStoreId()
  190. );
  191. }
  192. return $select;
  193. }
  194. /**
  195. * @param \Magento\Framework\DB\Select $select
  196. * @param string $table
  197. * @param string $type
  198. * @return \Magento\Framework\DB\Select
  199. */
  200. protected function _addLoadAttributesSelectValues($select, $table, $type)
  201. {
  202. $storeId = $this->getStoreId();
  203. if ($storeId) {
  204. $connection = $this->getConnection();
  205. $valueExpr = $connection->getCheckSql('t_s.value_id IS NULL', 't_d.value', 't_s.value');
  206. $select->columns(
  207. ['default_value' => 't_d.value', 'store_value' => 't_s.value', 'value' => $valueExpr]
  208. );
  209. } else {
  210. $select = parent::_addLoadAttributesSelectValues($select, $table, $type);
  211. }
  212. return $select;
  213. }
  214. /**
  215. * Adding join statement to collection select instance
  216. *
  217. * @param string $method
  218. * @param object $attribute
  219. * @param string $tableAlias
  220. * @param array $condition
  221. * @param string $fieldCode
  222. * @param string $fieldAlias
  223. * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection
  224. */
  225. protected function _joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias)
  226. {
  227. if (isset($this->_joinAttributes[$fieldCode]['store_id'])) {
  228. $storeId = $this->_joinAttributes[$fieldCode]['store_id'];
  229. } else {
  230. $storeId = $this->getStoreId();
  231. }
  232. $connection = $this->getConnection();
  233. if ($storeId != $this->getDefaultStoreId() && !$attribute->isScopeGlobal()) {
  234. /**
  235. * Add joining default value for not default store
  236. * if value for store is null - we use default value
  237. */
  238. $defCondition = '(' . implode(') AND (', $condition) . ')';
  239. $defAlias = $tableAlias . '_default';
  240. $defAlias = $this->getConnection()->getTableName($defAlias);
  241. $defFieldAlias = str_replace($tableAlias, $defAlias, $fieldAlias);
  242. $tableAlias = $this->getConnection()->getTableName($tableAlias);
  243. $defCondition = str_replace($tableAlias, $defAlias, $defCondition);
  244. $defCondition .= $connection->quoteInto(
  245. " AND " . $connection->quoteColumnAs("{$defAlias}.store_id", null) . " = ?",
  246. $this->getDefaultStoreId()
  247. );
  248. $this->getSelect()->{$method}(
  249. [$defAlias => $attribute->getBackend()->getTable()],
  250. $defCondition,
  251. []
  252. );
  253. $method = 'joinLeft';
  254. $fieldAlias = $this->getConnection()->getCheckSql(
  255. "{$tableAlias}.value_id > 0",
  256. $fieldAlias,
  257. $defFieldAlias
  258. );
  259. $this->_joinAttributes[$fieldCode]['condition_alias'] = $fieldAlias;
  260. $this->_joinAttributes[$fieldCode]['attribute'] = $attribute;
  261. } else {
  262. $storeId = $this->getDefaultStoreId();
  263. }
  264. $condition[] = $connection->quoteInto(
  265. $connection->quoteColumnAs("{$tableAlias}.store_id", null) . ' = ?',
  266. $storeId
  267. );
  268. return parent::_joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias);
  269. }
  270. }