Newer
Older
Angie Byron
committed
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\file\Entity\File;
use Drupal\user\Entity\User;
Alex Pott
committed
use Drupal\user\UserInterface;
use Drupal\user\RoleInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\TypedData\DataDefinition;
use Symfony\Component\HttpFoundation\RedirectResponse;
Dries Buytaert
committed
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Drupal\menu_link\Entity\MenuLink;
/**
* @file
* Enables the user registration and login system.
*/
/**
* Maximum length of username text field.
*/
const USERNAME_MAX_LENGTH = 60;
Dries Buytaert
committed
/**
* Only administrators can create user accounts.
*/
Angie Byron
committed
const USER_REGISTER_ADMINISTRATORS_ONLY = 'admin_only';
Dries Buytaert
committed
/**
* Visitors can create their own accounts.
*/
Angie Byron
committed
const USER_REGISTER_VISITORS = 'visitors';
Dries Buytaert
committed
/**
* Visitors can create accounts, but they don't become active without
* administrative approval.
*/
Angie Byron
committed
const USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL = 'visitors_admin_approval';
Dries Buytaert
committed
Angie Byron
committed
/**
* Implement hook_help().
*/
function user_help($path, $arg) {
switch ($path) {
case 'admin/help#user':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The User module allows users to register, log in, and log out. It also allows users with proper permissions to manage user roles (used to classify users) and permissions associated with those roles. For more information, see the online handbook entry for <a href="@user">User module</a>.', array('@user' => 'http://drupal.org/documentation/modules/user')) . '</p>';
Angie Byron
committed
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Creating and managing users') . '</dt>';
Angie Byron
committed
$output .= '<dd>' . t('The User module allows users with the appropriate <a href="@permissions">permissions</a> to create user accounts through the <a href="@people">People administration page</a>, where they can also assign users to one or more roles, and block or delete user accounts. If allowed, users without accounts (anonymous users) can create their own accounts on the <a href="@register">Create new account</a> page.', array('@permissions' => url('admin/people/permissions', array('fragment' => 'module-user')), '@people' => url('admin/people'), '@register' => url('user/register'))) . '</dd>';
Angie Byron
committed
$output .= '<dt>' . t('User roles and permissions') . '</dt>';
Dries Buytaert
committed
$output .= '<dd>' . t('<em>Roles</em> are used to group and classify users; each user can be assigned one or more roles. By default there are two roles: <em>anonymous user</em> (users that are not logged in) and <em>authenticated user</em> (users that are registered and logged in). Depending on choices you made when you installed Drupal, the installation process may have defined more roles, and you can create additional custom roles on the <a href="@roles">Roles page</a>. After creating roles, you can set permissions for each role on the <a href="@permissions_user">Permissions page</a>. Granting a permission allows users who have been assigned a particular role to perform an action on the site, such as viewing a particular type of content, editing or creating content, administering settings for a particular module, or using a particular function of the site (such as search).', array('@permissions_user' => url('admin/people/permissions'), '@roles' => url('admin/people/roles'))) . '</dd>';
Angie Byron
committed
$output .= '<dt>' . t('Account settings') . '</dt>';
$output .= '<dd>' . t('The <a href="@accounts">Account settings page</a> allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization (including signatures), and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '</dd>';
Angie Byron
committed
$output .= '</dl>';
return $output;
case 'admin/people/create':
return '<p>' . t("This web page allows administrators to register new users. Users' e-mail addresses and usernames must be unique.") . '</p>';
Angie Byron
committed
case 'admin/people/permissions':
Dries Buytaert
committed
return '<p>' . t('Permissions let you control what users can do and see on your site. You can define a specific set of permissions for each role. (See the <a href="@role">Roles</a> page to create a role). Two important roles to consider are Authenticated Users and Administrators. Any permissions granted to the Authenticated Users role will be given to any user who can log into your site. You can make any role the Administrator role for the site, meaning this will be granted all new permissions automatically. You can do this on the <a href="@settings">User Settings</a> page. You should be careful to ensure that only trusted users are given this access and level of control of your site.', array('@role' => url('admin/people/roles'), '@settings' => url('admin/config/people/accounts'))) . '</p>';
case 'admin/people/roles':
$output = '<p>' . t('Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined on the <a href="@permissions">permissions page</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the names and order of the roles on your site. It is recommended to order your roles from least permissive (anonymous user) to most permissive (administrator). To delete a role choose "edit role".', array('@permissions' => url('admin/people/permissions'))) . '</p>';
Dries Buytaert
committed
$output .= '<p>' . t('Drupal has three special user roles:') . '</p>';
Angie Byron
committed
$output .= '<ul>';
$output .= '<li>' . t("Anonymous user: this role is used for users that don't have a user account or that are not authenticated.") . '</li>';
$output .= '<li>' . t('Authenticated user: this role is automatically granted to all logged in users.') . '</li>';
Dries Buytaert
committed
$output .= '<li>' . t('Administrator role: this role is automatically granted all new permissions when you install a new module. Configure which role is the administrator role on the <a href="@account_settings">Account settings page</a>.', array('@account_settings' => url('admin/config/people/accounts'))) . '</li>';
Angie Byron
committed
$output .= '</ul>';
return $output;
case 'admin/config/people/accounts/fields':
Alex Pott
committed
return '<p>' . t('This form lets administrators add and edit fields for storing user data.') . '</p>';
case 'admin/config/people/accounts/form-display':
return '<p>' . t('This form lets administrators configure how form fields should be displayed when editing a user profile.') . '</p>';
Angie Byron
committed
case 'admin/config/people/accounts/display':
return '<p>' . t('This form lets administrators configure how fields should be displayed when rendering a user profile page.') . '</p>';
case 'admin/people/search':
return '<p>' . t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username or e-mail address. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda@example.com".') . '</p>';
}
}
Angie Byron
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_theme().
Dries Buytaert
committed
*/
function user_theme() {
return array(
'user' => array(
'render element' => 'elements',
'file' => 'user.pages.inc',
'template' => 'user',
Steven Wittens
committed
),
Dries Buytaert
committed
'user_permission_description' => array(
'variables' => array('permission_item' => NULL, 'hide' => NULL),
'file' => 'user.admin.inc',
),
Dries Buytaert
committed
'user_signature' => array(
'variables' => array('signature' => NULL),
Dries Buytaert
committed
),
'username' => array(
'variables' => array('account' => NULL, 'attributes' => array()),
),
Dries Buytaert
committed
);
}
catch
committed
/**
* Implements hook_page_build().
*/
function user_page_build(&$page) {
$path = drupal_get_path('module', 'user');
Alex Pott
committed
$page['#attached']['css'][$path . '/css/user.module.css'] = array('every_page' => TRUE);
}
/**
* Implements hook_js_alter().
*/
function user_js_alter(&$javascript) {
// If >=1 JavaScript asset has declared a dependency on drupalSettings, the
// 'settings' key will exist. Thus when that key does not exist, return early.
if (!isset($javascript['settings'])) {
return;
}
// Provide the user ID in drupalSettings to allow JavaScript code to customize
// the experience for the end user, rather than the server side, which would
// break the render cache.
// Similarly, provide a permissions hash, so that permission-dependent data
// can be reliably cached on the client side.
$user = \Drupal::currentUser();
$javascript['settings']['data'][] = array(
'user' => array(
'uid' => $user->id(),
'permissionsHash' => \Drupal::service('user.permissions_hash')->generate($user),
),
catch
committed
}
Dries Buytaert
committed
/**
* Implements hook_entity_bundle_info().
*/
function user_entity_bundle_info() {
Alex Pott
committed
$bundles['user']['user']['label'] = t('User');
Dries Buytaert
committed
return $bundles;
}
Angie Byron
committed
/**
Angie Byron
committed
* Entity URI callback.
Angie Byron
committed
*/
Angie Byron
committed
function user_uri($user) {
return array(
Alex Pott
committed
'path' => 'user/' . $user->id(),
Angie Byron
committed
);
Angie Byron
committed
}
/**
* Populates $entity->account for each prepared entity.
*
Alex Pott
committed
* Called by Drupal\Core\Entity\EntityViewBuilderInterface::buildContent()
Angie Byron
committed
* implementations.
*
* @param array $entities
* The entities keyed by entity ID.
*/
function user_attach_accounts(array $entities) {
$uids = array();
foreach ($entities as $entity) {
$uids[] = $entity->getAuthorId();
}
$uids = array_unique($uids);
$accounts = user_load_multiple($uids);
$anonymous = drupal_anonymous_user();
foreach ($entities as $id => $entity) {
if (isset($accounts[$entity->getAuthorId()])) {
$entities[$id]->account = $accounts[$entity->getAuthorId()];
}
else {
$entities[$id]->account = $anonymous;
}
}
}
/**
* Returns whether this site supports the default user picture feature.
*
* This approach preserves compatibility with node/comment templates. Alternate
* user picture implementations (e.g., Gravatar) should provide their own
* add/edit/delete forms and populate the 'picture' variable during the
* preprocess stage.
*/
function user_picture_enabled() {
return (bool) field_info_instance('user', 'user_picture', 'user');
}
Angie Byron
committed
/**
Dries Buytaert
committed
* Implements hook_field_extra_fields().
Angie Byron
committed
*/
function user_field_extra_fields() {
Dries Buytaert
committed
$fields['user']['user']['form']['account'] = array(
'label' => t('User name and password'),
'description' => t('User module account form elements.'),
'weight' => -10,
);
if (\Drupal::config('user.settings')->get('signatures')) {
Dries Buytaert
committed
$fields['user']['user']['form']['signature_settings'] = array(
'label' => t('Signature settings'),
'description' => t('User module form element.'),
'weight' => 1,
);
}
$fields['user']['user']['form']['language'] = array(
'label' => t('Language settings'),
'description' => t('User module form element.'),
'weight' => 0,
);
if (\Drupal::config('system.date')->get('timezone.user.configurable')) {
Dries Buytaert
committed
$fields['user']['user']['form']['timezone'] = array(
'label' => t('Timezone'),
'description' => t('System module form element.'),
'weight' => 6,
);
}
$fields['user']['user']['display']['member_for'] = array(
'label' => t('Member for'),
'description' => t('User module \'member for\' view element.'),
'weight' => 5,
Angie Byron
committed
Dries Buytaert
committed
return $fields;
Angie Byron
committed
}
* Loads multiple users based on certain conditions.
Angie Byron
committed
* This function should be used whenever you need to load more than one user
* from the database. Users are loaded into memory and will not require
* database access if loaded again during the same page request.
* @param array $uids
* (optional) An array of entity IDs. If omitted, all entities are loaded.
* @param bool $reset
Angie Byron
committed
* A boolean indicating that the internal cache should be reset. Use this if
* loading a user object which has been altered during the page request.
Angie Byron
committed
*
* @return array
Angie Byron
committed
* An array of user objects, indexed by uid.
*
* @see entity_load_multiple()
Angie Byron
committed
* @see user_load()
* @see user_load_by_mail()
* @see user_load_by_name()
* @see \Drupal\Core\Entity\Query\QueryInterface
function user_load_multiple(array $uids = NULL, $reset = FALSE) {
Alex Pott
committed
return entity_load_multiple('user', $uids, $reset);
Dries Buytaert
committed
}
Angie Byron
committed
/**
Dries Buytaert
committed
* Loads a user object.
*
* Drupal has a global $user object, which represents the currently-logged-in
* user. So to avoid confusion and to avoid clobbering the global $user object,
* it is a good idea to assign the result of this function to a different local
* variable, generally $account. If you actually do want to act as the user you
* are loading, it is essential to call drupal_save_session(FALSE); first.
* See
* @link http://drupal.org/node/218104 Safely impersonating another user @endlink
* for more information.
Angie Byron
committed
*
* @param int $uid
Dries Buytaert
committed
* Integer specifying the user ID to load.
* @param bool $reset
Dries Buytaert
committed
* TRUE to reset the internal cache and load from the database; FALSE
* (default) to load from the internal cache, if set.
*
Angie Byron
committed
* @return \Drupal\user\UserInterface
Dries Buytaert
committed
* A fully-loaded user object upon successful user load, or NULL if the user
Angie Byron
committed
* cannot be loaded.
*
* @see user_load_multiple()
*/
function user_load($uid, $reset = FALSE) {
Alex Pott
committed
return entity_load('user', $uid, $reset);
Angie Byron
committed
}
/**
* Fetches a user object by email address.
Angie Byron
committed
*
* @param string $mail
Angie Byron
committed
* String with the account's e-mail address.
* @return object|bool
Angie Byron
committed
* A fully-loaded $user object upon successful user load or FALSE if user
* cannot be loaded.
*
* @see user_load_multiple()
*/
function user_load_by_mail($mail) {
$users = entity_load_multiple_by_properties('user', array('mail' => $mail));
Alex Pott
committed
return $users ? reset($users) : FALSE;
Angie Byron
committed
}
/**
* Fetches a user object by account name.
Angie Byron
committed
*
* @param string $name
Angie Byron
committed
* String with the account's user name.
* @return object|bool
Angie Byron
committed
* A fully-loaded $user object upon successful user load or FALSE if user
* cannot be loaded.
*
* @see user_load_multiple()
*/
function user_load_by_name($name) {
$users = entity_load_multiple_by_properties('user', array('name' => $name));
Alex Pott
committed
return $users ? reset($users) : FALSE;
/**
* Verify the syntax of the given name.
catch
committed
*
* @param string $name
* The user name to validate.
*
* @return string|null
* A translated violation message if the name is invalid or NULL if the name
* is valid.
*
$definition = DataDefinition::create('string')
->setConstraints(array('UserName' => array()));
$data = \Drupal::typedDataManager()->create($definition);
catch
committed
$data->setValue($name);
$violations = $data->validate();
if (count($violations) > 0) {
return $violations[0]->getMessage();
}
/**
* Generate a random alphanumeric password.
*/
function user_password($length = 10) {
// This variable contains the list of allowable characters for the
// password. Note that the number 0 and the letter 'O' have been
// removed to avoid confusion between the two. The same is true
Gábor Hojtsy
committed
// of 'I', 1, and 'l'.
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
// Zero-based count of characters in the allowable list:
$len = strlen($allowable_characters) - 1;
// Declare the password as a blank string.
$pass = '';
// Loop the number of times specified by $length.
for ($i = 0; $i < $length; $i++) {
// Each iteration, pick a random character from the
// allowable string and append it to the password:
$pass .= $allowable_characters[mt_rand(0, $len)];
/**
* Determine the permissions for one or more roles.
*
* @param array $roles
* An array of role IDs.
*
* @return array
* An array indexed by role ID. Each value is an array of permission strings
* for the given role.
*/
function user_role_permissions(array $roles) {
if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
return _user_role_permissions_update($roles);
}
$entities = entity_load_multiple('user_role', $roles);
$role_permissions = array();
Alex Pott
committed
foreach ($roles as $rid) {
$role_permissions[$rid] = isset($entities[$rid]) ? $entities[$rid]->getPermissions() : array();
}
return $role_permissions;
}
/**
* Determine the permissions for one or more roles during update.
*
* A separate version is needed because during update the entity system can't
* be used and in non-update situations the entity system is preferred because
* of the hook system.
*
* @param array $roles
* An array of role IDs.
*
* @return array
* An array indexed by role ID. Each value is an array of permission strings
* for the given role.
*/
function _user_role_permissions_update($roles) {
$role_permissions = array();
foreach ($roles as $rid) {
$role_permissions[$rid] = \Drupal::config("user.role.$rid")->get('permissions') ?: array();
}
return $role_permissions;
}
/**
* Determine whether the user has a given privilege.
*
* @param $string
* The permission, such as "administer nodes", being checked for.
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) The account to check, if not given use currently logged in user.
* @return bool
Gábor Hojtsy
committed
* Boolean TRUE if the current user has the requested permission.
* @deprecated as of Drupal 8.0. Use
* \Drupal\Core\Session\AccountInterface::hasPermission()
function user_access($string, AccountInterface $account = NULL) {
Gábor Hojtsy
committed
if (!isset($account)) {
// In the installer request session is not set, so we have to fall back
// to the global $user. In all other cases the session key is preferred.
$account = \Drupal::currentUser() ?: $user;
return $account->hasPermission($string);
Dries Buytaert
committed
/**
Gábor Hojtsy
committed
* Checks for usernames blocked by user administration.
Dries Buytaert
committed
*
* @param $name
* A string containing a name of the user.
*
* @return
* Object with property 'name' (the user name), if the user is blocked;
* FALSE if the user is not blocked.
Dries Buytaert
committed
*/
function user_is_blocked($name) {
Angie Byron
committed
return db_select('users')
->fields('users', array('name'))
->condition('name', db_like($name), 'LIKE')
->condition('status', 0)
->execute()->fetchObject();
Dries Buytaert
committed
}
Dries Buytaert
committed
* Implements hook_permission().
function user_permission() {
return array(
'administer permissions' => array(
'title' => t('Administer permissions'),
Dries Buytaert
committed
'restrict access' => TRUE,
'administer account settings' => array(
'title' => t('Administer account settings'),
'description' => t('Configure site-wide settings and behavior for <a href="@url">user accounts and registration</a>.', array('@url' => url('admin/config/people'))),
'restrict access' => TRUE,
),
'administer users' => array(
'title' => t('Administer users'),
Dries Buytaert
committed
'restrict access' => TRUE,
),
'access user profiles' => array(
'title' => t('View user profiles'),
),
'change own username' => array(
'title' => t('Change own username'),
),
'cancel account' => array(
'title' => t('Cancel own user account'),
'description' => t('Note: content may be kept, unpublished, deleted or transferred to the %anonymous-name user depending on the configured <a href="@user-settings-url">user settings</a>.', array('%anonymous-name' => \Drupal::config('user.settings')->get('anonymous'), '@user-settings-url' => url('admin/config/people/accounts'))),
),
'select account cancellation method' => array(
'title' => t('Select method for cancelling own account'),
Dries Buytaert
committed
'restrict access' => TRUE,
Dries Buytaert
committed
* Implements hook_user_view().
function user_user_view(UserInterface $account, EntityViewDisplayInterface $display) {
Angie Byron
committed
if ($display->getComponent('member_for')) {
$account->content['member_for'] = array(
'#type' => 'item',
'#title' => t('Member for'),
'#markup' => format_interval(REQUEST_TIME - $account->getCreatedTime()),
Angie Byron
committed
);
}
Dries Buytaert
committed
}
/**
* Sets the value of the user register and profile forms' langcode element.
*/
function _user_language_selector_langcode_value($element, $input, &$form_state) {
// Only add to the description if the form element have a description.
if (isset($form_state['complete_form']['language']['preferred_langcode']['#description'])) {
$form_state['complete_form']['language']['preferred_langcode']['#description'] .= ' ' . t("This is also assumed to be the primary language of this account's profile information.");
}
return $form_state['values']['preferred_langcode'];
Angie Byron
committed
/**
* Form validation handler for the current password on the user account form.
Dries Buytaert
committed
*
* @see AccountFormController::form()
Angie Byron
committed
*/
function user_validate_current_pass(&$form, &$form_state) {
$account = $form_state['user'];
Angie Byron
committed
foreach ($form_state['values']['current_pass_required_values'] as $key => $name) {
// This validation only works for required textfields (like mail) or
// form values like password_confirm that have their own validation
// that prevent them from being empty if they are changed.
$current_value = $account->hasField($key) ? $account->get($key)->value : $account->$key;
Alex Pott
committed
if ((strlen(trim($form_state['values'][$key])) > 0) && ($form_state['values'][$key] != $current_value)) {
$current_pass_failed = empty($form_state['values']['current_pass']) || !\Drupal::service('password')->check($form_state['values']['current_pass'], $account);
Angie Byron
committed
if ($current_pass_failed) {
Angie Byron
committed
form_set_error('current_pass', $form_state, t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => $name)));
form_set_error($key, $form_state);
Angie Byron
committed
}
// We only need to check the password once.
break;
}
}
}
/**
Angie Byron
committed
* Implements hook_preprocess_HOOK() for block templates.
*/
function user_preprocess_block(&$variables) {
if ($variables['configuration']['module'] == 'user') {
switch ($variables['elements']['#plugin_id']) {
Dries Buytaert
committed
case 'user_login_block':
Dries Buytaert
committed
$variables['attributes']['role'] = 'form';
break;
}
}
}
/**
* Format a username.
*
* @param \Drupal\Core\Session\Interface $account
* The account object for the user whose name is to be formatted.
*
* @return
* An unsanitized string with the username to display. The code receiving
* this result must ensure that check_plain() is called on it before it is
* printed to the page.
*
* @deprecated Use \Drupal\Core\Session\Interface::getUsername() instead.
*/
function user_format_name(AccountInterface $account) {
return $account->getUsername();
}
/**
* Implements hook_template_preprocess_default_variables_alter().
*
* @see user_user_login()
* @see user_user_logout()
*/
function user_template_preprocess_default_variables_alter(&$variables) {
Angie Byron
committed
$user = \Drupal::currentUser();
Angie Byron
committed
// If this function is called from the installer after Drupal has been
// installed then $user will not be set.
if (!is_object($user)) {
return;
}
$variables['user'] = clone $user;
Angie Byron
committed
// Remove password and session IDs, $form_state, since themes should not need nor see them.
unset($variables['user']->pass, $variables['user']->sid, $variables['user']->ssid);
Angie Byron
committed
$variables['is_admin'] = $user->hasPermission('access administration pages');
$variables['logged_in'] = $user->isAuthenticated();
}
/**
* Preprocesses variables for theme_username().
*
* Modules that make any changes to variables like 'name' or 'extra' must ensure
* that the final string is safe to include directly in the output by using
* check_plain() or filter_xss().
*/
function template_preprocess_username(&$variables) {
$account = $variables['account'] ?: drupal_anonymous_user();
$variables['extra'] = '';
$variables['uid'] = $account->id();
if (empty($variables['uid'])) {
if (theme_get_setting('features.comment_user_verification')) {
$variables['extra'] = ' (' . t('not verified') . ')';
}
}
// Set the name to a formatted name that is safe for printing and
// that won't break tables by being too long. Keep an unshortened,
// unsanitized version, in case other preprocess functions want to implement
// their own shortening logic or add markup. If they do so, they must ensure
// that $variables['name'] is safe for printing.
$name = $variables['name_raw'] = $account->getUsername();
if (drupal_strlen($name) > 20) {
$name = drupal_substr($name, 0, 15) . '...';
}
$variables['name'] = check_plain($name);
Angie Byron
committed
$variables['profile_access'] = \Drupal::currentUser()->hasPermission('access user profiles');
Dries Buytaert
committed
// Populate link path and attributes if appropriate.
if ($variables['uid'] && $variables['profile_access']) {
// We are linking to a local user.
Alex Pott
committed
$variables['link_options']['attributes']['title'] = t('View user profile.');
$variables['link_path'] = 'user/' . $variables['uid'];
}
elseif (!empty($account->homepage)) {
// Like the 'class' attribute, the 'rel' attribute can hold a
// space-separated set of values, so initialize it as an array to make it
// easier for other preprocess functions to append to it.
Alex Pott
committed
$variables['link_options']['attributes']['rel'] = 'nofollow';
$variables['link_path'] = $account->homepage;
$variables['homepage'] = $account->homepage;
}
// We do not want the l() function to check_plain() a second time.
$variables['link_options']['html'] = TRUE;
// Set a default class.
Alex Pott
committed
$variables['link_options']['attributes']['class'] = array('username');
}
/**
* Returns HTML for a username, potentially linked to the user's page.
*
* @param $variables
* An associative array containing:
* - account: The user object to format.
* - name: The user's name, sanitized.
* - extra: Additional text to append to the user's name, sanitized.
* - link_path: The path or URL of the user's profile page, home page, or
* other desired page to link to for more information about the user.
* - link_options: An array of options to pass to the l() function's $options
* parameter if linking the user's name to the user's page.
* - attributes: An array of attributes to instantiate the
* Drupal\Core\Template\Attribute class if not linking to the user's page.
*
* @see template_preprocess_username()
*/
function theme_username($variables) {
if (isset($variables['link_path'])) {
// We have a link path, so we should generate a link using l().
// Additional classes may be added as array elements like
// $variables['link_options']['attributes']['class'][] = 'myclass';
$output = l($variables['name'] . $variables['extra'], $variables['link_path'], $variables['link_options']);
}
else {
// Modules may have added important attributes so they must be included
// in the output. Additional classes may be added as array elements like
Dries Buytaert
committed
// $variables['attributes']['class'][] = 'myclass';
$output = '<span' . new Attribute($variables['attributes']) . '>' . $variables['name'] . $variables['extra'] . '</span>';
}
return $output;
}
Dries Buytaert
committed
/**
* Determines if the current user is anonymous.
*
* @return bool
* TRUE if the user is anonymous, FALSE if the user is authenticated.
*/
Dries Buytaert
committed
function user_is_anonymous() {
Dries Buytaert
committed
// Menu administrators can see items for anonymous when administering.
return $GLOBALS['user']->isAnonymous() || !empty($GLOBALS['menu_admin']);
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Determines if the current user is logged in.
*
* @return bool
* TRUE if the user is logged in, FALSE if the user is anonymous.
*
* @deprecated Use \Drupal\Core\Session\UserSession::isAuthenticated().
Dries Buytaert
committed
*/
Dries Buytaert
committed
function user_is_logged_in() {
return $GLOBALS['user']->isAuthenticated();
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Determines if the current user has access to the user registration page.
*
* @return bool
* TRUE if the user is not already logged in and can register for an account.
*/
Dries Buytaert
committed
function user_register_access() {
return user_is_anonymous() && (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY);
Dries Buytaert
committed
}
Dries Buytaert
committed
* Implements hook_menu().
Dries Buytaert
committed
function user_menu() {
// Registration and login pages.
$items['user'] = array(
Gábor Hojtsy
committed
'title' => 'User account',
Angie Byron
committed
'title callback' => 'user_menu_title',
'weight' => -10,
'route_name' => 'user.page',
Dries Buytaert
committed
'menu_name' => 'account',
Alex Pott
committed
// Since menu_get_ancestors() does not support multiple placeholders in a row,
// this MENU_CALLBACK cannot be removed yet.
Dries Buytaert
committed
$items['user/reset/%/%/%'] = array(
'title' => 'Reset password',
Alex Pott
committed
'route_name' => 'user.reset',
Dries Buytaert
committed
'type' => MENU_CALLBACK,
);
$items['user/logout'] = array(
'title' => 'Log out',
'route_name' => 'user.logout',
'weight' => 10,
Dries Buytaert
committed
'menu_name' => 'account',
);
Dries Buytaert
committed
// User listing pages.
Dries Buytaert
committed
$items['admin/people'] = array(
'title' => 'People',
'description' => 'Manage user accounts, roles, and permissions.',
Angie Byron
committed
'route_name' => 'user.admin_account',
Angie Byron
committed
'position' => 'left',
'weight' => -4,
Angie Byron
committed
);
// Permissions and role forms.
Angie Byron
committed
$items['admin/people/permissions'] = array(
'title' => 'Permissions',
'description' => 'Determine access to features by selecting permissions for roles.',
'route_name' => 'user.admin_permissions',
'type' => MENU_SIBLING_LOCAL_TASK,
Angie Byron
committed
);
Alex Pott
committed
$items['admin/people/roles/manage/%user_role'] = array(
Angie Byron
committed
'title' => 'Edit role',
'route_name' => 'user.role_edit',
Angie Byron
committed
);
Dries Buytaert
committed
// Administration pages.
$items['admin/config/people'] = array(
'title' => 'People',
'description' => 'Configure user accounts.',
'position' => 'left',
'weight' => -20,
'route_name' => 'user.admin_index',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['admin/config/people/accounts'] = array(
'title' => 'Account settings',
'description' => 'Configure default behavior of users, including registration requirements, e-mails, and fields.',
Dries Buytaert
committed
'weight' => -10,
'route_name' => 'user.account_settings',
Dries Buytaert
committed
);
Angie Byron
committed
$items['user/%user'] = array(
'title' => 'My account',
'title callback' => 'user_page_title',
'title arguments' => array(1),
Angie Byron
committed
'route_name' => 'user.view',
Dries Buytaert
committed
);
Angie Byron
committed
$items['user/%user/cancel'] = array(
Angie Byron
committed
'route_name' => 'user.cancel',
Angie Byron
committed
);
$items['user/%user/cancel/confirm/%/%'] = array(
'title' => 'Confirm account cancellation',
Angie Byron
committed
'route_name' => 'user.cancel_confirm',
Dries Buytaert
committed
);
Angie Byron
committed
/**
Angie Byron
committed
* Implements hook_menu_link_presave().
Angie Byron
committed
*/
function user_menu_link_presave(MenuLink $menu_link) {
Angie Byron
committed
// The path 'user' must be accessible for anonymous users, but only visible
// for authenticated users. Authenticated users should see "My account", but
// anonymous users should not see it at all. Therefore, invoke
Angie Byron
committed
// user_menu_link_load() to conditionally hide the link.
if ($menu_link->link_path == 'user' && $menu_link->module == 'system') {
$menu_link->options['alter'] = TRUE;
Angie Byron
committed
}
// Force the Logout link to appear on the top-level of 'account' menu by
// default (i.e., unless it has been customized).
if ($menu_link->link_path == 'user/logout' && $menu_link->module == 'system' && empty($menu_link->customized)) {
$menu_link->plid = 0;
}
Angie Byron
committed
}
catch
committed
/**
* Implements hook_menu_breadcrumb_alter().
*/
function user_menu_breadcrumb_alter(&$active_trail, $item) {
// Remove "My account" from the breadcrumb when $item is descendant-or-self
// of system path user/%.
if (isset($active_trail[1]['module']) && $active_trail[1]['module'] == 'system' && $active_trail[1]['link_path'] == 'user' && strpos($item['path'], 'user/%') === 0) {
array_splice($active_trail, 1, 1);
}
}
Angie Byron
committed
/**
* Implements hook_translated_menu_link_alter().
Angie Byron
committed
*/
function user_translated_menu_link_alter(MenuLink &$menu_link) {
Angie Byron
committed
// Hide the "User account" link for anonymous users.
if ($menu_link->link_path == 'user' && $menu_link->module == 'system' && \Drupal::currentUser()->isAnonymous()) {
$menu_link->hidden = 1;
Angie Byron
committed
}
}
Dries Buytaert
committed
/**
* Implements hook_admin_paths().
*/
function user_admin_paths() {
$paths = array(
'user/*/cancel' => TRUE,
'user/*/edit' => TRUE,
'user/*/edit/*' => TRUE,
Angie Byron
committed
'user/*/translations' => TRUE,
'user/*/translations/*' => TRUE,
Dries Buytaert
committed
);
return $paths;
}
Angie Byron
committed
/**
* Returns $arg or the user ID of the current user if $arg is '%' or empty.
*
* Deprecated. Use %user_uid_optional instead.
*
* @todo D8: Remove.
*/
function user_uid_only_optional_to_arg($arg) {
return user_uid_optional_to_arg($arg);
}
Dries Buytaert
committed
/**
* Load either a specified or the current user account.
Dries Buytaert
committed
*
* @param $uid
* An optional user ID of the user to load. If not provided, the current
* user's ID will be used.
* @return
Dries Buytaert
committed
* A fully-loaded $user object upon successful user load, NULL if user
Dries Buytaert
committed
* cannot be loaded.
*
* @see user_load()
Dries Buytaert
committed
* @todo rethink the naming of this in Drupal 8.
Dries Buytaert
committed
*/
function user_uid_optional_load($uid = NULL) {
if (!isset($uid)) {
$uid = $GLOBALS['user']->id();
Dries Buytaert
committed
}
return user_load($uid);
Gábor Hojtsy
committed
/**
Dries Buytaert
committed
* Returns $arg or the user ID of the current user if $arg is '%' or empty.
*
* @todo rethink the naming of this in Drupal 8.
Gábor Hojtsy
committed
*/
Dries Buytaert
committed
function user_uid_optional_to_arg($arg) {
Gábor Hojtsy
committed
// Give back the current user uid when called from eg. tracker, aka.
// with an empty arg. Also use the current user uid when called from
// the menu with a % for the current account link.
return empty($arg) || $arg == '%' ? $GLOBALS['user']->id() : $arg;
Dries Buytaert
committed
/**
Angie Byron
committed
* Menu item title callback for the 'user' path.
Dries Buytaert
committed
*
* Anonymous users should see a title based on the requested page, but
* authenticated users are expected to see "My account".
Dries Buytaert
committed
*/
Angie Byron
committed
function user_menu_title() {
if ($GLOBALS['user']->isAnonymous()) {
switch (current_path()) {
case 'user' :
case 'user/login' :
return t('Log in');
case 'user/register' :
return t('Create new account');
case 'user/password' :
return t('Request new password');
default :
return t('User account');
}
}
else {
return t('My account');
}
Dries Buytaert
committed
}
/**
Angie Byron
committed
* Menu item title callback - use the user name.
*/
function user_page_title(UserInterface $account = NULL) {
return $account ? $account->getUsername() : '';
}
Dries Buytaert
committed
/**
* Try to validate the user's login credentials locally.
Gábor Hojtsy
committed
*
* @param $name
* User name to authenticate.
* @param $password
* A plain-text password, such as trimmed text from form values.
* @return
* The user's uid on success, or FALSE on failure to authenticate.
*/
function user_authenticate($name, $password) {
$uid = FALSE;
if (!empty($name) && !empty($password)) {
Dries Buytaert
committed
$account = user_load_by_name($name);
if ($account) {
$password_hasher = \Drupal::service('password');
Dries Buytaert
committed
if ($password_hasher->check($password, $account)) {
// Successful authentication.
$uid = $account->id();
Dries Buytaert
committed
// Update user to new password scheme if needed.
Dries Buytaert
committed
if ($password_hasher->userNeedsNewHash($account)) {
$account->setPassword($password);
$account->save();
}
}
}
Dries Buytaert
committed
}
return $uid;
Dries Buytaert
committed
}
Gábor Hojtsy
committed
/**
Alex Pott
committed
* Finalizes the login process and logs in a user.
Gábor Hojtsy
committed
*
Alex Pott
committed
* The function logs in the user, records a watchdog message about the new
* session, saves the login timestamp, calls hook_user_login(), and generates a
* new session.
Jennifer Hodgdon
committed
*
Alex Pott
committed
* The global $user object is replaced with the passed in account.
*
* @param \Drupal\user\UserInterface $account
Alex Pott
committed
* The account to log in.
Jennifer Hodgdon
committed
*
* @see hook_user_login()
Gábor Hojtsy
committed
*/
function user_login_finalize(UserInterface $account) {
Gábor Hojtsy
committed
global $user;
Alex Pott
committed
$user = $account;
watchdog('user', 'Session opened for %name.', array('%name' => $user->getUsername()));
Gábor Hojtsy
committed
// Update the user table timestamp noting user has logged in.
// This is also used to invalidate one-time login links.
$account->setLastLoginTime(REQUEST_TIME);
Dries Buytaert
committed
db_update('users')
->fields(array('login' => $user->getLastLoginTime()))
->condition('uid', $user->id())
Dries Buytaert
committed
->execute();
Dries Buytaert
committed
Dries Buytaert
committed
// Regenerate the session ID to prevent against session fixation attacks.
// This is called before hook_user in case one of those functions fails
// or incorrectly does a redirect which would leave the old session in place.
Dries Buytaert
committed
drupal_session_regenerate();
Dries Buytaert
committed
\Drupal::moduleHandler()->invokeAll('user_login', array($user));
Gábor Hojtsy
committed
}
/**
* Implements hook_user_login().
*/
function user_user_login($account) {
// Reset static cache of default variables in template_preprocess() to reflect
// the new user.
drupal_static_reset('template_preprocess');
}
/**
* Implements hook_user_logout().
*/
function user_user_logout($account) {
// Reset static cache of default variables in template_preprocess() to reflect
// the new user.