Skip to content

Commit

Permalink
Merge pull request #10906 from MegaphoneJon/CRM-21108-2
Browse files Browse the repository at this point in the history
CRM-21108 - Greatly improve performance of adding contacts
  • Loading branch information
monishdeb authored Aug 29, 2017
2 parents 58c51cb + 578c7a3 commit 0857857
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
7 changes: 3 additions & 4 deletions CRM/Contact/BAO/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -2651,10 +2651,9 @@ public static function processGreetings(&$contact, $useDefaults = FALSE) {
$contactDefaults = $defaultGreetings[$contact->contact_type];
}

// note that contact object not always has required greeting related
// fields that are required to calculate greeting and
// also other fields used in tokens etc,
// hence we need to retrieve it again.
// The contact object has not always required the
// fields that are required to calculate greetings
// so we need to retrieve it again.
if ($contact->_query !== FALSE) {
$contact->find(TRUE);
}
Expand Down
48 changes: 45 additions & 3 deletions CRM/Utils/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -1235,9 +1235,7 @@ public static function getTokenDetails(
}
}

$query = new CRM_Contact_BAO_Query($params, $returnProperties);

$details = $query->apiQuery($params, $returnProperties, NULL, NULL, 0, count($contactIDs));
$details = CRM_Contact_BAO_Query::apiQuery($params, $returnProperties, NULL, NULL, 0, count($contactIDs));

$contactDetails = &$details[0];

Expand Down Expand Up @@ -1368,6 +1366,7 @@ public static function replaceGreetingTokens(&$tokenString, $contactDetails = NU
$tokenString = CRM_Utils_Token::replaceContactTokens($tokenString, $contactDetails, TRUE, $greetingTokens, TRUE, $escapeSmarty);
}

self::removeNullContactTokens($tokenString, $contactDetails, $greetingTokens);
// check if there are any unevaluated tokens
$greetingTokens = self::getTokens($tokenString);

Expand Down Expand Up @@ -1426,6 +1425,49 @@ public static function replaceGreetingTokens(&$tokenString, $contactDetails = NU
}
}

/**
* At this point, $contactDetails has loaded the contact from the DAO. Any
* (non-custom) missing fields are null. By removing them, we can avoid
* expensive calls to CRM_Contact_BAO_Query.
*
* @param string $tokenString
* @param array $contactDetails
*/
private static function removeNullContactTokens(&$tokenString, $contactDetails, &$greetingTokens) {
$greetingTokensOriginal = $greetingTokens;
$contactFieldList = CRM_Contact_DAO_Contact::fields();
// Sometimes contactDetails are in a multidemensional array, sometimes a
// single-dimension array.
if (array_key_exists(0, $contactDetails) && is_array($contactDetails[0])) {
$contactDetails = current($contactDetails[0]);
}
$nullFields = array_keys(array_diff_key($contactFieldList, $contactDetails));

// Handle legacy tokens
foreach (self::legacyContactTokens() as $oldToken => $newToken) {
if (CRM_Utils_Array::key($newToken, $nullFields)) {
$nullFields[] = $oldToken;
}
}

// Remove null contact fields from $greetingTokens
$greetingTokens['contact'] = array_diff($greetingTokens['contact'], $nullFields);

// Also remove them from $tokenString
$removedTokens = array_diff($greetingTokensOriginal['contact'], $greetingTokens['contact']);
// Handle legacy tokens again, sigh
if (!empty($removedTokens)) {
foreach ($removedTokens as $token) {
if (CRM_Utils_Array::value($token, self::legacyContactTokens()) !== NULL) {
$removedTokens[] = CRM_Utils_Array::value($token, self::legacyContactTokens());
}
}
foreach ($removedTokens as $token) {
$tokenString = str_replace("{contact.$token}", '', $tokenString);
}
}
}

/**
* @param $tokens
*
Expand Down
24 changes: 24 additions & 0 deletions tests/phpunit/CRM/Utils/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ public function testGetTokenDetails() {
$this->assertEquals('Phone, Fax', $resolvedTokens[0][$contactID]['preferred_communication_method']);
}

/**
* Test for replaceGreetingTokens.
*
*/
public function testReplaceGreetingTokens() {
$tokenString = 'First Name: {contact.first_name} Last Name: {contact.last_name} Birth Date: {contact.birth_date} Prefix: {contact.prefix_id} Suffix: {contact.individual_suffix}';
$contactDetails = array(
array(
2811 => array(
'id' => '2811',
'contact_type' => 'Individual',
'first_name' => 'Morticia',
'last_name' => 'Addams',
'prefix_id' => 2,
),
),
);
$contactId = 2811;
$className = 'CRM_Contact_BAO_Contact';
$escapeSmarty = TRUE;
CRM_Utils_Token::replaceGreetingTokens($tokenString, $contactDetails, $contactId, $className, $escapeSmarty);
$this->assertEquals($tokenString, 'First Name: Morticia Last Name: Addams Birth Date: Prefix: Ms. Suffix: ');
}

/**
* Test getting multiple contacts.
*
Expand Down

0 comments on commit 0857857

Please sign in to comment.