| 1 |
<?php |
<?php |
| 2 |
// $Id: user.module,v 1.951 2008/12/30 16:43:20 dries Exp $ |
// $Id: user.module,v 1.952 2009/01/04 16:10:48 dries Exp $ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* @file |
* @file |
| 16 |
*/ |
*/ |
| 17 |
define('EMAIL_MAX_LENGTH', 64); |
define('EMAIL_MAX_LENGTH', 64); |
| 18 |
|
|
| 19 |
|
|
| 20 |
/** |
/** |
| 21 |
* Invokes hook_user() in every module. |
* Invokes hook_user() in every module. |
| 22 |
* |
* |
| 588 |
'title' => t('Change own username'), |
'title' => t('Change own username'), |
| 589 |
'description' => t('Select a different username.'), |
'description' => t('Select a different username.'), |
| 590 |
), |
), |
| 591 |
|
'cancel account' => array( |
| 592 |
|
'title' => t('Cancel account'), |
| 593 |
|
'description' => t('Remove or disable own user account and unpublish, anonymize, or remove own submissions depending on the configured <a href="@user-settings-url">user settings</a>.', array('@user-settings-url' => url('admin/user/settings'))), |
| 594 |
|
), |
| 595 |
|
'select account cancellation method' => array( |
| 596 |
|
'title' => t('Select method for cancelling own account'), |
| 597 |
|
'description' => t('Select the method for cancelling own user account. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), |
| 598 |
|
), |
| 599 |
); |
); |
| 600 |
} |
} |
| 601 |
|
|
| 957 |
return (($GLOBALS['user']->uid == $account->uid) || user_access('administer users')) && $account->uid > 0; |
return (($GLOBALS['user']->uid == $account->uid) || user_access('administer users')) && $account->uid > 0; |
| 958 |
} |
} |
| 959 |
|
|
| 960 |
|
/** |
| 961 |
|
* Menu access callback; limit access to account cancellation pages. |
| 962 |
|
* |
| 963 |
|
* Limit access to users with the 'cancel account' permission or administrative |
| 964 |
|
* users, and prevent the anonymous user from cancelling the account. |
| 965 |
|
*/ |
| 966 |
|
function user_cancel_access($account) { |
| 967 |
|
return ((($GLOBALS['user']->uid == $account->uid) && user_access('cancel account')) || user_access('administer users')) && $account->uid > 0; |
| 968 |
|
} |
| 969 |
|
|
| 970 |
function user_load_self($arg) { |
function user_load_self($arg) { |
| 971 |
$arg[1] = user_load($GLOBALS['user']->uid); |
$arg[1] = user_load($GLOBALS['user']->uid); |
| 972 |
return $arg; |
return $arg; |
| 1101 |
'weight' => -10, |
'weight' => -10, |
| 1102 |
); |
); |
| 1103 |
|
|
| 1104 |
$items['user/%user/delete'] = array( |
$items['user/%user/cancel'] = array( |
| 1105 |
'title' => 'Delete', |
'title' => 'Cancel account', |
| 1106 |
'page callback' => 'drupal_get_form', |
'page callback' => 'drupal_get_form', |
| 1107 |
'page arguments' => array('user_confirm_delete', 1), |
'page arguments' => array('user_cancel_confirm_form', 1), |
| 1108 |
'access callback' => 'user_access', |
'access callback' => 'user_cancel_access', |
| 1109 |
'access arguments' => array('administer users'), |
'access arguments' => array(1), |
| 1110 |
|
'type' => MENU_CALLBACK, |
| 1111 |
|
); |
| 1112 |
|
|
| 1113 |
|
$items['user/%user/cancel/confirm/%/%'] = array( |
| 1114 |
|
'title' => 'Confirm account cancellation', |
| 1115 |
|
'page callback' => 'user_cancel_confirm', |
| 1116 |
|
'page arguments' => array(1, 4, 5), |
| 1117 |
|
'access callback' => 'user_cancel_access', |
| 1118 |
|
'access arguments' => array(1), |
| 1119 |
'type' => MENU_CALLBACK, |
'type' => MENU_CALLBACK, |
| 1120 |
); |
); |
| 1121 |
|
|
| 1473 |
return url("user/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE)); |
return url("user/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE)); |
| 1474 |
} |
} |
| 1475 |
|
|
| 1476 |
|
/** |
| 1477 |
|
* Generate a URL to confirm an account cancellation request. |
| 1478 |
|
* |
| 1479 |
|
* @see user_mail_tokens() |
| 1480 |
|
* @see user_cancel_confirm() |
| 1481 |
|
*/ |
| 1482 |
|
function user_cancel_url($account) { |
| 1483 |
|
$timestamp = REQUEST_TIME; |
| 1484 |
|
return url("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE)); |
| 1485 |
|
} |
| 1486 |
|
|
| 1487 |
function user_pass_rehash($password, $timestamp, $login) { |
function user_pass_rehash($password, $timestamp, $login) { |
| 1488 |
return md5($timestamp . $password . $login); |
return md5($timestamp . $password . $login); |
| 1489 |
} |
} |
| 1634 |
} |
} |
| 1635 |
|
|
| 1636 |
/** |
/** |
| 1637 |
* Delete a user. |
* Cancel a user account. |
| 1638 |
* |
* |
| 1639 |
* @param $edit An array of submitted form values. |
* Since the user cancellation process needs to be run in a batch, either |
| 1640 |
* @param $uid The user ID of the user to delete. |
* Form API will invoke it, or batch_process() needs to be invoked after calling |
| 1641 |
|
* this function and should define the path to redirect to. |
| 1642 |
|
* |
| 1643 |
|
* @param $edit |
| 1644 |
|
* An array of submitted form values. |
| 1645 |
|
* @param $uid |
| 1646 |
|
* The user ID of the user account to cancel. |
| 1647 |
|
* @param $method |
| 1648 |
|
* The account cancellation method to use. |
| 1649 |
|
* |
| 1650 |
|
* @see _user_cancel() |
| 1651 |
*/ |
*/ |
| 1652 |
function user_delete($edit, $uid) { |
function user_cancel($edit, $uid, $method) { |
| 1653 |
|
global $user; |
| 1654 |
|
|
| 1655 |
$account = user_load(array('uid' => $uid)); |
$account = user_load(array('uid' => $uid)); |
| 1656 |
drupal_session_destroy_uid($uid); |
|
| 1657 |
_user_mail_notify('status_deleted', $account); |
if (!$account) { |
| 1658 |
module_invoke_all('user_delete', $edit, $account); |
drupal_set_message(t('The user account %id does not exist.', array('%id' => $uid)), 'error'); |
| 1659 |
db_query('DELETE FROM {users} WHERE uid = %d', $uid); |
watchdog('user', 'Attempted to cancel non-existing user account: %id.', array('%id' => $uid), WATCHDOG_ERROR); |
| 1660 |
db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid); |
return; |
| 1661 |
db_query('DELETE FROM {authmap} WHERE uid = %d', $uid); |
} |
| 1662 |
$variables = array('%name' => $account->name, '%email' => '<' . $account->mail . '>'); |
|
| 1663 |
watchdog('user', 'Deleted user: %name %email.', $variables, WATCHDOG_NOTICE); |
// Initialize batch (to set title). |
| 1664 |
|
$batch = array( |
| 1665 |
|
'title' => t('Cancelling account'), |
| 1666 |
|
'operations' => array(), |
| 1667 |
|
); |
| 1668 |
|
batch_set($batch); |
| 1669 |
|
|
| 1670 |
|
// Allow modules to add further sets to this batch. |
| 1671 |
|
module_invoke_all('user_cancel', $edit, $account, $method); |
| 1672 |
|
|
| 1673 |
|
// Finish the batch and actually cancel the account. |
| 1674 |
|
$batch = array( |
| 1675 |
|
'title' => t('Cancelling user account'), |
| 1676 |
|
'operations' => array( |
| 1677 |
|
array('_user_cancel', array($edit, $account, $method)), |
| 1678 |
|
), |
| 1679 |
|
); |
| 1680 |
|
batch_set($batch); |
| 1681 |
|
|
| 1682 |
|
// Batch processing is either handled via Form API or has to be invoked |
| 1683 |
|
// manually. |
| 1684 |
|
} |
| 1685 |
|
|
| 1686 |
|
/** |
| 1687 |
|
* Last batch processing step for cancelling a user account. |
| 1688 |
|
* |
| 1689 |
|
* Since batch and session API require a valid user account, the actual |
| 1690 |
|
* cancellation of a user account needs to happen last. |
| 1691 |
|
* |
| 1692 |
|
* @see user_cancel() |
| 1693 |
|
*/ |
| 1694 |
|
function _user_cancel($edit, $account, $method) { |
| 1695 |
|
global $user; |
| 1696 |
|
|
| 1697 |
|
switch ($method) { |
| 1698 |
|
case 'user_cancel_block': |
| 1699 |
|
case 'user_cancel_block_unpublish': |
| 1700 |
|
default: |
| 1701 |
|
// Send account blocked notification if option was checked. |
| 1702 |
|
if (!empty($edit['user_cancel_notify'])) { |
| 1703 |
|
_user_mail_notify('status_blocked', $account); |
| 1704 |
|
} |
| 1705 |
|
db_update('users')->fields(array('status' => 0))->condition('uid', $account->uid)->execute(); |
| 1706 |
|
drupal_set_message(t('%name has been disabled.', array('%name' => $account->name))); |
| 1707 |
|
break; |
| 1708 |
|
|
| 1709 |
|
case 'user_cancel_reassign': |
| 1710 |
|
case 'user_cancel_delete': |
| 1711 |
|
// Send account canceled notification if option was checked. |
| 1712 |
|
if (!empty($edit['user_cancel_notify'])) { |
| 1713 |
|
_user_mail_notify('status_canceled', $account); |
| 1714 |
|
} |
| 1715 |
|
db_delete('users')->condition('uid', $account->uid)->execute(); |
| 1716 |
|
db_delete('users_roles')->condition('uid', $account->uid)->execute(); |
| 1717 |
|
db_delete('authmap')->condition('uid', $account->uid)->execute(); |
| 1718 |
|
drupal_set_message(t('%name has been deleted.', array('%name' => $account->name))); |
| 1719 |
|
$variables = array('%name' => $account->name, '%email' => '<' . $account->mail . '>'); |
| 1720 |
|
watchdog('user', 'Deleted user: %name %email.', $variables, WATCHDOG_NOTICE); |
| 1721 |
|
break; |
| 1722 |
|
} |
| 1723 |
|
|
| 1724 |
|
// After cancelling account, ensure that user is logged out. |
| 1725 |
|
if ($account->uid == $user->uid) { |
| 1726 |
|
// Destroy the current session. |
| 1727 |
|
session_destroy(); |
| 1728 |
|
// Load the anonymous user. |
| 1729 |
|
$user = drupal_anonymous_user(); |
| 1730 |
|
} |
| 1731 |
|
else { |
| 1732 |
|
drupal_session_destroy_uid($account->uid); |
| 1733 |
|
} |
| 1734 |
|
|
| 1735 |
|
// Clear the cache for anonymous users. |
| 1736 |
|
cache_clear_all(); |
| 1737 |
} |
} |
| 1738 |
|
|
| 1739 |
/** |
/** |
| 1806 |
return t('Account details for !username at !site (blocked)', $variables, $langcode); |
return t('Account details for !username at !site (blocked)', $variables, $langcode); |
| 1807 |
case 'status_blocked_body': |
case 'status_blocked_body': |
| 1808 |
return t("!username,\n\nYour account on !site has been blocked.", $variables, $langcode); |
return t("!username,\n\nYour account on !site has been blocked.", $variables, $langcode); |
| 1809 |
case 'status_deleted_subject': |
|
| 1810 |
return t('Account details for !username at !site (deleted)', $variables, $langcode); |
case 'cancel_confirm_subject': |
| 1811 |
case 'status_deleted_body': |
return t('Account cancellation request for !username at !site', $variables, $langcode); |
| 1812 |
return t("!username,\n\nYour account on !site has been deleted.", $variables, $langcode); |
case 'cancel_confirm_body': |
| 1813 |
|
return t("!username, |
| 1814 |
|
|
| 1815 |
|
A request to cancel your account has been made at !site. |
| 1816 |
|
|
| 1817 |
|
You may now cancel your account on !uri_brief by clicking this link or copying and pasting it into your browser: |
| 1818 |
|
|
| 1819 |
|
!cancel_url |
| 1820 |
|
|
| 1821 |
|
NOTE: The cancellation of your account is not reversible. |
| 1822 |
|
|
| 1823 |
|
This link expires in one day and nothing will happen if it is not used.", $variables, $langcode); |
| 1824 |
|
|
| 1825 |
|
case 'status_canceled_subject': |
| 1826 |
|
return t('Account details for !username at !site (canceled)', $variables, $langcode); |
| 1827 |
|
case 'status_canceled_body': |
| 1828 |
|
return t("!username, |
| 1829 |
|
|
| 1830 |
|
Your account on !site has been canceled.", $variables, $langcode); |
| 1831 |
} |
} |
| 1832 |
} |
} |
| 1833 |
} |
} |
| 1894 |
'label' => t('Block the selected users'), |
'label' => t('Block the selected users'), |
| 1895 |
'callback' => 'user_user_operations_block', |
'callback' => 'user_user_operations_block', |
| 1896 |
), |
), |
| 1897 |
'delete' => array( |
'cancel' => array( |
| 1898 |
'label' => t('Delete the selected users'), |
'label' => t('Cancel the selected user accounts'), |
| 1899 |
), |
), |
| 1900 |
); |
); |
| 1901 |
|
|
| 2008 |
} |
} |
| 2009 |
} |
} |
| 2010 |
|
|
| 2011 |
function user_multiple_delete_confirm(&$form_state) { |
function user_multiple_cancel_confirm(&$form_state) { |
| 2012 |
$edit = $form_state['post']; |
$edit = $form_state['post']; |
| 2013 |
|
|
| 2014 |
$form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); |
$form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); |
| 2017 |
$user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid)); |
$user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid)); |
| 2018 |
$form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) . "</li>\n"); |
$form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) . "</li>\n"); |
| 2019 |
} |
} |
| 2020 |
$form['operation'] = array('#type' => 'hidden', '#value' => 'delete'); |
|
| 2021 |
|
$form['operation'] = array('#type' => 'hidden', '#value' => 'cancel'); |
| 2022 |
|
|
| 2023 |
|
module_load_include('inc', 'user', 'user.pages'); |
| 2024 |
|
$form['user_cancel_method'] = array( |
| 2025 |
|
'#type' => 'item', |
| 2026 |
|
'#title' => t('When cancelling these accounts'), |
| 2027 |
|
); |
| 2028 |
|
$form['user_cancel_method'] += user_cancel_methods(); |
| 2029 |
|
// Remove method descriptions. |
| 2030 |
|
foreach (element_children($form['user_cancel_method']) as $element) { |
| 2031 |
|
unset($form['user_cancel_method'][$element]['#description']); |
| 2032 |
|
} |
| 2033 |
|
|
| 2034 |
|
// Allow to send the account cancellation confirmation mail. |
| 2035 |
|
$form['user_cancel_confirm'] = array( |
| 2036 |
|
'#type' => 'checkbox', |
| 2037 |
|
'#title' => t('Require e-mail confirmation to cancel account.'), |
| 2038 |
|
'#default_value' => FALSE, |
| 2039 |
|
'#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'), |
| 2040 |
|
); |
| 2041 |
|
// Also allow to send account canceled notification mail, if enabled. |
| 2042 |
|
$form['user_cancel_notify'] = array( |
| 2043 |
|
'#type' => 'checkbox', |
| 2044 |
|
'#title' => t('Notify user when account is canceled.'), |
| 2045 |
|
'#default_value' => FALSE, |
| 2046 |
|
'#access' => variable_get('user_mail_status_canceled_notify', FALSE), |
| 2047 |
|
'#description' => t('When enabled, the user will receive an e-mail notification after the account has been cancelled.'), |
| 2048 |
|
); |
| 2049 |
|
|
| 2050 |
return confirm_form($form, |
return confirm_form($form, |
| 2051 |
t('Are you sure you want to delete these users?'), |
t('Are you sure you want to cancel these user accounts?'), |
| 2052 |
'admin/user/user', t('This action cannot be undone.'), |
'admin/user/user', t('This action cannot be undone.'), |
| 2053 |
t('Delete all'), t('Cancel')); |
t('Cancel accounts'), t('Cancel')); |
| 2054 |
} |
} |
| 2055 |
|
|
| 2056 |
function user_multiple_delete_confirm_submit($form, &$form_state) { |
/** |
| 2057 |
|
* Submit handler for mass-account cancellation form. |
| 2058 |
|
* |
| 2059 |
|
* @see user_multiple_cancel_confirm() |
| 2060 |
|
* @see user_cancel_confirm_form_submit() |
| 2061 |
|
*/ |
| 2062 |
|
function user_multiple_cancel_confirm_submit($form, &$form_state) { |
| 2063 |
|
global $user; |
| 2064 |
|
|
| 2065 |
if ($form_state['values']['confirm']) { |
if ($form_state['values']['confirm']) { |
| 2066 |
foreach ($form_state['values']['accounts'] as $uid => $value) { |
foreach ($form_state['values']['accounts'] as $uid => $value) { |
| 2067 |
user_delete($form_state['values'], $uid); |
// Prevent user administrators from deleting themselves without confirmation. |
| 2068 |
|
if ($uid == $user->uid) { |
| 2069 |
|
$admin_form_state = $form_state; |
| 2070 |
|
unset($admin_form_state['values']['user_cancel_confirm']); |
| 2071 |
|
$admin_form_state['values']['_account'] = $user; |
| 2072 |
|
user_cancel_confirm_form_submit(array(), $admin_form_state); |
| 2073 |
|
} |
| 2074 |
|
else { |
| 2075 |
|
user_cancel($form_state['values'], $uid, $form_state['values']['user_cancel_method']); |
| 2076 |
|
} |
| 2077 |
} |
} |
|
drupal_set_message(t('The users have been deleted.')); |
|
| 2078 |
} |
} |
| 2079 |
$form_state['redirect'] = 'admin/user/user'; |
$form_state['redirect'] = 'admin/user/user'; |
| 2080 |
return; |
return; |
| 2268 |
'!username' => $account->name, |
'!username' => $account->name, |
| 2269 |
'!site' => variable_get('site_name', 'Drupal'), |
'!site' => variable_get('site_name', 'Drupal'), |
| 2270 |
'!login_url' => user_pass_reset_url($account), |
'!login_url' => user_pass_reset_url($account), |
| 2271 |
|
'!cancel_url' => user_cancel_url($account), |
| 2272 |
'!uri' => $base_url, |
'!uri' => $base_url, |
| 2273 |
'!uri_brief' => preg_replace('!^https?://!', '', $base_url), |
'!uri_brief' => preg_replace('!^https?://!', '', $base_url), |
| 2274 |
'!mailto' => $account->mail, |
'!mailto' => $account->mail, |
| 2320 |
* 'password_reset': Password recovery request |
* 'password_reset': Password recovery request |
| 2321 |
* 'status_activated': Account activated |
* 'status_activated': Account activated |
| 2322 |
* 'status_blocked': Account blocked |
* 'status_blocked': Account blocked |
| 2323 |
* 'status_deleted': Account deleted |
* 'cancel_confirm': Account cancellation request |
| 2324 |
|
* 'status_canceled': Account canceled |
| 2325 |
* |
* |
| 2326 |
* @param $account |
* @param $account |
| 2327 |
* The user object of the account being notified. Must contain at |
* The user object of the account being notified. Must contain at |
| 2332 |
* The return value from drupal_mail_send(), if ends up being called. |
* The return value from drupal_mail_send(), if ends up being called. |
| 2333 |
*/ |
*/ |
| 2334 |
function _user_mail_notify($op, $account, $language = NULL) { |
function _user_mail_notify($op, $account, $language = NULL) { |
| 2335 |
// By default, we always notify except for deleted and blocked. |
// By default, we always notify except for canceled and blocked. |
| 2336 |
$default_notify = ($op != 'status_deleted' && $op != 'status_blocked'); |
$default_notify = ($op != 'status_canceled' && $op != 'status_blocked'); |
| 2337 |
$notify = variable_get('user_mail_' . $op . '_notify', $default_notify); |
$notify = variable_get('user_mail_' . $op . '_notify', $default_notify); |
| 2338 |
if ($notify) { |
if ($notify) { |
| 2339 |
$params['account'] = $account; |
$params['account'] = $account; |