This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Analogue\ORM\Relationships; |
||
4 | |||
5 | use Analogue\ORM\System\Query; |
||
6 | use Analogue\ORM\System\Mapper; |
||
7 | use Analogue\ORM\EntityCollection; |
||
8 | use Illuminate\Database\Query\Expression; |
||
9 | |||
10 | class HasManyThrough extends Relationship |
||
11 | { |
||
12 | /** |
||
13 | * The distance parent Entity instance. |
||
14 | * |
||
15 | * @var \Analogue\ORM\Entity |
||
16 | */ |
||
17 | protected $farParent; |
||
18 | |||
19 | /** |
||
20 | * The far parent map instance |
||
21 | * |
||
22 | * @var \Analogue\ORM\EntityMap |
||
23 | */ |
||
24 | protected $farParentMap; |
||
25 | |||
26 | /** |
||
27 | * The near key on the relationship. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $firstKey; |
||
32 | |||
33 | /** |
||
34 | * The far key on the relationship. |
||
35 | * |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $secondKey; |
||
39 | |||
40 | /** |
||
41 | * Create a new has many relationship instance. |
||
42 | * |
||
43 | * @param Mapper $mapper |
||
44 | * @param \Analogue\ORM\Mappable $farParent |
||
45 | * @param \Analogue\ORM\EntityMap $parentMap |
||
46 | * @param string $firstKey |
||
47 | * @param string $secondKey |
||
48 | * @throws \Analogue\ORM\Exceptions\MappingException |
||
49 | */ |
||
50 | public function __construct(Mapper $mapper, $farParent, $parentMap, $firstKey, $secondKey) |
||
51 | { |
||
52 | $this->firstKey = $firstKey; |
||
53 | $this->secondKey = $secondKey; |
||
54 | $this->farParent = $farParent; |
||
0 ignored issues
–
show
|
|||
55 | |||
56 | $this->farParentMap = $mapper->getManager()->mapper($farParent)->getEntityMap(); |
||
57 | $parentInstance = $mapper->getManager()->mapper($parentMap->getClass())->newInstance(); |
||
58 | |||
59 | parent::__construct($mapper, $parentInstance); |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * @param $related |
||
64 | * @return mixed |
||
65 | */ |
||
66 | public function attachTo($related) |
||
67 | { |
||
68 | // N/A |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * @param $related |
||
73 | * @return mixed |
||
74 | */ |
||
75 | public function detachFrom($related) |
||
76 | { |
||
77 | // N/A |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * Set the base constraints on the relation query. |
||
82 | * |
||
83 | * @return void |
||
84 | */ |
||
85 | public function addConstraints() |
||
86 | { |
||
87 | $parentTable = $this->parentMap->getTable(); |
||
88 | |||
89 | $this->setJoin(); |
||
90 | |||
91 | if (static::$constraints) { |
||
92 | $farParentKeyName = $this->farParentMap->getKeyName(); |
||
93 | |||
94 | $this->query->where( |
||
95 | $parentTable . '.' . $this->firstKey, |
||
96 | '=', |
||
97 | $this->farParent->getEntityAttribute($farParentKeyName) |
||
98 | ); |
||
99 | } |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * Add the constraints for a relationship count query. |
||
104 | * |
||
105 | * @param Query $query |
||
106 | * @param Query $parent |
||
107 | * @return Query |
||
108 | */ |
||
109 | public function getRelationCountQuery(Query $query, Query $parent) |
||
110 | { |
||
111 | $parentTable = $this->parentMap->getTable(); |
||
112 | |||
113 | $this->setJoin($query); |
||
114 | |||
115 | $query->select(new Expression('count(*)')); |
||
0 ignored issues
–
show
The method
select does not exist on object<Analogue\ORM\System\Query> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
116 | |||
117 | $key = $this->wrap($parentTable . '.' . $this->firstKey); |
||
118 | |||
119 | return $query->where($this->getHasCompareKey(), '=', new Expression($key)); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Set the join clause on the query. |
||
124 | * |
||
125 | * @param null|Query $query |
||
126 | * @return void |
||
127 | */ |
||
128 | protected function setJoin(Query $query = null) |
||
129 | { |
||
130 | $query = $query ?: $this->query; |
||
131 | |||
132 | $foreignKey = $this->relatedMap->getTable() . '.' . $this->secondKey; |
||
133 | |||
134 | $query->join($this->parentMap->getTable(), $this->getQualifiedParentKeyName(), '=', $foreignKey); |
||
0 ignored issues
–
show
The method
join does not exist on object<Analogue\ORM\System\Query> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Set the constraints for an eager load of the relation. |
||
139 | * |
||
140 | * @param array $entities |
||
141 | * @return void |
||
142 | */ |
||
143 | public function addEagerConstraints(array $entities) |
||
144 | { |
||
145 | $table = $this->parentMap->getTable(); |
||
146 | |||
147 | $this->query->whereIn($table . '.' . $this->firstKey, $this->getKeys($entities)); |
||
0 ignored issues
–
show
The method
whereIn does not exist on object<Analogue\ORM\System\Query> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Initialize the relation on a set of entities. |
||
152 | * |
||
153 | * @param \Analogue\ORM\Entity[] $entities |
||
154 | * @param string $relation |
||
155 | * @return \Analogue\ORM\Entity[] |
||
156 | */ |
||
157 | public function initRelation(array $entities, $relation) |
||
158 | { |
||
159 | foreach ($entities as $entity) { |
||
160 | $entity->setEntityAttribute($relation, $this->relatedMap->newCollection()); |
||
161 | } |
||
162 | |||
163 | return $entities; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Match the eagerly loaded results to their parents. |
||
168 | * |
||
169 | * @param \Analogue\ORM\Entity[] $entities |
||
170 | * @param EntityCollection $results |
||
171 | * @param string $relation |
||
172 | * @return \Analogue\ORM\Entity[] |
||
173 | */ |
||
174 | public function match(array $entities, EntityCollection $results, $relation) |
||
175 | { |
||
176 | $dictionary = $this->buildDictionary($results); |
||
177 | |||
178 | $relatedKey = $this->relatedMap->getKeyName(); |
||
179 | |||
180 | $cache = $this->parentMapper->getEntityCache(); |
||
181 | |||
182 | // Once we have the dictionary we can simply spin through the parent entities to |
||
183 | // link them up with their children using the keyed dictionary to make the |
||
184 | // matching very convenient and easy work. Then we'll just return them. |
||
185 | foreach ($entities as $entity) { |
||
186 | $key = $entity->getEntityAttribute($relatedKey); |
||
187 | |||
188 | if (isset($dictionary[$key])) { |
||
189 | $value = $this->relatedMap->newCollection($dictionary[$key]); |
||
190 | |||
191 | $entity->setEntityAttribute($relation, $value); |
||
192 | |||
193 | $cache->cacheLoadedRelationResult($entity, $relation, $value, $this); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | return $entities; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Build model dictionary keyed by the relation's foreign key. |
||
202 | * |
||
203 | * @param EntityCollection $results |
||
204 | * @return array |
||
205 | */ |
||
206 | View Code Duplication | protected function buildDictionary(EntityCollection $results) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
207 | { |
||
208 | $dictionary = []; |
||
209 | |||
210 | $foreign = $this->firstKey; |
||
211 | |||
212 | // First we will create a dictionary of entities keyed by the foreign key of the |
||
213 | // relationship as this will allow us to quickly access all of the related |
||
214 | // entities without having to do nested looping which will be quite slow. |
||
215 | foreach ($results as $result) { |
||
216 | $dictionary[$result->{$foreign}][] = $result; |
||
217 | } |
||
218 | |||
219 | return $dictionary; |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Get the results of the relationship. |
||
224 | * |
||
225 | * @param $relation |
||
226 | * @return EntityCollection |
||
227 | */ |
||
228 | public function getResults($relation) |
||
229 | { |
||
230 | $results = $this->query->get(); |
||
231 | |||
232 | $this->cacheRelation($results, $relation); |
||
233 | |||
234 | return $results; |
||
235 | } |
||
236 | |||
237 | /** |
||
238 | * Execute the query as a "select" statement. |
||
239 | * |
||
240 | * @param array $columns |
||
241 | * @return EntityCollection |
||
242 | */ |
||
243 | public function get($columns = ['*']) |
||
244 | { |
||
245 | // First we'll add the proper select columns onto the query so it is run with |
||
246 | // the proper columns. Then, we will get the results and hydrate out pivot |
||
247 | // entities with the result of those columns as a separate model relation. |
||
248 | $select = $this->getSelectColumns($columns); |
||
249 | |||
250 | $entities = $this->query->addSelect($select)->getEntities(); |
||
0 ignored issues
–
show
The method
addSelect does not exist on object<Analogue\ORM\System\Query> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
251 | |||
252 | // If we actually found entities we will also eager load any relationships that |
||
253 | // have been specified as needing to be eager loaded. This will solve the |
||
254 | // n + 1 query problem for the developer and also increase performance. |
||
255 | if (count($entities) > 0) { |
||
256 | $entities = $this->query->eagerLoadRelations($entities); |
||
257 | } |
||
258 | |||
259 | return $this->relatedMap->newCollection($entities); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Set the select clause for the relation query. |
||
264 | * |
||
265 | * @param array $columns |
||
266 | * @return BelongsToMany |
||
267 | */ |
||
268 | protected function getSelectColumns(array $columns = ['*']) |
||
269 | { |
||
270 | if ($columns == ['*']) { |
||
271 | $columns = [$this->relatedMap->getTable() . '.*']; |
||
272 | } |
||
273 | |||
274 | return array_merge($columns, [$this->parentMap->getTable() . '.' . $this->firstKey]); |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Get a paginator for the "select" statement. |
||
279 | * |
||
280 | * @param int $perPage |
||
281 | * @param array $columns |
||
282 | * @return \Illuminate\Pagination\LengthAwarePaginator |
||
283 | */ |
||
284 | public function paginate($perPage = null, $columns = ['*']) |
||
285 | { |
||
286 | $this->query->addSelect($this->getSelectColumns($columns)); |
||
0 ignored issues
–
show
The method
addSelect does not exist on object<Analogue\ORM\System\Query> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
287 | |||
288 | return $this->query->paginate($perPage, $columns); |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Get the key name of the parent model. |
||
293 | * |
||
294 | * @return string |
||
295 | */ |
||
296 | protected function getQualifiedParentKeyName() |
||
297 | { |
||
298 | return $this->parentMap->getQualifiedKeyName(); |
||
299 | } |
||
300 | |||
301 | /** |
||
302 | * Get the key for comparing against the parent key in "has" query. |
||
303 | * |
||
304 | * @return string |
||
305 | */ |
||
306 | public function getHasCompareKey() |
||
307 | { |
||
308 | return $this->farParentMap->getQualifiedKeyName(); |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Run synchronization content if needed by the |
||
313 | * relation type. |
||
314 | * |
||
315 | * @param array $actualContent |
||
0 ignored issues
–
show
There is no parameter named
$actualContent . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
316 | * @return void |
||
317 | */ |
||
318 | public function sync(array $entities) |
||
319 | { |
||
320 | // N/A |
||
321 | } |
||
322 | } |
||
323 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.