Completed
Push — develop ( 6b671f...4eb6c9 )
by Freddie
11:11
created

Schema::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 5
dl 0
loc 12
ccs 6
cts 6
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 Exception;
13
use FlexPHP\Schema\Constants\Keyword;
14
use FlexPHP\Schema\Exception\InvalidFileSchemaException;
15
use FlexPHP\Schema\Exception\InvalidSchemaException;
16
use Symfony\Component\Yaml\Exception\ParseException;
17
use Symfony\Component\Yaml\Yaml;
18
19
final class Schema implements SchemaInterface
20
{
21
    /**
22
     * @var string
23
     */
24
    private $name;
25
26
    /**
27
     * @var string
28
     */
29
    private $title;
30
31
    /**
32
     * @var array<int,SchemaAttributeInterface>
33
     */
34
    private $attributes;
35
36
    /**
37
     * @var null|string
38
     */
39
    private $icon;
40
41
    /**
42
     * @var string
43
     */
44
    private $language;
45
46 12
    public static function fromArray(array $schema): SchemaInterface
47
    {
48
        /** @var string $name */
49 12
        $name = \key($schema) ?? '';
50 12
        $title = $schema[$name][Keyword::TITLE] ?? '';
51 12
        $attributes = $schema[$name][Keyword::ATTRIBUTES] ?? [];
52 12
        $icon = $schema[$name][Keyword::ICON] ?? null;
53 12
        $language = $schema[$name][Keyword::LANGUAGE] ?? null;
54
55 12
        return new self($name, $title, $attributes, $icon, $language);
56
    }
57
58 3
    public static function fromFile(string $schemafile): SchemaInterface
59
    {
60
        try {
61 3
            $yaml = new Yaml();
62 3
            $schema = $yaml->parseFile($schemafile);
63 1
        } catch (ParseException $e) {
64 1
            throw new InvalidFileSchemaException();
65
        }
66
67 2
        return self::fromArray($schema);
68
    }
69
70 22
    public function __construct(
71
        string $name,
72
        string $title,
73
        array $attributes,
74
        ?string $icon = null,
75
        ?string $language = null
76
    ) {
77 22
        $this->setName($name);
78 15
        $this->setTitle($title);
79 10
        $this->setAttributes($attributes);
80 8
        $this->setIcon($icon);
81 8
        $this->setLanguage($language);
82 8
    }
83
84 11
    public function name(): string
85
    {
86 11
        return $this->name;
87
    }
88
89 4
    public function title(): string
90
    {
91 4
        return $this->title;
92
    }
93
94 4
    public function attributes(): array
95
    {
96 4
        return $this->attributes;
97
    }
98
99 2
    public function icon(): ?string
100
    {
101 2
        return $this->icon;
102
    }
103
104 2
    public function language(): string
105
    {
106 2
        return $this->language;
107
    }
108
109 4
    public function pkName(): string
110
    {
111 4
        $pkName = 'id';
112
113
        \array_filter($this->attributes(), function (SchemaAttributeInterface $property) use (&$pkName) {
114 4
            if ($property->isPk()) {
115 2
                $pkName = $property->name();
116
            }
117
118 4
            return true;
119 4
        });
120
121 4
        return $pkName;
122
    }
123
124 2
    public function pkTypeHint(): string
125
    {
126 2
        $pkTypeHint = 'string';
127
128
        \array_filter($this->attributes(), function (SchemaAttributeInterface $property) use (&$pkTypeHint) {
129 2
            if ($property->isPk()) {
130 2
                $pkTypeHint = $property->typeHint();
131
            }
132
133 2
            return true;
134 2
        });
135
136 2
        return $pkTypeHint;
137
    }
138
139 2
    public function fkRelations(): array
140
    {
141 2
        $fkRelations = \array_reduce(
142 2
            $this->attributes(),
143
            function (array $result, SchemaAttributeInterface $property): array {
144 2
                if ($property->isfk()) {
145 2
                    $result[$property->name()] = [
146 2
                        'pkTable' => $property->fkTable(),
147 2
                        'pkId' => $property->name(),
148 2
                        'pkDataType' => $property->dataType(),
149 2
                        'pkTypeHint' => $property->typeHint(),
150 2
                        'fkId' => $property->fkId(),
151 2
                        'fkName' => $property->fkName(),
152 2
                        'fkTable' => $this->name(),
153 2
                        'isBlameBy' => $property->isBlameBy(),
154 2
                        'isRequired' => $property->isRequired(),
155
                    ];
156
                }
157
158 2
                return $result;
159 2
            },
160 2
            []
161
        );
162
163 2
        return $fkRelations;
164
    }
165
166 22
    private function setName(string $name): void
167
    {
168 22
        if (empty(\trim($name))) {
169 4
            throw new InvalidSchemaException('Schema name is required');
170
        }
171
172 18
        if (\preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $name) === 0) {
173 3
            throw new InvalidSchemaException('Schema name only accept alphanum and underscore');
174
        }
175
176 15
        $this->name = $name;
177 15
    }
178
179 15
    private function setTitle(string $title): void
180
    {
181 15
        if (empty(\trim($title))) {
182 5
            throw new InvalidSchemaException(\sprintf('Schema %s:title is required', $this->name()));
183
        }
184
185 10
        $this->title = $title;
186 10
    }
187
188 10
    private function setAttributes(array $attributes): void
189
    {
190 10
        $schemaAttributes = [];
191
192 10
        foreach ($attributes as $attribute) {
193 7
            if ($attribute instanceof SchemaAttributeInterface) {
194 2
                $schemaAttributes[] = $attribute;
195
196 2
                continue;
197
            }
198
199 5
            $name = $attribute[Keyword::NAME] ?? '';
200 5
            $dataType = $attribute[Keyword::DATATYPE] ?? '';
201 5
            $constraints = $attribute[Keyword::CONSTRAINTS] ?? '';
202
203
            try {
204 5
                $schemaAttributes[] = new SchemaAttribute($name, $dataType, $constraints);
205 2
            } catch (Exception $e) {
206 2
                throw new InvalidSchemaException(
207 5
                    \sprintf('Schema %s > %s', $this->name(), $e->getMessage())
208
                );
209
            }
210
        }
211
212 8
        $this->attributes = $schemaAttributes;
213 8
    }
214
215 8
    private function setIcon(?string $icon): void
216
    {
217 8
        $this->icon = $icon;
218 8
    }
219
220 8
    private function setLanguage(?string $language): void
221
    {
222 8
        if (empty($language)) {
223 8
            $language = 'en';
224
        }
225
226 8
        $this->language = $language;
227 8
    }
228
}
229