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 Sokil\Mongo\Document; |
||
4 | |||
5 | use Sokil\Mongo\Document; |
||
6 | |||
7 | class RelationManager |
||
8 | { |
||
9 | private $relations; |
||
10 | |||
11 | /** |
||
12 | * |
||
13 | * @var \Sokil\Mongo\Document |
||
14 | */ |
||
15 | private $document; |
||
16 | |||
17 | private $resolvedRelationIds = array(); |
||
18 | |||
19 | public function __construct(Document $document = null) |
||
20 | { |
||
21 | $this->document = $document; |
||
22 | $this->relations = $document->getRelationDefinition(); |
||
0 ignored issues
–
show
|
|||
23 | } |
||
24 | |||
25 | /** |
||
26 | * Check if relation with specified name configured |
||
27 | * @param string $name |
||
28 | * @return boolean |
||
29 | */ |
||
30 | public function isRelationExists($name) |
||
31 | { |
||
32 | return isset($this->relations[$name]); |
||
33 | } |
||
34 | |||
35 | /** |
||
36 | * Get related documents |
||
37 | * @param string $relationName name of relation |
||
38 | */ |
||
39 | public function getRelated($relationName) |
||
40 | { |
||
41 | // check if relation exists |
||
42 | if (!$this->isRelationExists($relationName)) { |
||
43 | throw new \Sokil\Mongo\Exception('Relation with name "' . $relationName . '" not found'); |
||
44 | } |
||
45 | |||
46 | // get relation metadata |
||
47 | $relation = $this->relations[$relationName]; |
||
48 | |||
49 | $relationType = $relation[0]; |
||
50 | $targetCollectionName = $relation[1]; |
||
51 | |||
52 | // get target collection |
||
53 | $foreignCollection = $this->document |
||
54 | ->getCollection() |
||
55 | ->getDatabase() |
||
56 | ->getCollection($targetCollectionName); |
||
57 | |||
58 | // check if relation already resolved |
||
59 | if (isset($this->resolvedRelationIds[$relationName])) { |
||
60 | if (is_array($this->resolvedRelationIds[$relationName])) { |
||
61 | // has_many, many_many |
||
62 | return $foreignCollection->getDocuments($this->resolvedRelationIds[$relationName]); |
||
63 | } else { |
||
64 | //has_one, belongs |
||
65 | return $foreignCollection->getDocument($this->resolvedRelationIds[$relationName]); |
||
66 | } |
||
67 | } |
||
68 | |||
69 | switch ($relationType) { |
||
70 | View Code Duplication | case Document::RELATION_HAS_ONE: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
71 | $localKey = isset($relation['localKey']) ? $relation['localKey'] : '_id'; |
||
72 | $foreignKey = $relation[2]; |
||
73 | |||
74 | $document = $foreignCollection |
||
0 ignored issues
–
show
The method
where does not exist on object<Sokil\Mongo\Cursor> ? 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 { }
![]() |
|||
75 | ->find() |
||
76 | ->where($foreignKey, $this->document->get($localKey)) |
||
77 | ->findOne(); |
||
78 | |||
79 | if ($document) { |
||
80 | $this->resolvedRelationIds[$relationName] = (string) $document->getId(); |
||
81 | } |
||
82 | |||
83 | return $document; |
||
84 | |||
85 | case Document::RELATION_BELONGS: |
||
86 | $localKey = $relation[2]; |
||
87 | $foreignKey = isset($relation['foreignKey']) ? $relation['foreignKey'] : '_id'; |
||
88 | |||
89 | if ($foreignKey === '_id') { |
||
90 | $document = $foreignCollection->getDocument($this->document->get($localKey)); |
||
91 | } else { |
||
92 | $document = $foreignCollection |
||
0 ignored issues
–
show
The method
where does not exist on object<Sokil\Mongo\Cursor> ? 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 { }
![]() |
|||
93 | ->find() |
||
94 | ->where($foreignKey, $this->document->get($localKey)) |
||
95 | ->findOne(); |
||
96 | } |
||
97 | |||
98 | if ($document) { |
||
99 | $this->resolvedRelationIds[$relationName] = (string) $document->getId(); |
||
100 | } |
||
101 | |||
102 | return $document; |
||
103 | |||
104 | View Code Duplication | case Document::RELATION_HAS_MANY: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
105 | $localKey = isset($relation['localKey']) ? $relation['localKey'] : '_id'; |
||
106 | $foreignKey = $relation[2]; |
||
107 | |||
108 | $documents = $foreignCollection |
||
0 ignored issues
–
show
The method
where does not exist on object<Sokil\Mongo\Cursor> ? 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 { }
![]() |
|||
109 | ->find() |
||
110 | ->where($foreignKey, $this->document->get($localKey)) |
||
111 | ->findAll(); |
||
112 | |||
113 | foreach ($documents as $document) { |
||
114 | $this->resolvedRelationIds[$relationName][] = (string) $document->getId(); |
||
115 | } |
||
116 | |||
117 | return $documents; |
||
118 | |||
119 | case Document::RELATION_MANY_MANY: |
||
120 | $isRelationListStoredInternally = isset($relation[3]) && $relation[3]; |
||
121 | if ($isRelationListStoredInternally) { |
||
122 | // relation list stored in this document |
||
123 | $localKey = $relation[2]; |
||
124 | $foreignKey = isset($relation['foreignKey']) ? $relation['foreignKey'] : '_id'; |
||
125 | ; |
||
126 | |||
127 | $relatedIdList = $this->document->get($localKey); |
||
128 | if (!$relatedIdList) { |
||
129 | return array(); |
||
130 | } |
||
131 | |||
132 | $documents = $foreignCollection |
||
0 ignored issues
–
show
The method
whereIn does not exist on object<Sokil\Mongo\Cursor> ? 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 { }
![]() |
|||
133 | ->find() |
||
134 | ->whereIn($foreignKey, $relatedIdList) |
||
135 | ->findAll(); |
||
136 | } else { |
||
137 | // relation list stored in external document |
||
138 | $localKey = isset($relation['localKey']) ? $relation['localKey'] : '_id'; |
||
139 | ; |
||
140 | $foreignKey = $relation[2]; |
||
141 | |||
142 | $documents = $foreignCollection |
||
0 ignored issues
–
show
The method
where does not exist on object<Sokil\Mongo\Cursor> ? 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 { }
![]() |
|||
143 | ->find() |
||
144 | ->where($foreignKey, $this->document->get($localKey)) |
||
145 | ->findAll(); |
||
146 | } |
||
147 | |||
148 | foreach ($documents as $document) { |
||
149 | $this->resolvedRelationIds[$relationName][] = (string) $document->getId(); |
||
150 | } |
||
151 | |||
152 | return $documents; |
||
153 | |||
154 | default: |
||
155 | throw new \Sokil\Mongo\Exception( |
||
156 | 'Unsupported relation type "' . $relationType . '" when resolve relation "' . $relationName . '"' |
||
157 | ); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | public function addRelation($relationName, Document $document) |
||
162 | { |
||
163 | if (!$this->isRelationExists($relationName)) { |
||
164 | throw new \Exception('Relation "' . $relationName . '" not configured'); |
||
165 | } |
||
166 | |||
167 | $relation = $this->relations[$relationName]; |
||
168 | |||
169 | list($relationType, $relatedCollectionName, $field) = $relation; |
||
170 | |||
171 | $relatedCollection = $this->document |
||
172 | ->getCollection() |
||
173 | ->getDatabase() |
||
174 | ->getCollection($relatedCollectionName); |
||
175 | |||
176 | if (!$relatedCollection->hasDocument($document)) { |
||
177 | throw new \Sokil\Mongo\Exception('Document must belongs to related collection'); |
||
178 | } |
||
179 | |||
180 | switch ($relationType) { |
||
181 | case Document::RELATION_BELONGS: |
||
182 | if (!$document->isStored()) { |
||
183 | throw new \Sokil\Mongo\Exception(sprintf( |
||
184 | 'Document %s must be saved before adding relation', |
||
185 | get_class($document) |
||
186 | )); |
||
187 | } |
||
188 | $this->document->set($field, $document->getId()); |
||
189 | break; |
||
190 | |||
191 | View Code Duplication | case Document::RELATION_HAS_ONE: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
192 | if (!$this->document->isStored()) { |
||
193 | throw new \Sokil\Mongo\Exception( |
||
194 | 'Document ' . get_class($this) . ' must be saved before adding relation' |
||
195 | ); |
||
196 | } |
||
197 | $document->set($field, $this->document->getId())->save(); |
||
198 | break; |
||
199 | |||
200 | View Code Duplication | case Document::RELATION_HAS_MANY: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
201 | if (!$this->document->isStored()) { |
||
202 | throw new \Sokil\Mongo\Exception( |
||
203 | 'Document ' . get_class($this) . ' must be saved before adding relation' |
||
204 | ); |
||
205 | } |
||
206 | $document->set($field, $this->document->getId())->save(); |
||
207 | break; |
||
208 | |||
209 | View Code Duplication | case Document::RELATION_MANY_MANY: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
210 | $isRelationListStoredInternally = isset($relation[3]) && $relation[3]; |
||
211 | if ($isRelationListStoredInternally) { |
||
212 | $this->document->push($field, $document->getId())->save(); |
||
213 | } else { |
||
214 | $document->push($field, $this->document->getId())->save(); |
||
215 | } |
||
216 | break; |
||
217 | |||
218 | default: |
||
219 | throw new \Sokil\Mongo\Exception( |
||
220 | 'Unsupported relation type "' . $relationType . '" when resolve relation "' . $relationName . '"' |
||
221 | ); |
||
222 | } |
||
223 | |||
224 | return $this; |
||
225 | } |
||
226 | |||
227 | public function removeRelation($relationName, Document $document = null) |
||
228 | { |
||
229 | if (!$this->isRelationExists($relationName)) { |
||
230 | throw new \Exception('Relation ' . $relationName . ' not configured'); |
||
231 | } |
||
232 | |||
233 | $relation = $this->relations[$relationName]; |
||
234 | |||
235 | list($relationType, $relatedCollectionName, $field) = $relation; |
||
236 | |||
237 | $relatedCollection = $this->document |
||
238 | ->getCollection() |
||
239 | ->getDatabase() |
||
240 | ->getCollection($relatedCollectionName); |
||
241 | |||
242 | if ($document && !$relatedCollection->hasDocument($document)) { |
||
243 | throw new \Sokil\Mongo\Exception('Document must belongs to related collection'); |
||
244 | } |
||
245 | |||
246 | switch ($relationType) { |
||
247 | case Document::RELATION_BELONGS: |
||
248 | $this->document->unsetField($field)->save(); |
||
249 | break; |
||
250 | |||
251 | case Document::RELATION_HAS_ONE: |
||
252 | $document = $this->getRelated($relationName); |
||
253 | if (!$document) { |
||
254 | // relation not exists |
||
255 | return $this; |
||
256 | } |
||
257 | $document->unsetField($field)->save(); |
||
258 | break; |
||
259 | |||
260 | case Document::RELATION_HAS_MANY: |
||
261 | if (!$document) { |
||
262 | throw new \Sokil\Mongo\Exception('Related document must be defined'); |
||
263 | } |
||
264 | $document->unsetField($field)->save(); |
||
265 | break; |
||
266 | |||
267 | |||
268 | View Code Duplication | case Document::RELATION_MANY_MANY: |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
269 | if (!$document) { |
||
270 | throw new \Sokil\Mongo\Exception('Related document must be defined'); |
||
271 | } |
||
272 | $isRelationListStoredInternally = isset($relation[3]) && $relation[3]; |
||
273 | if ($isRelationListStoredInternally) { |
||
274 | $this->document->pull($field, $document->getId())->save(); |
||
275 | } else { |
||
276 | $document->pull($field, $this->document->getId())->save(); |
||
277 | } |
||
278 | break; |
||
279 | |||
280 | default: |
||
281 | throw new \Sokil\Mongo\Exception( |
||
282 | 'Unsupported relation type "' . $relationType . '" when resolve relation "' . $relationName . '"' |
||
283 | ); |
||
284 | } |
||
285 | |||
286 | return $this; |
||
287 | } |
||
288 | } |
||
289 |
If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe: