2007-09-10 13:14:38 +00:00
< ? php
/**
* @ file
* User page callback file for the user module .
*/
2012-06-29 16:10:25 +00:00
use Symfony\Component\HttpFoundation\JsonResponse ;
2012-07-09 20:20:56 +00:00
use Symfony\Component\HttpFoundation\Request ;
2012-09-20 03:34:47 +00:00
use Symfony\Component\HttpFoundation\RedirectResponse ;
2012-06-04 12:06:09 +00:00
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException ;
2012-07-09 20:20:56 +00:00
use Symfony\Component\HttpKernel\HttpKernelInterface ;
2012-06-04 12:06:09 +00:00
2007-09-10 13:14:38 +00:00
/**
2007-12-04 18:34:44 +00:00
* Menu callback ; Retrieve a JSON object containing autocomplete suggestions for existing users .
2007-09-10 13:14:38 +00:00
*/
2012-12-03 03:23:33 +00:00
function user_autocomplete () {
2007-09-10 13:14:38 +00:00
$matches = array ();
2012-12-03 03:23:33 +00:00
if ( $string = drupal_container () -> get ( 'request' ) -> query -> get ( 'q' )) {
2010-02-28 20:10:34 +00:00
$result = db_select ( 'users' ) -> fields ( 'users' , array ( 'name' )) -> condition ( 'name' , db_like ( $string ) . '%' , 'LIKE' ) -> range ( 0 , 10 ) -> execute ();
2012-03-23 22:03:55 +00:00
foreach ( $result as $account ) {
$matches [ $account -> name ] = check_plain ( $account -> name );
2007-09-10 13:14:38 +00:00
}
}
2012-06-29 16:10:25 +00:00
return new JsonResponse ( $matches );
2007-09-10 13:14:38 +00:00
}
/**
* Form builder ; Request a password reset .
*
* @ ingroup forms
2008-01-08 10:35:43 +00:00
* @ see user_pass_validate ()
* @ see user_pass_submit ()
2007-09-10 13:14:38 +00:00
*/
function user_pass () {
2010-02-11 03:19:21 +00:00
global $user ;
2007-09-10 13:14:38 +00:00
$form [ 'name' ] = array (
'#type' => 'textfield' ,
'#title' => t ( 'Username or e-mail address' ),
'#size' => 60 ,
'#maxlength' => max ( USERNAME_MAX_LENGTH , EMAIL_MAX_LENGTH ),
'#required' => TRUE ,
);
2010-02-11 03:19:21 +00:00
// Allow logged in users to request this also.
if ( $user -> uid > 0 ) {
$form [ 'name' ][ '#type' ] = 'value' ;
$form [ 'name' ][ '#value' ] = $user -> mail ;
$form [ 'mail' ] = array (
'#prefix' => '<p>' ,
'#markup' => t ( 'Password reset instructions will be mailed to %email. You must log out to use the password reset link in the e-mail.' , array ( '%email' => $user -> mail )),
'#suffix' => '</p>' ,
);
}
2010-04-24 14:49:14 +00:00
$form [ 'actions' ] = array ( '#type' => 'actions' );
$form [ 'actions' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'E-mail new password' ));
2007-09-10 13:14:38 +00:00
return $form ;
}
function user_pass_validate ( $form , & $form_state ) {
$name = trim ( $form_state [ 'values' ][ 'name' ]);
2008-01-02 12:57:37 +00:00
// Try to load by email.
2012-08-21 15:38:04 +00:00
$users = entity_load_multiple_by_properties ( 'user' , array ( 'mail' => $name , 'status' => '1' ));
2009-03-14 23:01:38 +00:00
$account = reset ( $users );
2008-01-02 12:57:37 +00:00
if ( ! $account ) {
// No success, try to load by name.
2012-08-21 15:38:04 +00:00
$users = entity_load_multiple_by_properties ( 'user' , array ( 'name' => $name , 'status' => '1' ));
2009-03-14 23:01:38 +00:00
$account = reset ( $users );
2007-09-10 13:14:38 +00:00
}
if ( isset ( $account -> uid )) {
form_set_value ( array ( '#parents' => array ( 'account' )), $account , $form_state );
}
else {
2012-05-11 04:08:23 +00:00
form_set_error ( 'name' , t ( 'Sorry, %name is not recognized as a username or an e-mail address.' , array ( '%name' => $name )));
2007-09-10 13:14:38 +00:00
}
}
function user_pass_submit ( $form , & $form_state ) {
2012-08-09 20:17:01 +00:00
$language_interface = language ( LANGUAGE_TYPE_INTERFACE );
2007-09-10 13:14:38 +00:00
$account = $form_state [ 'values' ][ 'account' ];
// Mail one time login URL and instructions using current language.
2012-09-13 08:48:24 +00:00
$mail = _user_mail_notify ( 'password_reset' , $account , $language_interface -> langcode );
2011-09-05 18:59:30 +00:00
if ( ! empty ( $mail )) {
watchdog ( 'user' , 'Password reset instructions mailed to %name at %email.' , array ( '%name' => $account -> name , '%email' => $account -> mail ));
drupal_set_message ( t ( 'Further instructions have been sent to your e-mail address.' ));
}
2007-09-10 13:14:38 +00:00
$form_state [ 'redirect' ] = 'user' ;
return ;
}
/**
* Menu callback ; process one time login link and redirects to the user page on success .
*/
2009-09-18 00:12:48 +00:00
function user_pass_reset ( $form , & $form_state , $uid , $timestamp , $hashed_pass , $action = NULL ) {
2007-09-10 13:14:38 +00:00
global $user ;
2009-08-23 04:50:25 +00:00
// When processing the one-time login link, we have to make sure that a user
// isn't already logged in.
2007-09-10 13:14:38 +00:00
if ( $user -> uid ) {
2009-08-23 04:50:25 +00:00
// The existing user is already logged in.
if ( $user -> uid == $uid ) {
drupal_set_message ( t ( 'You are logged in as %user. <a href="!user_edit">Change your password.</a>' , array ( '%user' => $user -> name , '!user_edit' => url ( " user/ $user->uid /edit " ))));
}
// A different user is already logged in on the computer.
else {
$reset_link_account = user_load ( $uid );
if ( ! empty ( $reset_link_account )) {
drupal_set_message ( t ( 'Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please <a href="!logout">logout</a> and try using the link again.' ,
array ( '%other_user' => $user -> name , '%resetting_user' => $reset_link_account -> name , '!logout' => url ( 'user/logout' ))));
} else {
// Invalid one-time link specifies an unknown user.
drupal_set_message ( t ( 'The one-time login link you clicked is invalid.' ));
}
}
2007-09-10 13:14:38 +00:00
drupal_goto ();
}
else {
2012-11-02 17:35:51 +00:00
// Time out, in seconds, until login URL expires.
$timeout = config ( 'user.settings' ) -> get ( 'password_reset_timeout' );
2008-09-17 07:11:59 +00:00
$current = REQUEST_TIME ;
2012-08-21 15:38:04 +00:00
$account = user_load ( $uid );
// Verify that the user exists and is active.
if ( $timestamp <= $current && $account && $account -> status ) {
2007-09-10 13:14:38 +00:00
// No time out for first time login.
if ( $account -> login && $current - $timestamp > $timeout ) {
drupal_set_message ( t ( 'You have tried to use a one-time login link that has expired. Please request a new one using the form below.' ));
drupal_goto ( 'user/password' );
}
2009-06-05 09:26:06 +00:00
elseif ( $account -> uid && $timestamp >= $account -> login && $timestamp <= $current && $hashed_pass == user_pass_rehash ( $account -> pass , $timestamp , $account -> login )) {
2007-09-10 13:14:38 +00:00
// First stage is a confirmation form, then login
if ( $action == 'login' ) {
2007-12-13 12:53:47 +00:00
// Set the new user.
2007-09-10 13:14:38 +00:00
$user = $account ;
2009-06-30 11:32:08 +00:00
// user_login_finalize() also updates the login timestamp of the
2007-12-13 12:53:47 +00:00
// user, which invalidates further use of the one-time login link.
2009-06-30 11:32:08 +00:00
user_login_finalize ();
2012-05-14 03:22:49 +00:00
watchdog ( 'user' , 'User %name used one-time login link at time %timestamp.' , array ( '%name' => $account -> name , '%timestamp' => $timestamp ));
2010-01-11 16:25:16 +00:00
drupal_set_message ( t ( 'You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.' ));
2010-02-11 03:19:21 +00:00
// Let the user's password be changed without the current password check.
2010-05-01 08:12:23 +00:00
$token = drupal_hash_base64 ( drupal_random_bytes ( 55 ));
2010-02-11 03:19:21 +00:00
$_SESSION [ 'pass_reset_' . $user -> uid ] = $token ;
drupal_goto ( 'user/' . $user -> uid . '/edit' , array ( 'query' => array ( 'pass-reset-token' => $token )));
2007-09-10 13:14:38 +00:00
}
else {
2010-01-11 16:25:16 +00:00
$form [ 'message' ] = array ( '#markup' => t ( '<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>' , array ( '%user_name' => $account -> name , '%expiration_date' => format_date ( $timestamp + $timeout ))));
2008-07-16 21:59:29 +00:00
$form [ 'help' ] = array ( '#markup' => '<p>' . t ( 'This login can be used only once.' ) . '</p>' );
2010-04-24 14:49:14 +00:00
$form [ 'actions' ] = array ( '#type' => 'actions' );
$form [ 'actions' ][ 'submit' ] = array ( '#type' => 'submit' , '#value' => t ( 'Log in' ));
2007-09-10 13:14:38 +00:00
$form [ '#action' ] = url ( " user/reset/ $uid / $timestamp / $hashed_pass /login " );
return $form ;
}
}
else {
2010-01-11 16:25:16 +00:00
drupal_set_message ( t ( 'You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.' ));
2007-09-10 13:14:38 +00:00
drupal_goto ( 'user/password' );
}
}
else {
// Deny access, no more clues.
// Everything will be in the watchdog's URL for the administrator to check.
2012-06-04 12:06:09 +00:00
throw new AccessDeniedHttpException ();
2007-09-10 13:14:38 +00:00
}
}
}
/**
* Menu callback ; logs the current user out , and redirects to the home page .
*/
function user_logout () {
global $user ;
watchdog ( 'user' , 'Session closed for %name.' , array ( '%name' => $user -> name ));
2009-08-12 12:36:05 +00:00
module_invoke_all ( 'user_logout' , $user );
2007-09-10 13:14:38 +00:00
2009-07-01 12:47:30 +00:00
// Destroy the current session, and reset $user to the anonymous user.
session_destroy ();
2007-09-10 13:14:38 +00:00
drupal_goto ();
}
/**
2012-12-13 12:11:18 +00:00
* Process variables for user . tpl . php .
2007-09-10 13:14:38 +00:00
*
* The $variables array contains the following arguments :
* - $account
*
2012-12-13 12:11:18 +00:00
* @ see user . tpl . php
2007-09-10 13:14:38 +00:00
*/
2012-12-13 12:11:18 +00:00
function template_preprocess_user ( & $variables ) {
$account = $variables [ 'elements' ][ '#user' ];
2010-01-10 00:41:28 +00:00
2012-12-13 12:11:18 +00:00
// Helpful $content variable for templates.
2009-09-10 12:33:46 +00:00
foreach ( element_children ( $variables [ 'elements' ]) as $key ) {
2012-12-13 12:11:18 +00:00
$variables [ 'content' ][ $key ] = $variables [ 'elements' ][ $key ];
2009-09-10 12:33:46 +00:00
}
2010-01-10 00:41:28 +00:00
// Preprocess fields.
field_attach_preprocess ( 'user' , $account , $variables [ 'elements' ], $variables );
2007-09-10 13:14:38 +00:00
}
/**
2009-01-08 08:42:13 +00:00
* Submit function for the 'Cancel account' button on the user edit form .
2007-09-10 13:14:38 +00:00
*/
2009-01-08 08:42:13 +00:00
function user_edit_cancel_submit ( $form , & $form_state ) {
2009-09-29 15:31:17 +00:00
$destination = array ();
2009-09-21 06:44:14 +00:00
if ( isset ( $_GET [ 'destination' ])) {
2007-09-10 13:14:38 +00:00
$destination = drupal_get_destination ();
2009-09-21 06:44:14 +00:00
unset ( $_GET [ 'destination' ]);
2007-09-10 13:14:38 +00:00
}
2009-01-08 08:42:13 +00:00
// Note: We redirect from user/uid/edit to user/uid/cancel to make the tabs disappear.
2012-08-16 11:30:43 +00:00
$account = $form_state [ 'controller' ] -> getEntity ( $form_state );
$form_state [ 'redirect' ] = array ( " user/ " . $account -> uid . " /cancel " , array ( 'query' => $destination ));
2007-09-10 13:14:38 +00:00
}
/**
2009-01-08 08:42:13 +00:00
* Form builder ; confirm form for cancelling user account .
2007-09-10 13:14:38 +00:00
*
* @ ingroup forms
2009-01-08 08:42:13 +00:00
* @ see user_edit_cancel_submit ()
2007-09-10 13:14:38 +00:00
*/
2009-09-18 00:12:48 +00:00
function user_cancel_confirm_form ( $form , & $form_state , $account ) {
2009-01-08 08:42:13 +00:00
global $user ;
2007-09-10 13:14:38 +00:00
$form [ '_account' ] = array ( '#type' => 'value' , '#value' => $account );
2009-01-08 08:42:13 +00:00
// Display account cancellation method selection, if allowed.
$admin_access = user_access ( 'administer users' );
$can_select_method = $admin_access || user_access ( 'select account cancellation method' );
$form [ 'user_cancel_method' ] = array (
2012-12-02 15:33:15 +00:00
'#type' => 'radios' ,
2009-01-08 08:42:13 +00:00
'#title' => ( $account -> uid == $user -> uid ? t ( 'When cancelling your account' ) : t ( 'When cancelling the account' )),
'#access' => $can_select_method ,
);
$form [ 'user_cancel_method' ] += user_cancel_methods ();
// Allow user administrators to skip the account cancellation confirmation
// mail (by default), as long as they do not attempt to cancel their own
// account.
$override_access = $admin_access && ( $account -> uid != $user -> uid );
$form [ 'user_cancel_confirm' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( 'Require e-mail confirmation to cancel account.' ),
'#default_value' => ( $override_access ? FALSE : TRUE ),
'#access' => $override_access ,
'#description' => t ( 'When enabled, the user must confirm the account cancellation via e-mail.' ),
);
// Also allow to send account canceled notification mail, if enabled.
2012-08-26 21:15:58 +00:00
$default_notify = config ( 'user.settings' ) -> get ( 'notify.status_canceled' );
2009-01-08 08:42:13 +00:00
$form [ 'user_cancel_notify' ] = array (
'#type' => 'checkbox' ,
'#title' => t ( 'Notify user when account is canceled.' ),
'#default_value' => ( $override_access ? FALSE : $default_notify ),
'#access' => $override_access && $default_notify ,
'#description' => t ( 'When enabled, the user will receive an e-mail notification after the account has been cancelled.' ),
);
// Prepare confirmation form page title and description.
if ( $account -> uid == $user -> uid ) {
$question = t ( 'Are you sure you want to cancel your account?' );
}
else {
$question = t ( 'Are you sure you want to cancel the account %name?' , array ( '%name' => $account -> name ));
}
2012-12-02 15:33:15 +00:00
$default_method = config ( 'user.settings' ) -> get ( 'cancel_method' );
$description = NULL ;
2009-01-08 08:42:13 +00:00
if ( $can_select_method ) {
$description = t ( 'Select the method to cancel the account above.' );
}
2012-12-02 15:33:15 +00:00
// Options supplied via user_cancel_methods() can have a custom
// #confirm_description property for the confirmation form description.
elseif ( isset ( $form [ 'user_cancel_method' ][ $default_method ][ '#confirm_description' ])) {
$description = $form [ 'user_cancel_method' ][ $default_method ][ '#confirm_description' ];
2009-01-08 08:42:13 +00:00
}
2010-02-17 05:42:42 +00:00
// Always provide entity id in the same form key as in the entity edit form.
$form [ 'uid' ] = array ( '#type' => 'value' , '#value' => $account -> uid );
2007-09-10 13:14:38 +00:00
return confirm_form ( $form ,
2009-01-08 08:42:13 +00:00
$question ,
2008-04-14 17:48:46 +00:00
'user/' . $account -> uid ,
2009-01-08 08:42:13 +00:00
$description . ' ' . t ( 'This action cannot be undone.' ),
t ( 'Cancel account' ), t ( 'Cancel' ));
}
/**
* Submit handler for the account cancellation confirm form .
*
* @ see user_cancel_confirm_form ()
* @ see user_multiple_cancel_confirm_submit ()
*/
function user_cancel_confirm_form_submit ( $form , & $form_state ) {
global $user ;
$account = $form_state [ 'values' ][ '_account' ];
// Cancel account immediately, if the current user has administrative
// privileges, no confirmation mail shall be sent, and the user does not
// attempt to cancel the own account.
if ( user_access ( 'administer users' ) && empty ( $form_state [ 'values' ][ 'user_cancel_confirm' ]) && $account -> uid != $user -> uid ) {
user_cancel ( $form_state [ 'values' ], $account -> uid , $form_state [ 'values' ][ 'user_cancel_method' ]);
2009-09-21 06:44:14 +00:00
$form_state [ 'redirect' ] = 'admin/people' ;
2009-01-08 08:42:13 +00:00
}
else {
// Store cancelling method and whether to notify the user in $account for
// user_cancel_confirm().
2012-04-26 03:51:09 +00:00
$account -> user_cancel_method = $form_state [ 'values' ][ 'user_cancel_method' ];
$account -> user_cancel_notify = $form_state [ 'values' ][ 'user_cancel_notify' ];
$account -> save ();
2009-01-08 08:42:13 +00:00
_user_mail_notify ( 'cancel_confirm' , $account );
drupal_set_message ( t ( 'A confirmation request to cancel your account has been sent to your e-mail address.' ));
2011-07-04 16:58:33 +00:00
watchdog ( 'user' , 'Sent account cancellation request to %name %email.' , array ( '%name' => $account -> name , '%email' => '<' . $account -> mail . '>' ), WATCHDOG_NOTICE );
2009-01-08 08:42:13 +00:00
2009-09-21 06:44:14 +00:00
$form_state [ 'redirect' ] = " user/ $account->uid " ;
2009-01-08 08:42:13 +00:00
}
2007-09-10 13:14:38 +00:00
}
/**
2009-01-08 08:42:13 +00:00
* Helper function to return available account cancellation methods .
*
2010-12-01 00:29:41 +00:00
* See documentation of hook_user_cancel_methods_alter () .
2009-01-08 08:42:13 +00:00
*
* @ return
* An array containing all account cancellation methods as form elements .
*
* @ see hook_user_cancel_methods_alter ()
* @ see user_admin_settings ()
* @ see user_cancel_confirm_form ()
* @ see user_multiple_cancel_confirm ()
2007-09-10 13:14:38 +00:00
*/
2009-01-08 08:42:13 +00:00
function user_cancel_methods () {
2012-08-26 21:15:58 +00:00
$anonymous_name = config ( 'user.settings' ) -> get ( 'anonymous' );
2009-01-08 08:42:13 +00:00
$methods = array (
'user_cancel_block' => array (
2010-11-24 03:21:36 +00:00
'title' => t ( 'Disable the account and keep its content.' ),
2009-01-08 08:42:13 +00:00
'description' => t ( 'Your account will be blocked and you will no longer be able to log in. All of your content will remain attributed to your user name.' ),
),
'user_cancel_block_unpublish' => array (
2010-11-24 03:21:36 +00:00
'title' => t ( 'Disable the account and unpublish its content.' ),
2009-01-08 08:42:13 +00:00
'description' => t ( 'Your account will be blocked and you will no longer be able to log in. All of your content will be hidden from everyone but administrators.' ),
),
'user_cancel_reassign' => array (
2012-08-26 21:15:58 +00:00
'title' => t ( 'Delete the account and make its content belong to the %anonymous-name user.' , array ( '%anonymous-name' => $anonymous_name )),
'description' => t ( 'Your account will be removed and all account information deleted. All of your content will be assigned to the %anonymous-name user.' , array ( '%anonymous-name' => $anonymous_name )),
2009-01-08 08:42:13 +00:00
),
'user_cancel_delete' => array (
2010-11-24 03:21:36 +00:00
'title' => t ( 'Delete the account and its content.' ),
2009-01-08 08:42:13 +00:00
'description' => t ( 'Your account will be removed and all account information deleted. All of your content will also be deleted.' ),
'access' => user_access ( 'administer users' ),
),
);
// Allow modules to customize account cancellation methods.
drupal_alter ( 'user_cancel_methods' , $methods );
// Turn all methods into real form elements.
2012-12-02 15:33:15 +00:00
$default_method = config ( 'user.settings' ) -> get ( 'cancel_method' );
$form = array (
'#options' => array (),
'#default_value' => $default_method ,
);
2009-01-08 08:42:13 +00:00
foreach ( $methods as $name => $method ) {
2012-12-02 15:33:15 +00:00
$form [ '#options' ][ $name ] = $method [ 'title' ];
// Add the description for the confirmation form. This description is never
// shown for the cancel method option, only on the confirmation form.
// Therefore, we use a custom #confirm_description property.
if ( isset ( $method [ 'description' ])) {
$form [ $name ][ '#confirm_description' ] = $method [ 'description' ];
}
if ( isset ( $method [ 'access' ])) {
$form [ $name ][ '#access' ] = $method [ 'access' ];
}
2009-01-08 08:42:13 +00:00
}
return $form ;
}
2007-10-27 14:01:12 +00:00
2009-01-08 08:42:13 +00:00
/**
* Menu callback ; Cancel a user account via e - mail confirmation link .
*
* @ see user_cancel_confirm_form ()
* @ see user_cancel_url ()
*/
function user_cancel_confirm ( $account , $timestamp = 0 , $hashed_pass = '' ) {
// Time out in seconds until cancel URL expires; 24 hours = 86400 seconds.
$timeout = 86400 ;
$current = REQUEST_TIME ;
// Basic validation of arguments.
2012-11-27 22:26:22 +00:00
$account_data = drupal_container () -> get ( 'user.data' ) -> get ( 'user' , $account -> id ());
if ( isset ( $account_data [ 'cancel_method' ]) && ! empty ( $timestamp ) && ! empty ( $hashed_pass )) {
2009-01-08 08:42:13 +00:00
// Validate expiration and hashed password/login.
if ( $timestamp <= $current && $current - $timestamp < $timeout && $account -> uid && $timestamp >= $account -> login && $hashed_pass == user_pass_rehash ( $account -> pass , $timestamp , $account -> login )) {
$edit = array (
2012-11-27 22:26:22 +00:00
'user_cancel_notify' => isset ( $account_data [ 'cancel_notify' ]) ? $account_data [ 'cancel_notify' ] : config ( 'user.settings' ) -> get ( 'notify.status_canceled' ),
2009-01-08 08:42:13 +00:00
);
2012-11-27 22:26:22 +00:00
user_cancel ( $edit , $account -> id (), $account_data [ 'cancel_method' ]);
2009-01-08 08:42:13 +00:00
// Since user_cancel() is not invoked via Form API, batch processing needs
// to be invoked manually and should redirect to the front page after
// completion.
batch_process ( '' );
}
else {
drupal_set_message ( t ( 'You have tried to use an account cancellation link that has expired. Please request a new one using the form below.' ));
drupal_goto ( " user/ $account->uid /cancel " );
}
2007-09-10 13:14:38 +00:00
}
2012-06-04 12:06:09 +00:00
throw new AccessDeniedHttpException ();
2007-09-10 13:14:38 +00:00
}
/**
* Access callback for path / user .
*
* Displays user profile if user is logged in , or login form for anonymous
* users .
*/
function user_page () {
global $user ;
if ( $user -> uid ) {
2012-09-21 20:57:05 +00:00
return new RedirectResponse ( url ( 'user/' . $user -> uid , array ( 'absolute' => TRUE )));
2007-09-10 13:14:38 +00:00
}
else {
2012-10-24 03:28:47 +00:00
return drupal_get_form ( 'user_login_form' );
2007-09-10 13:14:38 +00:00
}
}