Passed
Push — master ( e96104...60e64e )
by Def
04:02 queued 24s
created

ColumnSchema   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 42
c 2
b 0
f 0
dl 0
loc 150
ccs 51
cts 51
cp 1
rs 10
wmc 18

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getDimension() 0 3 1
A getArrayParser() 0 3 1
A phpTypecast() 0 20 4
A sequenceName() 0 3 1
A dimension() 0 3 1
A getSequenceName() 0 3 1
A phpTypecastValue() 0 20 3
A dbTypecast() 0 22 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use JsonException;
8
use PDO;
9
use Yiisoft\Db\Command\Param;
10
use Yiisoft\Db\Expression\ArrayExpression;
11
use Yiisoft\Db\Expression\ExpressionInterface;
12
use Yiisoft\Db\Expression\JsonExpression;
13
use Yiisoft\Db\Schema\AbstractColumnSchema;
14
use Yiisoft\Db\Schema\SchemaInterface;
15
16
use function array_walk_recursive;
17
use function bindec;
18
use function decbin;
19
use function is_array;
20
use function is_int;
21
use function is_string;
22
use function json_decode;
23
use function str_pad;
24
25
/**
26
 * Represents the metadata of a column in a database table for PostgreSQL Server.
27
 *
28
 * It provides information about the column's name, type, size, precision, and other details.
29
 *
30
 * It's used to store and retrieve metadata about a column in a database table and is typically used in conjunction with
31
 * the {@see TableSchema}, which represents the metadata of a database table as a whole.
32
 *
33
 * The following code shows how to use:
34
 *
35
 * ```php
36
 * use Yiisoft\Db\Pgsql\ColumnSchema;
37
 *
38
 * $column = new ColumnSchema();
39
 * $column->name('id');
40
 * $column->allowNull(false);
41
 * $column->dbType('integer');
42
 * $column->phpType('integer');
43
 * $column->type('integer');
44
 * $column->defaultValue(0);
45
 * $column->autoIncrement(true);
46
 * $column->primaryKey(true);
47
 * ```
48
 */
49
final class ColumnSchema extends AbstractColumnSchema
50
{
51
    /**
52
     * @var int The dimension of array. Defaults to 0, means this column isn't an array.
53
     */
54
    private int $dimension = 0;
55
56
    /**
57
     * @var string|null Name of an associated sequence if column is auto incremental.
58
     */
59
    private string|null $sequenceName = null;
60
61
    /**
62
     * Converts the input value according to {@see type} and {@see dbType} for use in a db query.
63
     *
64
     * If the value is null or an {@see Expression}, it won't be converted.
65
     *
66
     * @param mixed $value input value
67
     *
68
     * @return mixed Converted value. This may also be an array containing the value as the first element and the PDO
69
     * type as the second element.
70
     */
71 87
    public function dbTypecast(mixed $value): mixed
72
    {
73 87
        if ($value === null || $value instanceof ExpressionInterface) {
74 30
            return $value;
75
        }
76
77 82
        if ($this->dimension > 0) {
78 2
            return new ArrayExpression($value, $this->getDbType(), $this->dimension);
79
        }
80
81 81
        return match ($this->getType()) {
82 81
            SchemaInterface::TYPE_JSON => new JsonExpression($value, $this->getDbType()),
83
84 81
            SchemaInterface::TYPE_BINARY => is_string($value)
85 3
                ? new Param($value, PDO::PARAM_LOB) // explicitly setup PDO param type for binary column
86 3
                : $this->typecast($value),
87
88 81
            Schema::TYPE_BIT => is_int($value)
0 ignored issues
show
Bug introduced by
The type Yiisoft\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...
89 1
                ? str_pad(decbin($value), (int) $this->getSize(), '0', STR_PAD_LEFT)
90 1
                : $this->typecast($value),
91
92 81
            default => $this->typecast($value),
93 81
        };
94
    }
95
96
    /**
97
     * Converts the input value according to {@see phpType} after retrieval from the database.
98
     *
99
     * If the value is null or an {@see Expression}, it won't be converted.
100
     *
101
     * @param mixed $value The input value
102
     *
103
     * @throws JsonException
104
     *
105
     * @return mixed The converted value
106
     */
107 94
    public function phpTypecast(mixed $value): mixed
108
    {
109 94
        if ($this->dimension > 0) {
110 10
            if (is_string($value)) {
111 10
                $value = $this->getArrayParser()->parse($value);
112
            }
113
114 10
            if (is_array($value)) {
115 10
                array_walk_recursive($value, function (string|null &$val) {
116
                    /** @psalm-var mixed $val */
117 10
                    $val = $this->phpTypecastValue($val);
118 10
                });
119
            } else {
120 1
                return null;
121
            }
122
123 10
            return $value;
124
        }
125
126 88
        return $this->phpTypecastValue($value);
127
    }
128
129
    /**
130
     * Casts $value after retrieving from the DBMS to PHP representation.
131
     *
132
     * @throws JsonException
133
     */
134 94
    protected function phpTypecastValue(mixed $value): mixed
135
    {
136 94
        if ($value === null) {
137 9
            return null;
138
        }
139
140 94
        return match ($this->getType()) {
141 94
            Schema::TYPE_BIT => is_string($value) ? bindec($value) : $value,
142
143 94
            SchemaInterface::TYPE_BOOLEAN
144 94
                => match ($value) {
145 94
                    't' => true,
146 94
                    'f' => false,
147 94
                    default => (bool) $value,
148 94
                },
149
150 94
            SchemaInterface::TYPE_JSON
151 94
                => json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR),
152
153 94
            default => parent::phpTypecast($value),
154 94
        };
155
    }
156
157
    /**
158
     * Creates instance of ArrayParser.
159
     */
160 10
    protected function getArrayParser(): ArrayParser
161
    {
162 10
        return new ArrayParser();
163
    }
164
165
    /**
166
     * @return int Get the dimension of the array.
167
     *
168
     * Defaults to 0, means this column isn't an array.
169
     */
170 1
    public function getDimension(): int
171
    {
172 1
        return $this->dimension;
173
    }
174
175
    /**
176
     * @return string|null name of an associated sequence if column is auto incremental.
177
     */
178 97
    public function getSequenceName(): string|null
179
    {
180 97
        return $this->sequenceName;
181
    }
182
183
    /**
184
     * Set dimension of an array.
185
     *
186
     * Defaults to 0, means this column isn't an array.
187
     */
188 156
    public function dimension(int $dimension): void
189
    {
190 156
        $this->dimension = $dimension;
191
    }
192
193
    /**
194
     * Set the name of an associated sequence if a column is auto incremental.
195
     */
196 82
    public function sequenceName(string|null $sequenceName): void
197
    {
198 82
        $this->sequenceName = $sequenceName;
199
    }
200
}
201