The [http://drupal.org/project/email_registration](email registration module) is
great for making sure users can only log in with their email address and don't
need to create an account name.

This doesn't work for logging in in the checkout though. To do that, we copy the
form_alter from the email_registration.module to a custom module (in this case: `custom_checkout`).

```
/**
* Implements hook_form_alter().
*/
function custom_checkout_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if (isset($form['login'])) {
$form['login']['returning_customer']['name']['#type'] = 'email';
$form['login']['returning_customer']['name']['#maxlength'] = Email::EMAIL_MAX_LENGTH;
$form['login']['returning_customer']['name']['#title'] = t('Email address');
$form['login']['returning_customer']['pass']['#description'] = t('Enter the password that accompanies your e-mail.');
$form['login']['returning_customer']['name']['#description'] = t('Enter your e-mail address.');
$form['login']['returning_customer']['name']['#element_validate'][] = 'custom_checkout_email_registration_user_login_validate';
}
}
```

There's a custom `#element_validate` defined in there, that's needed because by
default the username gets stored in 'name', and that is not readable by the pane
form.
We need to set the 'name' in the correct part of the form structure.

```
/**
* Form element validation handler for the user login form.
*
* Allows users to authenticate by email, which is our preferred method.
*/
function custom_checkout_email_registration_user_login_validate($form, FormStateInterface $form_state) {
$mail = $form_state->getValues()['login']['returning_customer']['name'];
if (!empty($mail) && ($user = user_load_by_mail($mail))) {
// Keep the email value in form state for further validation.
$form_state->setValue(['login', 'returning_customer', 'name'], $user->getAccountName());
}
}
```

---

As requested on irc. Hope that's enough. The code works on my machine, I only changed the function names, as they were namespaced to our customer project ;)

Comments

borisson_ created an issue. See original summary.

bojanz’s picture

Title: Docs for logging in with user email in checkout. » Document replacing the username with the email on the checkout login/register panes

We'll also need the register part before committing this to docs.

adrian83’s picture

Oh, I wish email login would be the Drupal standard! Would I create a module for this, or add it to my theme?

sevenfish’s picture

Add on header

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Email;
karlshea’s picture

This is what I've got for both login and registration during the checkout flow:

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Email;
use Drupal\Core\Url;

/**
 * Implements hook_form_alter().
 */
function custom_checkout_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form['#form_id'] !== 'commerce_checkout_flow_multistep_default') return;

  // Duplicates logic from email_registration_form_user_login_form_alter().
  $config = \Drupal::config('email_registration.settings');
  $login_with_username = $config->get('login_with_username');

  // Login form during checkout flow.
  if (isset($form['login'])) {
    $form['login']['returning_customer']['name']['#title'] = $login_with_username ? t('Email or username') : t('Email');
    $form['login']['returning_customer']['name']['#element_validate'][] = 'custom_checkout_user_login_validate';

    // Allow client side validation of input format.
    $form['login']['returning_customer']['name']['#type'] = $login_with_username ? 'textfield' : 'email';
    $form['login']['returning_customer']['name']['#maxlength'] = Email::EMAIL_MAX_LENGTH;
  }

  // Register form during checkout flow.
  if (isset($form['completion_register'])) {
    // Email Registration module handles setting the name on user insert, but we need a value. See email_registration_form_user_form_alter().
    $form['completion_register']['name']['#type'] = 'value';
    $form['completion_register']['name']['#value'] = 'email_registration_' . user_password();
  }
}

/**
 * Form element validation handler for the checkout user login form.
 *
 * Duplicates logic from email_registration_user_login_validate().
 */
function custom_checkout_user_login_validate($form, FormStateInterface $form_state) {
  $mail = $form_state->getValues()['login']['returning_customer']['name'];
  if (!empty($mail)) {
    $config = \Drupal::config('email_registration.settings');
    if ($user = user_load_by_mail($mail)) {
      $form_state->setValue(['login', 'returning_customer', 'name'], $user->getAccountName());
    }
    elseif (!$config->get('login_with_username')) {
      $user_input = $form_state->getUserInput();
      $query = isset($user_input['login']['returning_customer']['name']) ? ['name' => $user_input['login']['returning_customer']['name']] : [];
      $form_state->setErrorByName('login][returning_customer][name', t('Unrecognized email address or password. <a href=":password">Forgot your password?</a>', [
        ':password' => Url::fromRoute('user.pass', [], ['query' => $query])->toString(),
      ]));
    }
  }
}

perfectcu.be’s picture

Thanks for the hint KarlShea @#5; works like a champ!

socialnicheguru’s picture

socialnicheguru’s picture

Status: Active » Closed (duplicate)