<?php
// $Id: alt_login.module,v 1.19 2011/01/05 00:40:24 thehunmonkgroup Exp $

/**
 * Implement hook_help().
 */
function alt_login_help($path, $arg) {
  switch ($path) {
    case 'admin/help#alt_login':
      $output = t('
      <p>This module provides an interface that allows registered users to use a login name which is different than their username.</p>
      <p>To use, simply enable the module, then visit the user edit page. Enter the alternate login name in the \'Alternate login\' textfield, and save.</p>
      <p><em>Note that users can still login with their normal username--this just adds the option of another login name.  Also note that an alternate login name may not be equivalent to any other current alternate login name, nor any current username.</em></p>');
      return $output;
      break;
  }
}

/**
 * Implement hook_permission().
 */
function alt_login_permission() {
  return array(
    'create alternate login' => array(
      'title' => t('Create alternate login'),
      'description' => t('Allow users to create an alternate login name.'),
    ),
  );
}

/**
 * Implement hook_form_alter().
 */
function alt_login_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'user_login':
    case 'user_login_block':
    case 'user_pass':
      // This validation happens before the main login validation.
      $form['name']['#element_validate'][] = '_alt_login_username_validate';
      break;
  }
}

/**
 * Implement hook_form_FORM_ID_alter().
 */
function alt_login_form_user_register_form_alter(&$form, &$form_state) {
  if (variable_get('alt_login_user_registration', 1)) {
    $form['account']['alt_login'] = array(
      '#type' => 'textfield',
      '#title' => t('Alternate login'),
      '#maxlength' => USERNAME_MAX_LENGTH,
      '#description' => t('If you wish to provide another valid login name, enter it here: only letters, numbers and spaces are allowed.'),
      '#weight' => 29,  // Last field before the submit button.
    );
  }
  $form['#validate'][] = 'alt_login_user_validate';
}

/**
 * Implement hook_form_FORM_ID_alter().
 */
function alt_login_form_user_admin_settings_alter(&$form, &$form_state) {
  $form['registration_cancellation']['alt_login_user_registration'] = array(
    '#type' => 'checkbox',
    '#title' => t('Set alternate login on registration'),
    '#default_value' => variable_get('alt_login_user_registration', 1),
    '#description' => t('If selected, new users will be allowed to set an alternate login name as part of the user registration process.'),
  );
}

/**
 * Implement hook_form_FORM_ID_alter().
 */
function alt_login_form_user_profile_form_alter(&$form, &$form_state) {
  if ($form['#user_category'] == 'account') {
    $user = $form['#user'];
    // Grab the current alt login if it exists.
    $alt_login = db_query('SELECT alt_login FROM {alt_login} WHERE uid = :uid', array(
      ':uid' => $user->uid,
    ))->fetchField();
    $alt_login = $alt_login ? $alt_login : '';

    // Permissioned users can create/edit their own alt login.
    if (user_access('create alternate login')) {
      $form['account']['alt_login'] = array(
        '#type' => 'textfield',
        '#title' => t('Alternate login'),
        '#maxlength' => USERNAME_MAX_LENGTH,
        '#description' => t('If you wish to provide another valid login name, enter it here: only letters, numbers and spaces are allowed.'),
        '#default_value' => $alt_login,
      );
    }
    // For non-permissioned users, display their alt login if it exists.
    elseif ($alt_login) {
      $form['account']['alt_login'] = array(
        '#type' => 'item',
        '#title' => t('Alternate login'),
        '#description' => t('You may also login with this alternate username.'),
        '#markup' => $alt_login,
      );
    }
  }
  $form['#validate'][] = 'alt_login_user_validate';
}

/**
 * Implement hook_user_load().
 */
function alt_login_user_load($users) {
  $result = db_query('SELECT uid, alt_login FROM {alt_login} WHERE uid IN (:uids)', array(
    ':uids' => array_keys($users),
  ));
  foreach ($result as $record) {
    $users[$record->uid]->alt_login = $record->alt_login;
  }
}

/**
 * Implement hook_user_cancel().
 */
