*/
use Civi\Token\AbstractTokenSubscriber;
+use Civi\Token\Event\TokenValueEvent;
use Civi\Token\TokenRow;
use Civi\ActionSchedule\Event\MailingQueryEvent;
use Civi\Token\TokenProcessor;
public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) {
$this->prefetch = (array) $prefetch;
$fieldValue = $this->getFieldValue($row, $field);
+ if (is_array($fieldValue)) {
+ // eg. role_id for participant would be an array here.
+ $fieldValue = implode(',', $fieldValue);
+ }
if ($this->isPseudoField($field)) {
+ if (!empty($fieldValue)) {
+ // If it's set here it has already been loaded in pre-fetch.
+ return $row->format('text/plain')->tokens($entity, $field, (string) $fieldValue);
+ }
+ // Once prefetch is fully standardised we can remove this - as long
+ // as tests pass we should be fine as tests cover this.
$split = explode(':', $field);
return $row->tokens($entity, $field, $this->getPseudoValue($split[0], $split[1], $this->getFieldValue($row, $split[0])));
}
+ if ($this->isCustomField($field)) {
+ return $row->customToken($entity, \CRM_Core_BAO_CustomField::getKeyID($field), $this->getFieldValue($row, 'id'));
+ }
if ($this->isMoneyField($field)) {
return $row->format('text/plain')->tokens($entity, $field,
\CRM_Utils_Money::format($fieldValue, $this->getCurrency($row)));
if ($this->isDateField($field)) {
return $row->format('text/plain')->tokens($entity, $field, \CRM_Utils_Date::customFormat($fieldValue));
}
- if ($this->isCustomField($field)) {
- $row->customToken($entity, \CRM_Core_BAO_CustomField::getKeyID($field), $this->getFieldValue($row, 'id'));
- }
- else {
- $row->format('text/plain')->tokens($entity, $field, (string) $fieldValue);
- }
+ $row->format('text/plain')->tokens($entity, $field, (string) $fieldValue);
}
/**
* Get all the tokens supported by this processor.
*
* @return array|string[]
+ * @throws \API_Exception
*/
- public function getAllTokens(): array {
- return array_merge($this->getBasicTokens(), $this->getPseudoTokens(), CRM_Utils_Token::getCustomFieldTokens('Contribution'));
+ protected function getAllTokens(): array {
+ $basicTokens = $this->getBasicTokens();
+ foreach (array_keys($basicTokens) as $fieldName) {
+ // The goal is to be able to render more complete tokens
+ // (eg. actual booleans, field names, raw ids) for a more
+ // advanced audiences - ie those using conditionals
+ // and to specify that audience in the api that retrieves.
+ // But, for now, let's not advertise, given that most of these fields
+ // aren't really needed even once...
+ if ($this->isBooleanField($fieldName)) {
+ unset($basicTokens[$fieldName]);
+ }
+ }
+ return array_merge($basicTokens, $this->getPseudoTokens(), CRM_Utils_Token::getCustomFieldTokens($this->getApiEntityName()));
+ }
+
+ /**
+ * Is the given field a boolean field.
+ *
+ * @param string $fieldName
+ *
+ * @return bool
+ */
+ public function isBooleanField(string $fieldName): bool {
+ return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Boolean';
}
/**
* @return bool
*/
public function isDateField(string $fieldName): bool {
- return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Timestamp';
+ return in_array($this->getFieldMetadata()[$fieldName]['data_type'], ['Timestamp', 'Date'], TRUE);
}
/**
$return[$fieldName . ':label'] = $fieldLabel;
$return[$fieldName . ':name'] = ts('Machine name') . ': ' . $fieldLabel;
}
+ if ($this->isBooleanField($fieldName)) {
+ $return[$fieldName . ':label'] = $this->getFieldMetadata()[$fieldName]['title'];
+ }
}
return $return;
}
* @return string|int
*/
protected function getFieldValue(TokenRow $row, string $field) {
+ $entityName = $this->getEntityName();
+ if (isset($row->context[$entityName][$field])) {
+ return $row->context[$entityName][$field];
+ }
+
$actionSearchResult = $row->context['actionSearchResult'];
$aliasedField = $this->getEntityAlias() . $field;
if (isset($actionSearchResult->{$aliasedField})) {
* @return string[]
*/
public function getSkippedFields(): array {
- $fields = ['contact_id'];
+ // tags is offered in 'case' & is one of the only fields that is
+ // 'not a real field' offered up by case - seems like an oddity
+ // we should skip at the top level for now.
+ $fields = ['contact_id', 'tags'];
if (!CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
$fields[] = 'campaign_id';
}
return CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($this->getApiEntityName());
}
- public function getEntityIDField() {
+ public function getEntityIDField(): string {
return $this->getEntityName() . 'Id';
}
- public function prefetch(\Civi\Token\Event\TokenValueEvent $e): ?array {
+ public function prefetch(TokenValueEvent $e): ?array {
$entityIDs = $e->getTokenProcessor()->getContextValues($this->getEntityIDField());
if (empty($entityIDs)) {
return [];
return CRM_Core_Config::singleton()->defaultCurrency;
}
- public function getPrefetchFields(\Civi\Token\Event\TokenValueEvent $e): array {
- return array_intersect($this->getActiveTokens($e), $this->getCurrencyFieldName(), array_keys($this->getAllTokens()));
+ /**
+ * Get the fields required to prefetch the entity.
+ *
+ * @param \Civi\Token\Event\TokenValueEvent $e
+ *
+ * @return array
+ * @throws \API_Exception
+ */
+ public function getPrefetchFields(TokenValueEvent $e): array {
+ $allTokens = array_keys($this->getAllTokens());
+ $requiredFields = array_intersect($this->getActiveTokens($e), $allTokens);
+ if (empty($requiredFields)) {
+ return [];
+ }
+ $requiredFields = array_merge($requiredFields, array_intersect($allTokens, array_merge(['id'], $this->getCurrencyFieldName())));
+ foreach ($this->getDependencies() as $field => $required) {
+ if (in_array($field, $this->getActiveTokens($e), TRUE)) {
+ foreach ((array) $required as $key) {
+ $requiredFields[] = $key;
+ }
+ }
+ }
+ return $requiredFields;
+ }
+
+ /**
+ * Get fields which need to be returned to render another token.
+ *
+ * @return array
+ */
+ public function getDependencies(): array {
+ return [];
}
}