Passed
Pull Request — master (#20362)
by Wilmer
05:37
created

ArrayExpressionBuilder   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 42
dl 0
loc 125
ccs 0
cts 46
cp 0
rs 10
c 0
b 0
f 0
wmc 19

6 Methods

Rating   Name   Duplication   Size   Complexity  
A build() 0 15 3
A unnestArrayExpression() 0 5 1
A buildSubqueryArray() 0 3 1
A getTypehint() 0 10 2
A typecastValue() 0 11 3
B buildPlaceholders() 0 33 9
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\pgsql;
9
10
use yii\db\ArrayExpression;
11
use yii\db\ExpressionBuilderInterface;
12
use yii\db\ExpressionBuilderTrait;
13
use yii\db\ExpressionInterface;
14
use yii\db\JsonExpression;
15
use yii\db\Query;
16
17
/**
18
 * Class ArrayExpressionBuilder builds [[ArrayExpression]] for PostgreSQL DBMS.
19
 *
20
 * @author Dmytro Naumenko <[email protected]>
21
 * @since 2.0.14
22
 */
23
class ArrayExpressionBuilder implements ExpressionBuilderInterface
24
{
25
    use ExpressionBuilderTrait;
26
27
28
    /**
29
     * {@inheritdoc}
30
     * @param ArrayExpression|ExpressionInterface $expression the expression to be built
31
     */
32
    public function build(ExpressionInterface $expression, array &$params = [])
33
    {
34
        $value = $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

34
        /** @scrutinizer ignore-call */ 
35
        $value = $expression->getValue();
Loading history...
35
        if ($value === null) {
36
            return 'NULL';
37
        }
38
39
        if ($value instanceof Query) {
40
            list ($sql, $params) = $this->queryBuilder->build($value, $params);
41
            return $this->buildSubqueryArray($sql, $expression);
42
        }
43
44
        $placeholders = $this->buildPlaceholders($expression, $params);
45
46
        return 'ARRAY[' . implode(', ', $placeholders) . ']' . $this->getTypehint($expression);
47
    }
48
49
    /**
50
     * Builds placeholders array out of $expression values
51
     * @param ExpressionInterface|ArrayExpression $expression
52
     * @param array $params the binding parameters.
53
     * @return array
54
     */
55
    protected function buildPlaceholders(ExpressionInterface $expression, &$params)
56
    {
57
        $value = $expression->getValue();
58
59
        $placeholders = [];
60
        if ($value === null || !is_array($value) && !$value instanceof \Traversable) {
61
            return $placeholders;
62
        }
63
64
        if ($expression->getDimension() > 1) {
0 ignored issues
show
Bug introduced by
The method getDimension() 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\ArrayExpression or yii\db\Expression. ( Ignorable by Annotation )

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

64
        if ($expression->/** @scrutinizer ignore-call */ getDimension() > 1) {
Loading history...
65
            foreach ($value as $item) {
66
                $placeholders[] = $this->build($this->unnestArrayExpression($expression, $item), $params);
67
            }
68
            return $placeholders;
69
        }
70
71
        foreach ($value as $item) {
72
            if ($item instanceof Query) {
73
                list ($sql, $params) = $this->queryBuilder->build($item, $params);
74
                $placeholders[] = $this->buildSubqueryArray($sql, $expression);
75
                continue;
76
            }
77
78
            $item = $this->typecastValue($expression, $item);
79
            if ($item instanceof ExpressionInterface) {
80
                $placeholders[] = $this->queryBuilder->buildExpression($item, $params);
81
                continue;
82
            }
83
84
            $placeholders[] = $this->queryBuilder->bindParam($item, $params);
85
        }
86
87
        return $placeholders;
88
    }
89
90
    /**
91
     * @param ArrayExpression $expression
92
     * @param mixed $value
93
     * @return ArrayExpression
94
     */
95
    private function unnestArrayExpression(ArrayExpression $expression, $value)
96
    {
97
        $expressionClass = get_class($expression);
98
99
        return new $expressionClass($value, $expression->getType(), $expression->getDimension() - 1);
100
    }
101
102
    /**
103
     * @param ArrayExpression $expression
104
     * @return string the typecast expression based on [[type]].
105
     */
106
    protected function getTypehint(ArrayExpression $expression)
107
    {
108
        if ($expression->getType() === null) {
109
            return '';
110
        }
111
112
        $result = '::' . $expression->getType();
113
        $result .= str_repeat('[]', $expression->getDimension());
114
115
        return $result;
116
    }
117
118
    /**
119
     * Build an array expression from a subquery SQL.
120
     *
121
     * @param string $sql the subquery SQL.
122
     * @param ArrayExpression $expression
123
     * @return string the subquery array expression.
124
     */
125
    protected function buildSubqueryArray($sql, ArrayExpression $expression)
126
    {
127
        return 'ARRAY(' . $sql . ')' . $this->getTypehint($expression);
128
    }
129
130
    /**
131
     * Casts $value to use in $expression
132
     *
133
     * @param ArrayExpression $expression
134
     * @param mixed $value
135
     * @return JsonExpression
136
     */
137
    protected function typecastValue(ArrayExpression $expression, $value)
138
    {
139
        if ($value instanceof ExpressionInterface) {
140
            return $value;
141
        }
142
143
        if (in_array($expression->getType(), [Schema::TYPE_JSON, Schema::TYPE_JSONB], true)) {
0 ignored issues
show
Bug introduced by
The type yii\db\pgsql\Schema was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
144
            return new JsonExpression($value);
145
        }
146
147
        return $value;
148
    }
149
}
150