$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);
}
}
}
- $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];
$tokenString = CRM_Utils_Token::replaceContactTokens($tokenString, $contactDetails, TRUE, $greetingTokens, TRUE, $escapeSmarty);
}
+ self::removeNullContactTokens($tokenString, $contactDetails[0][$contactId], $greetingTokens);
// check if there are any unevaluated tokens
$greetingTokens = self::getTokens($tokenString);
}
}
+ /**
+ * 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();
+ $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
*
$this->assertEquals('Phone, Fax', $resolvedTokens[0][$contactID]['preferred_communication_method']);
}
+ /**
+ * Test for replaceContactTokens.
+ *
+ */
+ 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.
*