diff --git a/sites/all/modules/contrib/commerce_checkout_login/commerce_checkout_login.module b/sites/all/modules/contrib/commerce_checkout_login/commerce_checkout_login.module index e812f22..0526d53 100644 --- a/sites/all/modules/contrib/commerce_checkout_login/commerce_checkout_login.module +++ b/sites/all/modules/contrib/commerce_checkout_login/commerce_checkout_login.module @@ -5,6 +5,90 @@ * Adds an inline login form to the Account Information checkout pane. */ +/** + * Implements hook_form_FORM_ID_alter(). + * + * Capture checkout pane settings + */ +function commerce_checkout_login_form_commerce_checkout_pane_settings_form_alter(&$form, &$form_state, $form_id) { + // Exit if not account checkout pane + if (empty($form['checkout_pane']) || empty($form['checkout_pane']['#value']) || + empty($form['checkout_pane']['#value']['pane_id']) || $form['checkout_pane']['#value']['pane_id'] != 'account') { + return; + } + + $form['settings']['commerce_checkout_login'] = array( + '#type' => 'fieldset', + '#title' => t('Commerce checkout login configuration'), + ); + $settings_form = &$form['settings']['commerce_checkout_login']; + + $settings_form['commerce_checkout_login_existing_user_login_required'] = array( + '#type' => 'checkbox', + '#title' => t('Require login of existing users.'), + '#description' => t('If checked, the password field is required to proceed to the next checkout page. The customer will be logged in and the order converted to an authenticated user order.'), + '#default_value' => variable_get('commerce_checkout_login_existing_user_login_required', FALSE), + ); + + $settings_form['commerce_checkout_login_new_user_create'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically create a user account for new customers'), + '#description' => t('If checked, a new user will be created based on the order\'s email address. The user is created on submit of the checkout page.'), + '#default_value' => variable_get('commerce_checkout_login_new_user_create', FALSE), + ); + $settings_form['commerce_checkout_login_new_user_login'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically login the new user.'), + '#description' => t('If checked, the new user will be logged in and the order converted to an authenticated user order.'), + '#default_value' => variable_get('commerce_checkout_login_new_user_login', FALSE), + '#prefix' => '
', + '#suffix' => '
', + '#states' => array( + 'invisible' => array( + ':input[name="commerce_checkout_login_new_user_create"]' => array('checked' => FALSE), + ), + ), + ); + $settings_form['commerce_checkout_login_allow_registration'] = array( + '#type' => 'checkbox', + '#title' => t('Allow new customers to create a new account'), + '#description' => t('If checked, a new customer will have the option to create a new user account with a custom username and password if system settings do allow that.'), + '#default_value' => variable_get('commerce_checkout_login_allow_registration', FALSE), + ); + $settings_form['commerce_checkout_login_allow_registration_login'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically login the new user.'), + '#description' => t('If checked, the new user will be logged in and the order converted to an authenticated user order.'), + '#default_value' => variable_get('commerce_checkout_login_allow_registration_login', FALSE), + '#prefix' => '
', + '#suffix' => '
', + '#states' => array( + 'invisible' => array( + ':input[name="commerce_checkout_login_allow_registration"]' => array('checked' => FALSE), + ), + ), + ); + + $settings_form['commerce_checkout_login_send_welcome_message'] = array( + '#type' => 'checkbox', + '#title' => t('Send welcome e-mail after creating a new user.'), + '#description' => t('If checked, an e-mail with a welcome message (no approval required) will be sent to the new user. You can configue the message !here.', array('!here' => l(t('here'), 'admin/config/people/accounts'))), + '#default_value' => variable_get('commerce_checkout_login_send_welcome_message', FALSE), + ); + $settings_form['commerce_checkout_login_send_welcome_message_show_message'] = array( + '#type' => 'checkbox', + '#title' => t('Show an e-mail notification message.'), + '#description' => t('If checked, a system message will be set, notifying the user of the welcome e-mail being sent.'), + '#default_value' => variable_get('commerce_checkout_login_send_welcome_message_show_message', FALSE), + '#prefix' => '
', + '#suffix' => '
', + '#states' => array( + 'invisible' => array( + ':input[name="commerce_checkout_login_send_welcome_message"]' => array('checked' => FALSE), + ), + ), + ); +} /** * Implements hook_form_FORM_ID_alter(). @@ -14,6 +98,7 @@ */ function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$form_state) { global $user; + $show_conf_mail = variable_get('commerce_order_account_pane_mail_double_entry', FALSE); // If the Account Information pane is on the current checkout page and the // user is not logged in... @@ -25,15 +110,23 @@ function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$for ), ); + // Add ajax to confirmation mail for immediate validation: + if (isset($form['account']['login']['mail_confirm'])) { + $form['account']['login']['mail_confirm']['#ajax'] = array( + 'callback' => 'commerce_checkout_login_validate_mail_confirm', + 'wrapper' => 'account-login-container', + ); + } + // Check the form state to see if an e-mail address has been specified. - if (!empty($form_state['values']['account']['login'])) { - $mail = trim($form_state['values']['account']['login']['mail']); + if (!empty($form_state['values']['account']['login']) || !empty($form_state['order']->mail)) { + $mail = !empty($form_state['values']['account']['login']) ? trim($form_state['values']['account']['login']['mail']) : $form_state['order']->mail; + $mail_confirm = isset($form_state['values']['account']['login']['mail_confirm']) ? $form_state['values']['account']['login']['mail_confirm'] : $form_state['order']->mail; // Don't attempt to load the user for an invalid e-mail address. - if ($error = user_validate_mail($mail)) { - form_set_error('account][login][mail', $error); - } - elseif ($account = user_load_by_mail($mail)) { + if (!user_validate_mail($mail) && user_load_by_mail($mail)) { + $login_required = variable_get('commerce_checkout_login_existing_user_login_required', FALSE); + // If a user already exists for the given e-mail address, display a // message letting the customer know this. $form['account']['login']['mail']['#description'] = t('There is already an account registered to %mail. You can login now to use your account information during checkout.', array('%mail' => $mail)); @@ -41,6 +134,7 @@ function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$for $form['account']['login']['password'] = array( '#type' => 'password', '#title' => t('Password'), + '#required' => $login_required, ); $form['account']['login']['login_now'] = array( @@ -50,6 +144,88 @@ function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$for '#validate' => array('commerce_checkout_login_checkout_form_validate'), '#submit' => array('commerce_checkout_login_checkout_form_submit'), ); + + // Add validate and submit to overall checkout form if login is required. + if ($login_required && isset($form['buttons']['continue'])) { + $form['buttons']['continue']['#validate'][] = 'commerce_checkout_login_checkout_form_validate'; + $form['buttons']['continue']['#submit'][] = 'commerce_checkout_login_checkout_form_submit'; + } + + // Hide e-mail confirmation field if set. + if ($login_required && isset($form['account']['login']['mail_confirm'])) { + $form['account']['login']['mail_confirm']['#value'] = $mail; + $form['account']['login']['mail_confirm']['#prefix'] = '
'; + $form['account']['login']['mail_confirm']['#suffix'] = '
'; + } + } + elseif (variable_get('commerce_checkout_login_allow_registration', FALSE)) { + // Show registration form only if there's just one e-mail field or if both e-mail addresses do match. + if (!$show_conf_mail || ($mail == $mail_confirm)) { + // User may create a new account on its own. + $form['account']['login']['register'] = array( + '#type' => 'fieldset', + '#title' => t('Create new account'), + '#description' => t('Optionally you can create a new account to use your data for later orders.'), + '#collapsible' => FALSE, + '#attributes' => array( + 'class' => array('checkout-registration'), + ), + ); + $form['account']['login']['register']['name'] = array( + '#type' => 'textfield', + '#title' => t('Username'), + '#maxlength' => USERNAME_MAX_LENGTH, + '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'), + '#attributes' => array('class' => array('username')), + ); + if (!variable_get('user_email_verification', TRUE) || variable_get('logintoboggan_confirm_email_at_registration', 0)) { + $desc = t('Provide a password for the new account in both fields.'); + if ($min_pass = variable_get('logintoboggan_minimum_password_length', 0)) { + $desc .= ' ' . t('Password must be at least %length characters.', array('%length' => $min_pass)); + } + + $form['account']['login']['register']['pass'] = array( + '#type' => 'password_confirm', + '#size' => 25, + '#description' => $desc, + ); + } + + // Set default roles. + // @see user_account_form(). + $roles = array_map('check_plain', user_roles(TRUE)); + $checkbox_authenticated = array( + '#type' => 'checkbox', + '#title' => $roles[DRUPAL_AUTHENTICATED_RID], + '#default_value' => TRUE, + '#disabled' => TRUE, + ); + unset($roles[DRUPAL_AUTHENTICATED_RID]); + $form['account']['login']['register']['roles'] = array( + '#type' => 'checkboxes', + '#title' => t('Roles'), + '#default_value' => array(), + '#options' => $roles, + '#access' => FALSE, + DRUPAL_AUTHENTICATED_RID => $checkbox_authenticated, + ); + + $form['account']['login']['register']['submit'] = array( + '#type' => 'submit', + '#value' => t('Create new account'), + '#limit_validation_errors' => array(array('account')), + '#validate' => array('commerce_checkout_login_checkout_form_register_validate'), + '#submit' => array('commerce_checkout_login_checkout_form_new_user_submit'), + ); + + } + } + + if (variable_get('commerce_checkout_login_new_user_create', FALSE)) { + // New user creation + if (isset($form['buttons']['continue'])) { + $form['buttons']['continue']['#submit'][] = 'commerce_checkout_login_checkout_form_new_user_submit'; + } } } } @@ -59,10 +235,73 @@ function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$for * Ajax callback: returns the account information pane to an AJAX request. */ function commerce_checkout_login_checkout_form_refresh($form, $form_state) { + $show_conf_mail = variable_get('commerce_order_account_pane_mail_double_entry', FALSE); + + $mail = !empty($form_state['values']['account']['login']) ? trim($form_state['values']['account']['login']['mail']) : $form_state['order']->mail; + + if ($error = user_validate_mail($mail)) { + form_set_error('account][login][mail', $error); + } + + if (!$show_conf_mail) { + return $form['account']['login']; + } + + // Return AJAX commands to set focus to the mail confirmation field for better UX. + $commands = array(); + $commands[] = ajax_command_replace('#' . $form['account']['login']['mail']['#ajax']['wrapper'], drupal_render($form['account']['login'])); + $commands[] = ajax_command_invoke('[name="account[login][mail_confirm]"]', 'focus'); + print ajax_render($commands); + exit; +} + +/** + * Ajax callback: validate mail confirmation field. + */ +function commerce_checkout_login_validate_mail_confirm($form, $form_state) { + $mail = trim($form_state['values']['account']['login']['mail']); + $mail_confirm = trim($form_state['values']['account']['login']['mail_confirm']); + + if (!empty($mail_confirm) && $mail != $mail_confirm) { + form_set_error('account][login][mail_confirm', t('The specified e-mail addresses do not match.')); + } return $form['account']['login']; } /** + * Validate callback: validate username (and password). + */ +function commerce_checkout_login_checkout_form_register_validate($form, &$form_state) { + $account = user_load_by_mail($form_state['values']['account']['login']['mail']); + + // Skip if a user with this mail address has been created in the meantime. + if ($account) { + return; + } + + // Validate username. + if ($error = user_validate_name($form_state['values']['account']['login']['register']['name'])) { + form_set_error('account][login][register][name', $error); + } + elseif ((bool) db_select('users') + ->fields('users', array('uid')) + ->condition('name', db_like($form_state['values']['account']['login']['register']['name']), 'LIKE') + ->range(0, 1) + ->execute() + ->fetchField() + ) { + form_set_error('account][login][register][name', t('The name %name is already taken.', array('%name' => $form_state['values']['account']['login']['register']['name']))); + } + + // Validate password if logintoboggan is present. + if (isset($form_state['values']['account']['login']['register']['pass']) && module_exists('logintoboggan')) { + if ($error = logintoboggan_validate_pass($form_state['values']['account']['login']['register']['pass'])) { + form_set_error('account][login][register][pass', $error); + } + } +} + +/** * Validate callback: validate the user credentials */ function commerce_checkout_login_checkout_form_validate($form, &$form_state) { @@ -87,22 +326,119 @@ function commerce_checkout_login_checkout_form_validate($form, &$form_state) { } /** - * Submit callback: attempt a login of the user now. + * Submit callback: attempt a login an existing user. */ function commerce_checkout_login_checkout_form_submit($form, &$form_state) { global $user; if (!empty($form_state['commerce_checkout_login_uid'])) { - // Load the specified user into the global $user variable. - $user = user_load($form_state['commerce_checkout_login_uid']); + if (!empty($user->uid)) { + // Load the full user object + $user = user_load($user->uid); + } + else { + // Load the specified user into the global $user variable. + $user = user_load($form_state['commerce_checkout_login_uid']); - // "Finalize" the login by triggering the appropriate system messages, IP - // address and login timestamp logging, and user login hook. - user_login_finalize(); + // "Finalize" the login by triggering the appropriate system messages, IP + // address and login timestamp logging, and user login hook. + user_login_finalize(); + } // Convert the current cart order to an authenticated cart for the current // user and clear out our variable from the form state. - commerce_cart_order_convert($form_state['order'], $user); + $oid = is_object($form_state['order']) ? $form_state['order']->order_id : $form_state['order']; + $order = commerce_order_load($oid); + if (empty($order->uid)) { + commerce_cart_order_convert($order, $user); + } unset($form_state['commerce_checkout_login_uid']); } } + +/** + * Submit callback: attempt to create the user and login. + */ +function commerce_checkout_login_checkout_form_new_user_submit($form, &$form_state) { + global $user; + + $values = &$form_state['values']; + + // Exit if user has logged in since the pane form was created. + if (!empty($user->uid)) { + $account = user_load($user->uid); + if (empty($order->uid)) { + commerce_cart_order_convert($order, $account); + } + return; + } + + // Load a fresh order object. + $order = commerce_order_load($form_state['order']->order_id); + + // Ensure order mail is as entered in form + if (empty($order->mail) && !empty($values['account']['login']['mail'])) { + $order->mail = $values['account']['login']['mail']; + } + + // Wrap the order object. + $order_wrapper = entity_metadata_wrapper('commerce_order', $order); + + // Get user name. + $username = !empty($values['account']['login']['register']['name']) ? $values['account']['login']['register']['name'] : $order_wrapper->mail_username->value(); + + // Only create if user does not exist. + $account = user_load_by_name($username); + if (empty($account) && !empty($order->mail)) { + $account = user_load_by_mail($order->mail); + } + + // Create new user. + if (empty($account) || empty($account->uid)) { + $edit = array( + 'name' => $username, + 'mail' => $order->mail, + 'init' => $order->mail, + 'status' => 1, + 'timezone' => variable_get('user_default_timezone', DRUPAL_USER_TIMEZONE_DEFAULT) ? '' : variable_get('date_default_timezone', ''), + ); + + // Set password if specified: + if (isset($values['account']['login']['register']['pass'])) { + $edit['pass'] = $values['account']['login']['register']['pass']; + } + // Set roles if specified: + if (isset($values['account']['login']['register']['roles'])) { + $edit['roles'] = array(); + foreach ($values['account']['login']['register']['roles'] as $rid => $assign) { + if ($assign && isset($roles[$rid])) { + $edit['roles'][$rid] = $rid; + } + } + } + + $account = user_save(NULL, $edit); + } + + if (!empty($account)) { + // If either "automatic creation && automatic login" or "custom creation && automatic login": + if ((variable_get('commerce_checkout_login_new_user_create', FALSE) && variable_get('commerce_checkout_login_new_user_login', FALSE)) || (variable_get('commerce_checkout_login_allow_registration', FALSE) && variable_get('commerce_checkout_login_allow_registration_login', FALSE))) { + // Load the specified user into the global $user variable. + $user = $account; + + // "Finalize" the login by triggering the appropriate system messages, IP + // address and login timestamp logging, and user login hook. + user_login_finalize(); + + // Convert the current cart order to an authenticated cart for the current user. + commerce_cart_order_convert($order, $user); + } + + if (variable_get('commerce_checkout_login_send_welcome_message', FALSE)) { + _user_mail_notify('register_no_approval_required', $account); + if (variable_get('commerce_checkout_login_send_welcome_message_show_message', FALSE)) { + drupal_set_message(t('A welcome message with further instructions has been sent to your e-mail address.')); + } + } + } +}