Passed
Pull Request — master (#600)
by Alexander
02:31
created

AbstractColumnSchema::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Schema;
6
7
use PDO;
8
use Yiisoft\Db\Command\Param;
9
use Yiisoft\Db\Expression\ExpressionInterface;
10
use Yiisoft\Db\Helper\StringHelper;
11
12
use function count;
13
use function gettype;
14
use function in_array;
15
use function is_array;
16
use function is_bool;
17
use function is_float;
18
use function is_resource;
19
20
/**
21
 * Represents the metadata of a column in a database table.
22
 *
23
 * It provides information about the column's name, type, size, precision, and other details.
24
 *
25
 * The ColumnSchema class is used to store and retrieve metadata about a column in a database table.
26
 *
27
 * It's typically used in conjunction with the TableSchema class, which represents the metadata of a database table as a
28
 * whole.
29
 *
30
 * Here is an example of how the ColumnSchema class might be used:
31
 *
32
 * ```php
33
 * use Yiisoft\Db\Schema\ColumnSchema;
34
 *
35
 * $column = new ColumnSchema();
36
 * $column->name('id');
37
 * $column->allowNull(false);
38
 * $column->dbType('int(11)');
39
 * $column->phpType('integer');
40
 * $column->type('integer');
41
 * $column->defaultValue(0);
42
 * $column->autoIncrement(true);
43
 * $column->primaryKey(true);
44
 * ``
45
 */
46
abstract class AbstractColumnSchema implements ColumnSchemaInterface
47
{
48
    public function __construct(string $name, string $type, string $dbType)
49
    {
50
        $this->name = $name;
51
        $this->type = $type;
52
        $this->dbType = $dbType;
53
    }
54
55
    private bool $allowNull = false;
56
    private bool $autoIncrement = false;
57
    private string|null $comment = null;
58
    private bool $computed = false;
59
    private string $dbType;
60
    private mixed $defaultValue = null;
61
    private array|null $enumValues = null;
62
    private string|null $extra = null;
63
    private bool $isPrimaryKey = false;
64
    private string $name;
65
    private string|null $phpType = null;
66
    private int|null $precision = null;
67
    private int|null $scale = null;
68
    private int|null $size = null;
69
    private string $type;
70
    private bool $unsigned = false;
71
72
    public function allowNull(bool $value): void
73
    {
74
        $this->allowNull = $value;
75
    }
76
77
    public function autoIncrement(bool $value): void
78
    {
79
        $this->autoIncrement = $value;
80
    }
81
82
    public function comment(string|null $value): void
83
    {
84
        $this->comment = $value;
85
    }
86
87
    public function computed(bool $value): void
88
    {
89
        $this->computed = $value;
90
    }
91
92
    public function dbType(string $value): void
93
    {
94
        $this->dbType = $value;
95
    }
96
97
    public function dbTypecast(mixed $value): mixed
98
    {
99
        /**
100
         * The default implementation does the same as casting for PHP, but it should be possible to override this with
101
         * annotation of an explicit PDO type.
102
         */
103
        return $this->typecast($value);
104
    }
105
106
    public function defaultValue(mixed $value): void
107
    {
108
        $this->defaultValue = $value;
109
    }
110
111
    public function enumValues(array|null $value): void
112
    {
113
        $this->enumValues = $value;
114
    }
115
116
    public function extra(string|null $value): void
117
    {
118
        $this->extra = $value;
119
    }
120
121
    public function getComment(): string|null
122
    {
123
        return $this->comment;
124
    }
125
126
    public function getDbType(): string
127
    {
128
        return $this->dbType;
129
    }
130
131
    public function getDefaultValue(): mixed
132
    {
133
        return $this->defaultValue;
134
    }
135
136
    public function getEnumValues(): array|null
137
    {
138
        return $this->enumValues;
139
    }
140
141
    public function getExtra(): string|null
142
    {
143
        return $this->extra;
144
    }
145
146
    public function getName(): string
147
    {
148
        return $this->name;
149
    }
150
151
    public function getPrecision(): int|null
152
    {
153
        return $this->precision;
154
    }
155
156
    public function getPhpType(): string|null
157
    {
158
        return $this->phpType;
159
    }
160
161
    public function getScale(): int|null
162
    {
163
        return $this->scale;
164
    }
165
166
    public function getSize(): int|null
167
    {
168
        return $this->size;
169
    }
170
171
    public function getType(): string
172
    {
173
        return $this->type;
174
    }
175
176
    public function isAllowNull(): bool
177
    {
178
        return $this->allowNull;
179
    }
180
181
    public function isAutoIncrement(): bool
182
    {
183
        return $this->autoIncrement;
184
    }
185
186
    public function isComputed(): bool
187
    {
188
        return $this->computed;
189
    }
190
191
    public function isPrimaryKey(): bool
192
    {
193
        return $this->isPrimaryKey;
194
    }
195
196
    public function isUnsigned(): bool
197
    {
198
        return $this->unsigned;
199
    }
200
201
    public function name(string $value): void
202
    {
203
        $this->name = $value;
204
    }
205
206
    public function phpType(string|null $value): void
207
    {
208
        $this->phpType = $value;
209
    }
210
211
    public function phpTypecast(mixed $value): mixed
212
    {
213
        return $this->typecast($value);
214
    }
215
216
    public function precision(int|null $value): void
217
    {
218
        $this->precision = $value;
219
    }
220
221
    public function primaryKey(bool $value): void
222
    {
223
        $this->isPrimaryKey = $value;
224
    }
225
226
    public function scale(int|null $value): void
227
    {
228
        $this->scale = $value;
229
    }
230
231
    public function size(int|null $value): void
232
    {
233
        $this->size = $value;
234
    }
235
236
    public function type(string $value): void
237
    {
238
        $this->type = $value;
239
    }
240
241
    public function unsigned(bool $value): void
242
    {
243
        $this->unsigned = $value;
244
    }
245
246
    /**
247
     * Converts the input value according to {@see phpType} after retrieval from the database.
248
     *
249
     * If the value is null or an {@see Expression}, it won't be converted.
250
     *
251
     * @param mixed $value The value to be converted.
252
     *
253
     * @return mixed The converted value.
254
     */
255
    protected function typecast(mixed $value): mixed
256
    {
257
        if (
258
            $value === ''
259
            && !in_array(
260
                $this->type,
261
                [
262
                    SchemaInterface::TYPE_TEXT,
263
                    SchemaInterface::TYPE_STRING,
264
                    SchemaInterface::TYPE_BINARY,
265
                    SchemaInterface::TYPE_CHAR,
266
                ],
267
                true
268
            )
269
        ) {
270
            return null;
271
        }
272
273
        if (
274
            $value === null
275
            || $value instanceof ExpressionInterface
276
            || gettype($value) === $this->phpType
277
        ) {
278
            return $value;
279
        }
280
281
        if (
282
            is_array($value)
283
            && count($value) === 2
284
            && isset($value[1])
285
            && in_array($value[1], $this->getPdoParamTypes(), true)
286
        ) {
287
            return new Param((string) $value[0], $value[1]);
288
        }
289
290
        switch ($this->phpType) {
291
            case SchemaInterface::PHP_TYPE_RESOURCE:
292
            case SchemaInterface::PHP_TYPE_STRING:
293
                if (is_resource($value)) {
294
                    return $value;
295
                }
296
297
                if (is_float($value)) {
298
                    /** ensure type cast always has . as decimal separator in all locales */
299
                    return StringHelper::normalizeFloat($value);
300
                }
301
302
                if (is_bool($value)) {
303
                    return $value ? '1' : '0';
304
                }
305
306
                return (string) $value;
307
            case SchemaInterface::PHP_TYPE_INTEGER:
308
                return (int) $value;
309
            case SchemaInterface::PHP_TYPE_BOOLEAN:
310
                /**
311
                 * Treating a 0-bit value as false too.
312
                 *
313
                 * @link https://github.com/yiisoft/yii2/issues/9006
314
                 */
315
                return (bool) $value && $value !== "\0";
316
            case SchemaInterface::PHP_TYPE_DOUBLE:
317
                return (float) $value;
318
        }
319
320
        return $value;
321
    }
322
323
    /**
324
     * @return int[] Array of numbers that represent possible PDO parameter types
325
     */
326
    private function getPdoParamTypes(): array
327
    {
328
        return [
329
            PDO::PARAM_BOOL,
330
            PDO::PARAM_INT,
331
            PDO::PARAM_STR,
332
            PDO::PARAM_LOB,
333
            PDO::PARAM_NULL,
334
            PDO::PARAM_STMT,
335
        ];
336
    }
337
}
338