Completed
Push — develop ( 1a3273...1f2dbe )
by Freddie
05:42
created

SchemaAttribute::isFk()   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
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
crap 1
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 60
    public function __construct(string $name, string $dataType, $constraints = null)
37
    {
38 60
        $this->setName($name);
39 60
        $this->setDataType($dataType);
40 60
        $this->setConstraints($constraints);
41
42 60
        $this->validate();
43 57
    }
44
45 60
    public function name(): string
46
    {
47 60
        return $this->name;
48
    }
49
50 60
    public function dataType(): string
51
    {
52 60
        return $this->dataType;
53
    }
54
55 60
    public function constraints(): array
56
    {
57 60
        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] ?? null);
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 8
    public function isFk(): bool
106
    {
107 8
        return (bool)($this->constraints[Rule::FK] ?? null);
108
    }
109
110 8
    public function fkTable(): ?string
111
    {
112 8
        return $this->constraints[Rule::FK]['table'] ?? null;
113
    }
114
115 8
    public function fkId(): ?string
116
    {
117 8
        return $this->constraints[Rule::FK]['id'] ?? null;
118
    }
119
120 8
    public function fkName(): ?string
121
    {
122 8
        return $this->constraints[Rule::FK]['name'] ?? null;
123
    }
124
125 60
    public function properties(): array
126
    {
127
        return [
128 60
            Keyword::NAME => $this->name(),
129 60
            Keyword::DATATYPE => $this->dataType(),
130 60
            Keyword::CONSTRAINTS => $this->constraints(),
131
        ];
132
    }
133
134 60
    private function validate(): void
135
    {
136 60
        (new SchemaAttributeValidation($this->properties()))->validate();
137 57
    }
138
139 60
    private function setName(string $name): void
140
    {
141 60
        $this->name = $name;
142 60
    }
143
144 60
    private function setDataType(string $dataType): void
145
    {
146 60
        $this->dataType = $dataType;
147 60
    }
148
149
    /**
150
     * @param mixed $constraints
151
     */
152 60
    private function setConstraints($constraints): void
153
    {
154 60
        if (!empty($constraints)) {
155 45
            if (\is_string($constraints)) {
156 21
                $this->setConstraintsFromString($constraints);
157
            } else {
158 24
                $this->setConstraintsFromArray($constraints);
159
            }
160
        }
161 60
    }
162
163 21
    private function setConstraintsFromString(string $constraints): void
164
    {
165 21
        $this->setConstraintsFromArray($this->getConstraintsFromString($constraints));
166 21
    }
167
168 45
    private function setConstraintsFromArray(array $constraints): void
169
    {
170 45
        $this->constraints = $this->getConstraintsCast($constraints);
171 45
    }
172
173 21
    private function getConstraintsFromString(string $constraints): array
174
    {
175 21
        $_constraints = \explode('|', $constraints);
176
177
        /** @var mixed $_constraint */
178 21
        foreach ($_constraints as $index => $_constraint) {
179 21
            $_rule = \explode(':', $_constraint);
180
181 21
            if (\count($_rule) === 2) {
182 20
                [$_name, $_options] = $_rule;
183
184 20
                if (Rule::FK === $_name) { // Fk
185 5
                    $_options = $this->getFkOptions($_options);
186 17
                } elseif (\strpos($_options, ',') !== false) { // Range
187 2
                    [$min, $max] = \explode(',', $_options);
188 2
                    $_options = \compact('min', 'max');
189 15
                } elseif (\preg_match('/^false$/i', $_options)) { // False as string
190 4
                    $_options = false;
191 14
                } elseif (\preg_match('/^true$/i', $_options)) { // True as string
192 5
                    $_options = true;
193
                }
194
195 20
                $_constraints[$_name] = $_options;
196
            } else {
197 5
                $_constraints[$_rule[0]] = true;
198
            }
199
200 21
            unset($_constraints[$index]);
201
        }
202
203 21
        return $_constraints;
204
    }
205
206 45
    private function getConstraintsCast(array $constraints): array
207
    {
208 45
        foreach ($constraints as $name => $value) {
209 45
            if (\is_int($name)) {
210 3
                $constraints[$value] = true;
211 3
                unset($constraints[$name]);
212 44
            } elseif ($name === Rule::CHECK || $name === Rule::LENGTH) {
213 4
                $constraints['min' . $name] = (int)$value['min'];
214 4
                $constraints['max' . $name] = (int)$value['max'];
215 4
                unset($constraints[$name]);
216 40
            } elseif ($name === Rule::FK && \is_string($value)) {
217 4
                $constraints[$name] = $this->getFkOptions($value);
218
            } else {
219 45
                $constraints[$name] = \is_numeric($value) ? (int)$value : $value;
220
            }
221
        }
222
223 45
        return $constraints;
224
    }
225
226 9
    private function getFkOptions(string $constraint)
227
    {
228 9
        $_vars = \explode(',', $constraint);
229 9
        $name = 'name';
230 9
        $id = 'id';
231
232 9
        switch (\count($_vars)) {
233 9
            case 3:
234 3
                [$table, $name, $id] = $_vars;
235
236 3
                break;
237 6
            case 2:
238 4
                [$table, $name] = $_vars;
239
240 4
                break;
241
            default:
242 2
                [$table] = $_vars;
243
244 2
                break;
245
        }
246
247 9
        return \compact('table', 'name', 'id');
248
    }
249
}
250