Passed
Pull Request — master (#32)
by Wilmer
13:07
created

PgsqlColumnSchema::phpTypecastValue()   B

Complexity

Conditions 9
Paths 13

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 16
nc 13
nop 1
dl 0
loc 25
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql\Schema;
6
7
use Yiisoft\Db\Expression\ArrayExpression;
8
use Yiisoft\Db\Expression\ExpressionInterface;
9
use Yiisoft\Db\Expression\JsonExpression;
10
use Yiisoft\Db\Pgsql\Query\ArrayParser;
11
use Yiisoft\Db\Schema\ColumnSchema;
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
final class PgsqlColumnSchema extends ColumnSchema
21
{
22
    /**
23
     * @var int the dimension of array. Defaults to 0, means this column is not an array.
24
     */
25
    private int $dimension = 0;
26
27
    /**
28
     * @var string name of associated sequence if column is auto-incremental.
29
     */
30
    private ?string $sequenceName = null;
31
32
    /**
33
     * Converts the input value according to {@see type} and {@see dbType} for use in a db query.
34
     *
35
     * If the value is null or an {@see Expression}, it will not be converted.
36
     *
37
     * @param mixed $value input value
38
     *
39
     * @return mixed converted value. This may also be an array containing the value as the first element and the PDO
40
     * type as the second element.
41
     */
42
    public function dbTypecast($value)
43
    {
44
        if ($value === null) {
45
            return $value;
46
        }
47
48
        if ($value instanceof ExpressionInterface) {
49
            return $value;
50
        }
51
52
        if ($this->dimension > 0) {
53
            return new ArrayExpression($value, $this->getDbType(), $this->dimension);
54
        }
55
56
        if (in_array($this->getDbType(), [PgsqlSchema::TYPE_JSON, PgsqlSchema::TYPE_JSONB], true)) {
57
            return new JsonExpression($value, $this->getDbType());
58
        }
59
60
        return $this->typecast($value);
61
    }
62
63
    /**
64
     * Converts the input value according to {@see phpType} after retrieval from the database.
65
     *
66
     * If the value is null or an {@see Expression}, it will not be converted.
67
     *
68
     * @param mixed $value input value
69
     *
70
     * @return mixed converted value
71
     */
72
    public function phpTypecast($value)
73
    {
74
        if ($this->dimension > 0) {
75
            if (!is_array($value)) {
76
                $value = $this->getArrayParser()->parse($value);
77
            }
78
            if (is_array($value)) {
79
                array_walk_recursive($value, function (&$val) {
80
                    $val = $this->phpTypecastValue($val);
81
                });
82
            } elseif ($value === null) {
0 ignored issues
show
introduced by
The condition $value === null is always true.
Loading history...
83
                return null;
84
            }
85
86
            return $value;
87
        }
88
89
        return $this->phpTypecastValue($value);
90
    }
91
92
    /**
93
     * Casts $value after retrieving from the DBMS to PHP representation.
94
     *
95
     * @param string|int|null $value
96
     *
97
     * @return bool|mixed|null
98
     */
99
    protected function phpTypecastValue($value)
100
    {
101
        if ($value === null) {
102
            return null;
103
        }
104
105
        switch ($this->getType()) {
106
            case PgsqlSchema::TYPE_BOOLEAN:
107
                $value = is_string($value) ? strtolower($value) : $value;
108
109
                switch ($value) {
110
                    case 't':
111
                    case 'true':
112
                        return true;
113
                    case 'f':
114
                    case 'false':
115
                        return false;
116
                }
117
118
                return (bool) $value;
119
            case PgsqlSchema::TYPE_JSON:
120
                return json_decode($value, true, 512, JSON_THROW_ON_ERROR);
121
        }
122
123
        return parent::phpTypecast($value);
124
    }
125
126
    /**
127
     * Creates instance of ArrayParser.
128
     *
129
     * @return ArrayParser
130
     */
131
    protected function getArrayParser(): ArrayParser
132
    {
133
        static $parser = null;
134
135
        if ($parser === null) {
136
            $parser = new ArrayParser();
137
        }
138
139
        return $parser;
140
    }
141
142
    public function getDimension(): int
143
    {
144
        return $this->dimension;
145
    }
146
147
    public function getSequenceName(): ?string
148
    {
149
        return $this->sequenceName;
150
    }
151
152
    public function dimension(int $dimension): void
153
    {
154
        $this->dimension = $dimension;
155
    }
156
157
    public function sequenceName(?string $sequenceName): void
158
    {
159
        $this->sequenceName = $sequenceName;
160
    }
161
}
162