cms/drupal/modules/user/user.pages.inc
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * User page callback file for the user module.
       
     6  */
       
     7 
       
     8 /**
       
     9  * Menu callback; Retrieve a JSON object containing autocomplete suggestions for existing users.
       
    10  */
       
    11 function user_autocomplete($string = '') {
       
    12   $matches = array();
       
    13   if ($string) {
       
    14     $result = db_select('users')->fields('users', array('name'))->condition('name', db_like($string) . '%', 'LIKE')->range(0, 10)->execute();
       
    15     foreach ($result as $user) {
       
    16       $matches[$user->name] = check_plain($user->name);
       
    17     }
       
    18   }
       
    19 
       
    20   drupal_json_output($matches);
       
    21 }
       
    22 
       
    23 /**
       
    24  * Form builder; Request a password reset.
       
    25  *
       
    26  * @ingroup forms
       
    27  * @see user_pass_validate()
       
    28  * @see user_pass_submit()
       
    29  */
       
    30 function user_pass() {
       
    31   global $user;
       
    32 
       
    33   $form['name'] = array(
       
    34     '#type' => 'textfield',
       
    35     '#title' => t('Username or e-mail address'),
       
    36     '#size' => 60,
       
    37     '#maxlength' => max(USERNAME_MAX_LENGTH, EMAIL_MAX_LENGTH),
       
    38     '#required' => TRUE,
       
    39     '#default_value' => isset($_GET['name']) ? $_GET['name'] : '',
       
    40   );
       
    41   // Allow logged in users to request this also.
       
    42   if ($user->uid > 0) {
       
    43     $form['name']['#type'] = 'value';
       
    44     $form['name']['#value'] = $user->mail;
       
    45     $form['mail'] = array(
       
    46       '#prefix' => '<p>',
       
    47       // As of https://www.drupal.org/node/889772 the user no longer must log
       
    48       // out (if they are still logged in when using the password reset link,
       
    49       // they will be logged out automatically then), but this text is kept as
       
    50       // is to avoid breaking translations as well as to encourage the user to
       
    51       // log out manually at a time of their own choosing (when it will not
       
    52       // interrupt anything else they may have been in the middle of doing).
       
    53       '#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)),
       
    54       '#suffix' => '</p>',
       
    55     );
       
    56   }
       
    57   $form['actions'] = array('#type' => 'actions');
       
    58   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('E-mail new password'));
       
    59 
       
    60   return $form;
       
    61 }
       
    62 
       
    63 /**
       
    64  * Form validation handler for user_pass().
       
    65  *
       
    66  * @see user_pass_submit()
       
    67  */
       
    68 function user_pass_validate($form, &$form_state) {
       
    69   $name = trim($form_state['values']['name']);
       
    70   // Try to load by email.
       
    71   $users = user_load_multiple(array(), array('mail' => $name, 'status' => '1'));
       
    72   $account = reset($users);
       
    73   if (!$account) {
       
    74     // No success, try to load by name.
       
    75     $users = user_load_multiple(array(), array('name' => $name, 'status' => '1'));
       
    76     $account = reset($users);
       
    77   }
       
    78   if (isset($account->uid)) {
       
    79     form_set_value(array('#parents' => array('account')), $account, $form_state);
       
    80   }
       
    81   else {
       
    82     form_set_error('name', t('Sorry, %name is not recognized as a user name or an e-mail address.', array('%name' => $name)));
       
    83   }
       
    84 }
       
    85 
       
    86 /**
       
    87  * Form submission handler for user_pass().
       
    88  *
       
    89  * @see user_pass_validate()
       
    90  */
       
    91 function user_pass_submit($form, &$form_state) {
       
    92   global $language;
       
    93 
       
    94   $account = $form_state['values']['account'];
       
    95   // Mail one time login URL and instructions using current language.
       
    96   $mail = _user_mail_notify('password_reset', $account, $language);
       
    97   if (!empty($mail)) {
       
    98     watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
       
    99     drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
       
   100   }
       
   101 
       
   102   $form_state['redirect'] = 'user';
       
   103   return;
       
   104 }
       
   105 
       
   106 /**
       
   107  * Menu callback; process one time login link and redirects to the user page on success.
       
   108  */
       
   109 function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $action = NULL) {
       
   110   global $user;
       
   111 
       
   112   // When processing the one-time login link, we have to make sure that a user
       
   113   // isn't already logged in.
       
   114   if ($user->uid) {
       
   115     // The existing user is already logged in. Log them out and reload the
       
   116     // current page so the password reset process can continue.
       
   117     if ($user->uid == $uid) {
       
   118       // Preserve the current destination (if any) and ensure the redirect goes
       
   119       // back to the current page; any custom destination set in
       
   120       // hook_user_logout() and intended for regular logouts would not be
       
   121       // appropriate here.
       
   122       $destination = array();
       
   123       if (isset($_GET['destination'])) {
       
   124         $destination = drupal_get_destination();
       
   125       }
       
   126       user_logout_current_user();
       
   127       unset($_GET['destination']);
       
   128       drupal_goto(current_path(), array('query' => drupal_get_query_parameters() + $destination));
       
   129     }
       
   130     // A different user is already logged in on the computer.
       
   131     else {
       
   132       $reset_link_account = user_load($uid);
       
   133       if (!empty($reset_link_account)) {
       
   134         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.',
       
   135           array('%other_user' => $user->name, '%resetting_user' => $reset_link_account->name, '!logout' => url('user/logout'))), 'warning');
       
   136       } else {
       
   137         // Invalid one-time link specifies an unknown user.
       
   138         drupal_set_message(t('The one-time login link you clicked is invalid.'), 'error');
       
   139       }
       
   140       drupal_goto();
       
   141     }
       
   142   }
       
   143   else {
       
   144     // Time out, in seconds, until login URL expires. Defaults to 24 hours =
       
   145     // 86400 seconds.
       
   146     $timeout = variable_get('user_password_reset_timeout', 86400);
       
   147     $current = REQUEST_TIME;
       
   148     // Some redundant checks for extra security ?
       
   149     $users = user_load_multiple(array($uid), array('status' => '1'));
       
   150     if ($timestamp <= $current && $account = reset($users)) {
       
   151       // No time out for first time login.
       
   152       if ($account->login && $current - $timestamp > $timeout) {
       
   153         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.'), 'error');
       
   154         drupal_goto('user/password');
       
   155       }
       
   156       elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid)) {
       
   157         // First stage is a confirmation form, then login
       
   158         if ($action == 'login') {
       
   159           // Set the new user.
       
   160           $user = $account;
       
   161           // user_login_finalize() also updates the login timestamp of the
       
   162           // user, which invalidates further use of the one-time login link.
       
   163           user_login_finalize();
       
   164           watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp));
       
   165           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.'));
       
   166           // Let the user's password be changed without the current password check.
       
   167           $token = drupal_random_key();
       
   168           $_SESSION['pass_reset_' . $user->uid] = $token;
       
   169           drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token)));
       
   170         }
       
   171         else {
       
   172           $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))));
       
   173           $form['help'] = array('#markup' => '<p>' . t('This login can be used only once.') . '</p>');
       
   174           $form['actions'] = array('#type' => 'actions');
       
   175           $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Log in'));
       
   176           $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login");
       
   177           return $form;
       
   178         }
       
   179       }
       
   180       else {
       
   181         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.'), 'error');
       
   182         drupal_goto('user/password');
       
   183       }
       
   184     }
       
   185     else {
       
   186       // Deny access, no more clues.
       
   187       // Everything will be in the watchdog's URL for the administrator to check.
       
   188       drupal_access_denied();
       
   189       drupal_exit();
       
   190     }
       
   191   }
       
   192 }
       
   193 
       
   194 /**
       
   195  * Menu callback; logs the current user out, and redirects to the home page.
       
   196  */
       
   197 function user_logout() {
       
   198   user_logout_current_user();
       
   199   drupal_goto();
       
   200 }
       
   201 
       
   202 /**
       
   203  * Logs the current user out.
       
   204  */
       
   205 function user_logout_current_user() {
       
   206   global $user;
       
   207 
       
   208   watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
       
   209 
       
   210   module_invoke_all('user_logout', $user);
       
   211 
       
   212   // Destroy the current session, and reset $user to the anonymous user.
       
   213   session_destroy();
       
   214 }
       
   215 
       
   216 /**
       
   217  * Process variables for user-profile.tpl.php.
       
   218  *
       
   219  * @param array $variables
       
   220  *   An associative array containing:
       
   221  *   - elements: An associative array containing the user information and any
       
   222  *     fields attached to the user. Properties used:
       
   223  *     - #account: The user account of the profile being viewed.
       
   224  *
       
   225  * @see user-profile.tpl.php
       
   226  */
       
   227 function template_preprocess_user_profile(&$variables) {
       
   228   $account = $variables['elements']['#account'];
       
   229 
       
   230   // Helpful $user_profile variable for templates.
       
   231   foreach (element_children($variables['elements']) as $key) {
       
   232     $variables['user_profile'][$key] = $variables['elements'][$key];
       
   233   }
       
   234 
       
   235   // Preprocess fields.
       
   236   field_attach_preprocess('user', $account, $variables['elements'], $variables);
       
   237 }
       
   238 
       
   239 /**
       
   240  * Process variables for user-profile-item.tpl.php.
       
   241  *
       
   242  * The $variables array contains the following arguments:
       
   243  * - $element
       
   244  *
       
   245  * @see user-profile-item.tpl.php
       
   246  */
       
   247 function template_preprocess_user_profile_item(&$variables) {
       
   248   $variables['title'] = $variables['element']['#title'];
       
   249   $variables['value'] = $variables['element']['#markup'];
       
   250   $variables['attributes'] = '';
       
   251   if (isset($variables['element']['#attributes'])) {
       
   252     $variables['attributes'] = drupal_attributes($variables['element']['#attributes']);
       
   253   }
       
   254 }
       
   255 
       
   256 /**
       
   257  * Process variables for user-profile-category.tpl.php.
       
   258  *
       
   259  * The $variables array contains the following arguments:
       
   260  * - $element
       
   261  *
       
   262  * @see user-profile-category.tpl.php
       
   263  */
       
   264 function template_preprocess_user_profile_category(&$variables) {
       
   265   $variables['title'] = check_plain($variables['element']['#title']);
       
   266   $variables['profile_items'] = $variables['element']['#children'];
       
   267   $variables['attributes'] = '';
       
   268   if (isset($variables['element']['#attributes'])) {
       
   269     $variables['attributes'] = drupal_attributes($variables['element']['#attributes']);
       
   270   }
       
   271 }
       
   272 
       
   273 /**
       
   274  * Form builder; edit a user account or one of their profile categories.
       
   275  *
       
   276  * @ingroup forms
       
   277  * @see user_account_form()
       
   278  * @see user_account_form_validate()
       
   279  * @see user_profile_form_validate()
       
   280  * @see user_profile_form_submit()
       
   281  * @see user_cancel_confirm_form_submit()
       
   282  */
       
   283 function user_profile_form($form, &$form_state, $account, $category = 'account') {
       
   284   global $user;
       
   285 
       
   286   // During initial form build, add the entity to the form state for use during
       
   287   // form building and processing. During a rebuild, use what is in the form
       
   288   // state.
       
   289   if (!isset($form_state['user'])) {
       
   290     $form_state['user'] = $account;
       
   291   }
       
   292   else {
       
   293     $account = $form_state['user'];
       
   294   }
       
   295 
       
   296   // @todo Legacy support. Modules are encouraged to access the entity using
       
   297   //   $form_state. Remove in Drupal 8.
       
   298   $form['#user'] = $account;
       
   299   $form['#user_category'] = $category;
       
   300 
       
   301   if ($category == 'account') {
       
   302     user_account_form($form, $form_state);
       
   303     // Attach field widgets.
       
   304     $langcode = entity_language('user', $account);
       
   305     field_attach_form('user', $account, $form, $form_state, $langcode);
       
   306   }
       
   307 
       
   308   $form['actions'] = array('#type' => 'actions');
       
   309   $form['actions']['submit'] = array(
       
   310     '#type' => 'submit',
       
   311     '#value' => t('Save'),
       
   312   );
       
   313   if ($category == 'account') {
       
   314     $form['actions']['cancel'] = array(
       
   315       '#type' => 'submit',
       
   316       '#value' => t('Cancel account'),
       
   317       '#submit' => array('user_edit_cancel_submit'),
       
   318       '#access' => $account->uid > 1 && (($account->uid == $user->uid && user_access('cancel account')) || user_access('administer users')),
       
   319     );
       
   320   }
       
   321 
       
   322   $form['#validate'][] = 'user_profile_form_validate';
       
   323   // Add the final user profile form submit handler.
       
   324   $form['#submit'][] = 'user_profile_form_submit';
       
   325 
       
   326   return $form;
       
   327 }
       
   328 
       
   329 /**
       
   330  * Form validation handler for user_profile_form().
       
   331  *
       
   332  * @see user_profile_form_submit()
       
   333  */
       
   334 function user_profile_form_validate($form, &$form_state) {
       
   335   entity_form_field_validate('user', $form, $form_state);
       
   336 }
       
   337 
       
   338 /**
       
   339  * Form submission handler for user_profile_form().
       
   340  *
       
   341  * @see user_profile_form_validate()
       
   342  */
       
   343 function user_profile_form_submit($form, &$form_state) {
       
   344   $account = $form_state['user'];
       
   345   $category = $form['#user_category'];
       
   346   // Remove unneeded values.
       
   347   form_state_values_clean($form_state);
       
   348 
       
   349   // Before updating the account entity, keep an unchanged copy for use with
       
   350   // user_save() later. This is necessary for modules implementing the user
       
   351   // hooks to be able to react on changes by comparing the values of $account
       
   352   // and $edit.
       
   353   $account_unchanged = clone $account;
       
   354 
       
   355   entity_form_submit_build_entity('user', $account, $form, $form_state);
       
   356 
       
   357   // Populate $edit with the properties of $account, which have been edited on
       
   358   // this form by taking over all values, which appear in the form values too.
       
   359   $edit = array_intersect_key((array) $account, $form_state['values']);
       
   360 
       
   361   user_save($account_unchanged, $edit, $category);
       
   362   $form_state['values']['uid'] = $account->uid;
       
   363 
       
   364   if ($category == 'account' && !empty($edit['pass'])) {
       
   365     // Remove the password reset tag since a new password was saved.
       
   366     unset($_SESSION['pass_reset_'. $account->uid]);
       
   367   }
       
   368   // Clear the page cache because pages can contain usernames and/or profile information:
       
   369   cache_clear_all();
       
   370 
       
   371   drupal_set_message(t('The changes have been saved.'));
       
   372 }
       
   373 
       
   374 /**
       
   375  * Submit function for the 'Cancel account' button on the user edit form.
       
   376  */
       
   377 function user_edit_cancel_submit($form, &$form_state) {
       
   378   $destination = array();
       
   379   if (isset($_GET['destination'])) {
       
   380     $destination = drupal_get_destination();
       
   381     unset($_GET['destination']);
       
   382   }
       
   383   // Note: We redirect from user/uid/edit to user/uid/cancel to make the tabs disappear.
       
   384   $form_state['redirect'] = array("user/" . $form['#user']->uid . "/cancel", array('query' => $destination));
       
   385 }
       
   386 
       
   387 /**
       
   388  * Form builder; confirm form for cancelling user account.
       
   389  *
       
   390  * @ingroup forms
       
   391  * @see user_edit_cancel_submit()
       
   392  */
       
   393 function user_cancel_confirm_form($form, &$form_state, $account) {
       
   394   global $user;
       
   395 
       
   396   $form['_account'] = array('#type' => 'value', '#value' => $account);
       
   397 
       
   398   // Display account cancellation method selection, if allowed.
       
   399   $admin_access = user_access('administer users');
       
   400   $can_select_method = $admin_access || user_access('select account cancellation method');
       
   401   $form['user_cancel_method'] = array(
       
   402     '#type' => 'item',
       
   403     '#title' => ($account->uid == $user->uid ? t('When cancelling your account') : t('When cancelling the account')),
       
   404     '#access' => $can_select_method,
       
   405   );
       
   406   $form['user_cancel_method'] += user_cancel_methods();
       
   407 
       
   408   // Allow user administrators to skip the account cancellation confirmation
       
   409   // mail (by default), as long as they do not attempt to cancel their own
       
   410   // account.
       
   411   $override_access = $admin_access && ($account->uid != $user->uid);
       
   412   $form['user_cancel_confirm'] = array(
       
   413     '#type' => 'checkbox',
       
   414     '#title' => t('Require e-mail confirmation to cancel account.'),
       
   415     '#default_value' => ($override_access ? FALSE : TRUE),
       
   416     '#access' => $override_access,
       
   417     '#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'),
       
   418   );
       
   419   // Also allow to send account canceled notification mail, if enabled.
       
   420   $default_notify = variable_get('user_mail_status_canceled_notify', FALSE);
       
   421   $form['user_cancel_notify'] = array(
       
   422     '#type' => 'checkbox',
       
   423     '#title' => t('Notify user when account is canceled.'),
       
   424     '#default_value' => ($override_access ? FALSE : $default_notify),
       
   425     '#access' => $override_access && $default_notify,
       
   426     '#description' => t('When enabled, the user will receive an e-mail notification after the account has been cancelled.'),
       
   427   );
       
   428 
       
   429   // Prepare confirmation form page title and description.
       
   430   if ($account->uid == $user->uid) {
       
   431     $question = t('Are you sure you want to cancel your account?');
       
   432   }
       
   433   else {
       
   434     $question = t('Are you sure you want to cancel the account %name?', array('%name' => $account->name));
       
   435   }
       
   436   $description = '';
       
   437   if ($can_select_method) {
       
   438     $description = t('Select the method to cancel the account above.');
       
   439     foreach (element_children($form['user_cancel_method']) as $element) {
       
   440       unset($form['user_cancel_method'][$element]['#description']);
       
   441     }
       
   442   }
       
   443   else {
       
   444     // The radio button #description is used as description for the confirmation
       
   445     // form.
       
   446     foreach (element_children($form['user_cancel_method']) as $element) {
       
   447       if ($form['user_cancel_method'][$element]['#default_value'] == $form['user_cancel_method'][$element]['#return_value']) {
       
   448         $description = $form['user_cancel_method'][$element]['#description'];
       
   449       }
       
   450       unset($form['user_cancel_method'][$element]['#description']);
       
   451     }
       
   452   }
       
   453 
       
   454   // Always provide entity id in the same form key as in the entity edit form.
       
   455   $form['uid'] = array('#type' => 'value', '#value' => $account->uid);
       
   456   return confirm_form($form,
       
   457     $question,
       
   458     'user/' . $account->uid,
       
   459     $description . ' ' . t('This action cannot be undone.'),
       
   460     t('Cancel account'), t('Cancel'));
       
   461 }
       
   462 
       
   463 /**
       
   464  * Submit handler for the account cancellation confirm form.
       
   465  *
       
   466  * @see user_cancel_confirm_form()
       
   467  * @see user_multiple_cancel_confirm_submit()
       
   468  */
       
   469 function user_cancel_confirm_form_submit($form, &$form_state) {
       
   470   global $user;
       
   471   $account = $form_state['values']['_account'];
       
   472 
       
   473   // Cancel account immediately, if the current user has administrative
       
   474   // privileges, no confirmation mail shall be sent, and the user does not
       
   475   // attempt to cancel the own account.
       
   476   if (user_access('administer users') && empty($form_state['values']['user_cancel_confirm']) && $account->uid != $user->uid) {
       
   477     user_cancel($form_state['values'], $account->uid, $form_state['values']['user_cancel_method']);
       
   478 
       
   479     $form_state['redirect'] = 'admin/people';
       
   480   }
       
   481   else {
       
   482     // Store cancelling method and whether to notify the user in $account for
       
   483     // user_cancel_confirm().
       
   484     $edit = array(
       
   485       'user_cancel_method' => $form_state['values']['user_cancel_method'],
       
   486       'user_cancel_notify' => $form_state['values']['user_cancel_notify'],
       
   487     );
       
   488     $account = user_save($account, $edit);
       
   489     _user_mail_notify('cancel_confirm', $account);
       
   490     drupal_set_message(t('A confirmation request to cancel your account has been sent to your e-mail address.'));
       
   491     watchdog('user', 'Sent account cancellation request to %name %email.', array('%name' => $account->name, '%email' => '<' . $account->mail . '>'), WATCHDOG_NOTICE);
       
   492 
       
   493     $form_state['redirect'] = "user/$account->uid";
       
   494   }
       
   495 }
       
   496 
       
   497 /**
       
   498  * Helper function to return available account cancellation methods.
       
   499  *
       
   500  * See documentation of hook_user_cancel_methods_alter().
       
   501  *
       
   502  * @return
       
   503  *   An array containing all account cancellation methods as form elements.
       
   504  *
       
   505  * @see hook_user_cancel_methods_alter()
       
   506  * @see user_admin_settings()
       
   507  * @see user_cancel_confirm_form()
       
   508  * @see user_multiple_cancel_confirm()
       
   509  */
       
   510 function user_cancel_methods() {
       
   511   $methods = array(
       
   512     'user_cancel_block' => array(
       
   513       'title' => t('Disable the account and keep its content.'),
       
   514       '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.'),
       
   515     ),
       
   516     'user_cancel_block_unpublish' => array(
       
   517       'title' => t('Disable the account and unpublish its content.'),
       
   518       '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.'),
       
   519     ),
       
   520     'user_cancel_reassign' => array(
       
   521       'title' => t('Delete the account and make its content belong to the %anonymous-name user.', array('%anonymous-name' => variable_get('anonymous', t('Anonymous')))),
       
   522       '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' => variable_get('anonymous', t('Anonymous')))),
       
   523     ),
       
   524     'user_cancel_delete' => array(
       
   525       'title' => t('Delete the account and its content.'),
       
   526       'description' => t('Your account will be removed and all account information deleted. All of your content will also be deleted.'),
       
   527       'access' => user_access('administer users'),
       
   528     ),
       
   529   );
       
   530   // Allow modules to customize account cancellation methods.
       
   531   drupal_alter('user_cancel_methods', $methods);
       
   532 
       
   533   // Turn all methods into real form elements.
       
   534   $default_method = variable_get('user_cancel_method', 'user_cancel_block');
       
   535   foreach ($methods as $name => $method) {
       
   536     $form[$name] = array(
       
   537       '#type' => 'radio',
       
   538       '#title' => $method['title'],
       
   539       '#description' => (isset($method['description']) ? $method['description'] : NULL),
       
   540       '#return_value' => $name,
       
   541       '#default_value' => $default_method,
       
   542       '#parents' => array('user_cancel_method'),
       
   543     );
       
   544   }
       
   545   return $form;
       
   546 }
       
   547 
       
   548 /**
       
   549  * Menu callback; Cancel a user account via e-mail confirmation link.
       
   550  *
       
   551  * @see user_cancel_confirm_form()
       
   552  * @see user_cancel_url()
       
   553  */
       
   554 function user_cancel_confirm($account, $timestamp = 0, $hashed_pass = '') {
       
   555   // Time out in seconds until cancel URL expires; 24 hours = 86400 seconds.
       
   556   $timeout = 86400;
       
   557   $current = REQUEST_TIME;
       
   558 
       
   559   // Basic validation of arguments.
       
   560   if (isset($account->data['user_cancel_method']) && !empty($timestamp) && !empty($hashed_pass)) {
       
   561     // Validate expiration and hashed password/login.
       
   562     if ($timestamp <= $current && $current - $timestamp < $timeout && $account->uid && $timestamp >= $account->login && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid)) {
       
   563       $edit = array(
       
   564         'user_cancel_notify' => isset($account->data['user_cancel_notify']) ? $account->data['user_cancel_notify'] : variable_get('user_mail_status_canceled_notify', FALSE),
       
   565       );
       
   566       user_cancel($edit, $account->uid, $account->data['user_cancel_method']);
       
   567       // Since user_cancel() is not invoked via Form API, batch processing needs
       
   568       // to be invoked manually and should redirect to the front page after
       
   569       // completion.
       
   570       batch_process('');
       
   571     }
       
   572     else {
       
   573       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.'), 'error');
       
   574       drupal_goto("user/$account->uid/cancel");
       
   575     }
       
   576   }
       
   577   return MENU_ACCESS_DENIED;
       
   578 }
       
   579 
       
   580 /**
       
   581  * Page callback: Displays the user page.
       
   582  *
       
   583  * Displays user profile if user is logged in, or login form for anonymous
       
   584  * users.
       
   585  *
       
   586  * @return
       
   587  *   A render array for either a user profile or a login form.
       
   588  *
       
   589  * @see user_view_page()
       
   590  * @see user_login()
       
   591  */
       
   592 function user_page() {
       
   593   global $user;
       
   594   if ($user->uid) {
       
   595     menu_set_active_item('user/' . $user->uid);
       
   596     return menu_execute_active_handler(NULL, FALSE);
       
   597   }
       
   598   else {
       
   599     return drupal_get_form('user_login');
       
   600   }
       
   601 }