diff --git a/core/modules/user/lib/Drupal/user/Form/UserCancelConfirm.php b/core/modules/user/lib/Drupal/user/Form/UserCancelConfirm.php new file mode 100644 index 0000000..a88a3c2 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Form/UserCancelConfirm.php @@ -0,0 +1,156 @@ +account->id() == $user->uid) { + return t('Are you sure you want to cancel your account?'); + } + return t('Are you sure you want to cancel the account %name?', array('%name' => $this->account->label())); + } + + /** + * {@inheritdoc} + */ + protected function getCancelPath() { + return 'user/' . $this->account->id(); + } + + /** + * {@inheritdoc} + */ + protected function getDescription() { + $description = ''; + $default_method = config('user.settings')->get('cancel_method'); + if (user_access('administer users') || user_access('select account cancellation method')) { + $description = t('Select the method to cancel the account above.'); + } + // Options supplied via user_cancel_methods() can have a custom + // #confirm_description property for the confirmation form description. + elseif (isset($this->cancelMethods[$default_method]['#confirm_description'])) { + $description = $this->cancelMethods[$default_method]['#confirm_description']; + } + return $description . ' ' . t('This action cannot be undone.'); + } + + /** + * {@inheritdoc} + */ + protected function getConfirmText() { + return t('Cancel account'); + } + + /** + * {@inheritdoc} + * @param \Drupal\user\UserInterface $account + * The user account to be canceled. + */ + public function buildForm(array $form, array &$form_state, UserInterface $account = NULL) { + $this->account = $account; + // @todo move to proper place + form_load_include($form_state, 'inc', 'user', 'user.pages'); + $this->cancelMethods = user_cancel_methods(); + global $user; + + // Display account cancellation method selection, if allowed. + $admin_access = user_access('administer users'); + $form['user_cancel_method'] = array( + '#type' => 'radios', + '#title' => ($account->uid == $user->uid ? t('When cancelling your account') : t('When cancelling the account')), + '#access' => $admin_access || user_access('select account cancellation method'), + ); + $form['user_cancel_method'] += $this->cancelMethods; + + // 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. + $default_notify = config('user.settings')->get('notify.status_canceled'); + $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 canceled.'), + ); + + // Always provide entity id in the same form key as in the entity edit form. + $form['uid'] = array('#type' => 'value', '#value' => $account->uid); + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + global $user; + + // 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']) && $this->account->id() != $user->uid) { + user_cancel($form_state['values'], $this->account->id(), $form_state['values']['user_cancel_method']); + + $form_state['redirect'] = 'admin/people'; + } + else { + // Store cancelling method and whether to notify the user in + // $this->account for user_cancel_confirm(). + $this->account->user_cancel_method = $form_state['values']['user_cancel_method']; + $this->account->user_cancel_notify = $form_state['values']['user_cancel_notify']; + $this->account->save(); + _user_mail_notify('cancel_confirm', $this->account); + drupal_set_message(t('A confirmation request to cancel your account has been sent to your e-mail address.')); + watchdog('user', 'Sent account cancellation request to %name %email.', array('%name' => $this->account->label(), '%email' => '<' . $this->account->mail . '>'), WATCHDOG_NOTICE); + + $form_state['redirect'] = 'user/' . $this->account->id(); + } + } + +} diff --git a/core/modules/user/lib/Drupal/user/Form/UserMultipleCancelConfirm.php b/core/modules/user/lib/Drupal/user/Form/UserMultipleCancelConfirm.php new file mode 100644 index 0000000..58cccaa --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Form/UserMultipleCancelConfirm.php @@ -0,0 +1,187 @@ +tempStoreFactory = $temp_store_factory; + $this->configFactory = $config_factory; + $this->storageController = $storage_controller; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('user.tempstore'), + $container->get('config.factory'), + $container->get('plugin.manager.entity')->getStorageController('user') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'user_multiple_cancel_confirm'; + } + + /** + * {@inheritdoc} + */ + protected function getQuestion() { + return t('Are you sure you want to cancel these user accounts?'); + } + + /** + * {@inheritdoc} + */ + protected function getCancelPath() { + return 'admin/people'; + } + + /** + * {@inheritdoc} + */ + protected function getConfirmText() { + return t('Cancel accounts'); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + // Retrieve the accounts to be canceled from the temp store. + $accounts = $this->tempStoreFactory->get('user_user_operations_cancel')->get($GLOBALS['user']->uid); + if (!$accounts) { + drupal_goto('admin/people'); + } + + $form['accounts'] = array('#prefix' => '', '#tree' => TRUE); + foreach ($accounts as $uid => $account) { + // Prevent user 1 from being canceled. + if ($uid <= 1) { + continue; + } + $form['accounts'][$uid] = array( + '#type' => 'hidden', + '#value' => $uid, + '#prefix' => '
  • ', + '#suffix' => String::checkPlain($account->label()) . "
  • \n", + ); + } + + // Output a notice that user 1 cannot be canceled. + if (isset($accounts[1])) { + $redirect = (count($accounts) == 1); + $message = t('The user account %name cannot be canceled.', array('%name' => $accounts[1]->label())); + drupal_set_message($message, $redirect ? 'error' : 'warning'); + // If only user 1 was selected, redirect to the overview. + if ($redirect) { + drupal_goto('admin/people'); + } + } + + $form['operation'] = array('#type' => 'hidden', '#value' => 'cancel'); + + $form['user_cancel_method'] = array( + '#type' => 'radios', + '#title' => t('When cancelling these accounts'), + ); + + // @todo move to proper place + form_load_include($form_state, 'inc', 'user', 'user.pages'); + $form['user_cancel_method'] += user_cancel_methods(); + + // Allow to send the account cancellation confirmation mail. + $form['user_cancel_confirm'] = array( + '#type' => 'checkbox', + '#title' => t('Require e-mail confirmation to cancel account.'), + '#default_value' => FALSE, + '#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'), + ); + // Also allow to send account canceled notification mail, if enabled. + $form['user_cancel_notify'] = array( + '#type' => 'checkbox', + '#title' => t('Notify user when account is canceled.'), + '#default_value' => FALSE, + '#access' => $this->configFactory->get('user.settings')->get('notify.status_canceled'), + '#description' => t('When enabled, the user will receive an e-mail notification after the account has been canceled.'), + ); + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + global $user; + + // Clear out the accounts from the temp store. + $this->tempStoreFactory->get('user_user_operations_cancel')->delete($user->uid); + if ($form_state['values']['confirm']) { + foreach ($form_state['values']['accounts'] as $uid => $value) { + // Prevent programmatic form submissions from cancelling user 1. + if ($uid <= 1) { + continue; + } + // Prevent user administrators from deleting themselves without confirmation. + if ($uid == $user->uid) { + $admin_form_mock = array(); + $admin_form_state = $form_state; + unset($admin_form_state['values']['user_cancel_confirm']); + // The $user global is not a complete user entity, so load the full + // entity. + $accounts = $this->storageController->load((array($uid))); + $account = reset($accounts); + $admin_form = new UserCancelConfirm(); + // Calling this directly required to init form object with $account. + $admin_form->buildForm($admin_form_mock, $admin_form_state, $account); + $admin_form->submitForm($admin_form_mock, $admin_form_state); + } + else { + user_cancel($form_state['values'], $uid, $form_state['values']['user_cancel_method']); + } + } + } + $form_state['redirect'] = 'admin/people'; + } + +} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 9663af5..782fcc3 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -978,14 +978,6 @@ function user_menu() { 'route_name' => 'user_admin_create', 'type' => MENU_LOCAL_ACTION, ); - $items['admin/people/cancel'] = array( - 'title' => 'Cancel user', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_multiple_cancel_confirm'), - 'access arguments' => array('administer users'), - 'file' => 'user.admin.inc', - 'type' => MENU_CALLBACK, - ); // Administration pages. $items['admin/config/people'] = array( @@ -1024,11 +1016,7 @@ function user_menu() { ); $items['user/%user/cancel'] = array( 'title' => 'Cancel account', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_cancel_confirm_form', 1), - 'access callback' => 'entity_page_access', - 'access arguments' => array(1, 'delete'), - 'file' => 'user.pages.inc', + 'route_name' => 'user_cancel_confirm', ); $items['user/%user/cancel/confirm/%/%'] = array( 'title' => 'Confirm account cancellation', @@ -2012,100 +2000,6 @@ function user_role_revoke_permissions($rid, array $permissions = array()) { drupal_static_reset('user_role_permissions'); } -function user_multiple_cancel_confirm($form, &$form_state) { - // Retrieve the accounts to be canceled from the temp store. - $accounts = Drupal::service('user.tempstore')->get('user_user_operations_cancel')->get($GLOBALS['user']->uid); - $form['accounts'] = array('#prefix' => '', '#tree' => TRUE); - foreach ($accounts as $account) { - $uid = $account->id(); - // Prevent user 1 from being canceled. - if ($uid <= 1) { - continue; - } - $form['accounts'][$uid] = array( - '#type' => 'hidden', - '#value' => $uid, - '#prefix' => '
  • ', - '#suffix' => check_plain($account->name->value) . "
  • \n", - ); - } - - // Output a notice that user 1 cannot be canceled. - if (isset($accounts[1])) { - $redirect = (count($accounts) == 1); - $message = t('The user account %name cannot be cancelled.', array('%name' => $accounts[1]->name->value)); - drupal_set_message($message, $redirect ? 'error' : 'warning'); - // If only user 1 was selected, redirect to the overview. - if ($redirect) { - drupal_goto('admin/people'); - } - } - - $form['operation'] = array('#type' => 'hidden', '#value' => 'cancel'); - - form_load_include($form_state, 'inc', 'user', 'user.pages'); - $form['user_cancel_method'] = array( - '#type' => 'radios', - '#title' => t('When cancelling these accounts'), - ); - $form['user_cancel_method'] += user_cancel_methods(); - - // Allow to send the account cancellation confirmation mail. - $form['user_cancel_confirm'] = array( - '#type' => 'checkbox', - '#title' => t('Require e-mail confirmation to cancel account.'), - '#default_value' => FALSE, - '#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'), - ); - // Also allow to send account canceled notification mail, if enabled. - $form['user_cancel_notify'] = array( - '#type' => 'checkbox', - '#title' => t('Notify user when account is canceled.'), - '#default_value' => FALSE, - '#access' => config('user.settings')->get('notify.status_canceled'), - '#description' => t('When enabled, the user will receive an e-mail notification after the account has been cancelled.'), - ); - - return confirm_form($form, - t('Are you sure you want to cancel these user accounts?'), - 'admin/people', t('This action cannot be undone.'), - t('Cancel accounts'), t('Cancel')); -} - -/** - * Submit handler for mass-account cancellation form. - * - * @see user_multiple_cancel_confirm() - * @see user_cancel_confirm_form_submit() - */ -function user_multiple_cancel_confirm_submit($form, &$form_state) { - global $user; - - // Clear out the accounts from the temp store. - Drupal::service('user.tempstore')->get('user_user_operations_cancel')->delete($user->uid); - if ($form_state['values']['confirm']) { - foreach ($form_state['values']['accounts'] as $uid => $value) { - // Prevent programmatic form submissions from cancelling user 1. - if ($uid <= 1) { - continue; - } - // Prevent user administrators from deleting themselves without confirmation. - if ($uid == $user->uid) { - $admin_form_state = $form_state; - unset($admin_form_state['values']['user_cancel_confirm']); - // The $user global is not a complete user entity, so load the full - // entity. - $admin_form_state['values']['_account'] = user_load($user->uid); - user_cancel_confirm_form_submit(array(), $admin_form_state); - } - else { - user_cancel($form_state['values'], $uid, $form_state['values']['user_cancel_method']); - } - } - } - $form_state['redirect'] = 'admin/people'; -} - /** * List user administration filters that can be applied. */ diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 26fb040..c9c6f70 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -208,107 +208,6 @@ function user_edit_cancel_submit($form, &$form_state) { } /** - * Form builder; confirm form for cancelling user account. - * - * @ingroup forms - * @see user_edit_cancel_submit() - */ -function user_cancel_confirm_form($form, &$form_state, $account) { - global $user; - - $form['_account'] = array('#type' => 'value', '#value' => $account); - - // 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( - '#type' => 'radios', - '#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. - $default_notify = config('user.settings')->get('notify.status_canceled'); - $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)); - } - $default_method = config('user.settings')->get('cancel_method'); - $description = NULL; - if ($can_select_method) { - $description = t('Select the method to cancel the account above.'); - } - // 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']; - } - - // Always provide entity id in the same form key as in the entity edit form. - $form['uid'] = array('#type' => 'value', '#value' => $account->uid); - return confirm_form($form, - $question, - 'user/' . $account->uid, - $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']); - - $form_state['redirect'] = 'admin/people'; - } - else { - // Store cancelling method and whether to notify the user in $account for - // user_cancel_confirm(). - $account->user_cancel_method = $form_state['values']['user_cancel_method']; - $account->user_cancel_notify = $form_state['values']['user_cancel_notify']; - $account->save(); - _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.')); - watchdog('user', 'Sent account cancellation request to %name %email.', array('%name' => $account->name, '%email' => '<' . $account->mail . '>'), WATCHDOG_NOTICE); - - $form_state['redirect'] = "user/$account->uid"; - } -} - -/** * Helper function to return available account cancellation methods. * * See documentation of hook_user_cancel_methods_alter(). @@ -318,8 +217,6 @@ function user_cancel_confirm_form_submit($form, &$form_state) { * * @see hook_user_cancel_methods_alter() * @see user_admin_settings() - * @see user_cancel_confirm_form() - * @see user_multiple_cancel_confirm() */ function user_cancel_methods() { $anonymous_name = config('user.settings')->get('anonymous'); diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml index b48c808..e5aef3c 100644 --- a/core/modules/user/user.routing.yml +++ b/core/modules/user/user.routing.yml @@ -40,6 +40,13 @@ user_admin_create: requirements: _permission: 'administer users' +user_multiple_cancel_confirm: + pattern: '/admin/people/cancel' + defaults: + _form: '\Drupal\user\Form\UserMultipleCancelConfirm' + requirements: + _permission: 'administer users' + user_role_list: pattern: '/admin/people/roles' defaults: @@ -68,3 +75,13 @@ user_role_delete: _form: '\Drupal\user\Form\UserRoleDelete' requirements: _entity_access: user_role.delete + +user_cancel_confirm: + pattern: '/user/{account}/cancel' + options: + converters: + account: 'user' + defaults: + _form: '\Drupal\user\Form\UserCancelConfirm' + requirements: + _entity_access: account.delete