Elgg  Version 5.1
UserCapabilities.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
7 
15 
19  protected $events;
20 
24  protected $entities;
25 
29  protected $session_manager;
30 
38  public function __construct(EventsService $events, EntityTable $entities, SessionManagerService $session_manager) {
39  $this->events = $events;
40  $this->entities = $entities;
41  $this->session_manager = $session_manager;
42  }
43 
55  public function canBypassPermissionsCheck(int $user_guid = 0): bool {
56  if ($this->session_manager->getIgnoreAccess()) {
57  // Checking ignored access first to avoid infinite loops,
58  // when trying to fetch a user by guid
59  return true;
60  }
61 
62  try {
63  $user = $this->entities->getUserForPermissionsCheck($user_guid);
64  } catch (UserFetchFailureException $e) {
65  return false;
66  }
67 
68  return $user && $user->isAdmin();
69  }
70 
81  public function canEdit(\ElggEntity $entity, int $user_guid = 0): bool {
82  if ($this->canBypassPermissionsCheck($user_guid)) {
83  return true;
84  }
85 
86  try {
87  $user = $this->entities->getUserForPermissionsCheck($user_guid);
88  } catch (UserFetchFailureException $e) {
89  return false;
90  }
91 
92  // Test user if possible - should default to false unless an event says otherwise
93  $default = call_user_func(function () use ($entity, $user) {
94  if (!$user) {
95  return false;
96  }
97 
98  // favor the persisted attributes if not saved
99  $attrs = array_merge([
100  'owner_guid' => $entity->owner_guid,
101  'container_guid' => $entity->container_guid,
102  ], $entity->getOriginalAttributes());
103 
104  if ($attrs['owner_guid'] == $user->guid) {
105  return true;
106  }
107 
108  if ($attrs['container_guid'] == $user->guid) {
109  return true;
110  }
111 
112  if ($entity->guid == $user->guid) {
113  return true;
114  }
115 
116  if (!isset($attrs['container_guid'])) {
117  return false;
118  }
119 
120  $container = $this->entities->get($attrs['container_guid']);
121 
122  return ($container && $container->canEdit($user->guid));
123  });
124 
125  $params = ['entity' => $entity, 'user' => $user];
126  return $this->events->triggerResults('permissions_check', $entity->getType(), $params, $default);
127  }
128 
140  public function canDelete(\ElggEntity $entity, int $user_guid = 0): bool {
141  if ($this->canBypassPermissionsCheck($user_guid)) {
142  return true;
143  }
144 
145  try {
146  $user = $this->entities->getUserForPermissionsCheck($user_guid);
147  } catch (UserFetchFailureException $e) {
148  return false;
149  }
150 
151  $return = $entity->canEdit($user_guid);
152 
153  $params = [
154  'entity' => $entity,
155  'user' => $user
156  ];
157  return $this->events->triggerResults('permissions_check:delete', $entity->getType(), $params, $return);
158  }
159 
171  public function canDeleteRiverItem(\ElggRiverItem $item, int $user_guid = 0): bool {
172  if ($this->canBypassPermissionsCheck($user_guid)) {
173  return true;
174  }
175 
176  try {
177  $user = $this->entities->getUserForPermissionsCheck($user_guid);
178  } catch (UserFetchFailureException $e) {
179  return false;
180  }
181 
182  $params = [
183  'item' => $item,
184  'user' => $user,
185  ];
186  return $this->events->triggerResults('permissions_check:delete', 'river', $params, false);
187  }
188 
198  public function canEditAnnotation(\ElggEntity $entity, int $user_guid = 0, \ElggAnnotation $annotation = null): bool {
199  if (!$annotation) {
200  return false;
201  }
202 
203  if ($this->canBypassPermissionsCheck($user_guid)) {
204  return true;
205  }
206 
207  try {
208  $user = $this->entities->getUserForPermissionsCheck($user_guid);
209  } catch (UserFetchFailureException $e) {
210  return false;
211  }
212 
213  $result = false;
214 
215  if ($user) {
216  // If the owner of annotation is the specified user, they can edit.
217  if ($annotation->owner_guid == $user->guid) {
218  $result = true;
219  }
220 
221  // If the user can edit the entity this is attached to, they can edit.
222  if ($result === false && $entity->canEdit($user->guid)) {
223  $result = true;
224  }
225  }
226 
227  // Trigger event - note that $user may be null
228  $params = [
229  'entity' => $entity,
230  'user' => $user,
231  'annotation' => $annotation,
232  ];
233 
234  return $this->events->triggerResults('permissions_check', 'annotation', $params, $result);
235  }
236 
247  public function canWriteToContainer(\ElggEntity $entity, string $type, string $subtype, int $user_guid = 0): bool {
248  try {
249  $user = $this->entities->getUserForPermissionsCheck($user_guid);
250  } catch (UserFetchFailureException $e) {
251  return false;
252  }
253 
254  if ($user) {
255  $user_guid = $user->guid;
256  }
257 
258  $params = [
259  'container' => $entity,
260  'user' => $user,
261  'subtype' => $subtype
262  ];
263 
264  // Unlike permissions, logic check can be used to prevent certain entity
265  // types from being contained by other entity types,
266  // e.g. discussion reply objects can only be contained by discussion objects.
267  // This event can also be used to apply status logic, e.g. to disallow
268  // new replies in closed discussions.
269  // We do not take a stand hence the return is null. This can be used by
270  // handlers to check if another event has modified the value.
271  $logic_check = $this->events->triggerResults('container_logic_check', $type, $params);
272 
273  if ($logic_check === false) {
274  return false;
275  }
276 
277  if ($this->canBypassPermissionsCheck($user_guid)) {
278  return true;
279  }
280 
281  // If the user can edit the container, they can also write to it
282  $return = $entity->canEdit($user_guid);
283 
284  // Container permissions can prevent users from writing to an entity.
285  // For instance, these permissions can prevent non-group members from writing
286  // content to the group.
287  return $this->events->triggerResults('container_permissions_check', $type, $params, $return);
288  }
289 
301  public function canComment(\ElggEntity $entity, int $user_guid = 0): bool {
302  try {
303  $user = $this->entities->getUserForPermissionsCheck($user_guid);
304  } catch (UserFetchFailureException $e) {
305  return false;
306  }
307 
308  $container_result = $this->canWriteToContainer($entity, 'object', 'comment', $user_guid);
309  if ($this->canBypassPermissionsCheck($user_guid)) {
310  // doing this again here to prevent bypassed users to be influenced by 'permissions_check:comment' event
311  return $container_result;
312  }
313 
314  // By default, we don't take a position of whether commenting is allowed
315  // because it is handled by the subclasses of \ElggEntity
316  $params = [
317  'entity' => $entity,
318  'user' => $user,
319  ];
320  return $this->events->triggerResults('permissions_check:comment', $entity->getType(), $params, $container_result);
321  }
322 
338  public function canAnnotate(\ElggEntity $entity, int $user_guid = 0, string $annotation_name = ''): bool {
339  if ($this->canBypassPermissionsCheck($user_guid)) {
340  return true;
341  }
342 
343  try {
344  $user = $this->entities->getUserForPermissionsCheck($user_guid);
345  } catch (UserFetchFailureException $e) {
346  return false;
347  }
348 
349  $return = (bool) $user;
350 
351  $params = [
352  'entity' => $entity,
353  'user' => $user,
354  'annotation_name' => $annotation_name,
355  ];
356 
357  if (!empty($annotation_name)) {
358  $return = $this->events->triggerResults("permissions_check:annotate:$annotation_name", $entity->getType(), $params, $return);
359  }
360 
361  return $this->events->triggerResults('permissions_check:annotate', $entity->getType(), $params, $return);
362  }
363 
375  public function canDownload(\ElggFile $entity, int $user_guid = 0, bool $default = true): bool {
376  if ($this->canBypassPermissionsCheck($user_guid)) {
377  return true;
378  }
379 
380  try {
381  $user = $this->entities->getUserForPermissionsCheck($user_guid);
382  } catch (UserFetchFailureException $e) {
383  return false;
384  }
385 
386  $params = [
387  'entity' => $entity,
388  'user' => $user
389  ];
390 
391  return $this->events->triggerResults('permissions_check:download', 'file', $params, $default);
392  }
393 }
canBypassPermissionsCheck(int $user_guid=0)
Decides if the access system should be ignored for a user.
$default
Definition: checkbox.php:30
if(!$items) $item
Definition: delete.php:13
$user_guid
Definition: login_as.php:10
$params
Saves global plugin settings.
Definition: save.php:13
__construct(EventsService $events, EntityTable $entities, SessionManagerService $session_manager)
Constructor.
if($id< 1) $annotation
Definition: delete.php:11
canDownload(\ElggFile $entity, int $user_guid=0, bool $default=true)
Can a user download a file?
Entity Annotation.
Events service.
canWriteToContainer(\ElggEntity $entity, string $type, string $subtype, int $user_guid=0)
Can a user add an entity to this container.
$type
Definition: delete.php:22
canEdit(int $user_guid=0)
Can a user edit this entity?
Definition: ElggEntity.php:946
canEditAnnotation(\ElggEntity $entity, int $user_guid=0,\ElggAnnotation $annotation=null)
Determines whether or not the user can edit this annotation.
$entity
Definition: reset.php:8
Exception indicating a user could not be looked up for a permissions check.
$user
Definition: ban.php:7
$container
Definition: delete.php:24
canEdit(\ElggEntity $entity, int $user_guid=0)
Can a user edit this entity?
canComment(\ElggEntity $entity, int $user_guid=0)
Can a user comment on an entity?
canAnnotate(\ElggEntity $entity, int $user_guid=0, string $annotation_name= '')
Can a user annotate an entity?
getType()
Returns the entity type.
$subtype
Definition: delete.php:23
getOriginalAttributes()
Get the original values of attribute(s) that have been modified since the entity was persisted...
Definition: ElggEntity.php:283
canDelete(\ElggEntity $entity, int $user_guid=0)
Can a user delete this entity?
canDeleteRiverItem(\ElggRiverItem $item, int $user_guid=0)
Can a user delete this river item?
User capabilities service.
if(empty($title)&&empty($body)) if(!empty($link)) $attrs
Definition: message.php:28
Entity table database service.
Definition: EntityTable.php:26