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

AbstractColumnSchema::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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