Passed
Push — master ( 384538...4f7dc7 )
by Anton
02:27
created

src/Relation/BelongsTo.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * Cycle ORM Schema Builder.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
declare(strict_types=1);
9
10
namespace Cycle\Schema\Relation;
11
12
use Cycle\ORM\Relation;
13
use Cycle\Schema\Exception\RelationException;
14
use Cycle\Schema\InversableInterface;
15
use Cycle\Schema\Registry;
16
use Cycle\Schema\Relation\Traits\FieldTrait;
17
use Cycle\Schema\Relation\Traits\ForeignKeyTrait;
18
use Cycle\Schema\RelationInterface;
19
20
final class BelongsTo extends RelationSchema implements InversableInterface
21
{
22
    use FieldTrait, ForeignKeyTrait;
23
24
    // internal relation type
25
    protected const RELATION_TYPE = Relation::BELONGS_TO;
26
27
    // relation schema options
28
    protected const RELATION_SCHEMA = [
29
        // save with parent
30
        Relation::CASCADE            => true,
31
32
        // nullable by default
33
        Relation::NULLABLE           => true,
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
    ];
46
47
    /**
48
     * @param Registry $registry
49
     */
50
    public function compute(Registry $registry)
51
    {
52
        parent::compute($registry);
53
54
        $source = $registry->getEntity($this->source);
55
        $target = $registry->getEntity($this->target);
56
57
        // create target outer field
58
        $this->ensureField(
59
            $source,
60
            $this->options->get(Relation::INNER_KEY),
61
            $this->getField($target, Relation::OUTER_KEY),
62
            $this->options->get(Relation::NULLABLE)
0 ignored issues
show
It seems like $this->options->get(Cycle\ORM\Relation::NULLABLE) can also be of type string; however, parameter $nullable of Cycle\Schema\Relation\BelongsTo::ensureField() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
            /** @scrutinizer ignore-type */ $this->options->get(Relation::NULLABLE)
Loading history...
63
        );
64
    }
65
66
    /**
67
     * @param Registry $registry
68
     */
69
    public function render(Registry $registry)
70
    {
71
        $source = $registry->getEntity($this->source);
72
        $target = $registry->getEntity($this->target);
73
74
        $innerField = $this->getField($source, Relation::INNER_KEY);
75
        $outerField = $this->getField($target, Relation::OUTER_KEY);
76
77
        $table = $registry->getTableSchema($source);
78
79
        if ($this->options->get(self::INDEX_CREATE)) {
80
            $table->index([$innerField->getColumn()]);
81
        }
82
83
        if ($this->options->get(self::FK_CREATE)) {
84
            $this->createForeignKey($registry, $target, $source, $outerField, $innerField);
85
        }
86
    }
87
88
    /**
89
     * @param Registry $registry
90
     * @return array
91
     */
92
    public function inverseTargets(Registry $registry): array
93
    {
94
        return [
95
            $registry->getEntity($this->target)
96
        ];
97
    }
98
99
    /**
100
     * @param RelationInterface $relation
101
     * @param string            $into
102
     * @return RelationInterface
103
     *
104
     * @throws RelationException
105
     */
106
    public function inverseRelation(RelationInterface $relation, string $into): RelationInterface
107
    {
108
        if (!$relation instanceof HasOne && !$relation instanceof HasMany) {
109
            throw new RelationException("BelongsTo relation can only be inversed into HasOne or HasMany");
110
        }
111
112
        return $relation->withContext(
113
            $into,
114
            $this->target,
115
            $this->source,
116
            $this->options->withOptions([
117
                Relation::INNER_KEY => $this->options->get(Relation::OUTER_KEY),
118
                Relation::OUTER_KEY => $this->options->get(Relation::INNER_KEY),
119
            ])
120
        );
121
    }
122
}