1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
conditiontree.php
См. документацию.
1<?php
8
9namespace Bitrix\Main\ORM\Query\Filter;
10
11use Bitrix\Main\ORM\Fields\ArrayField;
12use Bitrix\Main\ORM\Fields\BooleanField;
13use Bitrix\Main\ORM\Fields\ExpressionField;
14use Bitrix\Main\ORM\Query\Filter\Expressions\ColumnExpression;
15use Bitrix\Main\ORM\Query\Query;
16use Bitrix\Main\ORM\Query\Chain;
17use Bitrix\Main\ORM\Fields\IReadable;
18use Bitrix\Main\DB\SqlExpression;
19use Bitrix\Main\ArgumentException;
20use Bitrix\Main\SystemException;
21use Bitrix\Main\Type\RandomSequence;
22
29{
31 protected $chains;
32
34 protected $conditions = array();
35
40 protected $logic;
41
44
45 const LOGIC_OR = 'or';
46
47 const LOGIC_AND = 'and';
48
53 protected $isNegative = false;
54
58 public function __construct()
59 {
60 $this->logic = static::LOGIC_AND;
61 }
62
71 public function logic($logic = null)
72 {
73 if ($logic === null)
74 {
75 return $this->logic;
76 }
77
78 if (!in_array(strtolower($logic), [static::LOGIC_AND, static::LOGIC_OR], true))
79 {
80 throw new ArgumentException("Unknown logic");
81 }
82
83 $this->logic = strtolower($logic);
84
85 return $this;
86 }
87
95 public function negative($negative = true)
96 {
97 $this->isNegative = (bool) $negative;
98 return $this;
99 }
100
126 public function where(...$filter)
127 {
128 // subfilter
129 if (count($filter) == 1 && $filter[0] instanceof ConditionTree)
130 {
131 $this->conditions[] = $filter[0];
132 return $this;
133 }
134
135 // ready condition
136 if (count($filter) == 1 && $filter[0] instanceof Condition)
137 {
138 $this->conditions[] = $filter[0];
139 return $this;
140 }
141
142 // array of conditions
143 if (count($filter) == 1 && is_array($filter[0]))
144 {
145 foreach ($filter[0] as $condition)
146 {
147 // call `where` for each condition
148 call_user_func_array(array($this, 'where'), $condition);
149 }
150 return $this;
151 }
152
153 // regular conditions
154 if (count($filter) == 3)
155 {
156 // everything is clear
157 list($column, $operator, $value) = $filter;
158 }
159 elseif (count($filter) == 2)
160 {
161 // equal by default
162 list($column, $value) = $filter;
163 $operator = '=';
164 }
165 elseif (count($filter) == 1)
166 {
167 // suppose it is boolean field with true value
168 $column = $filter[0];
169 $operator = '=';
170 $value = true;
171 }
172 else
173 {
174 throw new ArgumentException('Wrong arguments');
175 }
176
177 // validate operator
178 $operators = Operator::get();
179 if (!isset($operators[$operator]))
180 {
181 throw new ArgumentException("Unknown operator `{$operator}`");
182 }
183
184 // add condition
185 $this->conditions[] = new Condition($column, $operator, $value);
186
187 return $this;
188 }
189
198 public function whereNot(...$filter)
199 {
200 $subFilter = new static();
201 call_user_func_array(array($subFilter, 'where'), $filter);
202
203 $this->conditions[] = $subFilter->negative();
204 return $this;
205 }
206
216 public function whereColumn(...$filter)
217 {
218 if (count($filter) == 3)
219 {
220 list($column, $operator, $value) = $filter;
221 }
222 elseif (count($filter) == 2)
223 {
224 list($column, $value) = $filter;
225 $operator = '=';
226 }
227 else
228 {
229 throw new ArgumentException('Wrong arguments');
230 }
231
232 // convert value to column format
233 $value = new Expressions\ColumnExpression($value);
234
235 // put through general method
236 $this->where($column, $operator, $value);
237
238 return $this;
239 }
240
248 public function whereNull($column)
249 {
250 $this->conditions[] = new Condition($column, '=', null);
251
252 return $this;
253 }
254
262 public function whereNotNull($column)
263 {
264 $this->conditions[] = new Condition($column, '<>', null);
265
266 return $this;
267 }
268
277 public function whereIn($column, $values)
278 {
279 if (!empty($values))
280 {
281 $this->conditions[] = new Condition($column, 'in', $values);
282 }
283
284 return $this;
285 }
286
296 public function whereNotIn($column, $values)
297 {
298 $subFilter = new static();
299 $this->conditions[] = $subFilter->whereIn($column, $values)->negative();
300
301 return $this;
302 }
303
313 public function whereBetween($column, $valueMin, $valueMax)
314 {
315 $this->conditions[] = new Condition($column, 'between', array($valueMin, $valueMax));
316
317 return $this;
318 }
319
330 public function whereNotBetween($column, $valueMin, $valueMax)
331 {
332 $subFilter = new static();
333 $this->conditions[] = $subFilter->whereBetween($column, $valueMin, $valueMax)->negative();
334
335 return $this;
336 }
337
346 public function whereLike($column, $value)
347 {
348 $this->conditions[] = new Condition($column, 'like', $value);
349
350 return $this;
351 }
352
362 public function whereNotLike($column, $value)
363 {
364 $subFilter = new static();
365 $this->conditions[] = $subFilter->whereLike($column, $value)->negative();
366
367 return $this;
368 }
369
377 public function whereExists($query)
378 {
379 $this->conditions[] = new Condition(null, 'exists', $query);
380
381 return $this;
382 }
383
393 public function whereNotExists($query)
394 {
395 if ($query instanceof Query || $query instanceof SqlExpression)
396 {
397 $subFilter = new static();
398 $this->conditions[] = $subFilter->whereExists($query)->negative();
399
400 return $this;
401 }
402
403 throw new ArgumentException('Unknown type of query '.gettype($query));
404 }
405
415 public function whereMatch($column, $value)
416 {
417 $this->conditions[] = new Condition($column, 'match', $value);
418
419 return $this;
420 }
421
431 public function whereNotMatch($column, $value)
432 {
433 $subFilter = new static();
434 $this->conditions[] = $subFilter->whereMatch($column, $value)->negative();
435
436 return $this;
437 }
438
450 public function whereExpr($expr, $arguments)
451 {
452 // get random field name
453 $randomSequence = static::getRandomSequence();
454 $tmpName = 'TMP_'.$randomSequence->randString(10);
455
456 // set boolean expression
457 $tmpField = (new ExpressionField($tmpName, $expr, $arguments))
458 ->configureValueType(BooleanField::class);
459
460 // add condition
461 $this->where($tmpField, 'expr', true);
462
463 return $this;
464 }
465
475 public function getSql($chains)
476 {
477 // save chains
478 $this->chains = $chains;
479
480 $finalSql = array();
481
482 // build sql
483 foreach ($this->conditions as $condition)
484 {
485 if ($condition instanceof ConditionTree)
486 {
487 // subfilter
488 $subFilter = $condition;
489 $sql = $subFilter->getSql($chains);
490
491 if (count($subFilter->getConditions()) > 1)
492 {
493 $sql = "({$sql})";
494 }
495 }
496 else
497 {
498 // regular condition
499 $columnSqlDefinition = null;
500 $columnField = null;
501
502 // define column field
503 if ($condition->getColumn() !== null)
504 {
505 $chain = $chains[$condition->getDefinition()];
506 $columnSqlDefinition = $chain->getSqlDefinition();
507
509 $columnField = $chain->getLastElement()->getValue();
510 }
511
512 // final value's sql
513 if (in_array($condition->getOperator(), array('in', 'between'), true) && is_array($condition->getValue()))
514 {
515 // value is in array of atomic values
516 $finalValue = $this->convertValues($condition->getValue(), $columnField);
517 }
518 else
519 {
520 $finalValue = $this->convertValue($condition->getValue(), $columnField);
521 }
522
523 // operation method
524 $operators = Operator::get();
525 $operator = $operators[$condition->getOperator()];
526
527 // final sql
528 $sql = call_user_func(
529 array('Bitrix\Main\ORM\Query\Filter\Operator', $operator),
530 $columnSqlDefinition, $finalValue
531 );
532 }
533
534 if ($sql != '')
535 {
536 $finalSql[] = $sql;
537 }
538 }
539
540 $sql = null;
541
542 if (!empty($finalSql))
543 {
544 // concat with $this->logic
545 $sql = join(" ".strtoupper($this->logic)." ", $finalSql);
546
547 // and put NOT if negative
548 if ($this->isNegative)
549 {
550 $sql = count($finalSql) > 1 ? "NOT ({$sql})" : "NOT {$sql}";
551 }
552 }
553
554 return $sql;
555 }
556
562 public function getConditions()
563 {
564 return $this->conditions;
565 }
566
575 public function addCondition($condition)
576 {
577 if ($condition instanceof Condition || $condition instanceof ConditionTree)
578 {
579 $this->conditions[] = $condition;
580 return $this;
581 }
582
583 throw new ArgumentException('Unknown type of condition '.gettype($condition));
584 }
585
591 public function hasConditions()
592 {
593 return !empty($this->conditions);
594 }
595
604 public function replaceCondition($currentCondition, $newCondition)
605 {
606 foreach ($this->conditions as $k => $condition)
607 {
608 if ($condition === $currentCondition)
609 {
610 $this->conditions[$k] = $newCondition;
611 return true;
612 }
613 }
614
615 return false;
616 }
617
625 public function removeCondition($condition)
626 {
627 foreach ($this->conditions as $k => $_condition)
628 {
629 if ($condition == $_condition)
630 {
631 unset($this->conditions[$k]);
632 return true;
633 }
634 }
635
636 return false;
637 }
638
642 public function removeAllConditions()
643 {
644 $this->conditions = [];
645 }
646
657 protected function convertValue($value, IReadable $field = null)
658 {
659 // any sql expression
660 if ($value instanceof SqlExpression)
661 {
662 return $value->compile();
663 }
664
665 // subquery
666 if ($value instanceof Query)
667 {
668 return $value->getQuery();
669 }
670
671 // subfilter
672 if ($value instanceof ConditionTree)
673 {
674 return $value->getSql($this->chains);
675 }
676
677 // nulls
678 if ($value === null)
679 {
680 if ($field instanceof ArrayField
681 && $field->getSerializationType() === ArrayField::SERIALIZATION_TYPE_PHP)
682 {
683 return $field->convertValueToDb('N;');
684 }
685
686 return new Expressions\NullExpression;
687 }
688
689 if ($value instanceof Expressions\ColumnExpression)
690 {
692 $valueChain = $this->chains[$value->getDefinition()];
693 return $valueChain->getSqlDefinition();
694 }
695
696 return $field->convertValueToDb($value); // give them current sql helper
697 }
698
710 protected function convertValues($values, IReadable $field = null)
711 {
712 foreach ($values as $k => $value)
713 {
714 $values[$k] = $this->convertValue($value, $field);
715 }
716
717 return $values;
718 }
719
720 public function __clone()
721 {
722 $newConditions = array();
723
724 foreach ($this->conditions as $condition)
725 {
726 $newConditions[] = clone $condition;
727 }
728
729 $this->conditions = $newConditions;
730 }
731
735 protected static function getRandomSequence(): RandomSequence
736 {
737 if (!isset(static::$randomSequence))
738 {
739 static::$randomSequence = new RandomSequence('orm.filter.expr');
740 }
741
742 return static::$randomSequence;
743 }
744
753 public static function createFromArray($filter)
754 {
755 $conditionTree = Query::filter();
756
757 if (isset($filter['logic']))
758 {
759 $conditionTree->logic($filter['logic']);
760 unset($filter['logic']);
761 }
762
763 if (isset($filter['negative']))
764 {
765 $conditionTree->negative($filter['negative']);
766 unset($filter['negative']);
767 }
768
769 foreach ($filter as $condition)
770 {
771 if (isset($condition[0]) && is_array($condition[0]))
772 {
773 $conditionTree->where(static::createFromArray($condition));
774 }
775 else
776 {
777 // parse regular filter condition
778 $valueKey = key(array_reverse($condition, true));
779 $valueElement = $condition[$valueKey];
780
781 if (is_array($valueElement))
782 {
783 if (isset($valueElement['value']))
784 {
785 $value = $valueElement['value'];
786 }
787 elseif (isset($valueElement['column']))
788 {
789 $value = new ColumnExpression($valueElement['column']);
790 }
791 else
792 {
793 // could be an array of columns
794 foreach ($valueElement as $k => $singleValue)
795 {
796 if (is_array($singleValue))
797 {
798 if (isset($singleValue['value']))
799 {
800 $valueElement[$k] = $singleValue['value'];
801 }
802 elseif (isset($singleValue['column']))
803 {
804 $valueElement[$k] = new ColumnExpression($singleValue['column']);
805 }
806 }
807 }
808
809 $value = $valueElement;
810 }
811
812 $condition[$valueKey] = $value;
813 }
814
815 $conditionTree->where(...$condition);
816 }
817 }
818
819 return $conditionTree;
820 }
821}
whereNotIn($column, $values)
Определения conditiontree.php:296
whereNotMatch($column, $value)
Определения conditiontree.php:431
whereExpr($expr, $arguments)
Определения conditiontree.php:450
whereNotBetween($column, $valueMin, $valueMax)
Определения conditiontree.php:330
whereLike($column, $value)
Определения conditiontree.php:346
static createFromArray($filter)
Определения conditiontree.php:753
static RandomSequence $randomSequence
Определения conditiontree.php:43
whereNotLike($column, $value)
Определения conditiontree.php:362
whereBetween($column, $valueMin, $valueMax)
Определения conditiontree.php:313
whereIn($column, $values)
Определения conditiontree.php:277
whereMatch($column, $value)
Определения conditiontree.php:415
replaceCondition($currentCondition, $newCondition)
Определения conditiontree.php:604
convertValues($values, IReadable $field=null)
Определения conditiontree.php:710
static filter()
Определения query.php:906
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$query
Определения get_search.php:11
$filter
Определения iblock_catalog_list.php:54
Определения chain.php:3
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$k
Определения template_pdf.php:567