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 | // do not pre-load relation by default |
||||
34 | Relation::LOAD => null, |
||||
35 | |||||
36 | // nullable by default |
||||
37 | Relation::NULLABLE => true, |
||||
38 | |||||
39 | // default field name for inner key |
||||
40 | Relation::OUTER_KEY => '{target:primaryKey}', |
||||
41 | |||||
42 | // link to parent entity primary key by default |
||||
43 | Relation::INNER_KEY => '{relation}_{outerKey}', |
||||
44 | |||||
45 | // link to parent entity primary key by default |
||||
46 | Relation::MORPH_KEY => '{relation}_role', |
||||
47 | |||||
48 | // rendering options |
||||
49 | RelationSchema::INDEX_CREATE => true, |
||||
50 | RelationSchema::MORPH_KEY_LENGTH => 32 |
||||
51 | ]; |
||||
52 | |||||
53 | /** |
||||
54 | * @param Registry $registry |
||||
55 | */ |
||||
56 | public function compute(Registry $registry) |
||||
57 | { |
||||
58 | // compute local key |
||||
59 | $this->options = $this->options->withContext([ |
||||
60 | 'source:primaryKey' => $this->getPrimary($registry->getEntity($this->source)) |
||||
61 | ]); |
||||
62 | |||||
63 | $source = $registry->getEntity($this->source); |
||||
64 | |||||
65 | list($outerKey, $outerField) = $this->findOuterKey($registry, $this->target); |
||||
66 | |||||
67 | // register primary key reference |
||||
68 | $this->options = $this->options->withContext(['target:primaryKey' => $outerKey]); |
||||
69 | |||||
70 | // create target outer field |
||||
71 | $this->ensureField( |
||||
72 | $source, |
||||
73 | $this->options->get(Relation::INNER_KEY), |
||||
74 | $outerField, |
||||
75 | $this->options->get(Relation::NULLABLE) |
||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
76 | ); |
||||
77 | |||||
78 | $this->ensureMorphField( |
||||
79 | $source, |
||||
80 | $this->options->get(Relation::MORPH_KEY), |
||||
81 | $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
Loading history...
|
|||||
82 | $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
Loading history...
|
|||||
83 | ); |
||||
84 | } |
||||
85 | |||||
86 | /** |
||||
87 | * @param Registry $registry |
||||
88 | */ |
||||
89 | public function render(Registry $registry) |
||||
90 | { |
||||
91 | $source = $registry->getEntity($this->source); |
||||
92 | |||||
93 | $innerField = $this->getField($source, Relation::INNER_KEY); |
||||
94 | $morphField = $this->getField($source, Relation::MORPH_KEY); |
||||
95 | |||||
96 | $table = $registry->getTableSchema($source); |
||||
97 | |||||
98 | if ($this->options->get(self::INDEX_CREATE)) { |
||||
99 | $table->index([$innerField->getColumn(), $morphField->getColumn()]); |
||||
100 | } |
||||
101 | } |
||||
102 | |||||
103 | /** |
||||
104 | * @param Registry $registry |
||||
105 | * @return array |
||||
106 | */ |
||||
107 | public function inverseTargets(Registry $registry): array |
||||
108 | { |
||||
109 | return iterator_to_array($this->findTargets($registry, $this->target)); |
||||
110 | } |
||||
111 | |||||
112 | /** |
||||
113 | * @param RelationInterface $relation |
||||
114 | * @param string $into |
||||
115 | * @param int|null $load |
||||
116 | * @return RelationInterface |
||||
117 | * |
||||
118 | * @throws RelationException |
||||
119 | */ |
||||
120 | public function inverseRelation(RelationInterface $relation, string $into, ?int $load = null): RelationInterface |
||||
121 | { |
||||
122 | if (!$relation instanceof MorphedHasOne && !$relation instanceof MorphedHasMany) { |
||||
123 | throw new RelationException( |
||||
124 | "BelongsToMorphed relation can only be inversed into MorphedHasOne or MorphedHasMany" |
||||
125 | ); |
||||
126 | } |
||||
127 | |||||
128 | return $relation->withContext( |
||||
129 | $into, |
||||
130 | $this->target, |
||||
131 | $this->source, |
||||
132 | $this->options->withOptions([ |
||||
133 | Relation::LOAD => $load, |
||||
134 | Relation::INNER_KEY => $this->options->get(Relation::OUTER_KEY), |
||||
135 | Relation::OUTER_KEY => $this->options->get(Relation::INNER_KEY), |
||||
136 | ]) |
||||
137 | ); |
||||
138 | } |
||||
139 | } |
||||
140 |