Commit d84e1d08 authored by Julia Kulla-Mader's avatar Julia Kulla-Mader Committed by Greg Knaddison
Browse files

Issue #1203596 by JuliaKM: Drupal 7 port of user merge

parent 18ee89eb
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
name = User merge
description = Creates an extensible way to merge users together. The base module provides bonus support for nodes, comments, and profile since those are in Drupal core.
core = 6.x
core = 7.x

files[] = usermerge.module
+88 −91
Original line number Diff line number Diff line
<?

/**
 * @file
 * Main file for the user merge module, which re-assigns data from an abandoned account to a live one.
@@ -7,14 +6,19 @@
 */

/**
 * Implementation of hook_perm().
 * Implements hook_permission().
 */
function usermerge_perm() {
  return array('merge users');
function usermerge_permission() {
  return array(
    'merge users' => array(
      'title' => t('merge users'),
      'description' => t('Merge users using the user merge module'),
    ),
  );
}

/**
 * Implementation of hook_menu().
 * Implements hook_menu().
 */
function usermerge_menu() {
  $items['admin/user/merge'] = array(
@@ -41,12 +45,12 @@ function usermerge_menu() {
 * Form to collect the two uids.
 *
 */
function usermerge_merge_form() {
function usermerge_merge_form($form, &$form_state) {

  // Find out what's supported.
  $supported_actions = module_invoke_all('usermerge_actions_supported');
  $form['general']['supported_actions'] = array(
    '#value' => t('Supported actions:') . theme('item_list', $supported_actions)
    '#value' => t('Supported actions:') . theme('item_list', array('items' => $supported_actions)),
  );

  $form['general']['usermerge_user_delete'] = array(
@@ -73,6 +77,9 @@ function usermerge_merge_form() {
  return $form;
}

/**
 * Validates contents of form for user validation
 */
function usermerge_merge_form_validate($form, &$form_state) {
  // Can't be the same user.
  if ($form_state['values']['usermerge_user_keep'] == $form_state['values']['usermerge_user_delete']) {
@@ -80,19 +87,18 @@ function usermerge_merge_form_validate($form, &$form_state) {
  }

  // Load up the users. We store these in the form_state['values'] so that we don't have to load again later.
  $form_state['values']['user_to_delete'] = user_load(array('name' => $form_state['values']['usermerge_user_delete']));
  $form_state['values']['user_to_keep'] = user_load(array('name' => $form_state['values']['usermerge_user_keep']));
  $form_state['values']['user_to_delete'] = array_shift(user_load_multiple(array(), array('name' => $form_state['values']['usermerge_user_delete'])));
  $form_state['values']['user_to_keep'] = array_shift(user_load_multiple(array(), array('name' => $form_state['values']['usermerge_user_keep'])));

  // Use the validat helper function.
  // Use the validate helper function.
  usermerge_validate_merge($form_state['values']['user_to_delete'], $form_state['values']['user_to_keep']);

}

/**
 * Helper validation function used by the form submit and the API.
 *
 * @param unknown_type $user_to_delete
 * @param unknown_type $user_to_keep
 * @param int $user_to_delete uid of user to delete
 * @param int $user_to_keep uid of user to keep
 */
function usermerge_validate_merge($user_to_delete, $user_to_keep) {
  $valid = TRUE;
@@ -113,6 +119,10 @@ function usermerge_validate_merge($user_to_delete, $user_to_keep) {
  return $valid;
}


/**
 * Merges two users after submitting merge form
 */
function usermerge_merge_form_submit($form, &$form_state) {
  usermerge_do_the_merge($form_state['values']['user_to_delete'], $form_state['values']['user_to_keep']);
}
@@ -138,7 +148,7 @@ function usermerge_do_the_merge($user_to_delete, $user_to_keep) {
}

/**
 * Implement hook_usermerge_actions_supported().
 * Implements hook_usermerge_actions_supported().
 */
function usermerge_usermerge_actions_supported() {
  return array(
@@ -151,6 +161,7 @@ function usermerge_usermerge_actions_supported() {

/**
 * Implement hook_usermerge_actions_supported() on behalf of profile module.
 * Note: This uses the D6 profile module and not the entity API
 */
function profile_usermerge_actions_supported() {
  return array(
@@ -158,44 +169,52 @@ function profile_usermerge_actions_supported() {
  );
}

/**
 * Implement hook_usermerge_actions_supported() on behalf of og.
 */
function og_usermerge_actions_supported() {
  return array(
    'og' => t('Merge group membership.'),
  );
}

/**
 * Implement hook_usermerge_actions_supported() on behalf of notifications.
 */
function notifications_usermerge_actions_supported() {
  return array(
    'notifications' => t('Merge notification and messaging settings'),
  );
}

/**
 * Implement hook_usermerge_merge_users().
 * Implements hook_usermerge_merge_users().
 */
function usermerge_usermerge_merge_users($user_to_delete, $user_to_keep) {
  // Comment: change the uid to the new one.
  db_query('UPDATE {comments} SET uid = %d where uid = %d', $user_to_keep->uid, $user_to_delete->uid);
  db_update('comment')
    ->fields(array(
            'uid' => $user_to_keep->uid,
    ))
    ->condition('uid', $user_to_delete->uid, '=')
    ->execute();

  // Node: change uid of node and revisions to the new one.
  db_query('UPDATE {node} SET uid = %d where uid = %d', $user_to_keep->uid, $user_to_delete->uid);
  db_query('UPDATE {node_revisions} SET uid = %d where uid = %d', $user_to_keep->uid, $user_to_delete->uid);
//updating node table
  db_update('node')
  ->fields(array(
    'uid' => $user_to_keep->uid,
  ))
  ->condition('uid', $user_to_delete->uid, '=')
  ->execute();

  //Update roles.
//updating node_revisions table
  db_update('node_revision')
  ->fields(array(
    'uid' => $user_to_keep->uid,
  ))
  ->condition('uid', $user_to_delete->uid, '=')
  ->execute();

  //Update roles
  $merged_roles = $user_to_keep->roles + $user_to_delete->roles;

  // First, remove all roles from the user to keep to prevent duplicate key errors.
  db_query("DELETE FROM {users_roles} WHERE uid = %d", $user_to_keep->uid);
  db_delete('users_roles')
  ->condition('uid', $user_to_keep->uid)
  ->execute();

  // Then add them on to the user to keep.
  foreach (array_keys($merged_roles) as $rid) {
    if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
      db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $user_to_keep->uid, $rid);
      $id = db_insert('users_roles')
       ->fields(array(
          'uid' => $user_to_keep->uid,
          'rid' => $rid,
        ))
     ->execute();
    }
  }
  // Block the old user.
@@ -205,59 +224,37 @@ function usermerge_usermerge_merge_users($user_to_delete, $user_to_keep) {
  drupal_set_message(t('We successfully merged %user_to_delete into %user_to_keep', array('%user_to_delete' => $user_to_delete->name, '%user_to_keep' => $user_to_keep->name)));
}

/**
 * Implement hook_usermerge_merge_users() on behalf of og.
 */
function og_usermerge_merge_users($user_to_delete, $user_to_keep) {
  // Get groups kept-user is not a member of but blocked-user is.
  $result = db_query("SELECT nid FROM {og_uid} WHERE uid = %d AND nid NOT IN (SELECT nid FROM {og_uid} WHERE uid = %d)", $user_to_delete->uid, $user_to_keep->uid);
  while ($record = db_fetch_array($result)) {
    $groups[] = $record['nid'];
  }
  if (!empty($groups)) {
    // Update old user's groups to kept-user if kept-user is not already a member.
    db_query("UPDATE {og_uid} SET uid = %d WHERE uid = %d AND nid IN (%s)", $user_to_keep->uid, $user_to_delete->uid, implode(',', $groups));
  }
  // Set blocked-user to inactive.
  db_query("UPDATE {og_uid} SET is_active = 0 WHERE uid = %d", $user_to_delete->uid);
}

/**
 * Implement hook_usermerge_merge_users() on behalf of notifications.
 */
function notifications_usermerge_merge_users($user_to_delete, $user_to_keep) {
  // Get blocked-user's notifications.
  $blocked = array();
  $result = db_query("SELECT sid FROM {notifications} WHERE uid = %d". $user_to_delete->uid);
  while ($record = db_fetch_array($result)) {
    $blocked[] = $record['sid'];
  }
  if (!empty($blocked)) {
    // Delete notification settings.
    db_query("DELETE FROM {notifications} WHERE uid = %d", $user_to_delete->uid);
    // Delete fields of blocked-user's notifications settings, they aren't used.
    db_query("DELETE FROM {notifications_fields} WHERE sid IN (%s)", implode(',', $blocked));
  }
  // Delete notifications in the queue for blocked-user.
  db_query("DELETE FROM {notifications_queue} WHERE uid = %d", $user_to_delete->uid);
}

/**
 * Implement hook_usermerge_merge_users() on behalf of profile module.
 */
function profile_usermerge_merge_users($user_to_delete, $user_to_keep) {
  // Get kept-user's filled profile values.
  $result = db_query("SELECT fid FROM {profile_values} WHERE uid = %d AND VALUE != ''", $user_to_keep->uid);
  // retrieve kept-user's user field values
  if (module_exists('profile')) { //testing for profile, which is hidden in D6
      $result = db_query("SELECT fid FROM {profile_values} WHERE uid = :uid AND VALUE <> ''", array(':uid' => $user_to_keep->uid));
      $kept = array();
      while ($record = db_fetch_array($result)) {
        $kept[] = $record['fid'];
      }
      if (!empty($kept)) {
         // Remove profile values for blocked-user that kept-user has.
    db_query('DELETE FROM {profile_values} WHERE uid = %d AND fid IN (%s)', $user_to_delete->uid, implode(',', $kept));
        db_delete('profile_values')
        ->condition('uid', $user_to_delete->uid)
        ->condition('fid', implode(',', $kept), 'IN')
        ->execute();
      }

      // Remove empty profile values for kept-user.
  db_query("DELETE FROM {profile_values} WHERE uid = %d AND VALUE = ''", $user_to_keep->uid);
      db_delete('profile_values')
      ->condition('uid', $user_to_keep->uid)
      ->condition('VALUE', '')
      ->execute();

      // Change uid.
  db_query('UPDATE {profile_values} SET uid = %d WHERE uid = %d', $user_to_keep->uid, $user_to_delete->uid);
      db_update('profile_values')
      ->fields(array(
        'uid' => $user_to_keep->uid,
      ))
      ->condition('uid', $user_to_delete->uid)
      ->execute();
    }
}
 No newline at end of file