1 | <?php |
||||
2 | |||||
3 | namespace Staudenmeir\EloquentHasManyDeep; |
||||
4 | |||||
5 | use Illuminate\Database\Eloquent\Builder; |
||||
6 | use Illuminate\Database\Eloquent\Model; |
||||
7 | use Illuminate\Database\Eloquent\Relations\Pivot; |
||||
8 | use Staudenmeir\EloquentHasManyDeep\Eloquent\Traits\ConcatenatesRelationships; |
||||
9 | use Staudenmeir\EloquentHasManyDeep\Eloquent\Traits\ReversesRelationships; |
||||
10 | |||||
11 | trait HasRelationships |
||||
12 | { |
||||
13 | use ConcatenatesRelationships; |
||||
14 | use ReversesRelationships; |
||||
15 | |||||
16 | /** |
||||
17 | * Define a has-many-deep relationship. |
||||
18 | * |
||||
19 | * @param string $related |
||||
20 | * @param array $through |
||||
21 | * @param array $foreignKeys |
||||
22 | * @param array $localKeys |
||||
23 | * @return \Staudenmeir\EloquentHasManyDeep\HasManyDeep |
||||
24 | */ |
||||
25 | public function hasManyDeep($related, array $through, array $foreignKeys = [], array $localKeys = []) |
||||
26 | { |
||||
27 | return $this->newHasManyDeep(...$this->hasOneOrManyDeep($related, $through, $foreignKeys, $localKeys)); |
||||
28 | } |
||||
29 | |||||
30 | /** |
||||
31 | * Define a has-one-deep relationship. |
||||
32 | * |
||||
33 | * @param string $related |
||||
34 | * @param array $through |
||||
35 | * @param array $foreignKeys |
||||
36 | * @param array $localKeys |
||||
37 | * @return \Staudenmeir\EloquentHasManyDeep\HasOneDeep |
||||
38 | */ |
||||
39 | public function hasOneDeep($related, array $through, array $foreignKeys = [], array $localKeys = []) |
||||
40 | { |
||||
41 | return $this->newHasOneDeep(...$this->hasOneOrManyDeep($related, $through, $foreignKeys, $localKeys)); |
||||
42 | } |
||||
43 | |||||
44 | /** |
||||
45 | * Prepare a has-one-deep or has-many-deep relationship. |
||||
46 | * |
||||
47 | * @param string $related |
||||
48 | * @param array $through |
||||
49 | * @param array $foreignKeys |
||||
50 | * @param array $localKeys |
||||
51 | * @return array |
||||
52 | */ |
||||
53 | protected function hasOneOrManyDeep($related, array $through, array $foreignKeys, array $localKeys) |
||||
54 | { |
||||
55 | $relatedSegments = preg_split('/\s+from\s+/i', $related); |
||||
56 | |||||
57 | /** @var \Illuminate\Database\Eloquent\Model $relatedInstance */ |
||||
58 | $relatedInstance = $this->newRelatedInstance($relatedSegments[0]); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
59 | |||||
60 | if (isset($relatedSegments[1])) { |
||||
61 | $relatedInstance->setTable($relatedSegments[1]); |
||||
62 | } |
||||
63 | |||||
64 | $throughParents = $this->hasOneOrManyDeepThroughParents($through); |
||||
65 | |||||
66 | $foreignKeys = $this->hasOneOrManyDeepForeignKeys($relatedInstance, $throughParents, $foreignKeys); |
||||
67 | |||||
68 | $localKeys = $this->hasOneOrManyDeepLocalKeys($relatedInstance, $throughParents, $localKeys); |
||||
69 | |||||
70 | return [$relatedInstance->newQuery(), $this, $throughParents, $foreignKeys, $localKeys]; |
||||
71 | } |
||||
72 | |||||
73 | /** |
||||
74 | * Prepare the through parents for a has-one-deep or has-many-deep relationship. |
||||
75 | * |
||||
76 | * @param array $through |
||||
77 | * @return array |
||||
78 | */ |
||||
79 | protected function hasOneOrManyDeepThroughParents(array $through) |
||||
80 | { |
||||
81 | return array_map(function ($class) { |
||||
82 | $segments = preg_split('/\s+(as|from)\s+/i', $class, -1, PREG_SPLIT_DELIM_CAPTURE); |
||||
83 | |||||
84 | $instance = $this->newRelatedDeepThroughInstance($segments[0]); |
||||
85 | |||||
86 | if (isset($segments[1])) { |
||||
87 | $instance->setTable( |
||||
88 | $segments[1] === 'as' |
||||
89 | ? $instance->getTable().' as '.$segments[2] |
||||
90 | : $segments[2] |
||||
91 | ); |
||||
92 | } |
||||
93 | |||||
94 | return $instance; |
||||
95 | }, $through); |
||||
96 | } |
||||
97 | |||||
98 | /** |
||||
99 | * Create a new model instance for a related "deep through" model. |
||||
100 | * |
||||
101 | * @param string $class |
||||
102 | * @return \Illuminate\Database\Eloquent\Model |
||||
103 | */ |
||||
104 | protected function newRelatedDeepThroughInstance(string $class): Model |
||||
105 | { |
||||
106 | return str_contains($class, '\\') |
||||
107 | ? $this->newRelatedThroughInstance($class) |
||||
0 ignored issues
–
show
The method
newRelatedThroughInstance() does not exist on Staudenmeir\EloquentHasManyDeep\HasRelationships . Did you maybe mean newRelatedDeepThroughInstance() ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||
108 | : (new Pivot())->setTable($class); |
||||
109 | } |
||||
110 | |||||
111 | /** |
||||
112 | * Prepare the foreign keys for a has-one-deep or has-many-deep relationship. |
||||
113 | * |
||||
114 | * @param \Illuminate\Database\Eloquent\Model $related |
||||
115 | * @param \Illuminate\Database\Eloquent\Model[] $throughParents |
||||
116 | * @param array $foreignKeys |
||||
117 | * @return array |
||||
118 | */ |
||||
119 | protected function hasOneOrManyDeepForeignKeys(Model $related, array $throughParents, array $foreignKeys) |
||||
120 | { |
||||
121 | foreach (array_merge([$this], $throughParents) as $i => $instance) { |
||||
122 | /** @var \Illuminate\Database\Eloquent\Model $instance */ |
||||
123 | if (!isset($foreignKeys[$i])) { |
||||
124 | if ($instance instanceof Pivot) { |
||||
125 | $foreignKeys[$i] = ($throughParents[$i] ?? $related)->getKeyName(); |
||||
126 | } else { |
||||
127 | $foreignKeys[$i] = $instance->getForeignKey(); |
||||
128 | } |
||||
129 | } |
||||
130 | } |
||||
131 | |||||
132 | return $foreignKeys; |
||||
133 | } |
||||
134 | |||||
135 | /** |
||||
136 | * Prepare the local keys for a has-one-deep or has-many-deep relationship. |
||||
137 | * |
||||
138 | * @param \Illuminate\Database\Eloquent\Model $related |
||||
139 | * @param \Illuminate\Database\Eloquent\Model[] $throughParents |
||||
140 | * @param array $localKeys |
||||
141 | * @return array |
||||
142 | */ |
||||
143 | protected function hasOneOrManyDeepLocalKeys(Model $related, array $throughParents, array $localKeys) |
||||
144 | { |
||||
145 | foreach (array_merge([$this], $throughParents) as $i => $instance) { |
||||
146 | /** @var \Illuminate\Database\Eloquent\Model $instance */ |
||||
147 | if (!isset($localKeys[$i])) { |
||||
148 | if ($instance instanceof Pivot) { |
||||
149 | $localKeys[$i] = ($throughParents[$i] ?? $related)->getForeignKey(); |
||||
150 | } else { |
||||
151 | $localKeys[$i] = $instance->getKeyName(); |
||||
152 | } |
||||
153 | } |
||||
154 | } |
||||
155 | |||||
156 | return $localKeys; |
||||
157 | } |
||||
158 | |||||
159 | /** |
||||
160 | * Instantiate a new HasManyDeep relationship. |
||||
161 | * |
||||
162 | * @param \Illuminate\Database\Eloquent\Builder $query |
||||
163 | * @param \Illuminate\Database\Eloquent\Model $farParent |
||||
164 | * @param \Illuminate\Database\Eloquent\Model[] $throughParents |
||||
165 | * @param array $foreignKeys |
||||
166 | * @param array $localKeys |
||||
167 | * @return \Staudenmeir\EloquentHasManyDeep\HasManyDeep |
||||
168 | */ |
||||
169 | protected function newHasManyDeep(Builder $query, Model $farParent, array $throughParents, array $foreignKeys, array $localKeys) |
||||
170 | { |
||||
171 | return new HasManyDeep($query, $farParent, $throughParents, $foreignKeys, $localKeys); |
||||
172 | } |
||||
173 | |||||
174 | /** |
||||
175 | * Instantiate a new HasOneDeep relationship. |
||||
176 | * |
||||
177 | * @param \Illuminate\Database\Eloquent\Builder $query |
||||
178 | * @param \Illuminate\Database\Eloquent\Model $farParent |
||||
179 | * @param \Illuminate\Database\Eloquent\Model[] $throughParents |
||||
180 | * @param array $foreignKeys |
||||
181 | * @param array $localKeys |
||||
182 | * @return \Staudenmeir\EloquentHasManyDeep\HasOneDeep |
||||
183 | */ |
||||
184 | protected function newHasOneDeep(Builder $query, Model $farParent, array $throughParents, array $foreignKeys, array $localKeys) |
||||
185 | { |
||||
186 | return new HasOneDeep($query, $farParent, $throughParents, $foreignKeys, $localKeys); |
||||
187 | } |
||||
188 | } |
||||
189 |