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

ColumnSchema::phpTypecastValue()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
c 2
b 0
f 0
nc 2
nop 1
dl 0
loc 17
ccs 14
cts 14
cp 1
crap 4
rs 9.8666
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
        if (
75 85
            $value === null
76 85
            || $value instanceof ExpressionInterface
77
        ) {
78 29
            return $value;
79
        }
80
81 81
        if ($this->dimension > 0) {
82 2
            return new ArrayExpression($value, $this->getDbType(), $this->dimension);
83
        }
84
85 80
        return match ($this->getType()) {
86 80
            SchemaInterface::TYPE_JSON => new JsonExpression($value, $this->getDbType()),
87 80
            SchemaInterface::TYPE_BINARY => is_string($value)
88 3
                ? new Param($value, PDO::PARAM_LOB) // explicitly setup PDO param type for binary column
89 3
                : $this->typecast($value),
90 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...
91 1
                ? str_pad(decbin($value), (int) $this->getSize(), '0', STR_PAD_LEFT)
92 1
                : $this->typecast($value),
93 80
            default => $this->typecast($value),
94 80
        };
95
    }
96
97
    /**
98
     * Converts the input value according to {@see phpType} after retrieval from the database.
99
     *
100
     * If the value is null or an {@see Expression}, it won't be converted.
101
     *
102
     * @param mixed $value The input value
103
     *
104
     * @throws JsonException
105
     *
106
     * @return mixed The converted value
107
     */
108 93
    public function phpTypecast(mixed $value): mixed
109
    {
110 93
        if ($this->dimension > 0) {
111 2
            if (is_string($value)) {
112 2
                $value = $this->getArrayParser()->parse($value);
113
            }
114
115 2
            if (is_array($value)) {
116 2
                array_walk_recursive($value, function (string|null &$val) {
117
                    /** @psalm-var mixed $val */
118 2
                    $val = $this->phpTypecastValue($val);
119 2
                });
120
            } else {
121 1
                return null;
122
            }
123
124 2
            return $value;
125
        }
126
127 92
        return $this->phpTypecastValue($value);
128
    }
129
130
    /**
131
     * Casts $value after retrieving from the DBMS to PHP representation.
132
     *
133
     * @throws JsonException
134
     */
135 93
    protected function phpTypecastValue(mixed $value): mixed
136
    {
137 93
        if ($value === null) {
138 1
            return null;
139
        }
140
141 93
        return match ($this->getType()) {
142 93
            Schema::TYPE_BIT => is_string($value) ? bindec($value) : $value,
143 93
            SchemaInterface::TYPE_BOOLEAN
144 93
                => match (is_string($value) ? strtolower($value) : $value) {
145 93
                    't', 'true' => true,
146 93
                    'f', 'false' => false,
147 93
                    default => (bool) $value,
148 93
                },
149 93
            SchemaInterface::TYPE_JSON
150 93
                => json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR),
151 93
            default => parent::phpTypecast($value),
152 93
        };
153
    }
154
155
    /**
156
     * Creates instance of ArrayParser.
157
     */
158 2
    protected function getArrayParser(): ArrayParser
159
    {
160 2
        return new ArrayParser();
161
    }
162
163
    /**
164
     * @return int Get the dimension of the array.
165
     *
166
     * Defaults to 0, means this column isn't an array.
167
     */
168 1
    public function getDimension(): int
169
    {
170 1
        return $this->dimension;
171
    }
172
173
    /**
174
     * @return string|null name of an associated sequence if column is auto incremental.
175
     */
176 96
    public function getSequenceName(): string|null
177
    {
178 96
        return $this->sequenceName;
179
    }
180
181
    /**
182
     * Set dimension of an array.
183
     *
184
     * Defaults to 0, means this column isn't an array.
185
     */
186 154
    public function dimension(int $dimension): void
187
    {
188 154
        $this->dimension = $dimension;
189
    }
190
191
    /**
192
     * Set the name of an associated sequence if a column is auto incremental.
193
     */
194 81
    public function sequenceName(string|null $sequenceName): void
195
    {
196 81
        $this->sequenceName = $sequenceName;
197
    }
198
}
199