Completed
Branch feature/pre-split (4f3c6e)
by Anton
03:29
created

MorphedTrait::verifyOuter()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 4
nop 2
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
8
namespace Spiral\ORM\Schemas\Relations\Traits;
9
10
use Spiral\Database\Schemas\Prototypes\AbstractColumn;
11
use Spiral\ORM\Exceptions\RelationSchemaException;
12
use Spiral\ORM\ORMInterface;
13
use Spiral\ORM\Record;
14
use Spiral\ORM\Schemas\Definitions\RelationDefinition;
15
use Spiral\ORM\Schemas\SchemaBuilder;
16
17
/**
18
 * Helps to locate all outer records matching given interface.
19
 */
20
trait MorphedTrait
21
{
22
    /**
23
     * Resolving outer key.
24
     *
25
     * @param \Spiral\ORM\Schemas\SchemaBuilder $builder
26
     *
27
     * @return \Spiral\Database\Schemas\Prototypes\AbstractColumn|null When no outer records found
28
     *                                                                 NULL will be returned.
29
     */
30
    protected function findOuter(SchemaBuilder $builder)
31
    {
32
        foreach ($this->findTargets($builder) as $schema) {
33
            $outerTable = $builder->requestTable($schema->getTable(), $schema->getDatabase());
34
            $outerKey = $this->option(Record::OUTER_KEY);
35
36
            if ($outerKey == ORMInterface::R_PRIMARY_KEY) {
37
                $outerKey = current($outerTable->getPrimaryKeys());
38
            }
39
40
            if (!$outerTable->hasColumn($outerKey)) {
41
                throw new RelationSchemaException(sprintf("Outer key '%s'.'%s' (%s) does not exists",
42
                    $outerTable->getName(),
43
                    $outerKey,
44
                    $this->getDefinition()->getName()
45
                ));
46
            }
47
48
            return $outerTable->column($outerKey);
49
        }
50
51
        return null;
52
    }
53
54
    /**
55
     * Make sure all tables have same outer key.
56
     *
57
     * @param \Spiral\ORM\Schemas\SchemaBuilder                  $builder
58
     * @param \Spiral\Database\Schemas\Prototypes\AbstractColumn $column
59
     *
60
     * @throws RelationSchemaException
61
     */
62
    protected function verifyOuter(SchemaBuilder $builder, AbstractColumn $column)
63
    {
64
        foreach ($this->findTargets($builder) as $schema) {
65
            $outerTable = $builder->requestTable($schema->getTable(), $schema->getDatabase());
66
67
            if (!$outerTable->hasColumn($column->getName())) {
68
                //Column is missing
69
                throw new RelationSchemaException(
70
                    "Unable to build morphed relation, outer key '{$column->getName()}' "
71
                    . "is missing in '{$outerTable->getName()}'"
72
                );
73
            }
74
75
            if ($outerTable->column($column->getName())->phpType() != $column->phpType()) {
76
                //Inconsistent type
77
                throw new RelationSchemaException(
78
                    "Unable to build morphed relation, outer key '{$column->getName()}' "
79
                    . "has different type in '{$outerTable->getName()}'"
80
                );
81
            }
82
        }
83
    }
84
85
    /**
86
     * Find all matched schemas.
87
     *
88
     * @param \Spiral\ORM\Schemas\SchemaBuilder $builder
89
     *
90
     * @return \Generator|\Spiral\ORM\Schemas\SchemaInterface[]
91
     */
92
    protected function findTargets(SchemaBuilder $builder): \Generator
93
    {
94
        foreach ($builder->getSchemas() as $schema) {
95
            if (!is_a($schema->getClass(), $this->getDefinition()->getTarget(), true)) {
96
                //Not our targets
97
                continue;
98
            }
99
            yield $schema;
100
        }
101
    }
102
103
    /**
104
     * @return \Spiral\ORM\Schemas\Definitions\RelationDefinition
105
     */
106
    abstract public function getDefinition(): RelationDefinition;
107
108
    /**
109
     * @param string $key
110
     *
111
     * @return mixed
112
     */
113
    abstract protected function option(string $key);
114
}