Details
-
Type: Bug
-
Status: Done/Fixed
-
Priority: Minor
-
Resolution: Cannot Reproduce
-
Affects Version/s: 4.3.5
-
Fix Version/s: 4.4.0
-
Component/s: Core CiviCRM
-
Labels:None
Description
See http://forum.civicrm.org/index.php/topic,29979.0.html
- Scenario: existing Drupal user, existing Civi contact with matching email. I deleted civicrm_uf_match records because the Civi database had been copied from a live environment to a test environment where some of the Drupal users did not coincide.
What I did:
Logged in as the Drupal user mentioned above.
Expected behaviour:
The existing Drupal user is matched to the existing Civi contact on email. A civicrm_uf_match record is created to link them.
Actual behaviour:
The existing Drupal user is not matched to the existing Civi contact, instead a new contact is created. A civicrm_uf_match record is created to link the user to the new contact.
I tracked down the cause...
civicrm_user_login() calls:
return CRM_Core_BAO_UFMatch::synchronize($user, FALSE, 'Drupal',
civicrm_get_ctype('Individual')
);
CRM_Core_BAO_UFMatch::synchronize() calls CRM_Core_BAO_UFMatch::synchronizeUFMatch()
CRM_Core_BAO_UFMatch::synchronizeUFMatch() finds no existing civicrm_uf_match record and runs the following code...
if (!empty($_POST) && !$isLogin) {
$params = $_POST;
$params['email'] = $uniqId;
$dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
$dedupeParams['check_permission'] = FALSE;
$ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
dupesByParams() returns nothing. Because $dedupeParams contains:
Array
(
[civicrm_address] => Array
(
[name] => some-username
)
[civicrm_email] => Array
(
[email] => some@e.mail
)
[civicrm_im] => Array
(
[name] => some-username
)
[check_permission] =>
)
Hang on, why are civicrm_address and civicrm_im there and why do they contain the username? It looks like CRM_Dedupe_Finder::formatParams() iterates through CRM_Dedupe_BAO_RuleGroup::supportedFields(), including tables civicrm_address and civicrm_im, and because $_POST contains field 'name' (Drupal username) and those two tables contain a 'name' field, the username is interpreted as being both an address name and an IM name.
If you're thinking, "ah, but this is a login, so $isLogin will be true, so this code won't run" - that's what I assumed at first, but $isLogin is actually false. It's passed through to CRM_Core_BAO_UFMatch::synchronizeUFMatch() from CRM_Core_BAO_UFMatch::synchronize() , where it defaults to FALSE.
The call to CRM_Core_BAO_UFMatch::synchronize() from civicrm_user_login() does not specify the $isLogin parameter. Amending the call in civicrm_user_login() to:
return CRM_Core_BAO_UFMatch::synchronize($user, FALSE, 'Drupal',
civicrm_get_ctype('Individual'), TRUE
);
fixed the problem, because this bypasses the CRM_Dedupe_Finder::dupesByParams() route and instead does a good old-fashioned CRM_Contact_BAO_Contact::matchContactOnEmail().
Does this seem the right solution - should $isLogin be TRUE here and so using CRM_Contact_BAO_Contact::matchContactOnEmail() ?
Cheers,
Dave