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

src/Relation/Morphed/BelongsToMorphed.php (3 issues)

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\Morphed;
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\RelationSchema;
17
use Cycle\Schema\Relation\Traits\FieldTrait;
18
use Cycle\Schema\Relation\Traits\MorphTrait;
19
use Cycle\Schema\RelationInterface;
20
21
class BelongsToMorphed extends RelationSchema implements InversableInterface
22
{
23
    use FieldTrait, MorphTrait;
24
25
    // internal relation type
26
    protected const RELATION_TYPE = Relation::BELONGS_TO_MORPHED;
27
28
    // relation schema options
29
    protected const RELATION_SCHEMA = [
30
        // save with parent
31
        Relation::CASCADE                => true,
32
33
        // nullable by default
34
        Relation::NULLABLE               => true,
35
36
        // default field name for inner key
37
        Relation::OUTER_KEY              => '{target:primaryKey}',
38
39
        // link to parent entity primary key by default
40
        Relation::INNER_KEY              => '{relation}_{outerKey}',
41
42
        // link to parent entity primary key by default
43
        Relation::MORPH_KEY              => '{relation}_role',
44
45
        // rendering options
46
        RelationSchema::INDEX_CREATE     => true,
47
        RelationSchema::MORPH_KEY_LENGTH => 32
48
    ];
49
50
    /**
51
     * @param Registry $registry
52
     */
53
    public function compute(Registry $registry)
54
    {
55
        // compute local key
56
        $this->options = $this->options->withContext([
57
            'source:primaryKey' => $this->getPrimary($registry->getEntity($this->source))
58
        ]);
59
60
        $source = $registry->getEntity($this->source);
61
62
        list($outerKey, $outerField) = $this->findOuterKey($registry, $this->target);
63
64
        // register primary key reference
65
        $this->options = $this->options->withContext(['target:primaryKey' => $outerKey]);
66
67
        // create target outer field
68
        $this->ensureField(
69
            $source,
70
            $this->options->get(Relation::INNER_KEY),
71
            $outerField,
72
            $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\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

72
            /** @scrutinizer ignore-type */ $this->options->get(Relation::NULLABLE)
Loading history...
73
        );
74
75
        $this->ensureMorphField(
76
            $source,
77
            $this->options->get(Relation::MORPH_KEY),
78
            $this->options->get(RelationSchema::MORPH_KEY_LENGTH),
0 ignored issues
show
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

78
            /** @scrutinizer ignore-type */ $this->options->get(RelationSchema::MORPH_KEY_LENGTH),
Loading history...
79
            $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\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

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