Passed
Pull Request — master (#288)
by
unknown
03:50
created

ColumnSchema::dbTypecast()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6

Importance

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