function alt_login_user_cancel($edit, $user, $method) {
  switch ($method) {
    case 'user_cancel_reassign':
      alt_login_delete($user->uid);
      break;
  }
}

/**
 * Implement hook_user_delete().
 */
function alt_login_user_delete($account) {
  alt_login_delete($account->uid);
}


/**
 * Deletes a user's alt login.
 */
function alt_login_delete($uid) {
  db_delete('alt_login')
    ->condition('uid', $uid)
    ->execute();
}

/**
 * Validation handler for ensuring no duplication in alt_login/usernames.
 */
function alt_login_user_validate($form, &$form_state) {
  // Set uid to a non-existent user so the queries will still work if no user
  // object is present.
  $user = $form['#user'];
  $uid = isset($user->uid) ? $user->uid : -1;
  $values = $form_state['values'];
  $name = $values['name'];
  $alt_login = isset($values['alt_login']) ? $values['alt_login'] : NULL;

  // Make sure user can't set their username to an existing alt_login name.
  if (db_query("SELECT alt_login FROM {alt_login} WHERE alt_login = :alt_login AND uid != :uid", array(
    ':alt_login' => $name,
    ':uid' => $uid,
  ))->fetchField()) {
    form_set_error('name', t('The name %name is already in use.', array('%name' => $name)));
  }

  if ($alt_login) {
    // Can't have same username and alt login name.
    if ($name == $alt_login) {
      form_set_error('alt_login', t('Username and Alternate login cannot be the same.'));
    }

    // Make sure the name isn't already taken as either another alt login or username.
    if (db_query("SELECT uid FROM {alt_login} WHERE alt_login = :alt_login AND uid != :uid", array(':alt_login' => $alt_login, ':uid' => $uid))->fetchField() || db_query("SELECT uid FROM {users} WHERE name = :name AND uid != :uid", array(':name' => $alt_login, ':uid' => $uid))->fetchField()) {
      form_set_error('alt_login', t('The name %name is already in use.', array('%name' => $alt_login)));
    }

    // Same validation as the regular username.
    if ($error = user_validate_name($alt_login)) {
      form_set_error('alt_login', $error);
    }
  }
}

/**
 * Implement hook_user_update().
 */
function alt_login_user_update(&$edit, $user, $category = NULL) {
  if ($category == 'account') {
    // Only proceed if some alt_login value exists.
    if (isset($edit['alt_login'])) {
      $alt_login = $edit['alt_login'];
    }
    else {
      return;
    }

    $uid = $user->uid;

    // Only keep a database entry if an alternate login has been specified.
    if ($alt_login) {
      if (db_query('SELECT uid FROM {alt_login} WHERE uid = :uid', array(
        ':uid' => $uid,
      ))->fetchField()) {
        db_update('alt_login')
          ->fields(array(
            'alt_login' => $alt_login,
          ))
          ->condition('uid', $uid)
          ->execute();
      }
      else {
        db_insert('alt_login')
          ->fields(array(
            'uid' => $uid,
            'alt_login' => $alt_login,
          ))
          ->execute();
      }
    }
    // Delete the alt login if it was set to an empty string.
    elseif ($alt_login === '') {
      alt_login_delete($uid);
    }
  }
}

/**
 * Implement hook_user_insert().
 */
function alt_login_user_insert(&$edit, $user, $category = NULL) {
  $alt_login = isset($edit['alt_login']) ? $edit['alt_login'] : NULL;
  // Only insert a row if the alt login exists.
  if ($alt_login) {
    db_insert('alt_login')
          ->fields(array(
            'uid' => $user->uid,
            'alt_login' => $alt_login,
          ))
          ->execute();
  }
}

/**
 * Checks to see if a valid alt login was used, and converts it to the real username if so.
 *
 * @param $form Form element being validated.
 * @param $form_state
 */
function _alt_login_username_validate($form, &$form_state) {
  $name = $form['#value'];
  $username = db_query("SELECT u.name FROM {users} u INNER JOIN {alt_login} al ON u.uid = al.uid WHERE al.alt_login = :alt_login", array(
    ':alt_login' => $name,
  ))->fetchField();
  if ($username) {
    form_set_value($form, $username, $form_state);
  }
}

