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 Elgg; |
||
4 | |||
5 | use Elgg\Database\EntityTable; |
||
6 | use Elgg\Database\EntityTable\UserFetchFailureException; |
||
7 | use ElggAnnotation; |
||
8 | use ElggEntity; |
||
9 | use ElggFile; |
||
10 | use ElggRiverItem; |
||
11 | use ElggMetadata; |
||
12 | use ElggSession; |
||
13 | use InvalidArgumentException; |
||
14 | |||
15 | /** |
||
16 | * WARNING: API IN FLUX. DO NOT USE DIRECTLY. |
||
17 | * |
||
18 | * Use the elgg_* versions instead. |
||
19 | * |
||
20 | * @access private |
||
21 | * @since 2.2 |
||
22 | */ |
||
23 | class UserCapabilities { |
||
24 | |||
25 | /** |
||
26 | * @var PluginHooksService $hooks |
||
27 | */ |
||
28 | private $hooks; |
||
29 | |||
30 | /** |
||
31 | * @var EntityTable |
||
32 | */ |
||
33 | private $entities; |
||
34 | |||
35 | /** |
||
36 | * @var ElggSession |
||
37 | */ |
||
38 | private $session; |
||
39 | |||
40 | /** |
||
41 | * Constructor |
||
42 | * |
||
43 | * @param PluginHooksService $hooks Plugin hooks service |
||
44 | * @param EntityTable $entities Entity table |
||
45 | * @param ElggSession $session Session |
||
46 | */ |
||
47 | 43 | public function __construct(PluginHooksService $hooks, EntityTable $entities, ElggSession $session) { |
|
48 | 43 | $this->hooks = $hooks; |
|
49 | 43 | $this->entities = $entities; |
|
50 | 43 | $this->session = $session; |
|
51 | 43 | } |
|
52 | |||
53 | /** |
||
54 | * Can a user edit this entity? |
||
55 | * |
||
56 | * @tip Can be overridden by registering for the permissions_check plugin hook. |
||
57 | * |
||
58 | * @param ElggEntity $entity Object entity |
||
59 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
60 | * |
||
61 | * @return bool Whether this entity is editable by the given user. |
||
62 | * @see elgg_set_ignore_access() |
||
63 | */ |
||
64 | 22 | public function canEdit(ElggEntity $entity, $user_guid = 0) { |
|
65 | try { |
||
66 | 22 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
67 | } catch (UserFetchFailureException $e) { |
||
68 | return false; |
||
69 | } |
||
70 | |||
71 | // Test user if possible - should default to false unless a plugin hook says otherwise |
||
72 | 22 | $default = call_user_func(function () use ($entity, $user) { |
|
73 | 22 | if (!$user) { |
|
74 | 1 | return false; |
|
75 | } |
||
76 | |||
77 | // favor the persisted attributes if not saved |
||
78 | 21 | $attrs = array_merge( |
|
79 | [ |
||
80 | 21 | 'owner_guid' => $entity->owner_guid, |
|
81 | 21 | 'container_guid' => $entity->container_guid, |
|
82 | 21 | ], $entity->getOriginalAttributes() |
|
83 | ); |
||
84 | |||
85 | 21 | if ($attrs['owner_guid'] == $user->guid) { |
|
86 | 14 | return true; |
|
87 | } |
||
88 | |||
89 | 11 | if ($attrs['container_guid'] == $user->guid) { |
|
90 | 3 | return true; |
|
91 | } |
||
92 | |||
93 | 11 | if ($entity->guid == $user->guid) { |
|
94 | 2 | return true; |
|
95 | } |
||
96 | |||
97 | 10 | $container = $this->entities->get($attrs['container_guid']); |
|
98 | |||
99 | 10 | return ($container && $container->canEdit($user->guid)); |
|
100 | 22 | }); |
|
101 | |||
102 | 22 | $params = ['entity' => $entity, 'user' => $user]; |
|
103 | 22 | return $this->hooks->trigger('permissions_check', $entity->getType(), $params, $default); |
|
104 | } |
||
105 | |||
106 | /** |
||
107 | * Can a user delete this entity? |
||
108 | * |
||
109 | * @tip Can be overridden by registering for the permissions_check:delete plugin hook. |
||
110 | * |
||
111 | * @param ElggEntity $entity Object entity |
||
112 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
113 | * |
||
114 | * @return bool Whether this entity is deletable by the given user. |
||
115 | * @since 1.11 |
||
116 | * @see elgg_set_ignore_access() |
||
117 | */ |
||
118 | 4 | View Code Duplication | public function canDelete(ElggEntity $entity, $user_guid = 0) { |
0 ignored issues
–
show
|
|||
119 | try { |
||
120 | 4 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
121 | } catch (UserFetchFailureException $e) { |
||
122 | return false; |
||
123 | } |
||
124 | |||
125 | 4 | $return = $entity->canEdit($user_guid); |
|
126 | |||
127 | $params = [ |
||
128 | 4 | 'entity' => $entity, |
|
129 | 4 | 'user' => $user |
|
130 | ]; |
||
131 | 4 | return $this->hooks->trigger('permissions_check:delete', $entity->getType(), $params, $return); |
|
132 | } |
||
133 | |||
134 | /** |
||
135 | * Can a user delete this river item? |
||
136 | * |
||
137 | * @tip Can be overridden by registering for the "permissions_check:delete", "river" plugin hook. |
||
138 | * |
||
139 | * @param ElggRiverItem $item River item |
||
140 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
141 | * |
||
142 | * @return bool Whether this river item should be considered deletable by the given user. |
||
143 | * @since 2.3 |
||
144 | * @see elgg_set_ignore_access() |
||
145 | */ |
||
146 | View Code Duplication | public function canDeleteRiverItem(ElggRiverItem $item, $user_guid = 0) { |
|
147 | try { |
||
148 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
||
149 | } catch (UserFetchFailureException $e) { |
||
150 | return false; |
||
151 | } |
||
152 | |||
153 | $return = ($user && $user->isAdmin()); |
||
154 | |||
155 | $params = [ |
||
156 | 'item' => $item, |
||
157 | 'user' => $user, |
||
158 | ]; |
||
159 | return $this->hooks->trigger('permissions_check:delete', 'river', $params, $return); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Can a user edit metadata on this entity? |
||
164 | * |
||
165 | * If no specific metadata is passed, it returns whether the user can |
||
166 | * edit any metadata on the entity. |
||
167 | * |
||
168 | * @tip Can be overridden by by registering for the permissions_check:metadata |
||
169 | * plugin hook. |
||
170 | * |
||
171 | * @param ElggEntity $entity Object entity |
||
172 | * @param int $user_guid The user GUID, optionally (default: logged in user) |
||
173 | * @param ElggMetadata $metadata The piece of metadata to specifically check or null for any metadata |
||
174 | * |
||
175 | * @return bool |
||
176 | * @see elgg_set_ignore_access() |
||
177 | */ |
||
178 | 8 | public function canEditMetadata(ElggEntity $entity, $user_guid = 0, ElggMetadata $metadata = null) { |
|
179 | 8 | if (!$entity->guid) { |
|
180 | // @todo cannot edit metadata on unsaved entity? |
||
181 | 1 | return false; |
|
182 | } |
||
183 | |||
184 | try { |
||
185 | 7 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
186 | } catch (UserFetchFailureException $e) { |
||
187 | return false; |
||
188 | } |
||
189 | |||
190 | 7 | if ($user) { |
|
191 | 7 | $user_guid = $user->guid; |
|
192 | } |
||
193 | |||
194 | // if metadata is not owned or owned by the user, then can edit |
||
195 | 7 | if ($metadata && ($metadata->owner_guid == 0 || $metadata->owner_guid == $user_guid)) { |
|
196 | 6 | $return = true; |
|
197 | } else { |
||
198 | 3 | $return = $entity->canEdit($user_guid); |
|
199 | } |
||
200 | |||
201 | // metadata and user may be null |
||
202 | $params = [ |
||
203 | 7 | 'entity' => $entity, |
|
204 | 7 | 'user' => $user, |
|
205 | 7 | 'metadata' => $metadata |
|
206 | ]; |
||
207 | 7 | return $this->hooks->trigger('permissions_check:metadata', $entity->getType(), $params, $return); |
|
208 | } |
||
209 | |||
210 | /** |
||
211 | * Determines whether or not the user can edit this annotation |
||
212 | * |
||
213 | * @param Elggentity $entity Object entity |
||
214 | * @param int $user_guid The GUID of the user (defaults to currently logged in user) |
||
215 | * @param ElggAnnotation $annotation Annotation |
||
216 | * |
||
217 | * @return bool |
||
218 | * @see elgg_set_ignore_access() |
||
219 | */ |
||
220 | 5 | public function canEditAnnotation(ElggEntity $entity, $user_guid = 0, ElggAnnotation $annotation = null) { |
|
221 | 5 | if (!$annotation) { |
|
222 | return false; |
||
223 | } |
||
224 | try { |
||
225 | 5 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
226 | } catch (UserFetchFailureException $e) { |
||
227 | return false; |
||
228 | } |
||
229 | |||
230 | 5 | $result = false; |
|
231 | |||
232 | 5 | if ($user) { |
|
233 | // If the owner of annotation is the specified user, they can edit. |
||
234 | 5 | if ($annotation->owner_guid == $user->guid) { |
|
235 | 4 | $result = true; |
|
236 | } |
||
237 | |||
238 | // If the user can edit the entity this is attached to, they can edit. |
||
239 | 5 | if ($result == false && $entity->canEdit($user->guid)) { |
|
240 | 1 | $result = true; |
|
241 | } |
||
242 | } |
||
243 | |||
244 | // Trigger plugin hook - note that $user may be null |
||
245 | $params = [ |
||
246 | 5 | 'entity' => $entity, |
|
247 | 5 | 'user' => $user, |
|
248 | 5 | 'annotation' => $annotation |
|
249 | ]; |
||
250 | |||
251 | 5 | return $this->hooks->trigger('permissions_check', 'annotation', $params, $result); |
|
252 | } |
||
253 | |||
254 | /** |
||
255 | * Can a user add an entity to this container |
||
256 | * |
||
257 | * @param ElggEntity $entity Container entity |
||
258 | * @param int $user_guid The GUID of the user creating the entity (0 for logged in user). |
||
259 | * @param string $type The type of entity we're looking to write |
||
260 | * @param string $subtype The subtype of the entity we're looking to write |
||
261 | * |
||
262 | * @return bool |
||
263 | * @see elgg_set_ignore_access() |
||
264 | */ |
||
265 | 5 | public function canWriteToContainer(ElggEntity $entity, $user_guid = 0, $type = 'all', $subtype = 'all') { |
|
266 | try { |
||
267 | 5 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
268 | } catch (UserFetchFailureException $e) { |
||
269 | return false; |
||
270 | } |
||
271 | |||
272 | 5 | if ($user) { |
|
273 | 5 | $user_guid = $user->guid; |
|
274 | } |
||
275 | |||
276 | $params = [ |
||
277 | 5 | 'container' => $entity, |
|
278 | 5 | 'user' => $user, |
|
279 | 5 | 'subtype' => $subtype |
|
280 | ]; |
||
281 | |||
282 | // Unlike permissions, logic check can be used to prevent certain entity |
||
283 | // types from being contained by other entity types, |
||
284 | // e.g. discussion reply objects can only be contained by discussion objects. |
||
285 | // This hook can also be used to apply status logic, e.g. to disallow |
||
286 | // new replies in closed discussions. |
||
287 | // We do not take a stand hence the return is null. This can be used by |
||
288 | // handlers to check if another hook has modified the value. |
||
289 | 5 | $logic_check = $this->hooks->trigger('container_logic_check', $type, $params); |
|
290 | |||
291 | 5 | if ($logic_check === false) { |
|
292 | 1 | return false; |
|
293 | } |
||
294 | |||
295 | 5 | $return = false; |
|
296 | 5 | if ($entity) { |
|
297 | // If the user can edit the container, they can also write to it |
||
298 | 5 | if ($entity->canEdit($user_guid)) { |
|
299 | 4 | $return = true; |
|
300 | } |
||
301 | } |
||
302 | |||
303 | // Container permissions can prevent users from writing to an entity. |
||
304 | // For instance, these permissions can prevent non-group members from writing |
||
305 | // content to the group. |
||
306 | 5 | return $this->hooks->trigger('container_permissions_check', $type, $params, $return); |
|
307 | } |
||
308 | |||
309 | /** |
||
310 | * Can a user comment on an entity? |
||
311 | * |
||
312 | * @tip Can be overridden by registering for the permissions_check:comment, |
||
313 | * <entity type> plugin hook. |
||
314 | * |
||
315 | * @param ElggEntity $entity Object entity |
||
316 | * @param int $user_guid User guid (default is logged in user) |
||
317 | * @param bool $default Default permission |
||
318 | * @return bool |
||
319 | */ |
||
320 | 5 | View Code Duplication | public function canComment(ElggEntity $entity, $user_guid = 0, $default = null) { |
321 | try { |
||
322 | 5 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
323 | } catch (UserFetchFailureException $e) { |
||
324 | return false; |
||
325 | } |
||
326 | |||
327 | // By default, we don't take a position of whether commenting is allowed |
||
328 | // because it is handled by the subclasses of \ElggEntity |
||
329 | $params = [ |
||
330 | 5 | 'entity' => $entity, |
|
331 | 5 | 'user' => $user |
|
332 | ]; |
||
333 | 5 | return $this->hooks->trigger('permissions_check:comment', $entity->getType(), $params, $default); |
|
334 | } |
||
335 | |||
336 | /** |
||
337 | * Can a user annotate an entity? |
||
338 | * |
||
339 | * @tip Can be overridden by registering for the plugin hook [permissions_check:annotate:<name>, |
||
340 | * <entity type>] or [permissions_check:annotate, <entity type>]. The hooks are called in that order. |
||
341 | * |
||
342 | * @tip If you want logged out users to annotate an object, do not call |
||
343 | * canAnnotate(). It's easier than using the plugin hook. |
||
344 | * |
||
345 | * @param ElggEntity $entity Objet entity |
||
346 | * @param int $user_guid User guid (default is logged in user) |
||
347 | * @param string $annotation_name The name of the annotation (default is unspecified) |
||
348 | * |
||
349 | * @return bool |
||
350 | */ |
||
351 | 8 | public function canAnnotate(ElggEntity $entity, $user_guid = 0, $annotation_name = '') { |
|
352 | 8 | if ($annotation_name === null || $annotation_name === false) { |
|
353 | // accepting these for BC |
||
354 | 1 | $annotation_name = ''; |
|
355 | 8 | } elseif (!is_string($annotation_name)) { |
|
356 | 4 | throw new InvalidArgumentException(__METHOD__ . ' expects \$annotation_name to be a string'); |
|
357 | } |
||
358 | |||
359 | try { |
||
360 | 4 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
361 | } catch (UserFetchFailureException $e) { |
||
362 | return false; |
||
363 | } |
||
364 | |||
365 | 4 | $return = (bool) $user; |
|
366 | |||
367 | $params = [ |
||
368 | 4 | 'entity' => $entity, |
|
369 | 4 | 'user' => $user, |
|
370 | 4 | 'annotation_name' => $annotation_name, |
|
371 | ]; |
||
372 | |||
373 | 4 | if (!empty($annotation_name)) { |
|
374 | 4 | $return = $this->hooks->trigger("permissions_check:annotate:$annotation_name", $entity->getType(), $params, $return); |
|
375 | } |
||
376 | |||
377 | 4 | return $this->hooks->trigger('permissions_check:annotate', $entity->getType(), $params, $return); |
|
378 | } |
||
379 | |||
380 | /** |
||
381 | * Can a user download a file? |
||
382 | * |
||
383 | * @tip Can be overridden by registering for the permissions_check:download,file plugin hook. |
||
384 | * |
||
385 | * @param ElggFile $entity File entity |
||
386 | * @param int $user_guid User guid (default is logged in user) |
||
387 | * @param bool $default Default permission |
||
388 | * |
||
389 | * @return bool |
||
390 | */ |
||
391 | 2 | public function canDownload(ElggFile $entity, $user_guid = 0, $default = true) { |
|
392 | try { |
||
393 | 2 | $user = $this->entities->getUserForPermissionsCheck($user_guid); |
|
394 | } catch (UserFetchFailureException $e) { |
||
395 | return false; |
||
396 | } |
||
397 | |||
398 | $params = [ |
||
399 | 2 | 'entity' => $entity, |
|
400 | 2 | 'user' => $user |
|
401 | ]; |
||
402 | |||
403 | 2 | return $this->hooks->trigger('permissions_check:download', 'file', $params, $default); |
|
404 | } |
||
405 | |||
406 | } |
||
407 |
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.