Passed
Push — master ( ff3639...8a879c )
by Anton
01:54
created

BelongsToMorphed::inverseTargets()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Cycle\Schema\Relation\Morphed;
10
11
use Cycle\ORM\Relation;
12
use Cycle\Schema\Exception\RelationException;
13
use Cycle\Schema\InversableInterface;
14
use Cycle\Schema\Registry;
15
use Cycle\Schema\Relation\RelationSchema;
16
use Cycle\Schema\Relation\Traits\FieldTrait;
17
use Cycle\Schema\Relation\Traits\MorphTrait;
18
use Cycle\Schema\RelationInterface;
19
20
class BelongsToMorphed extends RelationSchema implements InversableInterface
21
{
22
    use FieldTrait, MorphTrait;
23
24
    // internal relation type
25
    protected const RELATION_TYPE = Relation::BELONGS_TO_MORPHED;
26
27
    // relation schema options
28
    protected const RELATION_SCHEMA = [
29
        // nullable by default
30
        Relation::NULLABLE               => true,
31
32
        // default field name for inner key
33
        Relation::OUTER_KEY              => '{target:primaryKey}',
34
35
        // link to parent entity primary key by default
36
        Relation::INNER_KEY              => '{relation}_{outerKey}',
37
38
        // link to parent entity primary key by default
39
        Relation::MORPH_KEY              => '{relation}_role',
40
41
        // rendering options
42
        RelationSchema::INDEX_CREATE     => true,
43
        RelationSchema::MORPH_KEY_LENGTH => 32
44
    ];
45
46
    /**
47
     * @param Registry $registry
48
     */
49
    public function compute(Registry $registry)
50
    {
51
        // compute local key
52
        $this->options = $this->options->withContext([
53
            'source:primaryKey' => $this->getPrimary($registry->getEntity($this->source))
54
        ]);
55
56
        $source = $registry->getEntity($this->source);
57
58
        list($outerKey, $outerField) = $this->findOuterKey($registry, $this->target);
59
60
        // register primary key reference
61
        $this->options = $this->options->withContext(['target:primaryKey' => $outerKey]);
62
63
        // create target outer field
64
        $this->ensureField(
65
            $source,
66
            $this->options->get(Relation::INNER_KEY),
67
            $outerField,
68
            $this->options->get(Relation::NULLABLE)
0 ignored issues
show
Bug introduced by
It seems like $this->options->get(Cycle\ORM\Relation::NULLABLE) can also be of type string; however, parameter $nullable of Cycle\Schema\Relation\Mo...oMorphed::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

68
            /** @scrutinizer ignore-type */ $this->options->get(Relation::NULLABLE)
Loading history...
69
        );
70
71
        $this->ensureMorphField(
72
            $source,
73
            $this->options->get(Relation::MORPH_KEY),
74
            $this->options->get(RelationSchema::MORPH_KEY_LENGTH),
0 ignored issues
show
Bug introduced by
It seems like $this->options->get(Cycl...hema::MORPH_KEY_LENGTH) can also be of type string; however, parameter $lenght of Cycle\Schema\Relation\Mo...hed::ensureMorphField() does only seem to accept integer, 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

74
            /** @scrutinizer ignore-type */ $this->options->get(RelationSchema::MORPH_KEY_LENGTH),
Loading history...
75
            $this->options->get(Relation::NULLABLE)
0 ignored issues
show
Bug introduced by
It seems like $this->options->get(Cycle\ORM\Relation::NULLABLE) can also be of type string; however, parameter $nullable of Cycle\Schema\Relation\Mo...hed::ensureMorphField() 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

75
            /** @scrutinizer ignore-type */ $this->options->get(Relation::NULLABLE)
Loading history...
76
        );
77
    }
78
79
    /**
80
     * @param Registry $registry
81
     */
82
    public function render(Registry $registry)
83
    {
84
        $source = $registry->getEntity($this->source);
85
86
        $innerField = $this->getField($source, Relation::INNER_KEY);
87
        $morphField = $this->getField($source, Relation::MORPH_KEY);
88
89
        $table = $registry->getTableSchema($source);
90
91
        if ($this->options->get(self::INDEX_CREATE)) {
92
            $table->index([$innerField->getColumn(), $morphField->getColumn()]);
93
        }
94
    }
95
96
    /**
97
     * @param Registry $registry
98
     * @return array
99
     */
100
    public function inverseTargets(Registry $registry): array
101
    {
102
        return iterator_to_array($this->findTargets($registry, $this->target));
103
    }
104
105
    /**
106
     * @param RelationInterface $relation
107
     * @param string            $into
108
     * @return RelationInterface
109
     *
110
     * @throws RelationException
111
     */
112
    public function inverseRelation(RelationInterface $relation, string $into): RelationInterface
113
    {
114
        if (!$relation instanceof MorphedHasOne && !$relation instanceof MorphedHasMany) {
115
            throw new RelationException(
116
                "BelongsToMorphed relation can only be inversed into MorphedHasOne or MorphedHasMany"
117
            );
118
        }
119
120
        return $relation->withContext(
121
            $into,
122
            $this->target,
123
            $this->source,
124
            $this->options->withOptions([
125
                Relation::INNER_KEY => $this->options->get(Relation::OUTER_KEY),
126
                Relation::OUTER_KEY => $this->options->get(Relation::INNER_KEY),
127
            ])
128
        );
129
    }
130
}