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
Bug
introduced
by
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
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
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 |