Elgg  Version 2.3
UsersTable.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
12 
22 class UsersTable {
23 
25 
29  protected $config;
30 
34  protected $db;
35 
39  protected $entities;
40 
44  protected $entity_cache;
45 
49  protected $events;
50 
54  protected $table;
55 
65  public function __construct(
67  ) {
68  $this->config = $config;
69  $this->db = $db;
70  $this->table = $this->db->prefix . "users_entity";
71  $this->entities = $entities;
72  $this->entity_cache = $cache;
73  $this->events = $events;
74  }
75 
84  public function getRow($guid) {
85  $sql = "
86  SELECT * FROM {$this->table}
87  WHERE guid = :guid
88  ";
89  $params = [
90  ':guid' => $guid,
91  ];
92  return $this->db->getDataRow($sql, null, $params);
93  }
94 
102  public function disableEntities($owner_guid) {
103  return $this->entities->disableEntities($owner_guid);
104  }
105 
113  public function ban($user_guid, $reason = "") {
114 
116 
117  if (!$user instanceof ElggUser || !$user->canEdit()) {
118  return false;
119  }
120 
121  if (!$this->events->trigger('ban', 'user', $user)) {
122  return false;
123  }
124 
125  create_metadata($user_guid, 'ban_reason', $reason, '', 0, ACCESS_PUBLIC);
126 
129 
130  if ($this->markBanned($user_guid, true)) {
131  return true;
132  }
133 
134  return false;
135  }
136 
146  public function markBanned($guid, $banned) {
147 
148  $query = "
149  UPDATE {$this->table}
150  SET banned = :banned
151  WHERE guid = :guid
152  ";
153 
154  $params = [
155  ':banned' => $banned ? 'yes' : 'no',
156  ':guid' => (int) $guid,
157  ];
158 
159  return $this->db->updateData($query, true, $params);
160  }
161 
168  public function unban($user_guid) {
169 
171 
172  if (!$user instanceof ElggUser || !$user->canEdit()) {
173  return false;
174  }
175 
176  if (!$this->events->trigger('unban', 'user', $user)) {
177  return false;
178  }
179 
180  create_metadata($user_guid, 'ban_reason', '', '', 0, ACCESS_PUBLIC);
181 
184 
185  return $this->markBanned($user_guid, false);
186  }
187 
194  public function makeAdmin($user_guid) {
196 
197  if (!$user instanceof ElggUser || !$user->canEdit()) {
198  return false;
199  }
200 
201  if (!$this->events->trigger('make_admin', 'user', $user)) {
202  return false;
203  }
204 
205  $query = "
206  UPDATE {$this->table}
207  SET admin = 'yes'
208  WHERE guid = :guid
209  ";
210 
211  $params = [
212  ':guid' => (int) $user_guid,
213  ];
214 
217 
218  if ($this->db->updateData($query, true, $params)) {
219  return true;
220  }
221 
222  return false;
223  }
224 
231  public function removeAdmin($user_guid) {
232 
234 
235  if (!$user instanceof ElggUser || !$user->canEdit()) {
236  return false;
237  }
238 
239  if (!$this->events->trigger('remove_admin', 'user', $user)) {
240  return false;
241  }
242 
243  $query = "
244  UPDATE {$this->table}
245  SET admin = 'no'
246  WHERE guid = :guid
247  ";
248 
249  $params = [
250  ':guid' => (int) $user_guid,
251  ];
252 
255 
256  if ($this->db->updateData($query, true, $params)) {
257  return true;
258  }
259 
260  return false;
261  }
262 
270  public function getByUsername($username) {
271 
272  // Fixes #6052. Username is frequently sniffed from the path info, which,
273  // unlike $_GET, is not URL decoded. If the username was not URL encoded,
274  // this is harmless.
275  $username = rawurldecode($username);
276 
277  if (!$username) {
278  return false;
279  }
280 
281  $entity = $this->entity_cache->getByUsername($username);
282  if ($entity) {
283  return $entity;
284  }
285 
286  $users = $this->entities->getEntitiesFromAttributes([
287  'types' => 'user',
288  'attribute_name_value_pairs' => [
289  'name' => 'username',
290  'value' => $username,
291  ],
292  'limit' => 1,
293  ]);
294  return $users ? $users[0] : false;
295  }
296 
303  public function getByEmail($email) {
304  if (!$email) {
305  return [];
306  }
307 
308  $users = $this->entities->getEntitiesFromAttributes([
309  'types' => 'user',
310  'attribute_name_value_pairs' => [
311  'name' => 'email',
312  'value' => $email,
313  ],
314  'limit' => 1,
315  ]);
316 
317  return $users ? : [];
318  }
319 
338  public function findActive($options = array(), $limit = 10, $offset = 0, $count = false) {
339 
340  $seconds = 600; //default value
341 
342  if (!is_array($options)) {
343  elgg_deprecated_notice("find_active_users() now accepts an \$options array", 1.9);
344  if (!$options) {
345  $options = $seconds; //assign default value
346  }
347  $options = array('seconds' => $options);
348  }
349 
350  if ($limit === null) {
351  $limit = $this->config->get('default_limit');
352  }
353 
354  $options = array_merge(array(
355  'seconds' => $seconds,
356  'limit' => $limit,
357  'offset' => $offset,
358  'count' => $count,
359  ), $options);
360 
361  // cast options we're sending to hook
362  foreach (array('seconds', 'limit', 'offset') as $key) {
363  $options[$key] = (int) $options[$key];
364  }
365  $options['count'] = (bool) $options['count'];
366 
367  // allow plugins to override
368  $params = array(
369  'seconds' => $options['seconds'],
370  'limit' => $options['limit'],
371  'offset' => $options['offset'],
372  'count' => $options['count'],
373  'options' => $options,
374  );
375  $data = _elgg_services()->hooks->trigger('find_active_users', 'system', $params, null);
376  // check null because the handler could legitimately return falsey values.
377  if ($data !== null) {
378  return $data;
379  }
380 
381  $dbprefix = $this->config->get('dbprefix');
382  $time = $this->getCurrentTime()->getTimestamp() - $options['seconds'];
383  return elgg_get_entities(array(
384  'type' => 'user',
385  'limit' => $options['limit'],
386  'offset' => $options['offset'],
387  'count' => $options['count'],
388  'joins' => array("join {$dbprefix}users_entity u on e.guid = u.guid"),
389  'wheres' => array("u.last_action >= {$time}"),
390  'order_by' => "u.last_action desc",
391  ));
392  }
393 
407  public function register($username, $password, $name, $email, $allow_multiple_emails = false) {
408 
409  // no need to trim password
410  $username = trim($username);
411  $name = trim(strip_tags($name));
412  $email = trim($email);
413 
414  // A little sanity checking
415  if (empty($username) || empty($password) || empty($name) || empty($email)) {
416  return false;
417  }
418 
419  // Make sure a user with conflicting details hasn't registered and been disabled
422 
423  if (!validate_email_address($email)) {
424  throw new RegistrationException(_elgg_services()->translator->translate('registration:emailnotvalid'));
425  }
426 
427  if (!validate_password($password)) {
428  throw new RegistrationException(_elgg_services()->translator->translate('registration:passwordnotvalid'));
429  }
430 
432  throw new RegistrationException(_elgg_services()->translator->translate('registration:usernamenotvalid'));
433  }
434 
436  throw new RegistrationException(_elgg_services()->translator->translate('registration:userexists'));
437  }
438 
439  if ((!$allow_multiple_emails) && (get_user_by_email($email))) {
440  throw new RegistrationException(_elgg_services()->translator->translate('registration:dupeemail'));
441  }
442 
444 
445  // Create user
446  $user = new ElggUser();
447  $user->username = $username;
448  $user->email = $email;
449  $user->name = $name;
450  $user->access_id = ACCESS_PUBLIC;
451  $user->setPassword($password);
452  $user->owner_guid = 0; // Users aren't owned by anyone, even if they are admin created.
453  $user->container_guid = 0; // Users aren't contained by anyone, even if they are admin created.
454  $user->language = _elgg_services()->translator->getCurrentLanguage();
455  if ($user->save() === false) {
456  return false;
457  }
458 
459  // Turn on email notifications by default
460  $user->setNotificationSetting('email', true);
461 
462  return $user->getGUID();
463  }
464 
473  public function generateInviteCode($username) {
474  $time = $this->getCurrentTime()->getTimestamp();
475  return "$time." . _elgg_services()->crypto->getHmac([(int) $time, $username])->getToken();
476  }
477 
487  public function validateInviteCode($username, $code) {
488  // validate the format of the token created by ->generateInviteCode()
489  if (!preg_match('~^(\d+)\.([a-zA-Z0-9\-_]+)$~', $code, $m)) {
490  return false;
491  }
492  $time = $m[1];
493  $mac = $m[2];
494 
495  return _elgg_services()->crypto->getHmac([(int) $time, $username])->matchesToken($mac);
496  }
497 
506  public function setValidationStatus($user_guid, $status, $method = '') {
507  $result1 = create_metadata($user_guid, 'validated', $status, '', 0, ACCESS_PUBLIC, false);
508  $result2 = create_metadata($user_guid, 'validated_method', $method, '', 0, ACCESS_PUBLIC, false);
509  if ($result1 && $result2) {
510  return true;
511  } else {
512  return false;
513  }
514  }
515 
522  public function getValidationStatus($user_guid) {
524  if (!$user || !isset($user->validated)) {
525  return null;
526  }
527  return (bool) $user->validated;
528  }
529 
538  public function setLastAction(ElggUser $user) {
539 
540  $time = $this->getCurrentTime()->getTimestamp();
541 
542  if ($user->last_action == $time) {
543  // no change required
544  return;
545  }
546 
547  $query = "
548  UPDATE {$this->table}
549  SET
550  prev_last_action = last_action,
551  last_action = :last_action
552  WHERE guid = :guid
553  ";
554 
555  $params = [
556  ':last_action' => $time,
557  ':guid' => (int) $user->guid,
558  ];
559 
560  $user->prev_last_action = $user->last_action;
561  $user->last_action = $time;
562 
563  execute_delayed_write_query($query, null, $params);
564 
565  $this->entity_cache->set($user);
566 
567  // If we save the user to memcache during this request, then we'll end up with the
568  // old (incorrect) attributes cached (notice the above query is delayed). So it's
569  // simplest to just resave the user after all plugin code runs.
570  register_shutdown_function(function () use ($user, $time) {
571  $this->entities->updateLastAction($user, $time); // keep entity table in sync
572  $user->storeInPersistedCache(_elgg_get_memcache('new_entity_cache'), $time);
573  });
574  }
575 
582  public function setLastLogin(ElggUser $user) {
583 
584  $time = $this->getCurrentTime()->getTimestamp();
585 
586  if ($user->last_login == $time) {
587  // no change required
588  return;
589  }
590 
591  $query = "
592  UPDATE {$this->table}
593  SET
594  prev_last_login = last_login,
595  last_login = :last_login
596  WHERE guid = :guid
597  ";
598 
599  $params = [
600  ':last_login' => $time,
601  ':guid' => (int) $user->guid,
602  ];
603 
604  $user->prev_last_login = $user->last_login;
605  $user->last_login = $time;
606 
607  execute_delayed_write_query($query, null, $params);
608 
609  $this->entity_cache->set($user);
610 
611  // If we save the user to memcache during this request, then we'll end up with the
612  // old (incorrect) attributes cached. Hence we want to invalidate as late as possible.
613  // the user object gets saved
614  register_shutdown_function(function () use ($user) {
615  $user->storeInPersistedCache(_elgg_get_memcache('new_entity_cache'));
616  });
617  }
618 
619 }
get_user_by_email($email)
Get an array of users from an email address.
Definition: users.php:120
setLastLogin(ElggUser $user)
Sets the last logon time of the given user to right now.
Definition: UsersTable.php:582
$username
Definition: delete.php:22
_elgg_invalidate_cache_for_entity($entity_guid)
Invalidate entity cache.
Definition: cache.php:249
$m
Definition: metadata.php:11
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
create_metadata($entity_guid, $name, $value, $value_type= '', $owner_guid=0, $access_id=null, $allow_multiple=false)
Create a new metadata object, or update an existing one.
Definition: metadata.php:66
$method
Definition: form.php:25
The Elgg database.
Definition: Database.php:17
getValidationStatus($user_guid)
Gets the validation status of a user.
Definition: UsersTable.php:522
$data
Definition: opendd.php:13
disableEntities($owner_guid)
Disables all of a user&#39;s entities.
Definition: UsersTable.php:102
validate_username($username)
Simple function which ensures that a username contains only valid characters.
Definition: users.php:205
if(!$count) $offset
Definition: pagination.php:26
setLastAction(ElggUser $user)
Sets the last action time of the given user to right now.
Definition: UsersTable.php:538
getCurrentTime($modifier= '')
Get the (cloned) time.
Definition: TimeUsing.php:26
validate_email_address($address)
Simple validation of a email.
Definition: users.php:292
$guid
Removes an admin notice.
$mac
Definition: contents.php:14
_elgg_get_memcache($namespace= 'default')
Get a namespaced ElggMemcache object (if memcache is available) or a null cache.
Definition: memcache.php:40
storeInPersistedCache(\ElggSharedMemoryCache $cache, $last_action=0)
Cache the entity in a persisted cache.
Definition: ElggEntity.php:602
$email
Definition: register.php:15
unban($user_guid)
Unban a user (calls events, removes the reason)
Definition: UsersTable.php:168
getByEmail($email)
Get an array of users from an email address.
Definition: UsersTable.php:303
getByUsername($username)
Get user by username.
Definition: UsersTable.php:270
makeAdmin($user_guid)
Makes user $guid an admin.
Definition: UsersTable.php:194
$options
Elgg admin footer.
Definition: footer.php:6
get_user_by_username($username)
Get user by username.
Definition: users.php:98
_elgg_invalidate_memcache_for_entity($entity_guid)
Invalidate an entity in memcache.
Definition: memcache.php:28
$access_status
Definition: unban.php:9
$params
Definition: login.php:72
$owner_guid
__construct(Conf $config, Database $db, EntityTable $entities, EntityCache $cache, EventsService $events)
Constructor.
Definition: UsersTable.php:65
$limit
Definition: userpicker.php:38
ban($user_guid, $reason="")
Ban a user (calls events, stores the reason)
Definition: UsersTable.php:113
$key
Definition: summary.php:34
validate_password($password)
Simple validation of a password.
Definition: users.php:267
execute_delayed_write_query($query, $callback=null, array $params=[])
Queue a query for running during shutdown that writes to the database.
Definition: database.php:21
Volatile cache for entities.
Definition: EntityCache.php:12
$users
Definition: newest.php:8
$dbprefix
Definition: index.php:13
$user
Definition: ban.php:13
table
Definition: admin.css.php:59
elgg ElggUser
Definition: ElggUser.js:12
elgg_get_entities(array $options=array())
Returns an array of entities with optional filtering.
Definition: entities.php:326
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1098
findActive($options=array(), $limit=10, $offset=0, $count=false)
Return users (or the number of them) who have been active within a recent period. ...
Definition: UsersTable.php:338
removeAdmin($user_guid)
Removes user $guid&#39;s admin flag.
Definition: UsersTable.php:231
validateInviteCode($username, $code)
Validate a user&#39;s invite code.
Definition: UsersTable.php:487
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
access_get_show_hidden_status()
Return current status of showing disabled entities.
Definition: access.php:170
$password
Definition: login.php:25
setValidationStatus($user_guid, $status, $method= '')
Set the validation status for a user.
Definition: UsersTable.php:506
const ACCESS_PUBLIC
Definition: elgglib.php:2084
access_show_hidden_entities($show_hidden)
Show or hide disabled entities.
Definition: access.php:158
$entity
Definition: delete.php:7
if(elgg_in_context('widget')) $count
Definition: pagination.php:21
generateInviteCode($username)
Generates a unique invite code for a user.
Definition: UsersTable.php:473
trait TimeUsing
Adds methods for setting the current time (for testing)
Definition: TimeUsing.php:11
$user_guid
Avatar remove action.
Definition: remove.php:6
getRow($guid)
Return the user specific details of a user by a row.
Definition: UsersTable.php:84
markBanned($guid, $banned)
Mark a user entity banned or unbanned.
Definition: UsersTable.php:146
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
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204