Elgg  Version 2.3
AccessCollections.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
14 
25 
29  protected $config;
30 
34  protected $db;
35 
39  protected $access_cache;
40 
44  protected $hooks;
45 
49  protected $session;
50 
54  protected $entities;
55 
59  protected $translator;
60 
64  protected $site_guid;
65 
77  public function __construct(
78  Conf $config,
79  Database $db,
85  $this->config = $config;
86  $this->site_guid = $this->config->get('site_guid');
87  $this->db = $db;
88  $this->entities = $entities;
89  $this->access_cache = $cache;
90  $this->hooks = $hooks;
91  $this->session = $session;
92  $this->translator = $translator;
93  }
94 
110  function getAccessList($user_guid = 0, $site_guid = 0, $flush = false) {
112  $cache = $this->access_cache;
113 
114  if ($flush) {
115  $cache->clear();
116  }
117 
118  if ($user_guid == 0) {
119  $user_guid = $this->session->getLoggedInUserGuid();
120  }
121 
122  if (($site_guid == 0) && $this->site_guid) {
124  }
125  $user_guid = (int) $user_guid;
126  $site_guid = (int) $site_guid;
127 
128  $hash = $user_guid . $site_guid . 'get_access_list';
129 
130  if ($cache[$hash]) {
131  return $cache[$hash];
132  }
133 
134  $access_array = $this->getAccessArray($user_guid, $site_guid, $flush);
135  $access = "(" . implode(",", $access_array) . ")";
136 
137  if ($init_finished) {
138  $cache[$hash] = $access;
139  }
140 
141  return $access;
142  }
143 
169  function getAccessArray($user_guid = 0, $site_guid = 0, $flush = false) {
171 
172  $cache = $this->access_cache;
173 
174  if ($flush) {
175  $cache->clear();
176  }
177 
178  if ($user_guid == 0) {
179  $user_guid = $this->session->getLoggedInUserGuid();
180  }
181 
182  if (($site_guid == 0) && $this->site_guid) {
184  }
185 
186  $user_guid = (int) $user_guid;
187  $site_guid = (int) $site_guid;
188 
189  $hash = $user_guid . $site_guid . 'get_access_array';
190 
191  if ($cache[$hash]) {
192  $access_array = $cache[$hash];
193  } else {
194  $access_array = array(ACCESS_PUBLIC);
195 
196  // The following can only return sensible data for a known user.
197  if ($user_guid) {
198  $db = $this->db;
199  $prefix = $db->prefix;
200 
201  $access_array[] = ACCESS_LOGGED_IN;
202 
203  // Get ACL memberships
204  $query = "SELECT am.access_collection_id"
205  . " FROM {$prefix}access_collection_membership am"
206  . " LEFT JOIN {$prefix}access_collections ag ON ag.id = am.access_collection_id"
207  . " WHERE am.user_guid = $user_guid AND (ag.site_guid = $site_guid OR ag.site_guid = 0)";
208 
209  $collections = $db->getData($query);
210  if ($collections) {
211  foreach ($collections as $collection) {
212  if (!empty($collection->access_collection_id)) {
213  $access_array[] = (int) $collection->access_collection_id;
214  }
215  }
216  }
217 
218  // Get ACLs owned.
219  $query = "SELECT ag.id FROM {$prefix}access_collections ag ";
220  $query .= "WHERE ag.owner_guid = $user_guid AND (ag.site_guid = $site_guid OR ag.site_guid = 0)";
221 
222  $collections = $db->getData($query);
223  if ($collections) {
224  foreach ($collections as $collection) {
225  if (!empty($collection->id)) {
226  $access_array[] = (int) $collection->id;
227  }
228  }
229  }
230 
231  $ignore_access = elgg_check_access_overrides($user_guid);
232 
233  if ($ignore_access == true) {
234  $access_array[] = ACCESS_PRIVATE;
235  }
236  }
237 
238  if ($init_finished) {
239  $cache[$hash] = $access_array;
240  }
241  }
242 
243  $options = array(
244  'user_id' => $user_guid,
245  'site_id' => $site_guid
246  );
247 
248  // see the warning in the docs for this function about infinite loop potential
249  return $this->hooks->trigger('access:collections:read', 'user', $options, $access_array);
250  }
251 
292  public function getWhereSql(array $options = array()) {
294 
295  $defaults = array(
296  'table_alias' => 'e',
297  'user_guid' => $this->session->getLoggedInUserGuid(),
298  'use_enabled_clause' => !$ENTITY_SHOW_HIDDEN_OVERRIDE,
299  'access_column' => 'access_id',
300  'owner_guid_column' => 'owner_guid',
301  'guid_column' => 'guid',
302  );
303 
304  foreach ($options as $key => $value) {
305  if (is_null($value)) {
306  // remove null values so we don't loose defaults in array_merge
307  unset($options[$key]);
308  }
309  }
310 
311  $options = array_merge($defaults, $options);
312 
313  // just in case someone passes a . at the end
314  $options['table_alias'] = rtrim($options['table_alias'], '.');
315 
316  foreach (array('table_alias', 'access_column', 'owner_guid_column', 'guid_column') as $key) {
318  }
319  $options['user_guid'] = sanitize_int($options['user_guid'], false);
320 
321  // only add dot if we have an alias or table name
322  $table_alias = $options['table_alias'] ? $options['table_alias'] . '.' : '';
323 
324  if (!isset($options['ignore_access'])) {
325  $options['ignore_access'] = elgg_check_access_overrides($options['user_guid']);
326  }
327 
328  $clauses = array(
329  'ors' => array(),
330  'ands' => array()
331  );
332 
333  $prefix = $this->db->prefix;
334 
335  if ($options['ignore_access']) {
336  $clauses['ors']['ignore_access'] = '1 = 1';
337  } else if ($options['user_guid']) {
338  // include content of user's friends
339  $clauses['ors']['friends_access'] = "$table_alias{$options['access_column']} = " . ACCESS_FRIENDS . "
340  AND $table_alias{$options['owner_guid_column']} IN (
341  SELECT guid_one FROM {$prefix}entity_relationships
342  WHERE relationship = 'friend' AND guid_two = {$options['user_guid']}
343  )";
344 
345  // include user's content
346  $clauses['ors']['owner_access'] = "$table_alias{$options['owner_guid_column']} = {$options['user_guid']}";
347  }
348 
349  // include standard accesses (public, logged in, access collections)
350  if (!$options['ignore_access']) {
351  $access_list = $this->getAccessList($options['user_guid']);
352  $clauses['ors']['acl_access'] = "$table_alias{$options['access_column']} IN {$access_list}";
353  }
354 
355  if ($options['use_enabled_clause']) {
356  $clauses['ands']['use_enabled'] = "{$table_alias}enabled = 'yes'";
357  }
358 
359  $clauses = $this->hooks->trigger('get_sql', 'access', $options, $clauses);
360 
361  $clauses_str = '';
362  if (is_array($clauses['ors']) && $clauses['ors']) {
363  $clauses_str = '(' . implode(' OR ', $clauses['ors']) . ')';
364  }
365 
366  if (is_array($clauses['ands']) && $clauses['ands']) {
367  if ($clauses_str) {
368  $clauses_str .= ' AND ';
369  }
370  $clauses_str .= '(' . implode(' AND ', $clauses['ands']) . ')';
371  }
372 
373  return "($clauses_str)";
374  }
375 
395  public function hasAccessToEntity($entity, $user = null) {
396  if (!$entity instanceof \ElggEntity) {
397  return false;
398  }
399 
400  if ($entity->access_id == ACCESS_PUBLIC) {
401  // Public entities are always accessible
402  return true;
403  }
404 
405  $user_guid = isset($user) ? (int) $user->guid : elgg_get_logged_in_user_guid();
406 
407  if ($user_guid && $user_guid == $entity->owner_guid) {
408  // Owners have access to their own content
409  return true;
410  }
411 
412  if ($user_guid && $entity->access_id == ACCESS_LOGGED_IN) {
413  // Existing users have access to entities with logged in access
414  return true;
415  }
416 
417  // See #7159. Must not allow ignore access to affect query
418  $ia = elgg_set_ignore_access(false);
419 
420  $row = $this->entities->getRow($entity->guid, $user_guid);
421 
423 
424  return !empty($row);
425  }
426 
453  function getWriteAccessArray($user_guid = 0, $site_guid = 0, $flush = false, array $input_params = array()) {
455  $cache = $this->access_cache;
456 
457  if ($flush) {
458  $cache->clear();
459  }
460 
461  if ($user_guid == 0) {
462  $user_guid = $this->session->getLoggedInUserGuid();
463  }
464 
465  if (($site_guid == 0) && $this->site_guid) {
467  }
468 
469  $user_guid = (int) $user_guid;
470  $site_guid = (int) $site_guid;
471 
472  $hash = $user_guid . $site_guid . 'get_write_access_array';
473 
474  if ($cache[$hash]) {
475  $access_array = $cache[$hash];
476  } else {
477  // @todo is there such a thing as public write access?
478  $access_array = array(
483  );
484 
485  $collections = $this->getEntityCollections($user_guid, $site_guid);
486  if ($collections) {
487  foreach ($collections as $collection) {
488  $access_array[$collection->id] = $collection->name;
489  }
490  }
491 
492  if ($init_finished) {
493  $cache[$hash] = $access_array;
494  }
495  }
496 
497  $options = array(
498  'user_id' => $user_guid,
499  'site_id' => $site_guid,
500  'input_params' => $input_params,
501  );
502  return $this->hooks->trigger('access:collections:write', 'user', $options, $access_array);
503  }
504 
519  function canEdit($collection_id, $user_guid = null) {
520  try {
521  $user = $this->entities->getUserForPermissionsCheck($user_guid);
522  } catch (UserFetchFailureException $e) {
523  return false;
524  }
525 
526  $collection = $this->get($collection_id);
527 
528  if (!$user || !$collection) {
529  return false;
530  }
531 
532  $write_access = $this->getWriteAccessArray($user->guid, 0, true);
533 
534  // don't ignore access when checking users.
535  if ($user_guid) {
536  return array_key_exists($collection_id, $write_access);
537  } else {
538  return elgg_get_ignore_access() || array_key_exists($collection_id, $write_access);
539  }
540  }
541 
559  function create($name, $owner_guid = 0, $site_guid = 0) {
560  $name = trim($name);
561  if (empty($name)) {
562  return false;
563  }
564 
565  if ($owner_guid == 0) {
566  $owner_guid = $this->session->getLoggedInUserGuid();
567  }
568  if (($site_guid == 0) && $this->site_guid) {
570  }
571 
572  $db = $this->db;
573  $prefix = $db->prefix;
574 
575  $name = $db->sanitizeString($name);
576 
577  $q = "INSERT INTO {$prefix}access_collections
578  SET name = '{$name}',
579  owner_guid = {$owner_guid},
580  site_guid = {$site_guid}";
581  $id = $db->insertData($q);
582  if (!$id) {
583  return false;
584  }
585 
586  $params = array(
587  'collection_id' => $id
588  );
589 
590  if (!$this->hooks->trigger('access:collections:addcollection', 'collection', $params, true)) {
591  return false;
592  }
593 
594  return $id;
595  }
596 
612  $acl = $this->get($collection_id);
613 
614  if (!$acl) {
615  return false;
616  }
617  $members = (is_array($members)) ? $members : array();
618 
619  $cur_members = $this->getMembers($collection_id, true);
620  $cur_members = (is_array($cur_members)) ? $cur_members : array();
621 
622  $remove_members = array_diff($cur_members, $members);
623  $add_members = array_diff($members, $cur_members);
624 
625  $result = true;
626 
627  foreach ($add_members as $guid) {
628  $result = $result && $this->addUser($guid, $collection_id);
629  }
630 
631  foreach ($remove_members as $guid) {
632  $result = $result && $this->removeUser($guid, $collection_id);
633  }
634 
635  return $result;
636  }
637 
645  function delete($collection_id) {
647  $params = array('collection_id' => $collection_id);
648 
649  if (!$this->hooks->trigger('access:collections:deletecollection', 'collection', $params, true)) {
650  return false;
651  }
652 
653  $db = $this->db;
654  $prefix = $db->prefix;
655 
656  // Deleting membership doesn't affect result of deleting ACL.
657  $q = "DELETE FROM {$prefix}access_collection_membership
658  WHERE access_collection_id = {$collection_id}";
659  $db->deleteData($q);
660 
661  $q = "DELETE FROM {$prefix}access_collections
662  WHERE id = {$collection_id}";
663  $result = $db->deleteData($q);
664 
665  return (bool) $result;
666  }
667 
680  function get($collection_id) {
681 
683 
684  $db = $this->db;
685  $prefix = $db->prefix;
686 
687  $query = "SELECT * FROM {$prefix}access_collections WHERE id = {$collection_id}";
688  $get_collection = $db->getDataRow($query);
689 
690  return $get_collection;
691  }
692 
705  $user_guid = (int) $user_guid;
707 
708  $collection = $this->get($collection_id);
709 
710  if (!($user instanceof ElggUser) || !$collection) {
711  return false;
712  }
713 
714  $params = array(
715  'collection_id' => $collection_id,
716  'user_guid' => $user_guid
717  );
718 
719  $result = $this->hooks->trigger('access:collections:add_user', 'collection', $params, true);
720  if ($result == false) {
721  return false;
722  }
723 
724  $db = $this->db;
725  $prefix = $db->prefix;
726 
727  // if someone tries to insert the same data twice, we do a no-op on duplicate key
728  $q = "INSERT INTO {$prefix}access_collection_membership
729  SET access_collection_id = $collection_id, user_guid = $user_guid
730  ON DUPLICATE KEY UPDATE user_guid = user_guid";
731  $result = $db->insertData($q);
732 
733  return $result !== false;
734  }
735 
748  $user_guid = (int) $user_guid;
750 
751  $collection = $this->get($collection_id);
752 
753  if (!($user instanceof ElggUser) || !$collection) {
754  return false;
755  }
756 
757  $params = array(
758  'collection_id' => $collection_id,
759  'user_guid' => $user_guid,
760  );
761 
762  if (!$this->hooks->trigger('access:collections:remove_user', 'collection', $params, true)) {
763  return false;
764  }
765 
766  $db = $this->db;
767  $prefix = $db->prefix;
768 
769  $q = "DELETE FROM {$prefix}access_collection_membership
770  WHERE access_collection_id = {$collection_id}
771  AND user_guid = {$user_guid}";
772 
773  return (bool) $db->deleteData($q);
774  }
775 
785  $owner_guid = (int) $owner_guid;
786  $site_guid = (int) $site_guid;
787 
788  if (($site_guid == 0) && $this->site_guid) {
790  }
791 
792  $db = $this->db;
793  $prefix = $db->prefix;
794 
795  $query = "SELECT * FROM {$prefix}access_collections
796  WHERE owner_guid = {$owner_guid}
797  AND site_guid = {$site_guid}
798  ORDER BY name ASC";
799 
800  $collections = $db->getData($query);
801 
802  return $collections;
803  }
804 
813  function getMembers($collection_id, $guids_only = false) {
815 
816  $db = $this->db;
817  $prefix = $db->prefix;
818 
819  if (!$guids_only) {
820  $query = "SELECT e.* FROM {$prefix}access_collection_membership m"
821  . " JOIN {$prefix}entities e ON e.guid = m.user_guid"
822  . " WHERE m.access_collection_id = {$collection_id}";
823  $collection_members = $db->getData($query, "entity_row_to_elggstar");
824  } else {
825  $query = "SELECT e.guid FROM {$prefix}access_collection_membership m"
826  . " JOIN {$prefix}entities e ON e.guid = m.user_guid"
827  . " WHERE m.access_collection_id = {$collection_id}";
828  $collection_members = $db->getData($query);
829  if (!$collection_members) {
830  return false;
831  }
832  foreach ($collection_members as $key => $val) {
833  $collection_members[$key] = $val->guid;
834  }
835  }
836 
837  return $collection_members;
838  }
839 
848  function getCollectionsByMember($member_guid, $site_guid = 0) {
849  $member_guid = (int) $member_guid;
850  $site_guid = (int) $site_guid;
851 
852  if (($site_guid == 0) && $this->site_guid) {
854  }
855 
856  $db = $this->db;
857  $prefix = $db->prefix;
858 
859  $query = "SELECT ac.* FROM {$prefix}access_collections ac
860  JOIN {$prefix}access_collection_membership m ON ac.id = m.access_collection_id
861  WHERE m.user_guid = {$member_guid}
862  AND ac.site_guid = {$site_guid}
863  ORDER BY name ASC";
864 
865  $collections = $db->getData($query);
866 
867  return $collections;
868  }
869 
887  function getReadableAccessLevel($entity_access_id) {
888  $access = (int) $entity_access_id;
889 
891 
892  // Check if entity access id is a defined global constant
893  $access_array = array(
894  ACCESS_PRIVATE => $translator->translate("PRIVATE"),
895  ACCESS_FRIENDS => $translator->translate("access:friends:label"),
896  ACCESS_LOGGED_IN => $translator->translate("LOGGED_IN"),
897  ACCESS_PUBLIC => $translator->translate("PUBLIC"),
898  );
899 
900  if (array_key_exists($access, $access_array)) {
901  return $access_array[$access];
902  }
903 
904  $user_guid = $this->session->getLoggedInUserGuid();
905  if (!$user_guid) {
906  // return 'Limited' if there is no logged in user
907  return $translator->translate('access:limited:label');
908  }
909 
910  // Entity access id is probably a custom access collection
911  // Check if the user has write access to it and can see it's label
912  // Admins should always be able to see the readable version
913  $collection = $this->get($access);
914 
915  if ($collection) {
916  if (($collection->owner_guid == $user_guid) || $this->session->isAdminLoggedIn()) {
917  return $collection->name;
918  }
919  }
920 
921  // return 'Limited' if the user does not have access to the access collection
922  return $translator->translate('access:limited:label');
923  }
924 
925 }
getAccessList($user_guid=0, $site_guid=0, $flush=false)
Return a string of access_ids for $user_guid appropriate for inserting into an SQL IN clause...
getCollectionsByMember($member_guid, $site_guid=0)
Return an array of database row objects of the access collections $entity_guid is a member of...
removeUser($user_guid, $collection_id)
Removes a user from an access collection.
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
getMembers($collection_id, $guids_only=false)
Get all of members of an access collection.
$e
Definition: metadata.php:12
$members
getWriteAccessArray($user_guid=0, $site_guid=0, $flush=false, array $input_params=array())
Returns an array of access permissions that the user is allowed to save content with.
$CONFIG site_guid
The guid of the current site object.
Definition: config.php:65
$defaults
hasAccessToEntity($entity, $user=null)
Can a user access an entity.
The Elgg database.
Definition: Database.php:17
update($collection_id, $members)
Updates the membership in an access collection.
getAccessArray($user_guid=0, $site_guid=0, $flush=false)
Returns an array of access IDs a user is permitted to see.
$value
Definition: longtext.php:42
$guid
Removes an admin notice.
const ACCESS_FRIENDS
Definition: elgglib.php:2085
$collection
getWhereSql(array $options=array())
Returns the SQL where clause for enforcing read access to data.
sanitize_string($string)
Sanitizes a string for use in a query.
Definition: database.php:153
$options
Elgg admin footer.
Definition: footer.php:6
elgg_get_ignore_access()
Get current ignore access setting.
Definition: access.php:54
$params
Definition: login.php:72
WARNING: API IN FLUX.
Definition: Translator.php:11
$owner_guid
addUser($user_guid, $collection_id)
Adds a user to an access collection.
$init_finished
A flag to set if Elgg&#39;s access initialization is finished.
Definition: access.php:521
getEntityCollections($owner_guid, $site_guid=0)
Returns an array of database row objects of the access collections owned by $owner_guid.
elgg_check_access_overrides($user_guid=0)
Decides if the access system should be ignored for a user.
Definition: access.php:503
get_user($guid)
Get a user object from a GUID.
Definition: users.php:87
$key
Definition: summary.php:34
elgg_set_ignore_access($ignore=true)
Set if Elgg&#39;s access system should be ignored.
Definition: access.php:43
$ENTITY_SHOW_HIDDEN_OVERRIDE
Allow disabled entities and metadata to be returned by getter functions.
Definition: access.php:150
Exception indicating a user could not be looked up for a permissions check.
$user
Definition: ban.php:13
const ACCESS_PRIVATE
Definition: elgglib.php:2082
elgg ElggUser
Definition: ElggUser.js:12
elgg global
Pointer to the global context.
Definition: elgglib.js:12
create($name, $owner_guid=0, $site_guid=0)
Creates a new access collection.
$collection_id
Definition: delete.php:9
const ACCESS_PUBLIC
Definition: elgglib.php:2084
getReadableAccessLevel($entity_access_id)
Return the name of an ACCESS_* constant or an access collection, but only if the logged in user owns ...
$entity
Definition: delete.php:7
__construct(Conf $config, Database $db, EntityTable $entities, ElggStaticVariableCache $cache, PluginHooksService $hooks, ElggSession $session, Translator $translator)
Constructor.
$row
const ACCESS_LOGGED_IN
Definition: elgglib.php:2083
sanitize_int($int, $signed=true)
Sanitizes an integer for database use.
Definition: database.php:180
$user_guid
Avatar remove action.
Definition: remove.php:6
if(!$collection_name) $id
Definition: add.php:17
elgg ElggEntity
Definition: ElggEntity.js:16
http free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:5
elgg_get_logged_in_user_guid()
Return the current logged in user by guid.
Definition: sessions.php:42
canEdit($collection_id, $user_guid=null)
Can the user change this access collection?
$access
Definition: save.php:15