Passed
Push — master ( 9bffc1...46953a )
by Anton
01:43
created

AbstractSchema::getPrimary()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
namespace Cycle\Schema\Relation;
11
12
use Cycle\ORM\Relation;
13
use Cycle\Schema\Definition\Entity;
14
use Cycle\Schema\Exception\BuilderException;
15
use Cycle\Schema\Registry;
16
use Cycle\Schema\Relation\Util\OptionRouter;
17
use Cycle\Schema\RelationInterface;
18
19
abstract class AbstractSchema implements RelationInterface
20
{
21
    // exported relation type
22
    protected const RELATION_TYPE = null;
23
24
    // name of all required relation options
25
    protected const OPTION_SCHEMA = [];
26
27
    // todo: exportable schema
28
29
    /** @var string */
30
    protected $source;
31
32
    /** @var string */
33
    protected $target;
34
35
    /** @var OptionRouter */
36
    protected $options;
37
38
    /**
39
     * @inheritdoc
40
     */
41
    public function withContext(string $name, string $source, string $target, OptionRouter $options): RelationInterface
42
    {
43
        $relation = clone $this;
44
        $relation->source = $source;
45
        $relation->target = $target;
46
47
        $relation->options = $options->withTemplate(static::OPTION_SCHEMA)->withContext([
48
            'relation'    => $name,
49
            'source:role' => $source,
50
            'target:role' => $target
51
        ]);
52
53
        return $relation;
54
    }
55
56
    /**
57
     * @param Registry $registry
58
     */
59
    public function compute(Registry $registry)
60
    {
61
        $this->options = $this->options->withContext([
62
            'source:primaryKey' => $this->getPrimary($registry->getEntity($this->source))
63
        ]);
64
65
        if ($registry->hasRole($this->target)) {
66
            $this->options = $this->options->withContext([
67
                'target:primaryKey' => $this->getPrimary($registry->getEntity($this->target))
68
            ]);
69
        }
70
    }
71
72
    /**
73
     * @return array
74
     */
75
    public function packSchema(): array
76
    {
77
        return [
78
            Relation::TYPE   => static::RELATION_TYPE,
79
            Relation::TARGET => $this->target,
80
            Relation::SCHEMA => []
81
        ];
82
    }
83
84
    /**
85
     * @param Entity $entity
86
     * @return string
87
     *
88
     * @throws BuilderException
89
     */
90
    protected function getPrimary(Entity $entity): string
91
    {
92
        foreach ($entity->getFields() as $name => $field) {
93
            if ($field->isPrimary()) {
94
                return $name;
95
            }
96
        }
97
98
        throw new BuilderException("Entity `{$entity->getRole()}` must have defined primary key");
99
    }
100
}