Contact name does not appear in membership edit page, if no email registered
Problem/Motivation
I've noticed that if a contact has no registered email but does have a membership, when you edit that membership, the variable $displayName
is not being populated.
I've traced the issue back to this call : CRM_Contact_BAO_Contact_Location::getEmailDetails
In CiviCRM 4.6.x (and possibly 4.7?), it used to be a query :
$sql = "
SELECT civicrm_contact.display_name,
civicrm_email.email,
civicrm_email.location_type_id,
civicrm_email.id
FROM civicrm_contact
LEFT JOIN civicrm_email ON ( civicrm_contact.id = civicrm_email.contact_id {$primaryClause} {$locationClause} )
WHERE civicrm_contact.id = %1";
then changed to an API call:
$params = array(
'location_type_id' => $locationTypeID,
'contact_id' => $id,
'return' => array('contact_id.display_name', 'email', 'location_type_id', 'id'),
);
if ($isPrimary) {
$params['is_primary'] = 1;
}
$emails = civicrm_api3('Email', 'get', $params);
The problem with the later is that if a contact has no registered email, his/her name is not appearing on the membership edit page because the API returns nothing (which is normal).
dmaster )
Steps to reproduce (onReplicating the broken behaviour
- Create a contact by using a first and last name but NO email
- Create a membership with any data inside
- Edit the membership
Contact's display name is not appearing.
If you add an email to that contact, contact's display name appears when you re-edit that membership.
Proposed solutions
-
Revert back to the SQL query (not preferable)
-
Change API call approach by doing a chained API call, starting from the Contact and chaining to the Email:
public static function getEmailDetails($id, $isPrimary = TRUE, $locationTypeID = NULL) {
$params = array(
'contact_id' => $id,
'return' => array('display_name','email.email'),
'api.Email.get' => array(
'location_type_id' => $locationTypeID,
'sequential' => 0,
'return' => array('email', 'location_type_id', 'id'),
),
);
if ($isPrimary) {
$params['api.Email.get']['is_primary'] = 1;
}
$contacts = civicrm_api3('Contact', 'get', $params);
if ($contacts['count'] > 0) {
$contact = reset($contacts['values']);
if ($contact['api.Email.get']['count'] > 0) {
$email = reset($contact['api.Email.get']['values']);
}
}
$returnParams = array(
(isset($contact['display_name'])) ? $contact['display_name'] : NULL,
(isset($email['email'])) ? $email['email'] : NULL,
(isset($email['location_type_id'])) ? $email['location_type_id'] : NULL,
(isset($email['id'])) ? $email['id'] : NULL,
);
return $returnParams;
}
Note: Well, I suppose that 'sequential' => 0
is not needed at all, as we do reset
to fetch the first entry of the email.