Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
CustomAttributeFilter.php
Go to the documentation of this file.
1 <?php
8 
12 use Magento\Eav\Model\Config as EavConfig;
17 
26 {
30  private $resourceConnection;
31 
35  private $conditionManager;
36 
40  private $eavConfig;
41 
45  private $storeManager;
46 
50  private $aliasResolver;
51 
59  public function __construct(
60  ResourceConnection $resourceConnection,
61  ConditionManager $conditionManager,
62  EavConfig $eavConfig,
63  StoreManagerInterface $storeManager,
64  AliasResolver $aliasResolver
65  ) {
66  $this->resourceConnection = $resourceConnection;
67  $this->conditionManager = $conditionManager;
68  $this->eavConfig = $eavConfig;
69  $this->storeManager = $storeManager;
70  $this->aliasResolver = $aliasResolver;
71  }
72 
84  {
85  $select = clone $select;
86  $mainTableAlias = $this->extractTableAliasFromSelect($select);
87  $attributes = [];
88 
89  foreach ($filters as $filter) {
90  $filterJoinAlias = $this->aliasResolver->getAlias($filter);
91 
92  $attributeId = $this->getAttributeIdByCode($filter->getField());
93 
94  if ($attributeId === null) {
95  throw new \InvalidArgumentException(
96  sprintf('Invalid attribute id for field: %s', $filter->getField())
97  );
98  }
99 
100  $attributes[] = $attributeId;
101 
102  $select->joinInner(
103  [$filterJoinAlias => $this->resourceConnection->getTableName('catalog_product_index_eav')],
104  $this->conditionManager->combineQueries(
105  $this->getJoinConditions($attributeId, $mainTableAlias, $filterJoinAlias),
107  ),
108  []
109  );
110  }
111 
112  if (count($attributes) === 1) {
113  // forces usage of PRIMARY key in main table
114  // is required to boost performance in case when we have just one filter by custom attribute
115  $attribute = reset($attributes);
116  $filter = reset($filters);
117  $select->where(
118  $this->conditionManager->generateCondition(
119  sprintf('%s.attribute_id', $mainTableAlias),
120  '=',
121  $attribute
122  )
123  )->where(
124  $this->conditionManager->generateCondition(
125  sprintf('%s.value', $mainTableAlias),
126  is_array($filter->getValue()) ? 'in' : '=',
127  $filter->getValue()
128  )
129  );
130  }
131 
132  return $select;
133  }
134 
143  private function getJoinConditions($attrId, $mainTable, $joinTable)
144  {
145  return [
146  sprintf('`%s`.`entity_id` = `%s`.`entity_id`', $mainTable, $joinTable),
147  sprintf('`%s`.`source_id` = `%s`.`source_id`', $mainTable, $joinTable),
148  $this->conditionManager->generateCondition(
149  sprintf('%s.attribute_id', $joinTable),
150  '=',
151  $attrId
152  ),
153  $this->conditionManager->generateCondition(
154  sprintf('%s.store_id', $joinTable),
155  '=',
156  (int) $this->storeManager->getStore()->getId()
157  )
158  ];
159  }
160 
168  private function getAttributeIdByCode($field)
169  {
170  $attr = $this->eavConfig->getAttribute(Product::ENTITY, $field);
171 
172  return ($attr && $attr->getId()) ? (int) $attr->getId() : null;
173  }
174 
182  private function extractTableAliasFromSelect(Select $select)
183  {
184  $fromArr = array_filter(
185  $select->getPart(Select::FROM),
186  function ($fromPart) {
187  return $fromPart['joinType'] === Select::FROM;
188  }
189  );
190 
191  return $fromArr ? array_keys($fromArr)[0] : null;
192  }
193 }
$attr
Definition: text.phtml:8
$storeManager
const FROM
Definition: Select.php:49
const SQL_AND
Definition: Select.php:77
$attributes
Definition: matrix.phtml:13
$filters
Definition: uploader.phtml:11
__construct(ResourceConnection $resourceConnection, ConditionManager $conditionManager, EavConfig $eavConfig, StoreManagerInterface $storeManager, AliasResolver $aliasResolver)