Jump to:
| Project: | Email Registration |
| Version: | 6.x-1.3 |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Issue Summary
I've skimmed through some of the issues here and I believe that several of them have this issue at their root--I'm curious to see if others feel the same way.
The issue: A lot of things happen in a lot of module's hook_submits. In fact, if you have things like logintoboggan or bakery in the mix, you can't even guarantee that you'll catch all the hook_submit functions. Bakery, for example, redirects away from the site to the master in hook_submit and makes the user there. It is entirely possible that it won't be possible for the hook_user insert op to execute properly at all.
I believe that the username should be generated long before the initial inserts and submit callbacks even come into play.
What I did to achieve this is altered the form alter to use a validate rather than submit callback like so:
<?php
$form['#validate'][-10] = 'email_registration_form_validate';
ksort($form['#validate']);
reset($form['#validate']);
?>Then I took the db queries that used to be in the hook_user insert op and put them in their own function like so:
<?php
function email_registration_generate_name($edit) {
// Other modules may implement hook_email_registration_name($edit, $account)
// to generate a username (return a string to be used as the username, NULL
// to have email_registration generate it)
$names = module_invoke_all('email_registration_name', $edit);
// Remove any empty entries
$names = array_filter($names);
if (empty($names)) {
// Default implementation of name generation
$namenew = preg_replace('/@.*$/', '', $edit['mail']);
// Remove unwanted characters
$namenew = preg_replace('/[^a-zA-Z0-9.-]/', '', $namenew);
// if username generated from email record already exists, append underscore and number eg:(chris_123)
if (db_result(db_query("SELECT count(*) FROM {users} WHERE LOWER(name) = LOWER('%s')", $namenew)) > 0) {
// find the next number available to append to the name
$sql = "SELECT SUBSTRING_INDEX(name,'_',-1) FROM {users} WHERE name REGEXP '%s' ORDER BY CAST(SUBSTRING_INDEX(name,'_',-1) AS UNSIGNED) DESC LIMIT 1";
$nameidx = db_result(db_query($sql, '^'. $namenew .'_[0-9]+$'));
$namenew .= '_'. ($nameidx + 1);
}
}
else {
// One would expect a single implementation of the hook, but if there
// are multiples out there use the last one
$namenew = array_pop($names);
}
return $namenew;
}
?>And finally put in my validate callback
<?php
function email_registration_form_validate($form, &$form_state) {
$admin = user_access('administer users');
if (!$admin) {
$newname = email_registration_generate_name($form_state['values']);
// override the various places in the form_state where the name exists.
$form_state['values']['name'] = $newname;
$form_state['clicked_button']['#post']['name'] = $newname;
}
}
?>This very easily plays nice with things like bakery and logintoboggan because before the user account is made, before any validation on the username, and before any other submit callbacks, the username is set and ready to roll.
Comments
#1
Can you roll this into a patch? Because it seems like a common issue and the patch might be applied to head.