Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Builder.php
Go to the documentation of this file.
1 <?php
8 
17 
21 class Builder
22 {
26  protected $_connection;
27 
31  protected $_conditionOperatorMap = [
32  '==' => ':field = ?',
33  '!=' => ':field <> ?',
34  '>=' => ':field >= ?',
35  '>' => ':field > ?',
36  '<=' => ':field <= ?',
37  '<' => ':field < ?',
38  '{}' => ':field IN (?)',
39  '!{}' => ':field NOT IN (?)',
40  '()' => ':field IN (?)',
41  '!()' => ':field NOT IN (?)',
42  ];
43 
47  private $stringConditionOperatorMap = [
48  '{}' => ':field LIKE ?',
49  '!{}' => ':field NOT LIKE ?',
50  ];
51 
56 
60  private $attributeRepository;
61 
66  public function __construct(
67  ExpressionFactory $expressionFactory,
68  AttributeRepositoryInterface $attributeRepository = null
69  ) {
70  $this->_expressionFactory = $expressionFactory;
71  $this->attributeRepository = $attributeRepository ?:
72  ObjectManager::getInstance()->get(AttributeRepositoryInterface::class);
73  }
74 
81  protected function _getCombineTablesToJoin(Combine $combine)
82  {
83  $tables = $this->_getChildCombineTablesToJoin($combine);
84  return $tables;
85  }
86 
94  protected function _getChildCombineTablesToJoin(Combine $combine, $tables = [])
95  {
96  foreach ($combine->getConditions() as $condition) {
97  if ($condition->getConditions()) {
98  $tables = $this->_getChildCombineTablesToJoin($condition);
99  } else {
101  foreach ($condition->getTablesToJoin() as $alias => $table) {
102  if (!isset($tables[$alias])) {
103  $tables[$alias] = $table;
104  }
105  }
106  }
107  }
108  return $tables;
109  }
110 
118  protected function _joinTablesToCollection(
119  AbstractCollection $collection,
120  Combine $combine
121  ): Builder {
122  foreach ($this->_getCombineTablesToJoin($combine) as $alias => $joinTable) {
124  $collection->getSelect()->joinLeft(
125  [$alias => $collection->getResource()->getTable($joinTable['name'])],
126  $joinTable['condition'],
127  isset($joinTable['columns']) ? $joinTable['columns'] : '*'
128  );
129  }
130 
131  return $this;
132  }
133 
144  protected function _getMappedSqlCondition(
145  AbstractCondition $condition,
146  string $value = '',
147  bool $isDefaultStoreUsed = true
148  ): string {
149  $argument = $condition->getMappedSqlField();
150 
151  // If rule hasn't valid argument - create negative expression to prevent incorrect rule behavior.
152  if (empty($argument)) {
153  return $this->_expressionFactory->create(['expression' => '1 = -1']);
154  }
155 
156  $conditionOperator = $condition->getOperatorForValidate();
157 
158  if (!isset($this->_conditionOperatorMap[$conditionOperator])) {
159  throw new \Magento\Framework\Exception\LocalizedException(__('Unknown condition operator'));
160  }
161 
162  $defaultValue = 0;
163  //operator 'contains {}' is mapped to 'IN()' query that cannot work with substrings
164  // adding mapping to 'LIKE %%'
165  if ($condition->getInputType() === 'string'
166  && in_array($conditionOperator, array_keys($this->stringConditionOperatorMap), true)
167  ) {
168  $sql = str_replace(
169  ':field',
170  $this->_connection->getIfNullSql($this->_connection->quoteIdentifier($argument), $defaultValue),
171  $this->stringConditionOperatorMap[$conditionOperator]
172  );
173  $bindValue = $condition->getBindArgumentValue();
174  $expression = $value . $this->_connection->quoteInto($sql, "%$bindValue%");
175  } else {
176  $sql = str_replace(
177  ':field',
178  $this->_connection->getIfNullSql($this->_connection->quoteIdentifier($argument), $defaultValue),
179  $this->_conditionOperatorMap[$conditionOperator]
180  );
181  $bindValue = $condition->getBindArgumentValue();
182  $expression = $value . $this->_connection->quoteInto($sql, $bindValue);
183  }
184  // values for multiselect attributes can be saved in comma-separated format
185  // below is a solution for matching such conditions with selected values
186  if (is_array($bindValue) && \in_array($conditionOperator, ['()', '{}'], true)) {
187  foreach ($bindValue as $item) {
188  $expression .= $this->_connection->quoteInto(
189  " OR (FIND_IN_SET (?, {$this->_connection->quoteIdentifier($argument)}) > 0)",
190  $item
191  );
192  }
193  }
194 
195  return $this->_expressionFactory->create(
196  ['expression' => $expression]
197  );
198  }
199 
210  protected function _getMappedSqlCombination(
211  Combine $combine,
212  string $value = '',
213  bool $isDefaultStoreUsed = true
214  ): string {
215  $out = (!empty($value) ? $value : '');
216  $value = ($combine->getValue() ? '' : ' NOT ');
217  $getAggregator = $combine->getAggregator();
218  $conditions = $combine->getConditions();
219  foreach ($conditions as $key => $condition) {
221  $con = ($getAggregator == 'any' ? Select::SQL_OR : Select::SQL_AND);
222  $con = (isset($conditions[$key+1]) ? $con : '');
223  if ($condition instanceof Combine) {
224  $out .= $this->_getMappedSqlCombination($condition, $value, $isDefaultStoreUsed);
225  } else {
226  $out .= $this->_getMappedSqlCondition($condition, $value, $isDefaultStoreUsed);
227  }
228  $out .= $out ? (' ' . $con) : '';
229  }
230 
231  return $this->_expressionFactory->create(['expression' => $out]);
232  }
233 
243  Combine $combine
244  ): void {
245  $this->_connection = $collection->getResource()->getConnection();
246  $this->_joinTablesToCollection($collection, $combine);
247  $whereExpression = (string)$this->_getMappedSqlCombination($combine);
248  if (!empty($whereExpression)) {
249  // Select ::where method adds braces even on empty expression
250  $collection->getSelect()->where($whereExpression);
251  }
252  }
253 }
__()
Definition: __.php:13
__construct(ExpressionFactory $expressionFactory, AttributeRepositoryInterface $attributeRepository=null)
Definition: Builder.php:66
$value
Definition: gender.phtml:16
const SQL_AND
Definition: Select.php:77
_getCombineTablesToJoin(Combine $combine)
Definition: Builder.php:81
_getMappedSqlCondition(AbstractCondition $condition, string $value='', bool $isDefaultStoreUsed=true)
Definition: Builder.php:144
attachConditionToCollection(AbstractCollection $collection, Combine $combine)
Definition: Builder.php:241
if(!trim($html)) $alias
Definition: details.phtml:20
$table
Definition: trigger.php:14
const SQL_OR
Definition: Select.php:79