email_registration.module 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. /**
  3. * @file
  4. * Allows users to register with an e-mail address as their username.
  5. */
  6. /**
  7. * Implements hook_user_insert().
  8. */
  9. function email_registration_user_insert(&$edit, &$account, $category = NULL) {
  10. // Don't create a new username if one is already set.
  11. if (!empty($account->name) && strpos($account->name, 'email_registration_') !== 0) {
  12. return;
  13. }
  14. // Other modules may implement hook_email_registration_name($edit, $account)
  15. // to generate a username (return a string to be used as the username, NULL
  16. // to have email_registration generate it).
  17. $names = module_invoke_all('email_registration_name', $edit, $account);
  18. // Remove any empty entries.
  19. $names = array_filter($names);
  20. if (empty($names)) {
  21. // Strip off everything after the @ sign.
  22. $new_name = preg_replace('/@.*$/', '', $edit['mail']);
  23. // Clean up the username.
  24. $new_name = email_registration_cleanup_username($new_name, $account->uid);
  25. }
  26. else {
  27. // One would expect a single implementation of the hook, but if there
  28. // are multiples out there use the last one.
  29. $new_name = array_pop($names);
  30. }
  31. // Ensure whatever name we have is unique.
  32. $new_name = email_registration_unique_username($new_name, $account->uid);
  33. // Replace with generated username.
  34. db_update('users')
  35. ->fields(array('name' => $new_name))
  36. ->condition('uid', $account->uid)
  37. ->execute();
  38. $edit['name'] = $new_name;
  39. $account->name = $new_name;
  40. }
  41. /**
  42. * Given a starting point returns a legal, unique Drupal username.
  43. *
  44. * This function is designed to work on the results of the /user/register or
  45. * /admin/people/create forms which have already called user_validate_name,
  46. * valid_email_address or a similar function. If your custom code is creating
  47. * users, you should ensure that the email/name is already validated using
  48. * something like that. Alternatively you can prepend the account user name
  49. * to contain 'email_registration_' to allow for the email registration hooks
  50. * to generate a unique username based on mail.
  51. *
  52. * @param string $name
  53. * A name from which to base the final user name. May contain illegal
  54. * characters; these will be stripped.
  55. * @param int $uid
  56. * (optional) Uid to ignore when searching for unique user
  57. * (e.g. if we update the username after the {users} row is inserted)
  58. *
  59. * @return string
  60. * A unique user name based on $name.
  61. *
  62. * @see user_validate_name()
  63. */
  64. function email_registration_unique_username($name, $uid = NULL) {
  65. // Iterate until we find a unique name.
  66. $i = 0;
  67. do {
  68. $new_name = empty($i) ? $name : $name . '_' . $i;
  69. if ($uid) {
  70. $found = db_query_range("SELECT uid from {users} WHERE uid <> :uid AND name = :name", 0, 1, array(':uid' => $uid, ':name' => $new_name))->fetchAssoc();
  71. }
  72. else {
  73. $found = db_query_range("SELECT uid from {users} WHERE name = :name", 0, 1, array(':name' => $new_name))->fetchAssoc();
  74. }
  75. $i++;
  76. } while (!empty($found));
  77. return $new_name;
  78. }
  79. /**
  80. * Function to clean up username.
  81. *
  82. * e.g.
  83. * Replace two or more spaces with a single underscore
  84. * Strip illegal characters.
  85. *
  86. * @param string $name
  87. * The username to be cleaned up.
  88. *
  89. * @return string
  90. * Cleaned up username.
  91. */
  92. function email_registration_cleanup_username($name, $uid = NULL) {
  93. // Strip illegal characters.
  94. $name = preg_replace('/[^\x{80}-\x{F7} a-zA-Z0-9@_.\'-]/', '', $name);
  95. // Strip leading and trailing spaces.
  96. $name = trim($name);
  97. // Convert any other series of spaces to a single underscore.
  98. $name = preg_replace('/\s+/', '_', $name);
  99. // If there's nothing left use a default.
  100. $name = ('' === $name) ? t('user') : $name;
  101. if (!empty($uid)) {
  102. // Put uid on the end of the name.
  103. $name = $name . '_' . $uid;
  104. }
  105. // Truncate to a reasonable size.
  106. $name = (drupal_strlen($name) > (USERNAME_MAX_LENGTH - 10)) ? drupal_substr($name, 0, USERNAME_MAX_LENGTH - 11) : $name;
  107. return $name;
  108. }
  109. /**
  110. * Implements hook_form_FORM_ID_alter().
  111. */
  112. function email_registration_form_user_register_form_alter(&$form, &$form_state) {
  113. $form['account']['name']['#type'] = 'hidden';
  114. $form['account']['name']['#value'] = 'email_registration_' . user_password();
  115. $form['account']['mail']['#title'] = t('E-mail');
  116. }
  117. /**
  118. * Implements hook_form_FORM_ID_alter().
  119. */
  120. function email_registration_form_user_pass_alter(&$form, &$form_state) {
  121. $form['name']['#title'] = t('E-mail');
  122. }
  123. /**
  124. * Implements hook_form_FORM_ID_alter().
  125. */
  126. function email_registration_form_user_login_alter(&$form, &$form_state) {
  127. $form['name']['#title'] = variable_get('email_registration_login_with_username', TRUE)
  128. ? t('E-mail or username')
  129. : t('E-mail');
  130. $form['name']['#description'] = variable_get('email_registration_login_with_username', TRUE)
  131. ? t('Enter your e-mail address or username.')
  132. : t('Enter your e-mail address.');
  133. $form['name']['#element_validate'][] = 'email_registration_user_login_validate';
  134. $form['pass']['#description'] = t('Enter the password that accompanies your e-mail.');
  135. }
  136. /**
  137. * Implements hook_form_FORM_ID_alter().
  138. */
  139. function email_registration_form_user_login_block_alter(&$form, &$form_state) {
  140. $form['name']['#title'] = variable_get('email_registration_login_with_username', TRUE)
  141. ? t('E-mail or username')
  142. : t('E-mail');
  143. $form['name']['#element_validate'][] = 'email_registration_user_login_validate';
  144. }
  145. /**
  146. * Implements hook_form_FORM_ID_alter().
  147. */
  148. function email_registration_form_user_admin_settings_alter(&$form, &$form_state) {
  149. $form['registration_cancellation']['email_registration_login_with_username'] = array(
  150. '#type' => 'checkbox',
  151. '#title' => t('Allow users login with e-mail or username.'),
  152. '#description' => t('Allow users to login with their username in addition to their e-mail.'),
  153. '#default_value' => variable_get('email_registration_login_with_username', TRUE),
  154. );
  155. $form['#submit'][] = 'email_registration_form_user_admin_settings_submit';
  156. }
  157. /**
  158. * Submit function for user_admin_settings to save our variable.
  159. *
  160. * @see email_registration_form_user_admin_settings_alter().
  161. */
  162. function email_registration_form_user_admin_settings_submit($form, &$form_state) {
  163. variable_set('email_registration_login_with_username', $form_state['values']['email_registration_login_with_username']);
  164. }
  165. /**
  166. * Form element validation handler for the user login form.
  167. *
  168. * Allows users to authenticate by email, which is our preferred method.
  169. */
  170. function email_registration_user_login_validate($form, &$form_state) {
  171. $name = NULL;
  172. if (isset($form_state['values']['name']) && valid_email_address($form_state['values']['name'])) {
  173. // Try to load the username matching the email, if any exists.
  174. $name = db_select('users')
  175. ->fields('users', array('name'))
  176. ->condition('mail', db_like($form_state['values']['name']), 'LIKE')
  177. ->execute()
  178. ->fetchField();
  179. }
  180. // If the value is set, and a valid email, and a match was found, use it.
  181. if (!empty($name)) {
  182. // Keep the email value in form state for further use/validation.
  183. $form_state['values']['email'] = $form_state['values']['name'];
  184. // If the name matches an e-mail, assume that it's the desired name and
  185. // set the username in the form values.
  186. $form_state['values']['name'] = $name;
  187. }
  188. elseif (!variable_get('email_registration_login_with_username', TRUE)) {
  189. // If no username was found for the e-mail, and registration with username
  190. // is not allowed, unset the name from the form. This prevents
  191. // user_login_authenticate_validate() from trying to load a user from the
  192. // value as a username, which in turn causes user_login_final_validate()
  193. // to set a form error telling the user that no account has been found.
  194. // We have to set this to NULL rather than FALSE, because
  195. // user_login_name_validate() uses isset() rather than empty().
  196. $form_state['values']['name'] = NULL;
  197. }
  198. }