BelongsTo::inverseTargets()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\Schema\Relation;
6
7
use Cycle\ORM\Relation;
8
use Cycle\Schema\Definition\Entity;
9
use Cycle\Schema\Exception\RelationException;
10
use Cycle\Schema\InversableInterface;
11
use Cycle\Schema\Registry;
12
use Cycle\Schema\Relation\Traits\FieldTrait;
13
use Cycle\Schema\Relation\Traits\ForeignKeyTrait;
14
use Cycle\Schema\RelationInterface;
15
16
final class BelongsTo extends RelationSchema implements InversableInterface
17
{
18
    use FieldTrait;
19
    use ForeignKeyTrait;
20
21
    // internal relation type
22
    protected const RELATION_TYPE = Relation::BELONGS_TO;
23
24
    // relation schema options
25
    protected const RELATION_SCHEMA = [
26
        // save with parent
27
        Relation::CASCADE => true,
28
29
        // do not pre-load relation by default
30
        Relation::LOAD => Relation::LOAD_PROMISE,
31
32
        // nullable by default
33
        Relation::NULLABLE => false,
34
35
        // link to parent entity primary key by default
36
        Relation::INNER_KEY => '{relation}_{outerKey}',
37
38
        // default field name for inner key
39
        Relation::OUTER_KEY => '{target:primaryKey}',
40
41
        // rendering options
42
        RelationSchema::INDEX_CREATE => true,
43
        RelationSchema::FK_CREATE => true,
44
        RelationSchema::FK_ACTION => 'CASCADE',
45
        RelationSchema::FK_ON_DELETE => null,
46
    ];
47
48
    public function compute(Registry $registry): void
49
    {
50 176
        parent::compute($registry);
51
52 176
        $source = $registry->getEntity($this->source);
53
        $target = $registry->getEntity($this->target);
54 160
55 160
        $this->normalizeContextFields($source, $target);
56
57 160
        // create target outer field
58
        $this->createRelatedFields(
59
            $target,
60 160
            Relation::OUTER_KEY,
61
            $source,
62 160
            Relation::INNER_KEY,
63
        );
64 160
    }
65
66 152
    public function render(Registry $registry): void
67
    {
68
        $source = $registry->getEntity($this->source);
69
        $target = $registry->getEntity($this->target);
70
71 32
        $sourceTable = $registry->getTableSchema($source);
72
73 32
        $innerFields = $this->getFields($source, Relation::INNER_KEY);
74 32
        $outerFields = $this->getFields($target, Relation::OUTER_KEY);
75
76 32
        if ($this->options->get(self::INDEX_CREATE) && $innerFields->count() > 0) {
77
            $sourceTable->index($innerFields->getColumnNames());
78 32
        }
79 32
80
        if ($this->options->get(self::FK_CREATE)) {
81 32
            $this->createForeignCompositeKey(
82 32
                $registry,
83
                $target,
84
                $source,
85 32
                $outerFields,
86 16
                $innerFields,
87
                $this->options->get(self::INDEX_CREATE),
88 32
            );
89
        }
90
    }
91
92
    /**
93
     *
94
     * @return Entity[]
95 64
     */
96
    public function inverseTargets(Registry $registry): array
97
    {
98 64
        return [
99
            $registry->getEntity($this->target),
100
        ];
101
    }
102
103
    /**
104
     *
105
     * @throws RelationException
106
     *
107
     */
108
    public function inverseRelation(RelationInterface $relation, string $into, ?int $load = null): RelationInterface
109
    {
110
        if (!$relation instanceof HasOne && !$relation instanceof HasMany) {
111 48
            throw new RelationException('BelongsTo relation can only be inversed into HasOne or HasMany');
112
        }
113 48
114 16
        return $relation->withContext(
115
            $into,
116
            $this->target,
117 32
            $this->source,
118 32
            $this->options->withOptions([
119 32
                Relation::LOAD => $load,
120 32
                Relation::INNER_KEY => $this->options->get(Relation::OUTER_KEY),
121 32
                Relation::OUTER_KEY => $this->options->get(Relation::INNER_KEY),
122 32
            ]),
123 32
        );
124 32
    }
125
}
126