Passed
Pull Request — php82 (#19828)
by
unknown
10:08
created

LikeConditionBuilder::parseOperator()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 10
ccs 6
cts 7
cp 0.8571
crap 3.0261
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db\conditions;
9
10
use yii\base\InvalidArgumentException;
11
use yii\db\ExpressionBuilderInterface;
12
use yii\db\ExpressionBuilderTrait;
13
use yii\db\ExpressionInterface;
14
15
/**
16
 * Class LikeConditionBuilder builds objects of [[LikeCondition]]
17
 *
18
 * @author Dmytro Naumenko <[email protected]>
19
 * @since 2.0.14
20
 */
21
class LikeConditionBuilder implements ExpressionBuilderInterface
22
{
23
    use ExpressionBuilderTrait;
24
25
    /**
26
     * @var array map of chars to their replacements in LIKE conditions.
27
     * By default it's configured to escape `%`, `_` and `\` with `\`.
28
     */
29
    protected $escapingReplacements = [
30
        '%' => '\%',
31
        '_' => '\_',
32
        '\\' => '\\\\',
33
    ];
34
    /**
35
     * @var string|null character used to escape special characters in LIKE conditions.
36
     * By default it's assumed to be `\`.
37
     */
38
    protected $escapeCharacter;
39
40
41
    /**
42
     * Method builds the raw SQL from the $expression that will not be additionally
43
     * escaped or quoted.
44
     *
45
     * @param ExpressionInterface|LikeCondition $expression the expression to be built.
46
     * @param array $params the binding parameters.
47
     * @return string the raw SQL that will not be additionally escaped or quoted.
48
     */
49 105
    public function build(ExpressionInterface $expression, array &$params = [])
50
    {
51 105
        $operator = strtoupper($expression->getOperator());
0 ignored issues
show
Bug introduced by
The method getOperator() does not exist on yii\db\ExpressionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in yii\db\JsonExpression or yii\db\ArrayExpression or yii\db\PdoValue or yii\db\conditions\ConditionInterface or yii\db\conditions\HashCondition or yii\db\conditions\NotCondition. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
        $operator = strtoupper($expression->/** @scrutinizer ignore-call */ getOperator());
Loading history...
52 105
        $column = $expression->getColumn();
0 ignored issues
show
Bug introduced by
The method getColumn() does not exist on yii\db\ExpressionInterface. It seems like you code against a sub-type of yii\db\ExpressionInterface such as yii\db\Query or yii\db\Expression or yii\db\conditions\InCondition or yii\db\conditions\BetweenCondition or yii\db\conditions\SimpleCondition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

52
        /** @scrutinizer ignore-call */ 
53
        $column = $expression->getColumn();
Loading history...
53 105
        $values = $expression->getValue();
0 ignored issues
show
Bug introduced by
The method getValue() does not exist on yii\db\ExpressionInterface. It seems like you code against a sub-type of yii\db\ExpressionInterface such as yii\db\JsonExpression or yii\db\Query or yii\db\ArrayExpression or yii\db\PdoValue or yii\db\Expression or yii\db\conditions\BetweenColumnsCondition or yii\db\conditions\SimpleCondition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
        /** @scrutinizer ignore-call */ 
54
        $values = $expression->getValue();
Loading history...
54 105
        $escape = $expression->getEscapingReplacements();
0 ignored issues
show
Bug introduced by
The method getEscapingReplacements() does not exist on yii\db\ExpressionInterface. It seems like you code against a sub-type of yii\db\ExpressionInterface such as yii\db\Query or yii\db\Expression or yii\db\conditions\LikeCondition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

54
        /** @scrutinizer ignore-call */ 
55
        $escape = $expression->getEscapingReplacements();
Loading history...
55 105
        if ($escape === null || $escape === []) {
56 102
            $escape = $this->escapingReplacements;
57
        }
58
59 105
        list($andor, $not, $operator) = $this->parseOperator($operator);
60
61 105
        if (!is_array($values)) {
62 49
            $values = [$values];
63
        }
64
65 105
        if (empty($values)) {
66 16
            return $not ? '' : '0=1';
67
        }
68
69 89
        if ($column instanceof ExpressionInterface) {
70 3
            $column = $this->queryBuilder->buildExpression($column, $params);
71 86
        } elseif (is_string($column) && strpos($column, '(') === false) {
72 86
            $column = $this->queryBuilder->db->quoteColumnName($column);
73
        }
74
75 89
        $escapeSql = $this->getEscapeSql();
76 89
        $parts = [];
77 89
        foreach ($values as $value) {
78 89
            if ($value instanceof ExpressionInterface) {
79 48
                $phName = $this->queryBuilder->buildExpression($value, $params);
80
            } elseif (empty($value)) {
81
                $phName = $this->queryBuilder->bindParam('%%', $params);
82
            } else {
83 65
                $phName = $this->queryBuilder->bindParam(empty($escape) ? $value : ('%' . strtr($value, $escape) . '%'), $params);
84
            }
85 89
            $parts[] = "{$column} {$operator} {$phName}{$escapeSql}";
86
        }
87
88 89
        return implode($andor, $parts);
89
    }
90
91
    /**
92
     * @return string
93
     */
94 89
    private function getEscapeSql()
95
    {
96 89
        if ($this->escapeCharacter !== null) {
97 27
            return " ESCAPE '{$this->escapeCharacter}'";
98
        }
99
100 62
        return '';
101
    }
102
103
    /**
104
     * @param string $operator
105
     * @return array
106
     */
107 105
    protected function parseOperator($operator)
108
    {
109 105
        if (!preg_match('/^(AND |OR |)(((NOT |))I?LIKE)/', $operator, $matches)) {
110
            throw new InvalidArgumentException("Invalid operator '$operator'.");
111
        }
112 105
        $andor = ' ' . (!empty($matches[1]) ? $matches[1] : 'AND ');
113 105
        $not = !empty($matches[3]);
114 105
        $operator = $matches[2];
115
116 105
        return [$andor, $not, $operator];
117
    }
118
}
119