Completed
Push — master ( 288a8b...65c32c )
by Neomerx
03:40
created

ModelSchemaInfo::getRawAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php namespace Limoncello\Application\Data;
2
3
/**
4
 * Copyright 2015-2018 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use InvalidArgumentException;
20
use Limoncello\Contracts\Data\ModelSchemaInfoInterface;
21
use Limoncello\Contracts\Data\RelationshipTypes;
22
23
/**
24
 * @package Limoncello\Application
25
 */
26
class ModelSchemaInfo implements ModelSchemaInfoInterface
27
{
28
    /**
29
     * @var array
30
     */
31
    private $relationshipTypes = [];
32
33
    /**
34
     * @var array
35
     */
36
    private $reversedRelationships = [];
37
38
    /**
39
     * @var array
40
     */
41
    private $reversedClasses = [];
42
43
    /**
44
     * @var array
45
     */
46
    private $foreignKeys = [];
47
48
    /**
49
     * @var array
50
     */
51
    private $belongsToMany = [];
52
53
    /**
54
     * @var array
55
     */
56
    private $tableNames = [];
57
58
    /**
59
     * @var array
60
     */
61
    private $primaryKeys = [];
62
63
    /**
64
     * @var array
65
     */
66
    private $attributeTypes = [];
67
68
    /**
69
     * @var array
70
     */
71
    private $attributeLengths = [];
72
73
    /**
74
     * @var array
75
     */
76
    private $attributes = [];
77
78
    /**
79
     * @var array
80
     */
81
    private $rawAttributes = [];
82
83
    /**
84
     * @return array
85
     */
86 8
    public function getData(): array
87
    {
88
        $result = [
89 8
            $this->foreignKeys,
90 8
            $this->belongsToMany,
91 8
            $this->relationshipTypes,
92 8
            $this->reversedRelationships,
93 8
            $this->tableNames,
94 8
            $this->primaryKeys,
95 8
            $this->attributeTypes,
96 8
            $this->attributeLengths,
97 8
            $this->attributes,
98 8
            $this->rawAttributes,
99 8
            $this->reversedClasses,
100
        ];
101
102 8
        return $result;
103
    }
104
105
    /**
106
     * @param array $data
107
     *
108
     * @return self
109
     */
110 7
    public function setData(array $data): self
111
    {
112 7
        list($this->foreignKeys, $this->belongsToMany, $this->relationshipTypes,
113 7
            $this->reversedRelationships,$this->tableNames, $this->primaryKeys,
114 7
            $this->attributeTypes, $this->attributeLengths, $this->attributes, $this->rawAttributes,
115 7
            $this->reversedClasses) = $data;
116
117 7
        return $this;
118
    }
119
120
    /** @noinspection PhpTooManyParametersInspection
121
     * @inheritdoc
122
     */
123 8
    public function registerClass(
124
        string $class,
125
        string $tableName,
126
        string $primaryKey,
127
        array $attributeTypes,
128
        array $attributeLengths,
129
        array $rawAttributes = []
130
    ): ModelSchemaInfoInterface {
131 8
        if (empty($class) === true) {
132 1
            throw new InvalidArgumentException('class');
133
        }
134
135 8
        if (empty($tableName) === true) {
136 1
            throw new InvalidArgumentException('tableName');
137
        }
138
139 8
        if (empty($primaryKey) === true) {
140 1
            throw new InvalidArgumentException('primaryKey');
141
        }
142
143 8
        $this->tableNames[$class]       = $tableName;
144 8
        $this->primaryKeys[$class]      = $primaryKey;
145 8
        $this->attributeTypes[$class]   = $attributeTypes;
146 8
        $this->attributeLengths[$class] = $attributeLengths;
147 8
        $this->attributes[$class]       = array_keys($attributeTypes);
148 8
        $this->rawAttributes[$class]    = $rawAttributes;
149
150 8
        return $this;
151
    }
152
153
    /**
154
     * @inheritdoc
155
     */
156 1
    public function hasClass(string $class): bool
157
    {
158 1
        $result = array_key_exists($class, $this->tableNames);
159
160 1
        return $result;
161
    }
162
163
    /**
164
     * @inheritdoc
165
     */
166 2
    public function getTable(string $class): string
167
    {
168 2
        $result = $this->tableNames[$class];
169
170 2
        return $result;
171
    }
172
173
    /**
174
     * @inheritdoc
175
     */
176 2
    public function getPrimaryKey(string $class): string
177
    {
178 2
        $result = $this->primaryKeys[$class];
179
180 2
        return $result;
181
    }
182
183
    /**
184
     * @inheritdoc
185
     */
186 1
    public function getAttributeTypes(string $class): array
187
    {
188 1
        $result = $this->attributeTypes[$class];
189
190 1
        return $result;
191
    }
192
193
    /**
194
     * @inheritdoc
195
     */
196 1
    public function getAttributeType(string $class, string $name): string
197
    {
198 1
        $result = $this->attributeTypes[$class][$name];
199
200 1
        return $result;
201
    }
202
203
    /**
204
     * @inheritdoc
205
     */
206 1
    public function hasAttributeType(string $class, string $name): bool
207
    {
208 1
        $result = isset($this->attributeTypes[$class][$name]);
209
210 1
        return $result;
211
    }
212
213
    /**
214
     * @inheritdoc
215
     */
216 1
    public function getAttributeLengths(string $class): array
217
    {
218 1
        $result = $this->attributeLengths[$class];
219
220 1
        return $result;
221
    }
222
223
    /**
224
     * @inheritdoc
225
     */
226 1
    public function hasAttributeLength(string $class, string $name): bool
227
    {
228 1
        $result = isset($this->attributeLengths[$class][$name]);
229
230 1
        return $result;
231
    }
232
233
    /**
234
     * @inheritdoc
235
     */
236 1 View Code Duplication
    public function getAttributeLength(string $class, string $name): int
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
    {
238 1
        assert(
239 1
            $this->hasAttributeLength($class, $name) === true,
240 1
            "Length not found for column `$name` in class `$class`."
241
        );
242
243 1
        $result = $this->attributeLengths[$class][$name];
244
245 1
        return $result;
246
    }
247
248
    /**
249
     * @inheritdoc
250
     */
251 1
    public function getAttributes(string $class): array
252
    {
253 1
        $result = $this->attributes[$class];
254
255 1
        return $result;
256
    }
257
258
    /**
259
     * @inheritdoc
260
     */
261 1
    public function getRawAttributes(string $class): array
262
    {
263 1
        $result = $this->rawAttributes[$class];
264
265 1
        return $result;
266
    }
267
268
    /**
269
     * @inheritdoc
270
     */
271 2
    public function hasRelationship(string $class, string $name): bool
272
    {
273 2
        $result = isset($this->relationshipTypes[$class][$name]);
274
275 2
        return $result;
276
    }
277
278
    /**
279
     * @inheritdoc
280
     */
281 2 View Code Duplication
    public function getRelationshipType(string $class, string $name): int
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
282
    {
283 2
        assert(
284 2
            $this->hasRelationship($class, $name) === true,
285 2
            "Relationship `$name` not found in class `$class`."
286
        );
287
288 2
        $result = $this->relationshipTypes[$class][$name];
289
290 2
        return $result;
291
    }
292
293
    /**
294
     * @inheritdoc
295
     */
296 2
    public function getReverseRelationship(string $class, string $name): array
297
    {
298 2
        $result = $this->reversedRelationships[$class][$name];
299
300 2
        return $result;
301
    }
302
303
    /**
304
     * @inheritdoc
305
     */
306 1 View Code Duplication
    public function getReversePrimaryKey(string $class, string $name): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
    {
308 1
        $reverseClass = $this->getReverseModelClass($class, $name);
309
310 1
        $table = $this->getTable($reverseClass);
311 1
        $key   = $this->getPrimaryKey($reverseClass);
312
313 1
        return [$key, $table];
314
    }
315
316
    /**
317
     * @inheritdoc
318
     */
319 1 View Code Duplication
    public function getReverseForeignKey(string $class, string $name): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
320
    {
321 1
        list ($reverseClass, $reverseName) = $this->getReverseRelationship($class, $name);
322
323 1
        $table = $this->getTable($reverseClass);
324
        // would work only if $name is hasMany relationship
325 1
        $key   = $this->getForeignKey($reverseClass, $reverseName);
326
327 1
        return [$key, $table];
328
    }
329
330
    /**
331
     * @inheritdoc
332
     */
333 1
    public function getReverseModelClass(string $class, string $name): string
334
    {
335 1
        $reverseClass = $this->reversedClasses[$class][$name];
336
337 1
        return $reverseClass;
338
    }
339
340
    /**
341
     * @inheritdoc
342
     */
343 1
    public function getForeignKey(string $class, string $name): string
344
    {
345 1
        $result = $this->foreignKeys[$class][$name];
346
347 1
        return $result;
348
    }
349
350
    /**
351
     * @inheritdoc
352
     */
353 1
    public function getBelongsToManyRelationship(string $class, string $name): array
354
    {
355 1
        $result = $this->belongsToMany[$class][$name];
356
357 1
        return $result;
358
    }
359
360
    /**
361
     * @inheritdoc
362
     */
363 8
    public function registerBelongsToOneRelationship(
364
        string $class,
365
        string $name,
366
        string $foreignKey,
367
        string $reverseClass,
368
        string $reverseName
369
    ): ModelSchemaInfoInterface {
370 8
        $this->registerRelationshipType(RelationshipTypes::BELONGS_TO, $class, $name);
371 8
        $this->registerRelationshipType(RelationshipTypes::HAS_MANY, $reverseClass, $reverseName);
372
373 8
        $this->registerReversedRelationship($class, $name, $reverseClass, $reverseName);
374 8
        $this->registerReversedRelationship($reverseClass, $reverseName, $class, $name);
375
376 8
        $this->foreignKeys[$class][$name] = $foreignKey;
377
378 8
        return $this;
379
    }
380
381
    /** @noinspection PhpTooManyParametersInspection
382
     * @inheritdoc
383
     */
384 8
    public function registerBelongsToManyRelationship(
385
        string $class,
386
        string $name,
387
        string $table,
388
        string $foreignKey,
389
        string $reverseForeignKey,
390
        string $reverseClass,
391
        string $reverseName
392
    ): ModelSchemaInfoInterface {
393 8
        $this->registerRelationshipType(RelationshipTypes::BELONGS_TO_MANY, $class, $name);
394 8
        $this->registerRelationshipType(RelationshipTypes::BELONGS_TO_MANY, $reverseClass, $reverseName);
395
396
        // NOTE:
397
        // `registerReversedRelationship` relies on duplicate registration check in `registerRelationshipType`
398
        // so it must be called afterwards
399 8
        $this->registerReversedRelationship($class, $name, $reverseClass, $reverseName);
400 8
        $this->registerReversedRelationship($reverseClass, $reverseName, $class, $name);
401
402 8
        $this->belongsToMany[$class][$name]               = [$table, $foreignKey, $reverseForeignKey];
403 8
        $this->belongsToMany[$reverseClass][$reverseName] = [$table, $reverseForeignKey, $foreignKey];
404
405 8
        return $this;
406
    }
407
408
    /**
409
     * @param int    $type
410
     * @param string $class
411
     * @param string $name
412
     *
413
     * @return void
414
     */
415 8
    private function registerRelationshipType(int $type, string $class, string $name): void
416
    {
417 8
        assert(empty($class) === false && empty($name) === false);
418 8
        assert(
419 8
            isset($this->relationshipTypes[$class][$name]) === false,
420 8
            "Relationship `$name` for class `$class` was already used."
421
        );
422
423 8
        $this->relationshipTypes[$class][$name] = $type;
424
    }
425
426
    /**
427
     * @param string $class
428
     * @param string $name
429
     * @param string $reverseClass
430
     * @param string $reverseName
431
     *
432
     * @return void
433
     */
434 8
    private function registerReversedRelationship(
435
        string $class,
436
        string $name,
437
        string $reverseClass,
438
        string $reverseName
439
    ): void {
440 8
        assert(
441 8
            empty($class) === false &&
442 8
            empty($name) === false &&
443 8
            empty($reverseClass) === false &&
444 8
            empty($reverseName) === false
445
        );
446
447
        // NOTE:
448
        // this function relies it would be called after
449
        // `registerRelationshipType` which prevents duplicate registrations
450
451 8
        $this->reversedRelationships[$class][$name] = [$reverseClass, $reverseName];
452 8
        $this->reversedClasses[$class][$name]       = $reverseClass;
453
    }
454
}
455