diff options
Diffstat (limited to 'engine/lib/users.php')
| -rw-r--r-- | engine/lib/users.php | 2596 |
1 files changed, 1588 insertions, 1008 deletions
diff --git a/engine/lib/users.php b/engine/lib/users.php index 229735960..a8fb9121c 100644 --- a/engine/lib/users.php +++ b/engine/lib/users.php @@ -1,1031 +1,1611 @@ -<?php
-
- /**
- * Elgg users
- * Functions to manage multiple or single users in an Elgg install
- *
- * @package Elgg
- * @subpackage Core
- * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
- * @author Curverider Ltd
- * @copyright Curverider Ltd 2008
- * @link http://elgg.org/
- */
- - /// Map a username to a cached GUID - $USERNAME_TO_GUID_MAP_CACHE = array(); - - /// Map a user code to a cached GUID - $CODE_TO_GUID_MAP_CACHE = array(); -
- /**
- * ElggUser
- * - * Representation of a "user" in the system. - * - * @package Elgg - * @subpackage Core
- */
- class ElggUser extends ElggEntity
- {
- /**
- * Initialise the attributes array.
- * This is vital to distinguish between metadata and base parameters.
- *
- * Place your base parameters here.
- */
- protected function initialise_attributes()
- {
- parent::initialise_attributes();
-
- $this->attributes['type'] = "user";
- $this->attributes['name'] = "";
- $this->attributes['username'] = "";
- $this->attributes['password'] = "";
- $this->attributes['email'] = "";
- $this->attributes['language'] = "";
- $this->attributes['code'] = "";
- $this->attributes['tables_split'] = 2;
- }
-
- /**
- * Construct a new user entity, optionally from a given id value.
- *
- * @param mixed $guid If an int, load that GUID.
- * If a db row then will attempt to load the rest of the data.
- * @throws Exception if there was a problem creating the user.
- */
- function __construct($guid = null)
- {
- $this->initialise_attributes();
-
- if (!empty($guid))
- {
- // Is $guid is a DB row - either a entity row, or a user table row.
- if ($guid instanceof stdClass) {
- // Load the rest
- if (!$this->load($guid->guid))
- throw new IOException(sprintf(elgg_echo('IOException:FailedToLoadGUID'), get_class(), $guid->guid));
- }
-
- // See if this is a username
- else if (is_string($guid))
- {
- $guid = get_user_by_username($guid);
- foreach ($guid->attributes as $key => $value)
- $this->attributes[$key] = $value;
-
- }
-
- // Is $guid is an ElggUser? Use a copy constructor
- else if ($guid instanceof ElggUser)
- {
- foreach ($guid->attributes as $key => $value)
- $this->attributes[$key] = $value;
- }
-
- // Is this is an ElggEntity but not an ElggUser = ERROR!
- else if ($guid instanceof ElggEntity)
- throw new InvalidParameterException(elgg_echo('InvalidParameterException:NonElggUser'));
-
- // We assume if we have got this far, $guid is an int
- else if (is_numeric($guid)) {
- if (!$this->load($guid)) IOException(sprintf(elgg_echo('IOException:FailedToLoadGUID'), get_class(), $guid));
+<?php +/** + * Elgg users + * Functions to manage multiple or single users in an Elgg install + * + * @package Elgg.Core + * @subpackage DataModel.User + */ + +/// Map a username to a cached GUID +global $USERNAME_TO_GUID_MAP_CACHE; +$USERNAME_TO_GUID_MAP_CACHE = array(); + +/// Map a user code to a cached GUID +global $CODE_TO_GUID_MAP_CACHE; +$CODE_TO_GUID_MAP_CACHE = array(); + +/** + * Return the user specific details of a user by a row. + * + * @param int $guid The ElggUser guid + * + * @return mixed + * @access private + */ +function get_user_entity_as_row($guid) { + global $CONFIG; + + $guid = (int)$guid; + return get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where guid=$guid"); +} + +/** + * Create or update the entities table for a given user. + * Call create_entity first. + * + * @param int $guid The user's GUID + * @param string $name The user's display name + * @param string $username The username + * @param string $password The password + * @param string $salt A salt for the password + * @param string $email The user's email address + * @param string $language The user's default language + * @param string $code A code + * + * @return bool + * @access private + */ +function create_user_entity($guid, $name, $username, $password, $salt, $email, $language, $code) { + global $CONFIG; + + $guid = (int)$guid; + $name = sanitise_string($name); + $username = sanitise_string($username); + $password = sanitise_string($password); + $salt = sanitise_string($salt); + $email = sanitise_string($email); + $language = sanitise_string($language); + $code = sanitise_string($code); + + $row = get_entity_as_row($guid); + if ($row) { + // Exists and you have access to it + $query = "SELECT guid from {$CONFIG->dbprefix}users_entity where guid = {$guid}"; + if ($exists = get_data_row($query)) { + $query = "UPDATE {$CONFIG->dbprefix}users_entity + SET name='$name', username='$username', password='$password', salt='$salt', + email='$email', language='$language', code='$code' + WHERE guid = $guid"; + + $result = update_data($query); + if ($result != false) { + // Update succeeded, continue + $entity = get_entity($guid); + if (elgg_trigger_event('update', $entity->type, $entity)) { + return $guid; + } else { + $entity->delete(); } - - else - throw new InvalidParameterException(elgg_echo('InvalidParameterException:UnrecognisedValue'));
- }
- }
- - /** - * Class member get overloading - * - * @param string $name - * @return mixed - */
- function __get($name) { return $this->get($name); } - - /** - * Class member set overloading - * - * @param string $name - * @param mixed $value - * @return mixed - */
- function __set($name, $value) { return $this->set($name, $value); }
-
- /**
- * Override the load function.
- * This function will ensure that all data is loaded (were possible), so
- * if only part of the ElggUser is loaded, it'll load the rest.
- *
- * @param int $guid
- * @return true|false
- */
- protected function load($guid)
- {
- // Test to see if we have the generic stuff
- if (!parent::load($guid))
- return false;
-
- // Check the type
- if ($this->attributes['type']!='user')
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $guid, get_class()));
-
- // Load missing data
- $row = get_user_entity_as_row($guid); - if (($row) && (!$this->isFullyLoaded())) $this->attributes['tables_loaded'] ++; // If $row isn't a cached copy then increment the counter -
- // Now put these into the attributes array as core values
- $objarray = (array) $row;
- foreach($objarray as $key => $value)
- $this->attributes[$key] = $value;
-
- return true;
- }
-
- /**
- * Saves this user to the database.
- * @return true|false
- */
- public function save()
- {
- // Save generic stuff
- if (!parent::save())
- return false;
-
- // Now save specific stuff
- return create_user_entity($this->get('guid'), $this->get('name'), $this->get('username'), $this->get('password'), $this->get('email'), $this->get('language'), $this->get('code')); - }
-
- /**
- * Delete this user.
- * @return true|false
- */
- public function delete()
- {
- if (!parent::delete())
- return false;
-
- return delete_user_entity($this->get('guid'));
- }
-
- /**
- * Get sites that this user is a member of
- *
- * @param string $subtype Optionally, the subtype of result we want to limit to
- * @param int $limit The number of results to return
- * @param int $offset Any indexing offset
- */
- function getSites($subtype="", $limit = 10, $offset = 0) {
- return get_site_users($this->getGUID(), $subtype, $limit, $offset);
- }
-
- /**
- * Add this user to a particular site
- *
- * @param int $site_guid The guid of the site to add it to
- * @return true|false
- */
- function addToSite($site_guid) {
- return add_site_user($this->getGUID(), $site_guid);
- }
-
- /**
- * Remove this user from a particular site
- *
- * @param int $site_guid The guid of the site to remove it from
- * @return true|false
- */
- function removeFromSite($site_guid) {
- return remove_site_user($this->getGUID(), $site_guid);
- }
-
- /**
- * Adds a user to this user's friends list
- *
- * @param int $friend_guid The GUID of the user to add
- * @return true|false Depending on success
- */
- function addFriend($friend_guid) { return user_add_friend($this->getGUID(), $friend_guid); }
-
- /**
- * Removes a user from this user's friends list
- *
- * @param int $friend_guid The GUID of the user to remove
- * @return true|false Depending on success
- */
- function removeFriend($friend_guid) { return user_remove_friend($this->getGUID(), $friend_guid); }
-
- /**
- * Determines whether or not this user is a friend of the currently logged in user
- *
- * @return true|false
- */
- function isFriend() { return user_is_friend($_SESSION['guid'], $this->getGUID()); }
-
- /**
- * Determines whether this user is friends with another user
- *
- * @param int $user_guid The GUID of the user to check is on this user's friends list
- * @return true|false
- */
- function isFriendsWith($user_guid) { return user_is_friend($this->getGUID(), $user_guid); }
-
- /**
- * Determines whether or not this user is on another user's friends list
- *
- * @param int $user_guid The GUID of the user to check against
- * @return true|false
- */
- function isFriendOf($user_guid) { return user_is_friend($user_guid, $this->getGUID()); }
-
- /**
- * Retrieves a list of this user's friends
- *
- * @param string $subtype Optionally, the subtype of user to filter to (leave blank for all)
- * @param int $limit The number of users to retrieve
- * @param int $offset Indexing offset, if any
- * @return array|false Array of ElggUsers, or false, depending on success
- */
- function getFriends($subtype = "", $limit = 10, $offset = 0) { return get_user_friends($this->getGUID(), $subtype, $limit, $offset); }
-
- /**
- * Retrieves a list of people who have made this user a friend
- *
- * @param string $subtype Optionally, the subtype of user to filter to (leave blank for all)
- * @param int $limit The number of users to retrieve
- * @param int $offset Indexing offset, if any
- * @return array|false Array of ElggUsers, or false, depending on success
- */
- function getFriendsOf($subtype = "", $limit = 10, $offset = 0) { return get_user_friends_of($this->getGUID(), $subtype, $limit, $offset); }
-
- /**
- * Get an array of ElggObjects owned by this user.
- *
- * @param string $subtype The subtype of the objects, if any
- * @param int $limit Number of results to return
- * @param int $offset Any indexing offset
- */
- public function getObjects($subtype="", $limit = 10, $offset = 0) { return get_user_objects($this->getGUID(), $subtype, $limit, $offset); }
-
- /**
- * Get an array of ElggObjects owned by this user's friends.
- *
- * @param string $subtype The subtype of the objects, if any
- * @param int $limit Number of results to return
- * @param int $offset Any indexing offset
- */
- public function getFriendsObjects($subtype = "", $limit = 10, $offset = 0) { return get_user_friends_objects($this->getGUID(), $subtype, $limit, $offset); }
-
- /**
- * Counts the number of ElggObjects owned by this user
- *
- * @param string $subtype The subtypes of the objects, if any
- * @return int The number of ElggObjects
- */
- public function countObjects($subtype = "") {
- return count_user_objects($this->getGUID(), $subtype);
- }
-
- /**
- * Get the collections associated with a user.
- *
- * @param string $subtype Optionally, the subtype of result we want to limit to
- * @param int $limit The number of results to return
- * @param int $offset Any indexing offset
- * @return unknown
- */
- public function getCollections($subtype="", $limit = 10, $offset = 0) { return get_user_collections($this->getGUID(), $subtype, $limit, $offset); }
-
- /**
- * If a user's owner is blank, return its own GUID as the owner
- *
- * @return int User GUID
- */
- function getOwner() {
- if ($this->owner_guid == 0)
- return $this->getGUID(); - - return $this->owner_guid;
- }
-
- }
-
- /**
- * Return the user specific details of a user by a row.
- *
- * @param int $guid
- */
- function get_user_entity_as_row($guid)
- {
- global $CONFIG;
- - $row = retrieve_cached_entity_row($guid); - if ($row) - { - // We have already cached this object, so retrieve its value from the cache - if (isset($CONFIG->debug) && $CONFIG->debug == true) - error_log("** Retrieving sub part of GUID:$guid from cache"); - - return $row; - } - else - { - // Object not cached, load it. - if (isset($CONFIG->debug) && $CONFIG->debug == true) - error_log("** Sub part of GUID:$guid loaded from DB"); -
- $guid = (int)$guid;
-
- return get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where guid=$guid"); - }
- }
-
- /**
- * Create or update the extras table for a given user.
- * Call create_entity first.
- *
- * @param int $guid
- * @param string $name
- * @param string $description
- * @param string $url
- */
- function create_user_entity($guid, $name, $username, $password, $email, $language, $code)
- {
- global $CONFIG;
-
- $guid = (int)$guid;
- $name = sanitise_string($name);
- $username = sanitise_string($username);
- $password = sanitise_string($password);
- $email = sanitise_string($email);
- $language = sanitise_string($language);
- $code = sanitise_string($code);
-
- $row = get_entity_as_row($guid);
-
- if ($row)
- {
- // Exists and you have access to it -
- if ($exists = get_data_row("select guid from {$CONFIG->dbprefix}users_entity where guid = {$guid}")) { - $result = update_data("UPDATE {$CONFIG->dbprefix}users_entity set name='$name', username='$username', password='$password', email='$email', language='$language', code='$code', last_action = ". time() ." where guid = {$guid}"); - if ($result != false) - { - // Update succeeded, continue - $entity = get_entity($guid); - if (trigger_elgg_event('update',$entity->type,$entity)) { - return true; - } else { - $entity->delete(); - } - }
} - else - { - // Update failed, attempt an insert. - $result = insert_data("INSERT into {$CONFIG->dbprefix}users_entity (guid, name, username, password, email, language, code) values ($guid, '$name', '$username', '$password', '$email', '$language', '$code')"); - if ($result!==false) { - $entity = get_entity($guid); - if (trigger_elgg_event('create',$entity->type,$entity)) { - return true; - } else { - delete_entity($guid); - } + } else { + // Exists query failed, attempt an insert. + $query = "INSERT into {$CONFIG->dbprefix}users_entity + (guid, name, username, password, salt, email, language, code) + values ($guid, '$name', '$username', '$password', '$salt', '$email', '$language', '$code')"; + + $result = insert_data($query); + if ($result !== false) { + $entity = get_entity($guid); + if (elgg_trigger_event('create', $entity->type, $entity)) { + return $guid; + } else { + $entity->delete(); } } -
- }
-
- return false;
- }
-
- /**
- * Delete a user's extra data.
- *
- * @param int $guid
- */
- function delete_user_entity($guid)
- {
- global $CONFIG;
-
- $guid = (int)$guid;
-
- $row = get_entity_as_row($guid);
-
- // Check to see if we have access and it exists
- if ($row)
- {
- // Delete any existing stuff
- return delete_data("DELETE from {$CONFIG->dbprefix}users_entity where guid=$guid");
- }
-
- return false;
- }
-
- /**
- * Get the sites this user is part of
- *
- * @param int $user_guid The user's GUID
- * @param int $limit Number of results to return
- * @param int $offset Any indexing offset
- * @return false|array On success, an array of ElggSites
- */
- function get_user_sites($user_guid, $limit = 10, $offset = 0) {
- $user_guid = (int)$user_guid;
- $limit = (int)$limit;
- $offset = (int)$offset;
-
- return get_entities_from_relationship("member_of_site", $user_guid, false, "site", "", 0, "time_created desc", $limit, $offset);
- }
-
- /**
- * Adds a user to another user's friends list.
- *
- * @param int $user_guid The GUID of the friending user
- * @param int $friend_guid The GUID of the user to friend
- * @return true|false Depending on success
- */
- function user_add_friend($user_guid, $friend_guid) {
- $user_guid = (int) $user_guid;
- $friend_guid = (int) $friend_guid;
- if (!$friend = get_entity($friend_guid)) return false;
- if (!$user = get_entity($user_guid)) return false;
- if (get_class($user) != "ElggUser" || get_class($friend) != "ElggUser") return false;
- return add_entity_relationship($user_guid, "friend", $friend_guid);
- }
-
- /**
- * Removes a user from another user's friends list.
- *
- * @param int $user_guid The GUID of the friending user
- * @param int $friend_guid The GUID of the user on the friends list
- * @return true|false Depending on success
- */
- function user_remove_friend($user_guid, $friend_guid) {
- $user_guid = (int) $user_guid;
- $friend_guid = (int) $friend_guid;
- return remove_entity_relationship($user_guid, "friend", $friend_guid);
- }
-
- /**
- * Determines whether or not a user is another user's friend.
- *
- * @param int $user_guid The GUID of the user
- * @param int $friend_guid The GUID of the friend
- * @return true|false
- */
- function user_is_friend($user_guid, $friend_guid) {
- return check_entity_relationship($user_guid, "friend", $friend_guid);
- }
-
- /**
- * Obtains a given user's friends
- *
- * @param int $user_guid The user's GUID
- * @param string $subtype The subtype of users, if any
- * @param int $limit Number of results to return (default 10)
- * @param int $offset Indexing offset, if any
- * @return false|array Either an array of ElggUsers or false, depending on success
- */
- function get_user_friends($user_guid, $subtype = "", $limit = 10, $offset = 0) {
- return get_entities_from_relationship("friend",$user_guid,false,"user",$subtype,0,"time_created desc",$limit,$offset);
- }
-
- /**
- * Obtains the people who have made a given user a friend
- *
- * @param int $user_guid The user's GUID
- * @param string $subtype The subtype of users, if any
- * @param int $limit Number of results to return (default 10)
- * @param int $offset Indexing offset, if any
- * @return false|array Either an array of ElggUsers or false, depending on success
- */
- function get_user_friends_of($user_guid, $subtype = "", $limit = 10, $offset = 0) {
- return get_entities_from_relationship("friend",$user_guid,true,"user",$subtype,0,"time_created desc",$limit,$offset);
- }
-
- /**
- * Obtains a list of objects owned by a user
- *
- * @param int $user_guid The GUID of the owning user
- * @param string $subtype Optionally, the subtype of objects
- * @param int $limit The number of results to return (default 10)
- * @param int $offset Indexing offset, if any
- * @return false|array An array of ElggObjects or false, depending on success
- */
- function get_user_objects($user_guid, $subtype = "", $limit = 10, $offset = 0) {
- $ntt = get_entities('object',$subtype, $user_guid, "time_created desc", $limit, $offset);
- return $ntt;
- }
-
- /**
- * Counts the objects (optionally of a particular subtype) owned by a user
- *
- * @param int $user_guid The GUID of the owning user
- * @param string $subtype Optionally, the subtype of objects
- * @return int The number of objects the user owns (of this subtype)
- */
- function count_user_objects($user_guid, $subtype = "") {
- $total = get_entities('object', $subtype, $user_guid, "time_created desc", null, null, true);
- return $total;
- }
-
- /**
- * Displays a list of user objects of a particular subtype, with navigation.
- *
- * @see elgg_view_entity_list
- *
- * @param int $user_guid The GUID of the user
- * @param string $subtype The object subtype
- * @param int $limit The number of entities to display on a page
- * @param true|false $fullview Whether or not to display the full view (default: true)
- * @return string The list in a form suitable to display
- */
- function list_user_objects($user_guid, $subtype = "", $limit = 10, $fullview = true) {
-
- $offset = (int) get_input('offset');
- $limit = (int) $limit;
- $count = (int) count_user_objects($user_guid, $subtype);
- $entities = get_user_objects($user_guid, $subtype, $limit, $offset);
-
- return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview);
- - }
-
-/**
- * Obtains a list of objects owned by a user's friends
- *
- * @param int $user_guid The GUID of the user to get the friends of
- * @param string $subtype Optionally, the subtype of objects
- * @param int $limit The number of results to return (default 10)
- * @param int $offset Indexing offset, if any
- * @return false|array An array of ElggObjects or false, depending on success
- */
- function get_user_friends_objects($user_guid, $subtype = "", $limit = 10, $offset = 0) {
- if ($friends = get_user_friends($user_guid, $subtype, 999999, 0)) {
- $friendguids = array();
- foreach($friends as $friend) {
- $friendguids[] = $friend->getGUID();
- }
- return get_entities('object',$subtype,$friendguids, "time_created desc", $limit, $offset);
- }
- return false;
- }
-
- /**
- * Counts the number of objects owned by a user's friends
- *
- * @param int $user_guid The GUID of the user to get the friends of
- * @param string $subtype Optionally, the subtype of objects
- * @return int The number of objects
- */
- function count_user_friends_objects($user_guid, $subtype = "") {
- if ($friends = get_user_friends($user_guid, $subtype, 999999, 0)) {
- $friendguids = array();
- foreach($friends as $friend) {
- $friendguids[] = $friend->getGUID();
- }
- return get_entities('object',$subtype,$friendguids, "time_created desc", $limit, $offset, true);
- }
- return 0;
- }
-
- /**
- * Displays a list of a user's friends' objects of a particular subtype, with navigation.
- *
- * @see elgg_view_entity_list
- *
- * @param int $user_guid The GUID of the user
- * @param string $subtype The object subtype
- * @param int $limit The number of entities to display on a page
- * @param true|false $fullview Whether or not to display the full view (default: true)
- * @return string The list in a form suitable to display
- */
- function list_user_friends_objects($user_guid, $subtype = "", $limit = 10, $fullview = true) {
-
- $offset = (int) get_input('offset');
- $limit = (int) $limit;
- $count = (int) count_user_friends_objects($user_guid, $subtype);
- $entities = get_user_friends_objects($user_guid, $subtype, $limit, $offset);
-
- return elgg_view_entity_list($entities, $count, $offset, $limit, $fullview);
-
- }
-
- /**
- * Get user objects by an array of metadata
- *
- * @param int $user_guid The GUID of the owning user
- * @param string $subtype Optionally, the subtype of objects
- * @paran array $metadata An array of metadata
- * @param int $limit The number of results to return (default 10)
- * @param int $offset Indexing offset, if any
- * @return false|array An array of ElggObjects or false, depending on success
- * @return unknown
- */
- function get_user_objects_by_metadata($user_guid, $subtype = "", $metadata = array(), $limit = 0, $offset = 0) {
-
- return get_entities_from_metadata_multi($metadata,"object",$subtype,$user_guid,$limit,$offset);
-
- }
-
- /**
- * Get a user object from a GUID.
- *
- * This function returns an ElggUser from a given GUID.
- * @param int $guid The GUID
- * @return ElggUser|false
- * @throws InvalidParameterException if $GUID exists but is not an ElggUser.
- */
- function get_user($guid)
- {
- if (!empty($guid)) // Fixes "Exception thrown without stack frame" when db_select fails
- $result = get_entity($guid);
-
- if ((!empty($result)) && (!($result instanceof ElggUser)))
- throw new InvalidClassException(sprintf(elgg_echo('InvalidClassException:NotValidElggStar'), $guid, get_class()));
-
- if (!empty($result))
- return $result;
-
- return false;
- }
-
- /**
- * Get user by username
- *
- * @param string $username The user's username
- * @return ElggUser|false Depending on success
- */
- function get_user_by_username($username)
- {
- global $CONFIG, $USERNAME_TO_GUID_MAP_CACHE;
-
- $username = sanitise_string($username); - - // Caching - if ( (isset($USERNAME_TO_GUID_MAP_CACHE[$username])) && (retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username])) ) - return retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]); -
- $row = get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where username='$username'");
- if ($row) { - $USERNAME_TO_GUID_MAP_CACHE[$username] = $row->guid;
- return new ElggUser($row); - }
-
- return false;
- }
-
- /**
- * Get user by session code
- *
- * @param string $code The session code
- * @return ElggUser|false Depending on success
- */
- function get_user_by_code($code)
- {
- global $CONFIG, $CODE_TO_GUID_MAP_CACHE;
-
- $code = sanitise_string($code); - - // Caching - if ( (isset($CODE_TO_GUID_MAP_CACHE[$code])) && (retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code])) ) - return retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]); -
- $row = get_data_row("SELECT * from {$CONFIG->dbprefix}users_entity where code='$code'");
- if ($row) { - $CODE_TO_GUID_MAP_CACHE[$code] = $row->guid;
- return new ElggUser($row); - }
-
- return false;
- }
- - /** - * Searches for a user based on a complete or partial name or username using full text searching. - * - * IMPORTANT NOTE: With MySQL's default setup: - * 1) $criteria must be 4 or more characters long - * 2) If $criteria matches greater than 50% of results NO RESULTS ARE RETURNED! - * - * @param string $criteria The partial or full name or username. - * @param int $limit Limit of the search. - * @param int $offset Offset. - * @param string $order_by The order. - * @param boolean $count Whether to return the count of results or just the results. - */ - function search_for_user($criteria, $limit = 10, $offset = 0, $order_by = "", $count = false) - { - global $CONFIG; - - $criteria = sanitise_string($criteria); - $limit = (int)$limit; - $offset = (int)$offset; - $order_by = sanitise_string($order_by); - - $access = get_access_sql_suffix("e"); - - if ($order_by == "") $order_by = "e.time_created desc"; - - if ($count) { - $query = "SELECT count(e.guid) as total "; - } else { - $query = "SELECT e.* "; } - $query .= "from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid where ";
- // $query .= " match(u.name,u.username) against ('$criteria') ";
- $query .= "(u.name like \"%{$criteria}%\" or u.username like \"%{$criteria}%\")";
- $query .= " and $access"; - - if (!$count) { - $query .= " order by $order_by limit $offset, $limit"; // Add order and limit - return get_data($query, "entity_row_to_elggstar"); - } else { - if ($count = get_data_row($query)) { - return $count->total; + } + + return false; +} + +/** + * Disables all of a user's entities + * + * @param int $owner_guid The owner GUID + * + * @return bool Depending on success + */ +function disable_user_entities($owner_guid) { + global $CONFIG; + $owner_guid = (int) $owner_guid; + if ($entity = get_entity($owner_guid)) { + if (elgg_trigger_event('disable', $entity->type, $entity)) { + if ($entity->canEdit()) { + $query = "UPDATE {$CONFIG->dbprefix}entities + set enabled='no' where owner_guid={$owner_guid} + or container_guid = {$owner_guid}"; + + $res = update_data($query); + return $res; + } + } + } + + return false; +} + +/** + * Ban a user + * + * @param int $user_guid The user guid + * @param string $reason A reason + * + * @return bool + */ +function ban_user($user_guid, $reason = "") { + global $CONFIG; + + $user_guid = (int)$user_guid; + + $user = get_entity($user_guid); + + if (($user) && ($user->canEdit()) && ($user instanceof ElggUser)) { + if (elgg_trigger_event('ban', 'user', $user)) { + // Add reason + if ($reason) { + create_metadata($user_guid, 'ban_reason', $reason, '', 0, ACCESS_PUBLIC); + } + + // clear "remember me" cookie code so user cannot login in using it + $user->code = ""; + $user->save(); + + // invalidate memcache for this user + static $newentity_cache; + if ((!$newentity_cache) && (is_memcache_available())) { + $newentity_cache = new ElggMemcache('new_entity_cache'); + } + + if ($newentity_cache) { + $newentity_cache->delete($user_guid); + } + + // Set ban flag + $query = "UPDATE {$CONFIG->dbprefix}users_entity set banned='yes' where guid=$user_guid"; + return update_data($query); + } + + return FALSE; + } + + return FALSE; +} + +/** + * Unban a user. + * + * @param int $user_guid Unban a user. + * + * @return bool + */ +function unban_user($user_guid) { + global $CONFIG; + + $user_guid = (int)$user_guid; + + $user = get_entity($user_guid); + + if (($user) && ($user->canEdit()) && ($user instanceof ElggUser)) { + if (elgg_trigger_event('unban', 'user', $user)) { + create_metadata($user_guid, 'ban_reason', '', '', 0, ACCESS_PUBLIC); + + // invalidate memcache for this user + static $newentity_cache; + if ((!$newentity_cache) && (is_memcache_available())) { + $newentity_cache = new ElggMemcache('new_entity_cache'); + } + + if ($newentity_cache) { + $newentity_cache->delete($user_guid); + } + + + $query = "UPDATE {$CONFIG->dbprefix}users_entity set banned='no' where guid=$user_guid"; + return update_data($query); + } + + return FALSE; + } + + return FALSE; +} + +/** + * Makes user $guid an admin. + * + * @param int $user_guid User guid + * + * @return bool + */ +function make_user_admin($user_guid) { + global $CONFIG; + + $user = get_entity((int)$user_guid); + + if (($user) && ($user instanceof ElggUser) && ($user->canEdit())) { + if (elgg_trigger_event('make_admin', 'user', $user)) { + + // invalidate memcache for this user + static $newentity_cache; + if ((!$newentity_cache) && (is_memcache_available())) { + $newentity_cache = new ElggMemcache('new_entity_cache'); + } + + if ($newentity_cache) { + $newentity_cache->delete($user_guid); + } + + $r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$user_guid"); + _elgg_invalidate_cache_for_entity($user_guid); + return $r; + } + + return FALSE; + } + + return FALSE; +} + +/** + * Removes user $guid's admin flag. + * + * @param int $user_guid User GUID + * + * @return bool + */ +function remove_user_admin($user_guid) { + global $CONFIG; + + $user = get_entity((int)$user_guid); + + if (($user) && ($user instanceof ElggUser) && ($user->canEdit())) { + if (elgg_trigger_event('remove_admin', 'user', $user)) { + + // invalidate memcache for this user + static $newentity_cache; + if ((!$newentity_cache) && (is_memcache_available())) { + $newentity_cache = new ElggMemcache('new_entity_cache'); } + + if ($newentity_cache) { + $newentity_cache->delete($user_guid); + } + + $r = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='no' where guid=$user_guid"); + _elgg_invalidate_cache_for_entity($user_guid); + return $r; + } + + return FALSE; + } + + return FALSE; +} + +/** + * Get the sites this user is part of + * + * @param int $user_guid The user's GUID + * @param int $limit Number of results to return + * @param int $offset Any indexing offset + * + * @return ElggSite[]|false On success, an array of ElggSites + */ +function get_user_sites($user_guid, $limit = 10, $offset = 0) { + $user_guid = (int)$user_guid; + $limit = (int)$limit; + $offset = (int)$offset; + + return elgg_get_entities_from_relationship(array( + 'site_guids' => ELGG_ENTITIES_ANY_VALUE, + 'relationship' => 'member_of_site', + 'relationship_guid' => $user_guid, + 'inverse_relationship' => FALSE, + 'type' => 'site', + 'limit' => $limit, + 'offset' => $offset, + )); +} + +/** + * Adds a user to another user's friends list. + * + * @param int $user_guid The GUID of the friending user + * @param int $friend_guid The GUID of the user to friend + * + * @return bool Depending on success + */ +function user_add_friend($user_guid, $friend_guid) { + $user_guid = (int) $user_guid; + $friend_guid = (int) $friend_guid; + if ($user_guid == $friend_guid) { + return false; + } + if (!$friend = get_entity($friend_guid)) { + return false; + } + if (!$user = get_entity($user_guid)) { + return false; + } + if ((!($user instanceof ElggUser)) || (!($friend instanceof ElggUser))) { + return false; + } + return add_entity_relationship($user_guid, "friend", $friend_guid); +} + +/** + * Removes a user from another user's friends list. + * + * @param int $user_guid The GUID of the friending user + * @param int $friend_guid The GUID of the user on the friends list + * + * @return bool Depending on success + */ +function user_remove_friend($user_guid, $friend_guid) { + $user_guid = (int) $user_guid; + $friend_guid = (int) $friend_guid; + + // perform cleanup for access lists. + $collections = get_user_access_collections($user_guid); + if ($collections) { + foreach ($collections as $collection) { + remove_user_from_access_collection($friend_guid, $collection->id); + } + } + + return remove_entity_relationship($user_guid, "friend", $friend_guid); +} + +/** + * Determines whether or not a user is another user's friend. + * + * @param int $user_guid The GUID of the user + * @param int $friend_guid The GUID of the friend + * + * @return bool + */ +function user_is_friend($user_guid, $friend_guid) { + return check_entity_relationship($user_guid, "friend", $friend_guid) !== false; +} + +/** + * Obtains a given user's friends + * + * @param int $user_guid The user's GUID + * @param string $subtype The subtype of users, if any + * @param int $limit Number of results to return (default 10) + * @param int $offset Indexing offset, if any + * + * @return ElggUser[]|false Either an array of ElggUsers or false, depending on success + */ +function get_user_friends($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10, +$offset = 0) { + + return elgg_get_entities_from_relationship(array( + 'relationship' => 'friend', + 'relationship_guid' => $user_guid, + 'type' => 'user', + 'subtype' => $subtype, + 'limit' => $limit, + 'offset' => $offset + )); +} + +/** + * Obtains the people who have made a given user a friend + * + * @param int $user_guid The user's GUID + * @param string $subtype The subtype of users, if any + * @param int $limit Number of results to return (default 10) + * @param int $offset Indexing offset, if any + * + * @return ElggUser[]|false Either an array of ElggUsers or false, depending on success + */ +function get_user_friends_of($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10, +$offset = 0) { + + return elgg_get_entities_from_relationship(array( + 'relationship' => 'friend', + 'relationship_guid' => $user_guid, + 'inverse_relationship' => TRUE, + 'type' => 'user', + 'subtype' => $subtype, + 'limit' => $limit, + 'offset' => $offset + )); +} + +/** + * Obtains a list of objects owned by a user's friends + * + * @param int $user_guid The GUID of the user to get the friends of + * @param string $subtype Optionally, the subtype of objects + * @param int $limit The number of results to return (default 10) + * @param int $offset Indexing offset, if any + * @param int $timelower The earliest time the entity can have been created. Default: all + * @param int $timeupper The latest time the entity can have been created. Default: all + * + * @return ElggObject[]|false An array of ElggObjects or false, depending on success + */ +function get_user_friends_objects($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, $limit = 10, +$offset = 0, $timelower = 0, $timeupper = 0) { + + if ($friends = get_user_friends($user_guid, "", 999999, 0)) { + $friendguids = array(); + foreach ($friends as $friend) { + $friendguids[] = $friend->getGUID(); } + return elgg_get_entities(array( + 'type' => 'object', + 'subtype' => $subtype, + 'owner_guids' => $friendguids, + 'limit' => $limit, + 'offset' => $offset, + 'container_guids' => $friendguids, + 'created_time_lower' => $timelower, + 'created_time_upper' => $timeupper + )); + } + return FALSE; +} + +/** + * Counts the number of objects owned by a user's friends + * + * @param int $user_guid The GUID of the user to get the friends of + * @param string $subtype Optionally, the subtype of objects + * @param int $timelower The earliest time the entity can have been created. Default: all + * @param int $timeupper The latest time the entity can have been created. Default: all + * + * @return int The number of objects + */ +function count_user_friends_objects($user_guid, $subtype = ELGG_ENTITIES_ANY_VALUE, +$timelower = 0, $timeupper = 0) { + + if ($friends = get_user_friends($user_guid, "", 999999, 0)) { + $friendguids = array(); + foreach ($friends as $friend) { + $friendguids[] = $friend->getGUID(); + } + return elgg_get_entities(array( + 'type' => 'object', + 'subtype' => $subtype, + 'owner_guids' => $friendguids, + 'count' => TRUE, + 'container_guids' => $friendguids, + 'created_time_lower' => $timelower, + 'created_time_upper' => $timeupper + )); + } + return 0; +} + +/** + * Displays a list of a user's friends' objects of a particular subtype, with navigation. + * + * @see elgg_view_entity_list + * + * @param int $user_guid The GUID of the user + * @param string $subtype The object subtype + * @param int $limit The number of entities to display on a page + * @param bool $full_view Whether or not to display the full view (default: true) + * @param bool $listtypetoggle Whether or not to allow you to flip to gallery mode (default: true) + * @param bool $pagination Whether to display pagination (default: true) + * @param int $timelower The earliest time the entity can have been created. Default: all + * @param int $timeupper The latest time the entity can have been created. Default: all + * + * @return string + */ +function list_user_friends_objects($user_guid, $subtype = "", $limit = 10, $full_view = true, +$listtypetoggle = true, $pagination = true, $timelower = 0, $timeupper = 0) { + + $offset = (int)get_input('offset'); + $limit = (int)$limit; + $count = (int)count_user_friends_objects($user_guid, $subtype, $timelower, $timeupper); + + $entities = get_user_friends_objects($user_guid, $subtype, $limit, $offset, + $timelower, $timeupper); + + return elgg_view_entity_list($entities, array( + 'count' => $count, + 'offset' => $offset, + 'limit' => $limit, + 'full_view' => $full_view, + 'list_type_toggle' => $listtypetoggle, + 'pagination' => $pagination, + )); +} + +/** + * Get a user object from a GUID. + * + * This function returns an ElggUser from a given GUID. + * + * @param int $guid The GUID + * + * @return ElggUser|false + */ +function get_user($guid) { + // Fixes "Exception thrown without stack frame" when db_select fails + if (!empty($guid)) { + $result = get_entity($guid); + } + + if ((!empty($result)) && (!($result instanceof ElggUser))) { return false; } - - /** - * A function that returns a maximum of $limit users who have done something within the last - * $seconds seconds. - * - * @param int $seconds Number of seconds (default 600 = 10min) - * @param int $limit Limit, default 10. - * @param int $offset Offset, defualt 0. - */ - function find_active_users($seconds = 600, $limit = 10, $offset = 0) - { + + if (!empty($result)) { + return $result; + } + + return false; +} + +/** + * Get user by username + * + * @param string $username The user's username + * + * @return ElggUser|false Depending on success + */ +function get_user_by_username($username) { + global $CONFIG, $USERNAME_TO_GUID_MAP_CACHE; + + // Fixes #6052. Username is frequently sniffed from the path info, which, + // unlike $_GET, is not URL decoded. If the username was not URL encoded, + // this is harmless. + $username = rawurldecode($username); + + $username = sanitise_string($username); + $access = get_access_sql_suffix('e'); + + // Caching + if ((isset($USERNAME_TO_GUID_MAP_CACHE[$username])) + && (_elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]))) { + return _elgg_retrieve_cached_entity($USERNAME_TO_GUID_MAP_CACHE[$username]); + } + + $query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u + join {$CONFIG->dbprefix}entities e on e.guid=u.guid + where u.username='$username' and $access "; + + $entity = get_data_row($query, 'entity_row_to_elggstar'); + if ($entity) { + $USERNAME_TO_GUID_MAP_CACHE[$username] = $entity->guid; + } else { + $entity = false; + } + + return $entity; +} + +/** + * Get user by session code + * + * @param string $code The session code + * + * @return ElggUser|false Depending on success + */ +function get_user_by_code($code) { + global $CONFIG, $CODE_TO_GUID_MAP_CACHE; + + $code = sanitise_string($code); + + $access = get_access_sql_suffix('e'); + + // Caching + if ((isset($CODE_TO_GUID_MAP_CACHE[$code])) + && (_elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]))) { + + return _elgg_retrieve_cached_entity($CODE_TO_GUID_MAP_CACHE[$code]); + } + + $query = "SELECT e.* from {$CONFIG->dbprefix}users_entity u + join {$CONFIG->dbprefix}entities e on e.guid=u.guid + where u.code='$code' and $access"; + + $entity = get_data_row($query, 'entity_row_to_elggstar'); + if ($entity) { + $CODE_TO_GUID_MAP_CACHE[$code] = $entity->guid; + } + + return $entity; +} + +/** + * Get an array of users from an email address + * + * @param string $email Email address. + * + * @return array + */ +function get_user_by_email($email) { + global $CONFIG; + + $email = sanitise_string($email); + + $access = get_access_sql_suffix('e'); + + $query = "SELECT e.* from {$CONFIG->dbprefix}entities e + join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid + where email='$email' and $access"; + + return get_data($query, 'entity_row_to_elggstar'); +} + +/** + * A function that returns a maximum of $limit users who have done something within the last + * $seconds seconds or the total count of active users. + * + * @param int $seconds Number of seconds (default 600 = 10min) + * @param int $limit Limit, default 10. + * @param int $offset Offset, default 0. + * @param bool $count Count, default false. + * + * @return mixed + */ +function find_active_users($seconds = 600, $limit = 10, $offset = 0, $count = false) { + $seconds = (int)$seconds; + $limit = (int)$limit; + $offset = (int)$offset; + $params = array('seconds' => $seconds, 'limit' => $limit, 'offset' => $offset, 'count' => $count); + $data = elgg_trigger_plugin_hook('find_active_users', 'system', $params, NULL); + if (!$data) { global $CONFIG; - - $seconds = (int)$seconds; - $limit = (int)$limit; - $offset = (int)$offset; - + $time = time() - $seconds; - - $query = "SELECT distinct e.* from {$CONFIG->dbprefix}entities e join {$CONFIG->dbprefix}users_entity u on e.guid = u.guid where u.last_action >= {$time} order by u.last_action desc limit {$offset},{$limit}"; - - return get_data($query, "entity_row_to_elggstar"); + + $data = elgg_get_entities(array( + 'type' => 'user', + 'limit' => $limit, + 'offset' => $offset, + 'count' => $count, + 'joins' => array("join {$CONFIG->dbprefix}users_entity u on e.guid = u.guid"), + 'wheres' => array("u.last_action >= {$time}"), + 'order_by' => "u.last_action desc" + )); } - - /** - * Generate a validation code for a given user's email address. - * - * @param int $user_guid The user id - * @param string $email_address The email address - */ - function generate_email_validation_code($user_guid, $email_address) - { - global $CONFIG; - - return md5($user_guid . $email_address . $CONFIG->site->url); // Note I bind to site URL, this is important on multisite! + return $data; +} + +/** + * Generate and send a password request email to a given user's registered email address. + * + * @param int $user_guid User GUID + * + * @return bool + */ +function send_new_password_request($user_guid) { + $user_guid = (int)$user_guid; + + $user = get_entity($user_guid); + if ($user instanceof ElggUser) { + // generate code + $code = generate_random_cleartext_password(); + $user->setPrivateSetting('passwd_conf_code', $code); + + // generate link + $link = elgg_get_site_url() . "resetpassword?u=$user_guid&c=$code"; + + // generate email + $email = elgg_echo('email:resetreq:body', array($user->name, $_SERVER['REMOTE_ADDR'], $link)); + + return notify_user($user->guid, elgg_get_site_entity()->guid, + elgg_echo('email:resetreq:subject'), $email, array(), 'email'); + } + + return false; +} + +/** + * Low level function to reset a given user's password. + * + * This can only be called from execute_new_password_request(). + * + * @param int $user_guid The user. + * @param string $password Text (which will then be converted into a hash and stored) + * + * @return bool + */ +function force_user_password_reset($user_guid, $password) { + $user = get_entity($user_guid); + if ($user instanceof ElggUser) { + $ia = elgg_set_ignore_access(); + + $user->salt = generate_random_cleartext_password(); + $hash = generate_user_password($user, $password); + $user->password = $hash; + $result = (bool)$user->save(); + + elgg_set_ignore_access($ia); + + return $result; + } + + return false; +} + +/** + * Validate and execute a password reset for a user. + * + * @param int $user_guid The user id + * @param string $conf_code Confirmation code as sent in the request email. + * + * @return mixed + */ +function execute_new_password_request($user_guid, $conf_code) { + global $CONFIG; + + $user_guid = (int)$user_guid; + $user = get_entity($user_guid); + + if ($user instanceof ElggUser) { + $saved_code = $user->getPrivateSetting('passwd_conf_code'); + + if ($saved_code && $saved_code == $conf_code) { + $password = generate_random_cleartext_password(); + + if (force_user_password_reset($user_guid, $password)) { + remove_private_setting($user_guid, 'passwd_conf_code'); + // clean the logins failures + reset_login_failure_count($user_guid); + + $email = elgg_echo('email:resetpassword:body', array($user->name, $password)); + + return notify_user($user->guid, $CONFIG->site->guid, + elgg_echo('email:resetpassword:subject'), $email, array(), 'email'); + } + } + } + + return FALSE; +} + +/** + * Simple function that will generate a random clear text password + * suitable for feeding into generate_user_password(). + * + * @see generate_user_password + * + * @return string + */ +function generate_random_cleartext_password() { + return substr(md5(microtime() . rand()), 0, 8); +} + +/** + * Generate a password for a user, currently uses MD5. + * + * @param ElggUser $user The user this is being generated for. + * @param string $password Password in clear text + * + * @return string + */ +function generate_user_password(ElggUser $user, $password) { + return md5($password . $user->salt); +} + +/** + * Simple function which ensures that a username contains only valid characters. + * + * This should only permit chars that are valid on the file system as well. + * + * @param string $username Username + * + * @return bool + * @throws RegistrationException on invalid + */ +function validate_username($username) { + global $CONFIG; + + // Basic, check length + if (!isset($CONFIG->minusername)) { + $CONFIG->minusername = 4; + } + + if (strlen($username) < $CONFIG->minusername) { + $msg = elgg_echo('registration:usernametooshort', array($CONFIG->minusername)); + throw new RegistrationException($msg); } - /** - * Send out a validation request for a given user. - * This function assumes that a user has already been created and that the email address has been - * saved in the email field in the database. - * - * @param int $user_guid The user. - * @return bool - */ - function request_email_validation($user_guid) - { - global $CONFIG; - - $user_guid = (int)$user_guid; - - $user = get_entity($user_guid); - if (($user) && ($user instanceof ElggUser)) - { - // Clear existing status - $user->validated_email = false; - - // Work out validate link - $link = $CONFIG->site->url . "action/email/confirm?u=$user_guid&c=" . generate_email_validation_code($user_guid, $user->email); - - // Send validation email - return notify_user($user->guid, $CONFIG->site->guid, elgg_echo('email:validate:subject'), sprintf(elgg_echo('email:validate:body'), $user->username, $link), NULL, 'email'); - + // username in the database has a limit of 128 characters + if (strlen($username) > 128) { + $msg = elgg_echo('registration:usernametoolong', array(128)); + throw new RegistrationException($msg); + } + + // Blacklist for bad characters (partially nicked from mediawiki) + $blacklist = '/[' . + '\x{0080}-\x{009f}' . // iso-8859-1 control chars + '\x{00a0}' . // non-breaking space + '\x{2000}-\x{200f}' . // various whitespace + '\x{2028}-\x{202f}' . // breaks and control chars + '\x{3000}' . // ideographic space + '\x{e000}-\x{f8ff}' . // private use + ']/u'; + + if ( + preg_match($blacklist, $username) + ) { + // @todo error message needs work + throw new RegistrationException(elgg_echo('registration:invalidchars')); + } + + // Belts and braces + // @todo Tidy into main unicode + $blacklist2 = '\'/\\"*& ?#%^(){}[]~?<>;|¬`@-+='; + + for ($n = 0; $n < strlen($blacklist2); $n++) { + if (strpos($username, $blacklist2[$n]) !== false) { + $msg = elgg_echo('registration:invalidchars', array($blacklist2[$n], $blacklist2)); + $msg = htmlspecialchars($msg, ENT_QUOTES, 'UTF-8'); + throw new RegistrationException($msg); } - + } + + $result = true; + return elgg_trigger_plugin_hook('registeruser:validate:username', 'all', + array('username' => $username), $result); +} + +/** + * Simple validation of a password. + * + * @param string $password Clear text password + * + * @return bool + * @throws RegistrationException on invalid + */ +function validate_password($password) { + global $CONFIG; + + if (!isset($CONFIG->min_password_length)) { + $CONFIG->min_password_length = 6; + } + + if (strlen($password) < $CONFIG->min_password_length) { + $msg = elgg_echo('registration:passwordtooshort', array($CONFIG->min_password_length)); + throw new RegistrationException($msg); + } + + $result = true; + return elgg_trigger_plugin_hook('registeruser:validate:password', 'all', + array('password' => $password), $result); +} + +/** + * Simple validation of a email. + * + * @param string $address Email address + * + * @throws RegistrationException on invalid + * @return bool + */ +function validate_email_address($address) { + if (!is_email_address($address)) { + throw new RegistrationException(elgg_echo('registration:notemail')); + } + + // Got here, so lets try a hook (defaulting to ok) + $result = true; + return elgg_trigger_plugin_hook('registeruser:validate:email', 'all', + array('email' => $address), $result); +} + +/** + * Registers a user, returning false if the username already exists + * + * @param string $username The username of the new user + * @param string $password The password + * @param string $name The user's display name + * @param string $email Their email address + * @param bool $allow_multiple_emails Allow the same email address to be + * registered multiple times? + * @param int $friend_guid GUID of a user to friend once fully registered + * @param string $invitecode An invite code from a friend + * + * @return int|false The new user's GUID; false on failure + * @throws RegistrationException + */ +function register_user($username, $password, $name, $email, +$allow_multiple_emails = false, $friend_guid = 0, $invitecode = '') { + + // no need to trim password. + $username = trim($username); + $name = trim(strip_tags($name)); + $email = trim($email); + + // A little sanity checking + if (empty($username) + || empty($password) + || empty($name) + || empty($email)) { return false; } - - /** - * Validate a user email address against the code provided, and if valid set the appropriate flag - * - * @param int $user_guid User GUID - * @param string $code The code provided on validation. - */ - function validate_email($user_guid, $code) - { - $user = get_entity($user_guid); - - $valid = ($code == generate_email_validation_code($user_guid, $user->email)); - if ($valid) - $user->validated_email = true; - - return $valid; + + // Make sure a user with conflicting details hasn't registered and been disabled + $access_status = access_get_show_hidden_status(); + access_show_hidden_entities(true); + + if (!validate_email_address($email)) { + throw new RegistrationException(elgg_echo('registration:emailnotvalid')); } - - /** - * Simple function that will generate a random clear text password suitable for feeding into generate_user_password(). - * - * @see generate_user_password - * @return string - */ - function generate_random_cleartext_password() - { - return substr(md5(microtime()), 0, 8); + + if (!validate_password($password)) { + throw new RegistrationException(elgg_echo('registration:passwordnotvalid')); + } + + if (!validate_username($username)) { + throw new RegistrationException(elgg_echo('registration:usernamenotvalid')); + } + + if ($user = get_user_by_username($username)) { + throw new RegistrationException(elgg_echo('registration:userexists')); + } + + if ((!$allow_multiple_emails) && (get_user_by_email($email))) { + throw new RegistrationException(elgg_echo('registration:dupeemail')); + } + + access_show_hidden_entities($access_status); + + // Create user + $user = new ElggUser(); + $user->username = $username; + $user->email = $email; + $user->name = $name; + $user->access_id = ACCESS_PUBLIC; + $user->salt = generate_random_cleartext_password(); // Note salt generated before password! + $user->password = generate_user_password($user, $password); + $user->owner_guid = 0; // Users aren't owned by anyone, even if they are admin created. + $user->container_guid = 0; // Users aren't contained by anyone, even if they are admin created. + $user->language = get_current_language(); + $user->save(); + + // If $friend_guid has been set, make mutual friends + if ($friend_guid) { + if ($friend_user = get_user($friend_guid)) { + if ($invitecode == generate_invite_code($friend_user->username)) { + $user->addFriend($friend_guid); + $friend_user->addFriend($user->guid); + + // @todo Should this be in addFriend? + add_to_river('river/relationship/friend/create', 'friend', $user->getGUID(), $friend_guid); + add_to_river('river/relationship/friend/create', 'friend', $friend_guid, $user->getGUID()); + } + } + } + + // Turn on email notifications by default + set_user_notification_setting($user->getGUID(), 'email', true); + + return $user->getGUID(); +} + +/** + * Generates a unique invite code for a user + * + * @param string $username The username of the user sending the invitation + * + * @return string Invite code + */ +function generate_invite_code($username) { + $secret = datalist_get('__site_secret__'); + return md5($username . $secret); +} + +/** + * Set the validation status for a user. + * + * @param int $user_guid The user's GUID + * @param bool $status Validated (true) or unvalidated (false) + * @param string $method Optional method to say how a user was validated + * @return bool + * @since 1.8.0 + */ +function elgg_set_user_validation_status($user_guid, $status, $method = '') { + $result1 = create_metadata($user_guid, 'validated', $status, '', 0, ACCESS_PUBLIC, false); + $result2 = create_metadata($user_guid, 'validated_method', $method, '', 0, ACCESS_PUBLIC, false); + if ($result1 && $result2) { + return true; + } else { + return false; + } +} + +/** + * Gets the validation status of a user. + * + * @param int $user_guid The user's GUID + * @return bool|null Null means status was not set for this user. + * @since 1.8.0 + */ +function elgg_get_user_validation_status($user_guid) { + $md = elgg_get_metadata(array( + 'guid' => $user_guid, + 'metadata_name' => 'validated' + )); + if ($md == false) { + return null; } + + if ($md[0]->value) { + return true; + } + + return false; +} + +/** + * Adds collection submenu items + * + * @return void + * @access private + */ +function collections_submenu_items() { + + $user = elgg_get_logged_in_user_entity(); + + elgg_register_menu_item('page', array( + 'name' => 'friends:view:collections', + 'text' => elgg_echo('friends:collections'), + 'href' => "collections/$user->username", + )); +} + +/** + * Page handler for friends-related pages + * + * @param array $segments URL segments + * @param string $handler The first segment in URL used for routing + * + * @return bool + * @access private + */ +function friends_page_handler($segments, $handler) { + elgg_set_context('friends'); - /** - * Generate a password for a user, currently uses MD5. - * - * Later may introduce salting etc. - * - * @param ElggUser $user The user this is being generated for. - * @param string $password Password in clear text - */ - function generate_user_password(ElggUser $user, $password) - { - return md5($password); + if (isset($segments[0]) && $user = get_user_by_username($segments[0])) { + elgg_set_page_owner_guid($user->getGUID()); + } + if (elgg_get_logged_in_user_guid() == elgg_get_page_owner_guid()) { + collections_submenu_items(); } -
- /**
- * Registers a user, returning false if the username already exists
- *
- * @param string $username The username of the new user
- * @param string $password The password
- * @param string $name The user's display name
- * @param string $email Their email address
- * @return int|false The new user's GUID; false on failure
- */
- function register_user($username, $password, $name, $email) {
-
- // Load the configuration
- global $CONFIG;
-
- // A little sanity checking
- if (empty($username)
- || empty($password)
- || empty($name)
- || empty($email)) {
- return false;
- }
-
- // Check to see if $username exists already
- if ($user = get_user_by_username($username)) {
- return false;
- }
-
- // Check to see if we've registered the first admin yet.
- // If not, this is the first admin user!
- $admin = datalist_get('admin_registered');
-
- // Otherwise ...
- $user = new ElggUser();
- $user->username = $username;
- $user->email = $email;
- $user->name = $name;
- $user->access_id = 2; - $user->password = generate_user_password($user, $password);
- $user->save();
-
- if (!$admin) {
- $user->admin = true;
- datalist_set('admin_registered',1);
+ + switch ($handler) { + case 'friends': + require_once(dirname(dirname(dirname(__FILE__))) . "/pages/friends/index.php"); + break; + case 'friendsof': + require_once(dirname(dirname(dirname(__FILE__))) . "/pages/friends/of.php"); + break; + default: + return false; + } + return true; +} + +/** + * Page handler for friends collections + * + * @param array $page_elements Page elements + * + * @return bool + * @access private + */ +function collections_page_handler($page_elements) { + gatekeeper(); + elgg_set_context('friends'); + $base = elgg_get_config('path'); + if (isset($page_elements[0])) { + if ($page_elements[0] == "add") { + elgg_set_page_owner_guid(elgg_get_logged_in_user_guid()); + collections_submenu_items(); + require_once "{$base}pages/friends/collections/add.php"; + return true; + } else { + $user = get_user_by_username($page_elements[0]); + if ($user) { + elgg_set_page_owner_guid($user->getGUID()); + if (elgg_get_logged_in_user_guid() == elgg_get_page_owner_guid()) { + collections_submenu_items(); + } + require_once "{$base}pages/friends/collections/view.php"; + return true; } - - // Turn on email notifications by default - set_user_notification_setting($user->getGUID(), 'email', true);
- - // Send email validation request - request_email_validation($user->getGUID()); -
- return $user->getGUID();
- }
-
- /**
- * Page handler for friends
- *
- */
- function friends_page_handler($page_elements) {
-
- if (isset($page_elements[0]) && $user = get_user_by_username($page_elements[0])) {
- set_page_owner($user->getGUID());
- }
- require_once(dirname(dirname(dirname(__FILE__))) . "/friends/index.php");
-
- }
-
- /**
- * Page handler for friends of
- *
- */
- function friends_of_page_handler($page_elements) {
-
- if (isset($page_elements[0]) && $user = get_user_by_username($page_elements[0])) {
- set_page_owner($user->getGUID());
- }
- require_once(dirname(dirname(dirname(__FILE__))) . "/friends/of.php");
-
- }
-
- /**
- * Sets the last action time of the given user to right now.
- *
- * @param int $user_guid The user GUID
- */
- function set_last_action($user_guid) {
-
- $user_guid = (int) $user_guid;
- global $CONFIG;
- $time = time();
- update_data("update {$CONFIG->dbprefix}users_entity set prev_last_action = last_action, last_action = {$time} where guid = {$user_guid}");
-
- }
-
- /**
- * Users initialisation function, which establishes the page handler
- *
- */
- function users_init() {
-
- register_page_handler('friends','friends_page_handler');
- register_page_handler('friendsof','friends_of_page_handler');
- register_action("register",true);
- register_action("useradd",true); - register_action("friends/add");
- register_action("friends/remove");
- register_action("email/confirm"); -
- register_action("usersettings/save");
- - // User name change - extend_elgg_settings_page('user/settings/name', 'usersettings/user', 1); - //register_action("user/name"); - - // User password change - extend_elgg_settings_page('user/settings/password', 'usersettings/user', 1); - //register_action("user/password"); - - // Add email settings - extend_elgg_settings_page('user/settings/email', 'usersettings/user', 1); - //register_action("email/save"); + } + } + return false; +} + +/** + * Page handler for account related pages + * + * @param array $page_elements Page elements + * @param string $handler The handler string + * + * @return bool + * @access private + */ +function elgg_user_account_page_handler($page_elements, $handler) { + + $base_dir = elgg_get_root_path() . 'pages/account'; + switch ($handler) { + case 'login': + require_once("$base_dir/login.php"); + break; + case 'forgotpassword': + require_once("$base_dir/forgotten_password.php"); + break; + case 'resetpassword': + require_once("$base_dir/reset_password.php"); + break; + case 'register': + require_once("$base_dir/register.php"); + break; + default: + return false; + } + return true; +} + +/** + * Sets the last action time of the given user to right now. + * + * @param int $user_guid The user GUID + * + * @return void + */ +function set_last_action($user_guid) { + $user_guid = (int) $user_guid; + global $CONFIG; + $time = time(); + + $query = "UPDATE {$CONFIG->dbprefix}users_entity + set prev_last_action = last_action, + last_action = {$time} where guid = {$user_guid}"; + + execute_delayed_write_query($query); +} + +/** + * Sets the last logon time of the given user to right now. + * + * @param int $user_guid The user GUID + * + * @return void + */ +function set_last_login($user_guid) { + $user_guid = (int) $user_guid; + global $CONFIG; + $time = time(); + + $query = "UPDATE {$CONFIG->dbprefix}users_entity + set prev_last_login = last_login, last_login = {$time} where guid = {$user_guid}"; + + execute_delayed_write_query($query); +} + +/** + * Creates a relationship between this site and the user. + * + * @param string $event create + * @param string $object_type user + * @param ElggUser $object User object + * + * @return void + * @access private + */ +function user_create_hook_add_site_relationship($event, $object_type, $object) { + add_entity_relationship($object->getGUID(), 'member_of_site', elgg_get_site_entity()->guid); +} + +/** + * Serves the user's avatar + * + * @param string $hook + * @param string $entity_type + * @param string $returnvalue + * @param array $params + * @return string + * @access private + */ +function user_avatar_hook($hook, $entity_type, $returnvalue, $params) { + $user = $params['entity']; + $size = $params['size']; + + if (isset($user->icontime)) { + return "avatar/view/$user->username/$size/$user->icontime"; + } else { + return "_graphics/icons/user/default{$size}.gif"; + } +} + +/** + * Setup the default user hover menu + * @access private + */ +function elgg_user_hover_menu($hook, $type, $return, $params) { + $user = $params['entity']; + /* @var ElggUser $user */ + + if (elgg_is_logged_in()) { + if (elgg_get_logged_in_user_guid() != $user->guid) { + if ($user->isFriend()) { + $url = "action/friends/remove?friend={$user->guid}"; + $text = elgg_echo('friend:remove'); + $name = 'remove_friend'; + } else { + $url = "action/friends/add?friend={$user->guid}"; + $text = elgg_echo('friend:add'); + $name = 'add_friend'; + } + $url = elgg_add_action_tokens_to_url($url); + $item = new ElggMenuItem($name, $text, $url); + $item->setSection('action'); + $return[] = $item; + } else { + $url = "profile/$user->username/edit"; + $item = new ElggMenuItem('profile:edit', elgg_echo('profile:edit'), $url); + $item->setSection('action'); + $return[] = $item; + + $url = "avatar/edit/$user->username"; + $item = new ElggMenuItem('avatar:edit', elgg_echo('avatar:edit'), $url); + $item->setSection('action'); + $return[] = $item; + } + } + + // prevent admins from banning or deleting themselves + if (elgg_get_logged_in_user_guid() == $user->guid) { + return $return; + } + + if (elgg_is_admin_logged_in()) { + $actions = array(); + if (!$user->isBanned()) { + $actions[] = 'ban'; + } else { + $actions[] = 'unban'; + } + $actions[] = 'delete'; + $actions[] = 'resetpassword'; + if (!$user->isAdmin()) { + $actions[] = 'makeadmin'; + } else { + $actions[] = 'removeadmin'; + } + + foreach ($actions as $action) { + $url = "action/admin/user/$action?guid={$user->guid}"; + $url = elgg_add_action_tokens_to_url($url); + $item = new ElggMenuItem($action, elgg_echo($action), $url); + $item->setSection('admin'); + $item->setLinkClass('elgg-requires-confirmation'); + + $return[] = $item; + } + + $url = "profile/$user->username/edit"; + $item = new ElggMenuItem('profile:edit', elgg_echo('profile:edit'), $url); + $item->setSection('admin'); + $return[] = $item; + + $url = "settings/user/$user->username"; + $item = new ElggMenuItem('settings:edit', elgg_echo('settings:edit'), $url); + $item->setSection('admin'); + $return[] = $item; + } + + return $return; +} + +/** + * Setup the menu shown with an entity + * + * @param string $hook + * @param string $type + * @param array $return + * @param array $params + * @return array + * + * @access private + */ +function elgg_users_setup_entity_menu($hook, $type, $return, $params) { + if (elgg_in_context('widgets')) { + return $return; + } + + $entity = $params['entity']; + if (!elgg_instanceof($entity, 'user')) { + return $return; + } + /* @var ElggUser $entity */ + + if ($entity->isBanned()) { + $banned = elgg_echo('banned'); + $options = array( + 'name' => 'banned', + 'text' => "<span>$banned</span>", + 'href' => false, + 'priority' => 0, + ); + $return = array(ElggMenuItem::factory($options)); + } else { + $return = array(); + if (isset($entity->location)) { + $location = htmlspecialchars($entity->location, ENT_QUOTES, 'UTF-8', false); + $options = array( + 'name' => 'location', + 'text' => "<span>$location</span>", + 'href' => false, + 'priority' => 150, + ); + $return[] = ElggMenuItem::factory($options); + } + } + + return $return; +} + +/** + * This function loads a set of default fields into the profile, then triggers a hook letting other plugins to edit + * add and delete fields. + * + * Note: This is a secondary system:init call and is run at a super low priority to guarantee that it is called after all + * other plugins have initialised. + * @access private + */ +function elgg_profile_fields_setup() { + global $CONFIG; + + $profile_defaults = array ( + 'description' => 'longtext', + 'briefdescription' => 'text', + 'location' => 'location', + 'interests' => 'tags', + 'skills' => 'tags', + 'contactemail' => 'email', + 'phone' => 'text', + 'mobile' => 'text', + 'website' => 'url', + 'twitter' => 'text' + ); + + $loaded_defaults = array(); + if ($fieldlist = elgg_get_config('profile_custom_fields')) { + if (!empty($fieldlist)) { + $fieldlistarray = explode(',', $fieldlist); + foreach ($fieldlistarray as $listitem) { + if ($translation = elgg_get_config("admin_defined_profile_{$listitem}")) { + $type = elgg_get_config("admin_defined_profile_type_{$listitem}"); + $loaded_defaults["admin_defined_profile_{$listitem}"] = $type; + add_translation(get_current_language(), array("profile:admin_defined_profile_{$listitem}" => $translation)); + } + } + } + } + + if (count($loaded_defaults)) { + $CONFIG->profile_using_custom = true; + $profile_defaults = $loaded_defaults; + } + + $CONFIG->profile_fields = elgg_trigger_plugin_hook('profile:fields', 'profile', NULL, $profile_defaults); + + // register any tag metadata names + foreach ($CONFIG->profile_fields as $name => $type) { + if ($type == 'tags' || $type == 'location' || $type == 'tag') { + elgg_register_tag_metadata_name($name); + // register a tag name translation + add_translation(get_current_language(), array("tag_names:$name" => elgg_echo("profile:$name"))); + } + } +} + +/** + * Avatar page handler + * + * /avatar/edit/<username> + * /avatar/view/<username>/<size>/<icontime> + * + * @param array $page + * @return bool + * @access private + */ +function elgg_avatar_page_handler($page) { + global $CONFIG; + + $user = get_user_by_username($page[1]); + if ($user) { + elgg_set_page_owner_guid($user->getGUID()); + } + + if ($page[0] == 'edit') { + require_once("{$CONFIG->path}pages/avatar/edit.php"); + return true; + } else { + set_input('size', $page[2]); + require_once("{$CONFIG->path}pages/avatar/view.php"); + return true; + } + return false; +} + +/** + * Profile page handler + * + * @param array $page + * @return bool + * @access private + */ +function elgg_profile_page_handler($page) { + global $CONFIG; + + $user = get_user_by_username($page[0]); + elgg_set_page_owner_guid($user->guid); + + if ($page[1] == 'edit') { + require_once("{$CONFIG->path}pages/profile/edit.php"); + return true; + } + return false; +} + +/** + * Sets up user-related menu items + * + * @return void + * @access private + */ +function users_pagesetup() { + + $owner = elgg_get_page_owner_entity(); + $viewer = elgg_get_logged_in_user_entity(); + + if ($owner) { + $params = array( + 'name' => 'friends', + 'text' => elgg_echo('friends'), + 'href' => 'friends/' . $owner->username, + 'contexts' => array('friends') + ); + elgg_register_menu_item('page', $params); + + $params = array( + 'name' => 'friends:of', + 'text' => elgg_echo('friends:of'), + 'href' => 'friendsof/' . $owner->username, + 'contexts' => array('friends') + ); + elgg_register_menu_item('page', $params); - // Add language settings - extend_elgg_settings_page('user/settings/language', 'usersettings/user', 1); - //register_action("user/language");
-
- register_plugin_hook('usersettings:save','user','users_settings_save');
- register_plugin_hook('search','all','search_list_users_by_name');
-
- }
-
- /**
- * Returns a formatted list of users suitable for injecting into search.
- *
- */
- function search_list_users_by_name($hook, $user, $returnvalue, $tag) {
-
- // Change this to set the number of users that display on the search page
- $threshold = 4;
-
- if ($users = search_for_user($tag,$threshold)) {
-
- $countusers = search_for_user($tag,0,0,"",true);
-
- $return = elgg_view('user/search/startblurb',array('count' => $countusers, 'tag' => $tag));
- foreach($users as $user) {
- $return .= elgg_view_entity($user);
- }
- $return .= elgg_view('user/search/finishblurb',array('count' => $countusers, 'threshold' => $threshold, 'tag' => $tag));
- return $return;
-
- }
-
- }
-
- function users_settings_save() {
-
- global $CONFIG;
- @include($CONFIG->path . "actions/user/name.php");
- @include($CONFIG->path . "actions/user/password.php");
- @include($CONFIG->path . "actions/email/save.php");
- @include($CONFIG->path . "actions/user/language.php");
-
- }
-
- //register actions *************************************************************
-
- register_elgg_event_handler('init','system','users_init',0);
-
-?>
\ No newline at end of file + elgg_register_menu_item('page', array( + 'name' => 'edit_avatar', + 'href' => "avatar/edit/{$owner->username}", + 'text' => elgg_echo('avatar:edit'), + 'contexts' => array('profile_edit'), + )); + + elgg_register_menu_item('page', array( + 'name' => 'edit_profile', + 'href' => "profile/{$owner->username}/edit", + 'text' => elgg_echo('profile:edit'), + 'contexts' => array('profile_edit'), + )); + } + + // topbar + if ($viewer) { + elgg_register_menu_item('topbar', array( + 'name' => 'profile', + 'href' => $viewer->getURL(), + 'text' => elgg_view('output/img', array( + 'src' => $viewer->getIconURL('topbar'), + 'alt' => $viewer->name, + 'title' => elgg_echo('profile'), + 'class' => 'elgg-border-plain elgg-transition', + )), + 'priority' => 100, + 'link_class' => 'elgg-topbar-avatar', + )); + + elgg_register_menu_item('topbar', array( + 'name' => 'friends', + 'href' => "friends/{$viewer->username}", + 'text' => elgg_view_icon('users'), + 'title' => elgg_echo('friends'), + 'priority' => 300, + )); + + elgg_register_menu_item('topbar', array( + 'name' => 'usersettings', + 'href' => "settings/user/{$viewer->username}", + 'text' => elgg_view_icon('settings') . elgg_echo('settings'), + 'priority' => 500, + 'section' => 'alt', + )); + + elgg_register_menu_item('topbar', array( + 'name' => 'logout', + 'href' => "action/logout", + 'text' => elgg_echo('logout'), + 'is_action' => TRUE, + 'priority' => 1000, + 'section' => 'alt', + )); + } +} + +/** + * Users initialisation function, which establishes the page handler + * + * @return void + * @access private + */ +function users_init() { + + elgg_register_page_handler('friends', 'friends_page_handler'); + elgg_register_page_handler('friendsof', 'friends_page_handler'); + elgg_register_page_handler('register', 'elgg_user_account_page_handler'); + elgg_register_page_handler('forgotpassword', 'elgg_user_account_page_handler'); + elgg_register_page_handler('resetpassword', 'elgg_user_account_page_handler'); + elgg_register_page_handler('login', 'elgg_user_account_page_handler'); + elgg_register_page_handler('avatar', 'elgg_avatar_page_handler'); + elgg_register_page_handler('profile', 'elgg_profile_page_handler'); + elgg_register_page_handler('collections', 'collections_page_handler'); + + elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'elgg_user_hover_menu'); + + elgg_register_action('register', '', 'public'); + elgg_register_action('useradd', '', 'admin'); + elgg_register_action('friends/add'); + elgg_register_action('friends/remove'); + elgg_register_action('avatar/upload'); + elgg_register_action('avatar/crop'); + elgg_register_action('avatar/remove'); + elgg_register_action('profile/edit'); + + elgg_register_action('friends/collections/add'); + elgg_register_action('friends/collections/delete'); + elgg_register_action('friends/collections/edit'); + + elgg_register_plugin_hook_handler('entity:icon:url', 'user', 'user_avatar_hook'); + + elgg_register_action('user/passwordreset', '', 'public'); + elgg_register_action('user/requestnewpassword', '', 'public'); + + elgg_register_widget_type('friends', elgg_echo('friends'), elgg_echo('friends:widget:description')); + + // Register the user type + elgg_register_entity_type('user', ''); + + elgg_register_plugin_hook_handler('register', 'menu:entity', 'elgg_users_setup_entity_menu', 501); + + elgg_register_event_handler('create', 'user', 'user_create_hook_add_site_relationship'); +} + +/** + * Runs unit tests for ElggObject + * + * @param string $hook unit_test + * @param string $type system + * @param mixed $value Array of tests + * @param mixed $params Params + * + * @return array + * @access private + */ +function users_test($hook, $type, $value, $params) { + global $CONFIG; + $value[] = "{$CONFIG->path}engine/tests/objects/users.php"; + return $value; +} + +elgg_register_event_handler('init', 'system', 'users_init', 0); +elgg_register_event_handler('init', 'system', 'elgg_profile_fields_setup', 10000); // Ensure this runs after other plugins +elgg_register_event_handler('pagesetup', 'system', 'users_pagesetup', 0); +elgg_register_plugin_hook_handler('unit_test', 'system', 'users_test'); |
