Completed
Push — develop ( 21f970...705c20 )
by Freddie
03:24
created

SchemaAttribute::maxCheck()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of FlexPHP.
4
 *
5
 * (c) Freddie Gar <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace FlexPHP\Schema;
11
12
use FlexPHP\Schema\Constants\Keyword;
13
use FlexPHP\Schema\Constants\Rule;
14
use FlexPHP\Schema\Validations\SchemaAttributeValidation;
15
16
final class SchemaAttribute implements SchemaAttributeInterface
17
{
18
    /**
19
     * @var string
20
     */
21
    private $name;
22
23
    /**
24
     * @var string
25
     */
26
    private $dataType;
27
28
    /**
29
     * @var array<string, mixed>
30
     */
31
    private $constraints = [];
32
33
    /**
34
     * @param mixed $constraints
35
     */
36 89
    public function __construct(string $name, string $dataType, $constraints = null)
37
    {
38 89
        $this->setName($name);
39 89
        $this->setDataType($dataType);
40 89
        $this->setConstraints($constraints);
41
42 89
        $this->validate();
43 86
    }
44
45 89
    public function name(): string
46
    {
47 89
        return $this->name;
48
    }
49
50 89
    public function dataType(): string
51
    {
52 89
        return $this->dataType;
53
    }
54
55 89
    public function constraints(): array
56
    {
57 89
        return $this->constraints;
58
    }
59
60 6
    public function type(): ?string
61
    {
62 6
        return $this->constraints[Rule::TYPE] ?? null;
63
    }
64
65 11
    public function isRequired(): bool
66
    {
67 11
        return (bool)($this->constraints[Rule::REQUIRED] ?? false);
68
    }
69
70 10
    public function minLength(): ?int
71
    {
72 10
        return $this->constraints[Rule::MINLENGTH] ?? null;
73
    }
74
75 10
    public function maxLength(): ?int
76
    {
77 10
        return $this->constraints[Rule::MAXLENGTH] ?? null;
78
    }
79
80 10
    public function minCheck(): ?int
81
    {
82 10
        return $this->constraints[Rule::MINCHECK] ?? null;
83
    }
84
85 10
    public function maxCheck(): ?int
86
    {
87 10
        return $this->constraints[Rule::MAXCHECK] ?? null;
88
    }
89
90 8
    public function min(): ?int
91
    {
92 8
        return $this->constraints[Rule::MIN] ?? null;
93
    }
94
95 8
    public function max(): ?int
96
    {
97 8
        return $this->constraints[Rule::MAX] ?? null;
98
    }
99
100 6
    public function equalTo(): ?string
101
    {
102 6
        return $this->constraints[Rule::EQUALTO] ?? null;
103
    }
104
105 12
    public function isPk(): bool
106
    {
107 12
        return (bool)($this->constraints[Rule::PRIMARYKEY] ?? false);
108
    }
109
110 9
    public function isAi(): bool
111
    {
112 9
        return (bool)($this->constraints[Rule::AUTOINCREMENT] ?? false);
113
    }
114
115 10
    public function isFk(): bool
116
    {
117 10
        return (bool)($this->constraints[Rule::FOREIGNKEY] ?? false);
118
    }
119
120 10
    public function fkTable(): ?string
121
    {
122 10
        return $this->constraints[Rule::FOREIGNKEY]['table'] ?? null;
123
    }
124
125 10
    public function fkId(): ?string
126
    {
127 10
        return $this->constraints[Rule::FOREIGNKEY]['id'] ?? null;
128
    }
129
130 10
    public function fkName(): ?string
131
    {
132 10
        return $this->constraints[Rule::FOREIGNKEY]['name'] ?? null;
133
    }
134
135 14
    public function isCa(): bool
136
    {
137 14
        return (bool)($this->constraints[Rule::CREATEDAT] ?? false);
138
    }
139
140 10
    public function isUa(): bool
141
    {
142 10
        return (bool)($this->constraints[Rule::UPDATEDAT] ?? false);
143
    }
144
145 14
    public function isBlame(): bool
146
    {
147 14
        return $this->isCa() || $this->isUa();
148
    }
149
150 89
    public function properties(): array
151
    {
152
        return [
153 89
            Keyword::NAME => $this->name(),
154 89
            Keyword::DATATYPE => $this->dataType(),
155 89
            Keyword::CONSTRAINTS => $this->constraints(),
156
        ];
157
    }
158
159 11
    public function typeHint(): string
160
    {
161
        $typeHintByDataType = [
162 11
            'smallint' => 'int',
163
            'integer' => 'int',
164
            'float' => 'float',
165
            'double' => 'float',
166
            'bool' => 'bool',
167
            'boolean' => 'bool',
168
            'date' => '\DateTime',
169
            'date_immutable' => '\DateTimeImmutable',
170
            'datetime' => '\DateTime',
171
            'datetime_immutable' => '\DateTimeImmutable',
172
            'datetimetz' => '\DateTime',
173
            'datetimetz_immutable' => '\DateTimeImmutable',
174
            'time' => '\DateTime',
175
            'time_immutable' => '\DateTimeImmutable',
176
            'array' => 'array',
177
            'simple_array' => 'array',
178
            'json_array' => 'array',
179
        ];
180
181 11
        if (isset($typeHintByDataType[$this->dataType()])) {
182 8
            return $typeHintByDataType[$this->dataType()];
183
        }
184
185 3
        return 'string';
186
    }
187
188 89
    private function validate(): void
189
    {
190 89
        (new SchemaAttributeValidation($this->properties()))->validate();
191 86
    }
192
193 89
    private function setName(string $name): void
194
    {
195 89
        $this->name = $name;
196 89
    }
197
198 89
    private function setDataType(string $dataType): void
199
    {
200 89
        $this->dataType = $dataType;
201 89
    }
202
203
    /**
204
     * @param mixed $constraints
205
     */
206 89
    private function setConstraints($constraints): void
207
    {
208 89
        if (!empty($constraints)) {
209 69
            if (\is_string($constraints)) {
210 33
                $this->setConstraintsFromString($constraints);
211
            } else {
212 36
                $this->setConstraintsFromArray($constraints);
213
            }
214
        }
215 89
    }
216
217 33
    private function setConstraintsFromString(string $constraints): void
218
    {
219 33
        $this->setConstraintsFromArray($this->getConstraintsFromString($constraints));
220 33
    }
221
222 69
    private function setConstraintsFromArray(array $constraints): void
223
    {
224 69
        $this->constraints = $this->getConstraintsCast($constraints);
225 69
    }
226
227 33
    private function getConstraintsFromString(string $constraints): array
228
    {
229 33
        $_constraints = \explode('|', $constraints);
230
231
        /** @var mixed $_constraint */
232 33
        foreach ($_constraints as $index => $_constraint) {
233 33
            $_rule = \explode(':', $_constraint);
234
235 33
            if (\count($_rule) === 2) {
236 28
                [$_name, $_options] = $_rule;
237
238 28
                if (Rule::FOREIGNKEY !== $_name && \strpos($_options, ',') !== false) { // Range
239 2
                    [$min, $max] = \explode(',', $_options);
240 2
                    $_options = \compact('min', 'max');
241 26
                } elseif (\preg_match('/^false$/i', $_options)) { // False as string
242 8
                    $_options = false;
243 21
                } elseif (\preg_match('/^true$/i', $_options)) { // True as string
244 9
                    $_options = true;
245
                }
246
247 28
                $_constraints[$_name] = $_options;
248
            } else {
249 9
                $_constraints[$_rule[0]] = true;
250
            }
251
252 33
            unset($_constraints[$index]);
253
        }
254
255 33
        return $_constraints;
256
    }
257
258 69
    private function getConstraintsCast(array $constraints): array
259
    {
260 69
        foreach ($constraints as $name => $value) {
261 69
            if (\is_int($name)) {
262 7
                $constraints[$value] = true;
263 7
                unset($constraints[$name]);
264 64
            } elseif ($name === Rule::CHECK || $name === Rule::LENGTH) {
265 4
                $constraints['min' . $name] = (int)$value['min'];
266 4
                $constraints['max' . $name] = (int)$value['max'];
267 4
                unset($constraints[$name]);
268 60
            } elseif ($name === Rule::FOREIGNKEY && \is_string($value)) {
269 9
                $constraints[$name] = $this->getFkOptions($value);
270
            } else {
271 69
                $constraints[$name] = \is_numeric($value) ? (int)$value : $value;
272
            }
273
        }
274
275 69
        return $constraints;
276
    }
277
278 9
    private function getFkOptions(string $constraint): array
279
    {
280 9
        $_vars = \explode(',', $constraint);
281 9
        $fkName = 'name';
282 9
        $fkId = 'id';
283
284 9
        switch (\count($_vars)) {
285 9
            case 3:
286 3
                [$fkTable, $fkName, $fkId] = $_vars;
287
288 3
                break;
289 6
            case 2:
290 4
                [$fkTable, $fkName] = $_vars;
291
292 4
                break;
293
            default:
294 2
                [$fkTable] = $_vars;
295
296 2
                break;
297
        }
298
299
        return [
300 9
            'table' => $fkTable,
301 9
            'name' => $fkName,
302 9
            'id' => $fkId,
303
        ];
304
    }
305
}
306