Skip to content
Snippets Groups Projects
Unverified Commit fe728c92 authored by colemanw's avatar colemanw Committed by GitHub
Browse files

Merge pull request #21570 from eileenmcnaughton/leg_contact

#2650 #2814 Add support for preferred syntax for contact tokens
parents e56af21c 2478a7f2
Branches
Tags
No related merge requests found
......@@ -158,28 +158,28 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
'display_name' => 'Display Name',
'nick_name' => 'Nickname',
'image_URL' => 'Image Url',
'preferred_communication_method' => 'Preferred Communication Method',
'preferred_language' => 'Preferred Language',
'preferred_mail_format' => 'Preferred Mail Format',
'preferred_communication_method:label' => 'Preferred Communication Method',
'preferred_language:label' => 'Preferred Language',
'preferred_mail_format:label' => 'Preferred Mail Format',
'hash' => 'Contact Hash',
'contact_source' => 'Contact Source',
'source' => 'Contact Source',
'first_name' => 'First Name',
'middle_name' => 'Middle Name',
'last_name' => 'Last Name',
'individual_prefix' => 'Individual Prefix',
'individual_suffix' => 'Individual Suffix',
'prefix_id:label' => 'Individual Prefix',
'suffix_id:label' => 'Individual Suffix',
'formal_title' => 'Formal Title',
'communication_style' => 'Communication Style',
'communication_style_id:label' => 'Communication Style',
'job_title' => 'Job Title',
'gender' => 'Gender ID',
'gender_id:label' => 'Gender ID',
'birth_date' => 'Birth Date',
'current_employer_id' => 'Current Employer ID',
'contact_is_deleted' => 'Contact is in Trash',
'is_deleted:label' => 'Contact is in Trash',
'created_date' => 'Created Date',
'modified_date' => 'Modified Date',
'addressee' => 'Addressee',
'email_greeting' => 'Email Greeting',
'postal_greeting' => 'Postal Greeting',
'addressee_display' => 'Addressee',
'email_greeting_display' => 'Email Greeting',
'postal_greeting_display' => 'Postal Greeting',
'current_employer' => 'Current Employer',
'location_type' => 'Location Type',
'address_id' => 'Address ID',
......@@ -216,7 +216,7 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
'world_region' => 'World Region',
'url' => 'Website',
'checksum' => 'Checksum',
'contact_id' => 'Internal Contact ID',
'id' => 'Internal Contact ID',
];
}
......@@ -348,12 +348,41 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
}
else {
$row->format('text/html')
->tokens('contact', $token, $row->context['contact'][$token] ?? '');
->tokens('contact', $token, $this->getFieldValue($row, $token));
}
}
}
}
/**
* Get the field value.
*
* @param \Civi\Token\TokenRow $row
* @param string $field
* @return string|int
*/
protected function getFieldValue(TokenRow $row, string $field) {
$entityName = 'contact';
if (isset($this->getDeprecatedTokens()[$field])) {
// Check the non-deprecated location first, fall back to deprecated
// this is important for the greetings because - they are weird in the query object.
$possibilities = [$this->getDeprecatedTokens()[$field], $field];
}
else {
$possibilities = [$field];
if (in_array($field, $this->getDeprecatedTokens(), TRUE)) {
$possibilities[] = array_search($field, $this->getDeprecatedTokens(), TRUE);
}
}
foreach ($possibilities as $possibility) {
if (isset($row->context[$entityName][$possibility])) {
return $row->context[$entityName][$possibility];
}
}
return '';
}
/**
* Is the given field a boolean field.
*
......@@ -446,18 +475,15 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
*/
protected function getContact(int $contactId, array $requiredFields, bool $getAll = FALSE): array {
$returnProperties = array_fill_keys($requiredFields, 1);
$mappedFields = [
'email_greeting' => 'email_greeting_display',
'postal_greeting' => 'postal_greeting_display',
'addressee' => 'addressee_display',
];
$mappedFields = array_flip($this->getDeprecatedTokens());
if (!empty($returnProperties['checksum'])) {
$returnProperties['hash'] = 1;
}
foreach ($mappedFields as $tokenName => $realName) {
foreach ($mappedFields as $tokenName => $api3Name) {
if (in_array($tokenName, $requiredFields, TRUE)) {
$returnProperties[$realName] = 1;
$returnProperties[$api3Name] = 1;
}
}
if ($getAll) {
......@@ -471,8 +497,14 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
[$contact] = \CRM_Contact_BAO_Query::apiQuery($params, $returnProperties ?? NULL);
//CRM-4524
$contact = reset($contact);
foreach ($mappedFields as $tokenName => $realName) {
$contact[$tokenName] = $contact[$realName] ?? '';
foreach ($mappedFields as $tokenName => $apiv3Name) {
// it would be set already with the right value for a greeting token
// the query object returns the db value for email_greeting_display
// and a numeric value for email_greeting if you put email_greeting
// in the return properties.
if (!isset($contact[$tokenName])) {
$contact[$tokenName] = $contact[$apiv3Name] ?? '';
}
}
//update value of custom field token
......@@ -550,4 +582,34 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
];
}
/**
* These tokens still work but we don't advertise them.
*
* We can remove from the following places
* - scheduled reminders
* - add to 'blocked' on pdf letter & email
*
* & then at some point start issuing warnings for them
* but contact tokens are pretty central so it might be
* a bit drawn out.
*
* @return string[]
* Keys are deprecated tokens and values are their replacements.
*/
protected function getDeprecatedTokens(): array {
return [
'individual_prefix' => 'prefix_id:label',
'individual_suffix' => 'suffix_id:label',
'gender' => 'gender_id:label',
'communication_style' => 'communication_style_id:label',
'preferred_communication_method' => 'preferred_communication_method:label',
'email_greeting' => 'email_greeting_display',
'postal_greeting' => 'postal_greeting_display',
'addressee' => 'addressee_display',
'contact_id' => 'id',
'contact_source' => 'source',
'contact_is_deleted' => 'is_deleted:label',
];
}
}
......@@ -2,6 +2,7 @@
use Civi\Api4\Address;
use Civi\Api4\Contact;
use Civi\Api4\MessageTemplate;
use Civi\Token\TokenProcessor;
/**
......@@ -110,7 +111,7 @@ class CRM_Core_BAO_MessageTemplateTest extends CiviUnitTestCase {
CRM_Core_Transaction::create(TRUE)->run(function(CRM_Core_Transaction $tx) {
$tx->rollback();
\Civi\Api4\MessageTemplate::update()
MessageTemplate::update()
->addWhere('workflow_name', '=', 'case_activity')
->addWhere('is_reserved', '=', 0)
->setValues([
......@@ -147,7 +148,7 @@ class CRM_Core_BAO_MessageTemplateTest extends CiviUnitTestCase {
CRM_Core_Transaction::create(TRUE)->run(function(CRM_Core_Transaction $tx) {
$tx->rollback();
\Civi\Api4\MessageTemplate::update()
MessageTemplate::update()
->addWhere('workflow_name', '=', 'case_activity')
->addWhere('is_reserved', '=', 0)
->setValues([
......@@ -327,12 +328,6 @@ London, 90210
$advertisedTokens = CRM_Core_SelectValues::contactTokens();
$this->assertEquals($this->getAdvertisedTokens(), $advertisedTokens);
// Compare with our token data.
unset($advertisedTokens['{important_stuff.favourite_emoticon}']);
foreach (array_keys($advertisedTokens) as $token) {
$this->assertArrayKeyExists(substr($token, 9, -1), $tokenData);
}
CRM_Core_Smarty::singleton()->assign('pre_assigned_smarty', 'wee');
// This string contains the 4 types of possible replaces just to be sure they
// work in combination.
......@@ -386,6 +381,36 @@ emo
CRM_Utils_Time::resetTime();
}
/**
* Test that old contact tokens still work, as we add new-style support.
*/
public function testLegacyTokens(): void {
$contactID = $this->individualCreate(['gender_id' => 'Female', 'communication_style' => 1, 'preferred_communication_method' => 'Phone']);
$mappings = [
['old' => '{contact.individual_prefix}', 'new' => '{contact.prefix_id:label}', 'output' => 'Mr.'],
['old' => '{contact.individual_suffix}', 'new' => '{contact.suffix_id:label}', 'output' => 'II'],
['old' => '{contact.gender}', 'new' => '{contact.gender_id:label}', 'output' => 'Female'],
['old' => '{contact.communication_style}', 'new' => '{contact.communication_style_id:label}', 'output' => 'Formal'],
['old' => '{contact.preferred_communication_method}', 'new' => '{contact.preferred_communication_method:label}', 'output' => 'Phone'],
['old' => '{contact.contact_id}', 'new' => '{contact.id}', 'output' => $contactID],
['old' => '{contact.email_greeting}', 'new' => '{contact.email_greeting_display}', 'output' => 'Dear Anthony'],
['old' => '{contact.postal_greeting}', 'new' => '{contact.postal_greeting_display}', 'output' => 'Dear Anthony'],
['old' => '{contact.addressee}', 'new' => '{contact.addressee_display}', 'output' => 'Mr. Anthony J. Anderson II'],
];
foreach ($mappings as $mapping) {
foreach (['old', 'new'] as $type) {
$messageContent = CRM_Core_BAO_MessageTemplate::renderTemplate([
'contactId' => $contactID,
'messageTemplate' => [
'msg_text' => $mapping[$type],
],
])['text'];
$this->assertEquals($mapping['output'], $messageContent, 'could not resolve ' . $mapping[$type]);
}
}
}
/**
* Implement token values hook.
*
......@@ -499,28 +524,28 @@ emo
'{contact.display_name}' => 'Display Name',
'{contact.nick_name}' => 'Nickname',
'{contact.image_URL}' => 'Image Url',
'{contact.preferred_communication_method}' => 'Preferred Communication Method',
'{contact.preferred_language}' => 'Preferred Language',
'{contact.preferred_mail_format}' => 'Preferred Mail Format',
'{contact.preferred_communication_method:label}' => 'Preferred Communication Method',
'{contact.preferred_language:label}' => 'Preferred Language',
'{contact.preferred_mail_format:label}' => 'Preferred Mail Format',
'{contact.hash}' => 'Contact Hash',
'{contact.contact_source}' => 'Contact Source',
'{contact.source}' => 'Contact Source',
'{contact.first_name}' => 'First Name',
'{contact.middle_name}' => 'Middle Name',
'{contact.last_name}' => 'Last Name',
'{contact.individual_prefix}' => 'Individual Prefix',
'{contact.individual_suffix}' => 'Individual Suffix',
'{contact.prefix_id:label}' => 'Individual Prefix',
'{contact.suffix_id:label}' => 'Individual Suffix',
'{contact.formal_title}' => 'Formal Title',
'{contact.communication_style}' => 'Communication Style',
'{contact.communication_style_id:label}' => 'Communication Style',
'{contact.job_title}' => 'Job Title',
'{contact.gender}' => 'Gender ID',
'{contact.gender_id:label}' => 'Gender ID',
'{contact.birth_date}' => 'Birth Date',
'{contact.current_employer_id}' => 'Current Employer ID',
'{contact.contact_is_deleted}' => 'Contact is in Trash',
'{contact.is_deleted:label}' => 'Contact is in Trash',
'{contact.created_date}' => 'Created Date',
'{contact.modified_date}' => 'Modified Date',
'{contact.addressee}' => 'Addressee',
'{contact.email_greeting}' => 'Email Greeting',
'{contact.postal_greeting}' => 'Postal Greeting',
'{contact.addressee_display}' => 'Addressee',
'{contact.email_greeting_display}' => 'Email Greeting',
'{contact.postal_greeting_display}' => 'Postal Greeting',
'{contact.current_employer}' => 'Current Employer',
'{contact.location_type}' => 'Location Type',
'{contact.address_id}' => 'Address ID',
......@@ -570,7 +595,7 @@ emo
'{contact.custom_12}' => 'Yes No :: Custom Group',
'{contact.custom_3}' => 'Test Date :: Custom Group',
'{contact.checksum}' => 'Checksum',
'{contact.contact_id}' => 'Internal Contact ID',
'{contact.id}' => 'Internal Contact ID',
'{important_stuff.favourite_emoticon}' => 'Best coolest emoticon',
];
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment