<?php

/**
 * @file
 * Functionality tests for user_registrationpassword.module.
 */

/**
 * Class UserRegistrationPasswordTestCase.
 */
class UserRegistrationPasswordTestCase extends DrupalWebTestCase {

  /**
   * Implements getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => t('Functionality'),
      'description' => t('Functionality tests for the User Registration Password module.'),
      'group' => t('User Registration Password'),
    );
  }

  /**
   * Implements setUp().
   */
  public function setUp() {
    $modules = func_get_args();
    if (isset($modules[0]) && is_array($modules[0])) {
      $modules = $modules[0];
    }
    $modules[] = 'field_test';
    $modules[] = 'user_registrationpassword';
    parent::setUp($modules);
  }

  /**
   * Implements testRegistrationWithEmailVerificationAndPassword().
   */
  public function testRegistrationWithEmailVerificationAndPassword() {
    // Allow registration by site visitors without administrator
    // approval and set password during registration.
    variable_set('user_register', USER_REGISTER_VISITORS);
    // Disable e-mail verification.
    variable_set('user_email_verification', FALSE);
    // Prevent standard notification email to administrators and to user.
    variable_set('user_mail_register_pending_approval_notify', FALSE);
    // Set the registration variable to 2, register with pass, but require
    // confirmation.
    variable_set('user_registrationpassword_registration', USER_REGISTRATIONPASSWORD_VERIFICATION_PASS);

    // Register a new account.
    $edit = array();
    $edit['name'] = $name = $this->randomName();
    $edit['mail'] = $mail = $edit['name'] . '@example.com';
    $edit['pass[pass1]'] = $new_pass = $this->randomName();
    $edit['pass[pass2]'] = $new_pass;
    $pass = $new_pass;
    $this->drupalPost('user/register', $edit, t('Create new account'));
    $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), t('User registered successfully.'));

    // Load the new user.
    $accounts = user_load_multiple(array(), array(
      'name' => $name,
      'mail' => $mail,
      'status' => 0,
    ));
    $account = reset($accounts);

    // Configure some timestamps.
    // We up the timestamp a bit, else the check will fail.
    // The function that checks this uses the execution time
    // and that's always larger in real-life situations
    // (and it fails correctly when you remove the + 5000).
    $timestamp = REQUEST_TIME + 5000;
    $test_timestamp = REQUEST_TIME;
    $bogus_timestamp = REQUEST_TIME - 86500;

    // Check if the account has not been activated.
    $this->assertFalse($account->status, t('New account is blocked until approved via e-mail confirmation. status check.'));
    $this->assertFalse($account->login, t('New account is blocked until approved via e-mail confirmation. login check.'));
    $this->assertFalse($account->access, t('New account is blocked until approved via e-mail confirmation. access check.'));

    // Login before activation.
    $auth = array(
      'name' => $name,
      'pass' => $pass,
    );
    $this->drupalPost('user/login', $auth, t('Log in'));
    $this->assertText(t('The username @name has not been activated or is blocked.', array('@name' => $name)), t('User cannot login yet.'));

    // Timestamp can not be smaller then current. (== registration time).
    // If this is the case, something is really wrong.
    $this->drupalGet("user/registrationpassword/$account->uid/$test_timestamp/" . user_pass_rehash($account->pass, $test_timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // Fake key combi.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // Fake timestamp.
    $this->drupalGet("user/registrationpassword/$account->uid/$bogus_timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // Wrong password.
    $this->drupalGet("user/registrationpassword/$account->uid/$bogus_timestamp/" . user_pass_rehash($this->randomName(), $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // Attempt to use the activation link.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have just used your one-time login link. Your account is now active and you are authenticated.'));

    // Attempt to use the activation link again.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You are currently authenticated as user !user.', array('!user' => $account->name)));

    // Logout the user.
    $this->drupalLogout();

    // Then attempt to use the activation link yet again.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // And then try to do normal login.
    $auth = array(
      'name' => $name,
      'pass' => $pass,
    );
    $this->drupalPost('user/login', $auth, t('Log in'));
    $this->assertText(t('Member for'), t('User logged in.'));
  }

  /**
   * Implements testPasswordResetFormResendActivation().
   */
  public function testPasswordResetFormResendActivation() {
    // Allow registration by site visitors without administrator
    // approval and set password during registration.
    variable_set('user_register', USER_REGISTER_VISITORS);
    // Disable e-mail verification.
    variable_set('user_email_verification', FALSE);
    // Prevent standard notification email to administrators and to user.
    variable_set('user_mail_register_pending_approval_notify', FALSE);
    // Set the registration variable to 2, register with pass, but require
    // confirmation.
    variable_set('user_registrationpassword_registration', USER_REGISTRATIONPASSWORD_VERIFICATION_PASS);

    // Register a new account.
    $edit1 = array();
    $edit1['name'] = $name = $this->randomName();
    $edit1['mail'] = $mail = $edit1['name'] . '@example.com';
    $edit1['pass[pass1]'] = $new_pass = $this->randomName();
    $edit1['pass[pass2]'] = $new_pass;
    $pass = $new_pass;
    $this->drupalPost('user/register', $edit1, t('Create new account'));
    $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), t('User registered successfully.'));

    // Load the new user.
    $accounts = user_load_multiple(array(), array(
      'name' => $name,
      'mail' => $mail,
      'status' => 0,
    ));
    $account = reset($accounts);

    // Request a new activation e-mail.
    $edit2 = array();
    $edit2['name'] = $edit1['name'];
    $this->drupalPost('user/password', $edit2, t('E-mail new password'));
    $this->assertText(t('Further instructions have been sent to your e-mail address.'), t('Password rest form submitted successfully.'));

    // Request a new activation e-mail for a non-existing user name.
    $edit3 = array();
    $edit3['name'] = $this->randomName();
    $this->drupalPost('user/password', $edit3, t('E-mail new password'));
    $this->assertText(t('Sorry, !name is not recognized as a user name or an e-mail address.', array('!name' => $edit3['name'])), t('Password rest form failed correctly.'));

    // Request a new activation e-mail for a non-existing user e-mail.
    $edit4 = array();
    $edit4['name'] = $this->randomName() . '@example.com';
    $this->drupalPost('user/password', $edit4, t('E-mail new password'));
    $this->assertText(t('Sorry, !mail is not recognized as a user name or an e-mail address.', array('!mail' => $edit4['name'])), t('Password rest form failed correctly.'));
  }

  /**
   * Implements testLoginWithUrpLinkWhileBlocked().
   */
  public function testLoginWithUrpLinkWhileBlocked() {
    // Allow registration by site visitors without administrator
    // approval and set password during registration.
    variable_set('user_register', USER_REGISTER_VISITORS);
    // Disable e-mail verification.
    variable_set('user_email_verification', FALSE);
    // Prevent standard notification email to administrators and to user.
    variable_set('user_mail_register_pending_approval_notify', FALSE);
    // Set the registration variable to 2, register with pass, but require
    // confirmation.
    variable_set('user_registrationpassword_registration', USER_REGISTRATIONPASSWORD_VERIFICATION_PASS);

    $timestamp = REQUEST_TIME + 5000;

    // Register a new account.
    $edit = array();
    $edit['name'] = $name = $this->randomName();
    $edit['mail'] = $mail = $edit['name'] . '@example.com';
    $edit['pass[pass1]'] = $new_pass = $this->randomName();
    $edit['pass[pass2]'] = $new_pass;
    $pass = $new_pass;
    $this->drupalPost('user/register', $edit, t('Create new account'));
    $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), t('User registered successfully.'));

    // Load the new user.
    $accounts = user_load_multiple(array(), array(
      'name' => $name,
      'mail' => $mail,
      'status' => 0,
    ));
    $account = reset($accounts);

    // Attempt to use the activation link.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have just used your one-time login link. Your account is now active and you are authenticated.'));

    // Logout the user.
    $this->drupalLogout();

    // Block the user.
    $admin_user = $this->drupalCreateUser(array('administer users'));
    $this->drupalLogin($admin_user);
    $this->drupalGet('admin/people');
    $editblock = array();
    $editblock['operation'] = 'block';
    $editblock['accounts[' . $account->uid . ']'] = TRUE;
    $this->drupalPost('admin/people', $editblock, t('Update'));

    // Logout the administrator.
    $this->drupalLogout();

    // Load the new user.
    $accounts_blocked = user_load_multiple(array(), array(
      'name' => $name,
      'mail' => $mail,
      'status' => 0,
    ));
    $account_blocked = reset($accounts_blocked);

    // Confirm status is really blocked.
    $this->assertEqual($account_blocked->status, 0, 'User blocked');

    // Then try to use the link.
    $this->drupalGet("user/registrationpassword/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
    $this->assertText(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));

    // Try to request a new activation e-mail.
    $edit2['name'] = $edit['name'];
    $this->drupalPost('user/password', $edit2, t('E-mail new password'));
    $this->assertText(t('Sorry, !name is not recognized as a user name or an e-mail address.', array('!name' => $edit2['name'])), t('Password rest form failed correctly.'));
  }

}
