diff --git a/core/modules/block/block.install b/core/modules/block/block.install index ee72e0f..3b50c85 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -233,6 +233,10 @@ function block_update_dependencies() { $dependencies['block'][8002] = array( 'user' => 8002, ); + // Migrate users.data after User module prepared the tables. + $dependencies['block'][8004] = array( + 'user' => 8011, + ); return $dependencies; } @@ -324,6 +328,23 @@ function block_update_8003() { } /** + * Migrate {users}.data into {users_data}. + */ +function block_update_8004() { + $query = db_select('_d7_users_data', 'ud'); + $query->addField('ud', 'uid'); + $query->addExpression('block', 'module'); + $query->addExpression('block', 'name'); + // Take over the extracted and serialized value in {_d7_users_data} as-is. + $query->addField('ud', 'value'); + $query->addExpression('1', 'serialized'); + + db_insert('users_data') + ->from($query) + ->execute(); +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 2978146..698ae80 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -599,6 +599,7 @@ function block_form_user_profile_form_alter(&$form, &$form_state) { $account = $form_state['controller']->getEntity($form_state); $rids = array_keys($account->roles); $result = db_query("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom <> 0 AND (r.rid IN (:rids) OR r.rid IS NULL) ORDER BY b.weight, b.module", array(':rids' => $rids)); + $account_data = user_data_get('block', $account->uid, 'block'); $blocks = array(); foreach ($result as $block) { @@ -607,7 +608,7 @@ function block_form_user_profile_form_alter(&$form, &$form_state) { $blocks[$block->module][$block->delta] = array( '#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), - '#default_value' => isset($account->data['block'][$block->module][$block->delta]) ? $account->data['block'][$block->module][$block->delta] : ($block->custom == 1), + '#default_value' => isset($account_data[$block->module][$block->delta]) ? $account_data[$block->module][$block->delta] : ($block->custom == 1), ); } } @@ -639,11 +640,11 @@ function block_field_extra_fields() { } /** - * Implements hook_user_presave(). + * Implements hook_user_update(). */ -function block_user_presave($account) { +function block_user_update($account) { if (isset($account->block)) { - $account->data['block'] = $account->block; + user_data_set('block', $account->uid, 'block', $account->block); } } @@ -805,6 +806,10 @@ function block_block_list_alter(&$blocks) { $block_langcodes[$record->module][$record->delta][$record->type][$record->langcode] = TRUE; } + if ($user->uid) { + $user_data = user_data_get('block', $user->uid, 'block'); + } + foreach ($blocks as $key => $block) { if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) { // This block was added by a contrib module, leave it in the list. @@ -822,8 +827,8 @@ function block_block_list_alter(&$blocks) { // Use the user's block visibility setting, if necessary. if ($block->custom != BLOCK_CUSTOM_FIXED) { - if ($user->uid && isset($user->data['block'][$block->module][$block->delta])) { - $enabled = $user->data['block'][$block->module][$block->delta]; + if ($user->uid && isset($user_data[$block->module][$block->delta])) { + $enabled = $user_data[$block->module][$block->delta]; } else { $enabled = ($block->custom == BLOCK_CUSTOM_ENABLED); diff --git a/core/modules/contact/contact.install b/core/modules/contact/contact.install index f956242..7f16b04 100644 --- a/core/modules/contact/contact.install +++ b/core/modules/contact/contact.install @@ -84,6 +84,17 @@ function contact_install() { } /** + * Implements hook_update_dependencies(). + */ +function contact_update_dependencies() { + // Migrate users.data after User module prepared the tables. + $dependencies['contact'][8001] = array( + 'user' => 8011, + ); + return $dependencies; +} + +/** * Moves contact setting from variable to config. * * @ingroup config_upgrade @@ -95,3 +106,25 @@ function contact_update_8000() { 'contact_threshold_window' => 'flood.interval', )); } + +/** + * Migrate {users}.data into {users_data}. + */ +function contact_update_8001() { + // Migrate in two passes; once all users who disabled their personal contact + // form, and once who enabled it. + foreach (array(serialize('0'), serialize('1')) as $enabled => $serialized_setting) { + $query = db_select('_d7_users_data', 'ud'); + $query->addField('ud', 'uid'); + $query->addExpression('contact', 'module'); + $query->addExpression('enabled', 'name'); + $query->condition('value', $serialized_setting); + $query->addExpression($enabled, 'value'); + $query->addExpression(0, 'serialized'); + + db_insert('users_data') + ->from($query) + ->execute(); + } +} + diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index 985abbd..fb00160 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -134,7 +134,8 @@ function _contact_personal_tab_access($account) { // If the requested user has disabled their contact form, or this preference // has not yet been saved, do not allow users to contact them. - if (empty($account->data['contact'])) { + $account_data = user_data_get('contact', $account->uid, 'enabled'); + if (empty($account_data)) { return FALSE; } @@ -222,19 +223,21 @@ function contact_form_user_profile_form_alter(&$form, &$form_state) { '#collapsible' => TRUE, ); $account = $form_state['controller']->getEntity($form_state); + $account_data = user_data_get('contact', $account->uid, 'enabled'); $form['contact']['contact'] = array( '#type' => 'checkbox', '#title' => t('Personal contact form'), - '#default_value' => !empty($account->data['contact']) ? $account->data['contact'] : FALSE, + '#default_value' => !empty($account_data) ? $account_data : FALSE, '#description' => t('Allow other users to contact you via a personal contact form which keeps your e-mail address hidden. Note that some privileged users such as site administrators are still able to contact you even if you choose to disable this feature.', array('@url' => url("user/$account->uid/contact"))), ); } /** - * Implements hook_user_presave(). + * Implements hook_user_update(). */ -function contact_user_presave($account) { - $account->data['contact'] = isset($account->contact) ? $account->contact : config('contact.settings')->get('user_default_enabled'); +function contact_user_update($account) { + $value = (bool) isset($account->contact) ? $account->contact : config('contact.settings')->get('user_default_enabled'); + user_data_set('contact', $account->uid, 'enabled', $value); } /** diff --git a/core/modules/openid/lib/Drupal/openid/Tests/OpenIDRegistrationTest.php b/core/modules/openid/lib/Drupal/openid/Tests/OpenIDRegistrationTest.php index debb9cd..51c2160 100644 --- a/core/modules/openid/lib/Drupal/openid/Tests/OpenIDRegistrationTest.php +++ b/core/modules/openid/lib/Drupal/openid/Tests/OpenIDRegistrationTest.php @@ -77,7 +77,6 @@ function testRegisterUserWithEmailVerification() { $this->assertEqual($user->mail, 'john@example.com', 'User was registered with right email address.'); $this->assertEqual($user->timezone, 'Europe/London', 'User was registered with right timezone.'); $this->assertEqual($user->preferred_langcode, 'pt', 'User was registered with right language.'); - $this->assertFalse($user->data, 'No additional user info was saved.'); $this->submitLoginForm($identity); $this->assertRaw(t('You must validate your email address for this account before logging in via OpenID.')); @@ -126,7 +125,6 @@ function testRegisterUserWithoutEmailVerification() { $this->assertEqual($user->mail, 'john@example.com', 'User was registered with right email address.'); $this->assertEqual($user->timezone, 'Europe/London', 'User was registered with right timezone.'); $this->assertEqual($user->preferred_langcode, 'pt-br', 'User was registered with right language.'); - $this->assertFalse($user->data, 'No additional user info was saved.'); $this->drupalLogout(); @@ -171,7 +169,6 @@ function testRegisterUserWithInvalidSreg() { $user = user_load_by_name('john'); $this->assertTrue($user, 'User was registered with right username.'); $this->assertEqual($user->preferred_langcode, language_default()->langcode, 'User language is site default.'); - $this->assertFalse($user->data, 'No additional user info was saved.'); // Follow the one-time login that was sent in the welcome e-mail. $this->drupalGet($reset_url); @@ -211,7 +208,6 @@ function testRegisterUserWithoutSreg() { $user = user_load_by_name('john'); $this->assertTrue($user, 'User was registered with right username.'); $this->assertEqual($user->preferred_langcode, language_default()->langcode, 'User language is site default.'); - $this->assertFalse($user->data, 'No additional user info was saved.'); // Follow the one-time login that was sent in the welcome e-mail. $this->drupalGet($reset_url); diff --git a/core/modules/overlay/overlay.install b/core/modules/overlay/overlay.install index 2df860b..4bac2f6 100644 --- a/core/modules/overlay/overlay.install +++ b/core/modules/overlay/overlay.install @@ -17,3 +17,47 @@ function overlay_enable() { $_SESSION['overlay_enable_redirect'] = 1; } } + +/** + * Implements hook_update_dependencies(). + */ +function overlay_update_dependencies() { + // Migrate users.data after User module prepared the tables. + $dependencies['overlay'][8000] = array( + 'user' => 8011, + ); + return $dependencies; +} + +/** + * Migrate {users}.data into {users_data}. + */ +function overlay_update_8000() { + // Migrate 'overlay' in two passes; once all users who disabled overlay, and + // once who enabled it. + foreach (array(serialize('0'), serialize('1')) as $enabled => $serialized_setting) { + $query = db_select('_d7_users_data', 'ud'); + $query->addField('ud', 'uid'); + $query->addExpression('overlay', 'module'); + $query->addExpression('enabled', 'name'); + $query->condition('value', $serialized_setting); + $query->addExpression($enabled, 'value'); + $query->addExpression(0, 'serialized'); + + db_insert('users_data') + ->from($query) + ->execute(); + } + // Migrate 'overlay_message_dismissed'. + $query = db_select('_d7_users_data', 'ud'); + $query->addField('ud', 'uid'); + $query->addExpression('overlay', 'module'); + $query->addExpression('message_dismissed', 'name'); + $query->condition('value', serialize('1')); + $query->addExpression(1, 'value'); + $query->addExpression(0, 'serialized'); + + db_insert('users_data') + ->from($query) + ->execute(); +} diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index 6d78e43..3b0e7bd 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -87,6 +87,7 @@ function overlay_theme() { function overlay_form_user_profile_form_alter(&$form, &$form_state) { $account = $form_state['controller']->getEntity($form_state); if (user_access('access overlay', $account)) { + $account_data = user_data_get('overlay', $account->uid, 'enabled'); $form['overlay_control'] = array( '#type' => 'fieldset', '#title' => t('Administrative overlay'), @@ -97,7 +98,7 @@ function overlay_form_user_profile_form_alter(&$form, &$form_state) { '#type' => 'checkbox', '#title' => t('Use the overlay for administrative pages.'), '#description' => t('Show administrative pages on top of the page you started from.'), - '#default_value' => isset($account->data['overlay']) ? $account->data['overlay'] : 1, + '#default_value' => isset($account_data) ? $account_data : 1, ); } } @@ -107,7 +108,7 @@ function overlay_form_user_profile_form_alter(&$form, &$form_state) { */ function overlay_user_presave($account) { if (isset($account->overlay)) { - $account->data['overlay'] = $account->overlay; + user_data_set('overlay', $account->uid, 'enabled', $account->overlay); } } @@ -126,7 +127,8 @@ function overlay_init() { // Only act if the user has access to the overlay and a mode was not already // set. Other modules can also enable the overlay directly for other uses. - $use_overlay = !isset($user->data['overlay']) || $user->data['overlay']; + $user_data = user_data_get('overlay', $user->uid, 'enabled'); + $use_overlay = !isset($user_data) || $user_data; if (empty($mode) && user_access('access overlay') && $use_overlay) { $current_path = current_path(); // After overlay is enabled on the modules page, redirect to @@ -354,9 +356,7 @@ function overlay_user_dismiss_message() { throw new AccessDeniedHttpException(); } - $account = user_load($user->uid); - $account->data['overlay_message_dismissed'] = 1; - $account->save(); + user_data_set('overlay', $user->uid, 'message_dismissed', 1); drupal_set_message(t('The message has been dismissed. You can change your overlay settings at any time by visiting your profile page.')); // Destination is normally given. Go to the user profile as a fallback. drupal_goto('user/' . $user->uid . '/edit'); @@ -378,7 +378,13 @@ function overlay_user_dismiss_message() { function overlay_disable_message() { global $user; - if (!empty($user->uid) && empty($user->data['overlay_message_dismissed']) && (!isset($user->data['overlay']) || $user->data['overlay']) && user_access('access overlay')) { + $build = array(); + if (empty($user->uid) || !user_access('access overlay')) { + return $build; + } + + $user_data = user_data_get('overlay', $user->uid); + if (empty($user_data['message_dismissed']) && (!isset($user_data['enabled']) || $user_data['enabled'])) { $build = array( '#theme' => 'overlay_disable_message', '#weight' => -99, @@ -418,9 +424,6 @@ function overlay_disable_message() { ) ); } - else { - $build = array(); - } return $build; } diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php index 9b22466..cacc318 100644 --- a/core/modules/user/lib/Drupal/user/UserStorageController.php +++ b/core/modules/user/lib/Drupal/user/UserStorageController.php @@ -220,7 +220,7 @@ protected function postSave(EntityInterface $entity, $update) { ->key(array( 'uid' => $entity->uid, 'module' => 'user', - 'name' => $key, + 'name' => substr($key, 5), )) ->fields(array( 'value' => $entity->{$key}, diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php index 0c3002c..84b26de 100644 --- a/core/modules/user/user.api.php +++ b/core/modules/user/user.api.php @@ -233,11 +233,6 @@ function hook_user_operations() { * * This hook is invoked before the user account is saved to the database. * - * Modules that want to store properties in the serialized {users}.data column, - * which is automatically loaded whenever a user account object is loaded, may - * add their properties to $account->data in order to have their data serialized - * on save. - * * @param $account * The user account object. * @@ -245,10 +240,9 @@ function hook_user_operations() { * @see hook_user_update() */ function hook_user_presave($account) { - // Make sure that our form value 'mymodule_foo' is stored as - // 'mymodule_bar' in the 'data' (serialized) column. + // Ensure that our value is an array. if (isset($account->mymodule_foo)) { - $account->data['mymodule_bar'] = $account->mymodule_foo; + $account->mymodule_foo = (array) $account->mymodule_foo; } } diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 1532013..b850f46 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -266,10 +266,10 @@ function user_schema() { ); $schema['users_data'] = array( - 'description' => 'Stores variables as key/value pairs per user.', + 'description' => 'Stores module data as key/value pairs per user.', 'fields' => array( 'uid' => array( - 'description' => 'Primary Key: {users}.uid for user.', + 'description' => 'Primary key: {users}.uid for user.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, @@ -283,24 +283,30 @@ function user_schema() { 'default' => '', ), 'name' => array( - 'description' => 'The name of the variable.', + 'description' => 'The identifier of the data.', 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', ), 'value' => array( - 'description' => 'The serialized value of the variable.', + 'description' => 'The value.', 'type' => 'blob', 'not null' => FALSE, 'size' => 'big', - 'serialize' => TRUE, + ), + 'serialized' => array( + 'description' => 'Whether value is serialized.', + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'default' => 0, ), ), - 'primary key' => array('uid', 'name'), + 'primary key' => array('uid', 'module', 'name'), 'indexes' => array( + 'module' => array('module'), 'name' => array('name'), - 'uid_module' => array('uid', 'module'), ), 'foreign keys' => array( 'uid' => array('users' => 'uid'), @@ -633,15 +639,15 @@ function user_update_8009(&$sandbox) { } /** - * Move {users}.data into an own {users_data} table. + * Create new {users_data} table. */ function user_update_8010() { - // Create new {users_data} table. + // Create the {users_data} table. db_create_table('users_data', array( - 'description' => 'Stores variables as key/value pairs per user.', + 'description' => 'Stores module data as key/value pairs per user.', 'fields' => array( 'uid' => array( - 'description' => 'Primary Key: {users}.uid for user.', + 'description' => 'Primary key: {users}.uid for user.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, @@ -655,24 +661,30 @@ function user_update_8010() { 'default' => '', ), 'name' => array( - 'description' => 'The name of the variable.', + 'description' => 'The identifier of the data.', 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '', ), 'value' => array( - 'description' => 'The serialized value of the variable.', + 'description' => 'The value.', 'type' => 'blob', 'not null' => FALSE, 'size' => 'big', - 'serialize' => TRUE, + ), + 'serialized' => array( + 'description' => 'Whether value is serialized.', + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'default' => 0, ), ), - 'primary key' => array('uid', 'name'), + 'primary key' => array('uid', 'module', 'name'), 'indexes' => array( + 'module' => array('module'), 'name' => array('name'), - 'uid_module' => array('uid', 'module'), ), 'foreign keys' => array( 'uid' => array('users' => 'uid'), @@ -681,8 +693,7 @@ function user_update_8010() { // Create backup table for data migration. // Since the origin/owner of individual values in {users}.data is unknown, - // other modules need to migrate their existing values from {_d7_users_data} - // after this update has run. + // other modules need to migrate their existing values from {_d7_users_data}. db_create_table('_d7_users_data', array( 'description' => 'Backup of {users}.data for migration.', 'fields' => array( @@ -713,18 +724,34 @@ function user_update_8010() { 'uid' => array('users' => 'uid'), ), )); +} - // Backup existing data. - // @todo Process in chunks of 100 users. - $result = db_query("SELECT uid, data FROM {users}")->fetchAllAssoc('uid'); +/** + * Move existing {users}.data into {_d7_users_data} migration table. + */ +function user_update_8011(&$sandbox) { + if (!isset($sandbox['progress'])) { + $sandbox['progress'] = 0; + // The anonymous user cannot have data, so start with uid 1. + $sandbox['last'] = 0; + $sandbox['max'] = db_query('SELECT COUNT(uid) FROM {users} WHERE uid > 0')->fetchField(); + } + + // Process 20 user records at a time. E.g., if there are 10 data keys per user + // record, that leads to an insert query with 200 values. + $result = db_query_range('SELECT uid, data FROM {users} WHERE uid > :uid ORDER BY uid ASC', 0, 20, array(':uid' => $sandbox['last']))->fetchAllKeyed(); $query = db_insert('_d7_users_data')->fields(array('uid', 'name', 'value')); - foreach ($result as $uid => $account) { - if (empty($account->data)) { + $has_values = FALSE; + foreach ($result as $uid => $data) { + $sandbox['progress']++; + $sandbox['last'] = $uid; + if (empty($data)) { continue; } - $account->data = unserialize($account->data); - if (!empty($account->data) && is_array($account->data)) { - foreach ($account->data as $name => $value) { + $data = unserialize($data); + if (!empty($data) && is_array($data)) { + $has_values = TRUE; + foreach ($data as $name => $value) { $query->values(array( 'uid' => $uid, 'name' => $name, @@ -733,9 +760,17 @@ function user_update_8010() { } } } - $query->execute(); + if ($has_values) { + $query->execute(); + } - // Delete {users}.data. + $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']); +} + +/** + * Drop {users}.data column. + */ +function user_update_8012() { db_drop_field('users', 'data'); } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 37d767d..ad09671 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -3185,3 +3185,127 @@ function user_library_info() { return $libraries; } + +/** + * Returns data stored for a user account. + * + * @param string $module + * The name of the module the data is associated with. + * @param integer $uid + * (optional) The user account ID the data is associated with. + * @param string $name + * (optional) The name of the data key. + * + * @return mixed|array + * The requested user account data, depending on the arguments passed: + * - For $module, $name, and $uid, the stored data is returned, or NULL if no + * data was found. + * - For $module and $uid, an associative array is returned that contains the + * stored data name/value pairs. + * - For $module and $name, an associative array is returned whose keys are + * user IDs and whose values contain the stored data. + * - For $module only, an associative array is returned that contains all + * existing data for $module in all user accounts, keyed by first by user ID + * and $name second. + */ +function user_data_get($module, $uid = NULL, $name = NULL) { + $query = db_select('users_data', 'ud', array('fetch' => PDO::FETCH_ASSOC)) + ->fields('ud') + ->condition('module', $module); + if (isset($uid)) { + $query->condition('uid', $uid); + } + if (isset($name)) { + $query->condition('name', $name); + } + $result = $query->execute()->fetchAllAssoc('uid'); + // If $module, $name, and $uid was passed, return the value. + if (isset($name) && isset($uid)) { + if (isset($result[$uid])) { + return $result[$uid]['serialized'] ? unserialize($result[$uid]['value']) : $result[$uid]['value']; + } + return NULL; + } + // If $module and $uid was passed, return the name/value pairs. + elseif (isset($uid)) { + $return = array(); + foreach ($result as $record) { + $return[$record['name']] = ($record['serialized'] ? unserialize($record['value']) : $record['value']); + } + return $return; + } + // If $module and $name was passed, return the values keyed by uid. + elseif (isset($name)) { + foreach ($result as $_uid => $record) { + $result[$_uid] = ($record['serialized'] ? unserialize($record['value']) : $record['value']); + } + return $result; + } + // If only $module was passed, return data keyed by uid and name. + else { + $return = array(); + foreach ($result as $_uid => $record) { + $return[$_uid][$record['name']] = ($record['serialized'] ? unserialize($record['value']) : $record['value']); + } + return $return; + } +} + +/** + * Stores data for a user account. + * + * @param string $module + * The name of the module the data is associated with. + * @param integer $uid + * The user account ID the data is associated with. + * @param string $name + * The name of the data key. + * @param mixed $value + * The value to store. Non-scalar values are serialized automatically. + * + * @return void + */ +function user_data_set($module, $uid, $name, $value) { + $serialized = 0; + if (!is_scalar($value)) { + $value = serialize($value); + $serialized = 1; + } + db_merge('users_data') + ->key(array( + 'uid' => $uid, + 'module' => $module, + 'name' => $name, + )) + ->fields(array( + 'value' => $value, + 'serialized' => $serialized, + )) + ->execute(); +} + +/** + * Deletes data stored for a user account. + * + * @param string $module + * The name of the module the data is associated with. + * @param integer $uid + * (optional) The user account ID the data is associated with. If omitted, all + * data for $module is deleted. + * @param string $name + * (optional) The name of the data key. If omitted, all data associated with + * $module and $uid is deleted. + * + * @return void + */ +function user_data_del($module, $uid = NULL, $name = NULL) { + $query = db_delete('users_data') + ->condition('module', $module); + if (isset($uid)) { + $query->condition('uid', $uid); + } + if (isset($name)) { + $query->condition('name', $name); + } + $query->execute(); +} diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 90d804e..f0220ac 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -391,13 +391,14 @@ function user_cancel_confirm($account, $timestamp = 0, $hashed_pass = '') { $current = REQUEST_TIME; // Basic validation of arguments. - if (isset($account->data['user_cancel_method']) && !empty($timestamp) && !empty($hashed_pass)) { + $account_data = user_data_get('user', $account->uid); + if (isset($account_data['cancel_method']) && !empty($timestamp) && !empty($hashed_pass)) { // 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( - 'user_cancel_notify' => isset($account->data['user_cancel_notify']) ? $account->data['user_cancel_notify'] : config('user.settings')->get('notify.status_canceled'), + 'user_cancel_notify' => isset($account_data['cancel_notify']) ? $account_data['cancel_notify'] : config('user.settings')->get('notify.status_canceled'), ); - user_cancel($edit, $account->uid, $account->data['user_cancel_method']); + user_cancel($edit, $account->uid, $account_data['cancel_method']); // 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.