Passed
Pull Request — master (#93)
by Wilmer
12:16
created

ColumnSchema   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Test Coverage

Coverage 94.12%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 45
c 1
b 0
f 0
dl 0
loc 165
ccs 48
cts 51
cp 0.9412
rs 10
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
A dbTypecast() 0 19 5
A getDimension() 0 3 1
A getArrayParser() 0 3 1
A getRangeParser() 0 3 1
A sequenceName() 0 3 1
A dimension() 0 3 1
A getSequenceName() 0 3 1
B phpTypecastValue() 0 25 9
A phpTypecast() 0 23 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use JsonException;
8
use Yiisoft\Db\Expression\ArrayExpression;
9
use Yiisoft\Db\Expression\ExpressionInterface;
10
use Yiisoft\Db\Expression\JsonExpression;
11
use Yiisoft\Db\Schema\ColumnSchema as AbstractColumnSchema;
12
13
use function array_walk_recursive;
14
use function in_array;
15
use function is_array;
16
use function is_string;
17
use function json_decode;
18
use function strtolower;
19
20
/**
21
 * The class ColumnSchema for PostgreSQL database.
22
 */
23
final class ColumnSchema extends AbstractColumnSchema
24
{
25
    /**
26
     * @var int the dimension of array. Defaults to 0, means this column is not an array.
27
     */
28
    private int $dimension = 0;
29
30
    /**
31
     * @var string|null name of associated sequence if column is auto-incremental.
32
     */
33
    private ?string $sequenceName = null;
34
35
    /**
36
     * Converts the input value according to {@see type} and {@see dbType} for use in a db query.
37
     *
38
     * If the value is null or an {@see Expression}, it will not be converted.
39
     *
40
     * @param mixed $value input value
41
     *
42
     * @return mixed converted value. This may also be an array containing the value as the first element and the PDO
43
     * type as the second element.
44
     */
45 104
    public function dbTypecast($value)
46
    {
47 104
        if ($value === null) {
48 6
            return null;
49
        }
50
51 104
        if ($value instanceof ExpressionInterface) {
52 64
            return $value;
53
        }
54
55 46
        if ($this->dimension > 0) {
56 1
            return new ArrayExpression($value, $this->getDbType(), $this->dimension);
57
        }
58
59 46
        if (in_array($this->getDbType(), [Schema::TYPE_JSON, Schema::TYPE_JSONB], true)) {
60 2
            return new JsonExpression($value, $this->getDbType());
61
        }
62
63 45
        return $this->typecast($value);
64
    }
65
66
    /**
67
     * Converts the input value according to {@see phpType} after retrieval from the database.
68
     *
69
     * If the value is null or an {@see Expression}, it will not be converted.
70
     *
71
     * @param mixed $value input value
72
     *
73
     * @throws JsonException
74
     *
75
     * @return mixed converted value
76
     */
77 32
    public function phpTypecast($value)
78
    {
79 32
        if (RangeParser::isAllowedType($this->getType())) {
80
            return $this->getRangeParser()->parse($value);
81
        }
82
83 32
        if ($this->dimension > 0) {
84 1
            if (!is_array($value)) {
85 1
                $value = $this->getArrayParser()->parse($value);
86
            }
87
88 1
            if (is_array($value)) {
89 1
                array_walk_recursive($value, function (?string &$val) {
90 1
                    $val = $this->phpTypecastValue($val);
91 1
                });
92
            } else {
93 1
                return null;
94
            }
95
96 1
            return $value;
97
        }
98
99 32
        return $this->phpTypecastValue($value);
100
    }
101
102
    /**
103
     * Casts $value after retrieving from the DBMS to PHP representation.
104
     *
105
     * @param int|string|null $value
106
     *
107
     * @throws JsonException
108
     *
109
     * @return mixed
110
     */
111 32
    protected function phpTypecastValue($value)
112
    {
113 32
        if ($value === null) {
114 1
            return null;
115
        }
116
117 32
        switch ($this->getType()) {
118
            case Schema::TYPE_BOOLEAN:
119 2
                $value = is_string($value) ? strtolower($value) : $value;
120
121 2
                switch ($value) {
122 2
                    case 't':
123 2
                    case 'true':
124 1
                        return true;
125 2
                    case 'f':
126 2
                    case 'false':
127 1
                        return false;
128
                }
129
130 1
                return (bool) $value;
131
            case Schema::TYPE_JSON:
132 28
                return json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR);
133
        }
134
135 31
        return parent::phpTypecast($value);
136
    }
137
138
    /**
139
     * Creates instance of ArrayParser.
140
     *
141
     * @return ArrayParser
142
     */
143 1
    protected function getArrayParser(): ArrayParser
144
    {
145 1
        return new ArrayParser();
146
    }
147
148
    /**
149
     * Creates instance of RangeParser.
150
     *
151
     * @return RangeParser
152
     */
153
    protected function getRangeParser(): RangeParser
154
    {
155
        return new RangeParser($this->getType());
156
    }
157
158
    /**
159
     * @return int Get the dimension of array. Defaults to 0, means this column is not an array.
160
     */
161 1
    public function getDimension(): int
162
    {
163 1
        return $this->dimension;
164
    }
165
166
    /**
167
     * @return string name of associated sequence if column is auto-incremental.
168
     */
169 119
    public function getSequenceName(): ?string
170
    {
171 119
        return $this->sequenceName;
172
    }
173
174
    /**
175
     * Set dimension of array. Defaults to 0, means this column is not an array.
176
     */
177 151
    public function dimension(int $dimension): void
178
    {
179 151
        $this->dimension = $dimension;
180 151
    }
181
182
    /**
183
     * Set name of associated sequence if column is auto-incremental.
184
     */
185 115
    public function sequenceName(?string $sequenceName): void
186
    {
187 115
        $this->sequenceName = $sequenceName;
188 115
    }
189
}
190