diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php index 45da688677b9..a61dcc59e821 100644 --- a/CRM/Core/EntityTokens.php +++ b/CRM/Core/EntityTokens.php @@ -57,11 +57,11 @@ public function registerTokens(TokenRegisterEvent $e) { if (!$this->checkActive($e->getTokenProcessor())) { return; } - foreach ($this->getTokenMetadata() as $field) { + foreach ($this->getTokenMetadata() as $tokenName => $field) { if ($field['audience'] === 'user') { $e->register([ 'entity' => $this->entity, - 'field' => $field['name'], + 'field' => $tokenName, 'label' => $field['title'], ]); } @@ -83,31 +83,30 @@ protected function getTokenMetadata(): array { $this->tokensMetadata = Civi::cache('metadata')->get($cacheKey); } else { - foreach (array_merge($this->getFieldMetadata(), $this->getBespokeTokens()) as $field) { - if ( - $field['type'] === 'Custom' - || !empty($this->getBespokeTokens()[$field['name']]) - || in_array($field['name'], $this->getExposedFields(), TRUE) - ) { - $field['audience'] = 'user'; - if ($field['name'] === 'contact_id') { - // Since {contact.id} is almost always present don't confuse users - // by also adding (e.g {participant.contact_id) - $field['audience'] = 'sysadmin'; - } - if (!empty($this->getTokenMetadataOverrides()[$field['name']])) { - $field = array_merge($field, $this->getTokenMetadataOverrides()[$field['name']]); - } - if ($field['type'] === 'Custom') { - // Convert to apiv3 style for now. Later we can add v4 with - // portable naming & support for labels/ dates etc so let's leave - // the space open for that. - // Not the existing quickform widget has handling for the custom field - // format based on the title using this syntax. - $field['name'] = 'custom_' . $field['custom_field_id']; - $parts = explode(': ', $field['label']); - $field['title'] = "{$parts[1]} :: {$parts[0]}"; - } + $this->tokensMetadata = $this->getBespokeTokens(); + foreach ($this->getFieldMetadata() as $field) { + $field['audience'] = 'user'; + if ($field['name'] === 'contact_id') { + // Since {contact.id} is almost always present don't confuse users + // by also adding (e.g {participant.contact_id) + $field['audience'] = 'sysadmin'; + } + if (!empty($this->getTokenMetadataOverrides()[$field['name']])) { + $field = array_merge($field, $this->getTokenMetadataOverrides()[$field['name']]); + } + if ($field['type'] === 'Custom') { + // Convert to apiv3 style for now. Later we can add v4 with + // portable naming & support for labels/ dates etc so let's leave + // the space open for that. + // Not the existing quickform widget has handling for the custom field + // format based on the title using this syntax. + $parts = explode(': ', $field['label']); + $field['title'] = "{$parts[1]} :: {$parts[0]}"; + $tokenName = 'custom_' . $field['custom_field_id']; + $this->tokensMetadata[$tokenName] = $field; + continue; + } + if (in_array($field['name'], $this->getExposedFields(), TRUE)) { if ( ($field['options'] || !empty($field['suffixes'])) // At the time of writing currency didn't have a label option - this may have changed. @@ -247,7 +246,7 @@ public function getReturnFields(): array { * @return bool */ public function isBooleanField(string $fieldName): bool { - return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Boolean'; + return $this->getMetadataForField($fieldName)['data_type'] === 'Boolean'; } /** @@ -258,7 +257,7 @@ public function isBooleanField(string $fieldName): bool { * @return bool */ public function isDateField(string $fieldName): bool { - return in_array($this->getFieldMetadata()[$fieldName]['data_type'], ['Timestamp', 'Date'], TRUE); + return in_array($this->getMetadataForField($fieldName)['data_type'], ['Timestamp', 'Date'], TRUE); } /** @@ -291,7 +290,7 @@ public function isCustomField(string $fieldName) : bool { * @return bool */ public function isMoneyField(string $fieldName): bool { - return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Money'; + return $this->getMetadataForField($fieldName)['data_type'] === 'Money'; } /** @@ -553,7 +552,7 @@ public function getDependencies(): array { * @return string */ protected function getCustomFieldName(int $id): string { - foreach ($this->getFieldMetadata() as $key => $field) { + foreach ($this->getTokenMetadata() as $key => $field) { if (($field['custom_field_id'] ?? NULL) === $id) { return $key; } @@ -570,12 +569,35 @@ protected function getCustomFieldName(int $id): string { */ protected function getCustomFieldValue($entityID, string $field) { $id = str_replace('custom_', '', $field); - $value = $this->prefetch[$entityID][$this->getCustomFieldName($id)] ?? NULL; + $value = $this->prefetch[$entityID][$this->getCustomFieldName($id)] ?? ''; if ($value !== NULL) { return CRM_Core_BAO_CustomField::displayValue($value, $id); } } + /** + * Get the metadata for the field. + * + * @param string $fieldName + * + * @return array + */ + protected function getMetadataForField($fieldName): array { + if (isset($this->getTokenMetadata()[$fieldName])) { + return $this->getTokenMetadata()[$fieldName]; + } + return $this->getTokenMetadata()[$this->getDeprecatedTokens()[$fieldName]]; + } + + /** + * Get array of deprecated tokens and the new token they map to. + * + * @return array + */ + protected function getDeprecatedTokens(): array { + return []; + } + /** * Get any overrides for token metadata. * diff --git a/CRM/Event/Tokens.php b/CRM/Event/Tokens.php index 91d5a8797b4c..8c437057b1fb 100644 --- a/CRM/Event/Tokens.php +++ b/CRM/Event/Tokens.php @@ -49,6 +49,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => 'String', + 'audience' => 'user', ], 'info_url' => [ 'title' => ts('Event Info URL'), @@ -56,6 +57,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => 'String', + 'audience' => 'user', ], 'registration_url' => [ 'title' => ts('Event Registration URL'), @@ -63,6 +65,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => 'String', + 'audience' => 'user', ], 'contact_email' => [ 'title' => ts('Event Contact Email'), @@ -70,6 +73,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => 'String', + 'audience' => 'user', ], 'contact_phone' => [ 'title' => ts('Event Contact Phone'), @@ -77,6 +81,7 @@ protected function getBespokeTokens(): array { 'type' => 'calculated', 'options' => NULL, 'data_type' => '', + 'audience' => 'user', ], ]; } @@ -92,7 +97,7 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) } if (array_key_exists($field, $this->getEventTokenValues($eventID))) { foreach ($this->getEventTokenValues($eventID)[$field] as $format => $value) { - $row->format($format)->tokens($entity, $field, $value); + $row->format($format)->tokens($entity, $field, $value ?? ''); } } } @@ -143,14 +148,15 @@ protected function getEventTokenValues(int $eventID = NULL): array { $tokens['contact_phone']['text/html'] = $event['loc_block_id.phone_id.phone']; $tokens['contact_email']['text/html'] = $event['loc_block_id.email_id.email']; - foreach (array_keys($this->getTokenMetadata()) as $field) { - if (!isset($tokens[$field])) { - if ($this->isCustomField($field)) { + foreach ($this->getTokenMetadata() as $fieldName => $fieldSpec) { + if (!isset($tokens[$fieldName])) { + if ($fieldSpec['type'] === 'Custom') { $this->prefetch[$eventID] = $event; - $tokens[$field]['text/html'] = $this->getCustomFieldValue($eventID, $field); + $value = $event[$fieldSpec['name']]; + $tokens[$fieldName]['text/html'] = CRM_Core_BAO_CustomField::displayValue($value, $fieldSpec['custom_field_id']); } else { - $tokens[$field]['text/html'] = $event[$field]; + $tokens[$fieldName]['text/html'] = $event[$fieldName]; } } }