Passed
Pull Request — master (#601)
by Wilmer
07:26 queued 05:14
created

AbstractColumnSchema::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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