Skip to content

Commit

Permalink
Switch to using apiv4 for metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
eileenmcnaughton committed Aug 6, 2021
1 parent e586838 commit 742941f
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 56 deletions.
57 changes: 11 additions & 46 deletions CRM/Contribute/Tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ protected function getEntityName(): string {
}

/**
* Get the relevant bao name.
* Get the entity name for api v4 calls.
*
* In practice this IS just ucfirst($this->GetEntityName)
* but declaring it seems more legible.
*
* @return string
*/
public function getBAOName(): string {
return CRM_Core_DAO_AllCoreTables::getFullName(ucfirst($this->getEntityName()));
protected function getApiEntityName(): string {
return 'Contribution';
}

/**
Expand Down Expand Up @@ -91,24 +96,6 @@ public function getBasicTokens(): array {
return $return;
}

/**
* Get pseudoTokens - it tokens that reflect the name or label of a pseudoconstant.
*
* @internal - this function will likely be made protected soon.
*
* @return array
*/
public function getPseudoTokens(): array {
$return = [];
foreach (array_keys($this->getBasicTokens()) as $fieldName) {
if (!empty($this->fieldMetadata[$fieldName]['pseudoconstant'])) {
$return[$fieldName . ':label'] = $this->fieldMetadata[$fieldName]['html']['label'];
$return[$fieldName . ':name'] = ts('Machine name') . ': ' . $this->fieldMetadata[$fieldName]['html']['label'];
}
}
return $return;
}

/**
* Class constructor.
*/
Expand Down Expand Up @@ -161,7 +148,7 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL)
$actionSearchResult = $row->context['actionSearchResult'];
$fieldValue = $actionSearchResult->{"contrib_$field"} ?? NULL;

if (array_key_exists($field, $this->getPseudoTokens())) {
if ($this->isPseudoField($field)) {
$split = explode(':', $field);
return $row->tokens($entity, $field, $this->getPseudoValue($split[0], $split[1], $actionSearchResult->{"contrib_$split[0]"} ?? NULL));
}
Expand All @@ -172,34 +159,12 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL)
if ($this->isDateField($field)) {
return $row->format('text/plain')->tokens($entity, $field, \CRM_Utils_Date::customFormat($fieldValue));
}
if ($cfID = \CRM_Core_BAO_CustomField::getKeyID($field)) {
$row->customToken($entity, $cfID, $actionSearchResult->entity_id);
if ($this->isCustomField($field)) {
$row->customToken($entity, \CRM_Core_BAO_CustomField::getKeyID($field), $actionSearchResult->entity_id);
}
else {
$row->format('text/plain')->tokens($entity, $field, (string) $fieldValue);
}
}

/**
* Get the value for the relevant pseudo field.
*
* @param string $realField e.g contribution_status_id
* @param string $pseudoKey e.g name
* @param int|string $fieldValue e.g 1
*
* @return string
* Eg. 'Completed' in the example above.
*
* @internal function will likely be protected soon.
*/
public function getPseudoValue(string $realField, string $pseudoKey, $fieldValue): string {
if ($pseudoKey === 'name') {
$fieldValue = (string) CRM_Core_PseudoConstant::getName($this->getBAOName(), $realField, $fieldValue);
}
if ($pseudoKey === 'label') {
$fieldValue = (string) CRM_Core_PseudoConstant::getLabel($this->getBAOName(), $realField, $fieldValue);
}
return (string) $fieldValue;
}

}
117 changes: 107 additions & 10 deletions CRM/Core/EntityTokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL) {
}

/**
* Get the entity name for api v4 calls.
*
* @return string
*/
protected function getApiEntityName(): string {
return '';
}


/**
* Get the relevant bao name.
*/
public function getBAOName(): string {
return CRM_Core_DAO_AllCoreTables::getFullName($this->getApiEntityName());
}

/**
* Is the given field a date field.
*
Expand All @@ -41,7 +58,29 @@ public function evaluateToken(TokenRow $row, $entity, $field, $prefetch = NULL)
* @return bool
*/
public function isDateField(string $fieldName): bool {
return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME);
return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Timestamp';
}

/**
* Is the given field a pseudo field.
*
* @param string $fieldName
*
* @return bool
*/
public function isPseudoField(string $fieldName): bool {
return strpos($fieldName, ':') !== FALSE;
}

/**
* Is the given field a custom field.
*
* @param string $fieldName
*
* @return bool
*/
public function isCustomField(string $fieldName) : bool {
return (bool) \CRM_Core_BAO_CustomField::getKeyID($fieldName);
}

/**
Expand All @@ -52,7 +91,7 @@ public function isDateField(string $fieldName): bool {
* @return bool
*/
public function isMoneyField(string $fieldName): bool {
return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_MONEY);
return $this->getFieldMetadata()[$fieldName]['data_type'] === 'Money';
}

/**
Expand All @@ -62,17 +101,75 @@ public function isMoneyField(string $fieldName): bool {
*/
protected function getFieldMetadata(): array {
if (empty($this->fieldMetadata)) {
$baoName = $this->getBAOName();

$fields = (array) $baoName::fields();
// re-index by real field name. I originally wanted to use apiv4
// getfields - but it returns different stuff for 'type' and
// does not return 'pseudoconstant' as a key so for now...
foreach ($fields as $details) {
$this->fieldMetadata[$details['name']] = $details;
try {
// Tests fail without checkPermissions = FALSE
$this->fieldMetadata = (array) civicrm_api4($this->getApiEntityName(), 'getfields', ['checkPermissions' => FALSE], 'name');
}
catch (API_Exception $e) {
$this->fieldMetadata = [];
}
}
return $this->fieldMetadata;
}

/**
* Get pseudoTokens - it tokens that reflect the name or label of a pseudoconstant.
*
* @internal - this function will likely be made protected soon.
*
* @return array
*/
public function getPseudoTokens(): array {
$return = [];
foreach (array_keys($this->getBasicTokens()) as $fieldName) {
if ($this->isAddPseudoTokens($fieldName)) {
$return[$fieldName . ':label'] = $this->fieldMetadata[$fieldName]['input_attrs']['label'];
$return[$fieldName . ':name'] = ts('Machine name') . ': ' . $this->fieldMetadata[$fieldName]['input_attrs']['label'];
}
}
return $return;
}

/**
* Is this a field we should add pseudo-tokens to?
*
* Pseudo-tokens allow access to name and label fields - e.g
*
* {contribution.contribution_status_id:name} might resolve to 'Completed'
*
* @param string $fieldName
*/
public function isAddPseudoTokens($fieldName): bool {
if ($fieldName === 'currency') {
// 'currency' is manually added to the skip list as an anomaly.
// name & label aren't that suitable for 'currency' (symbol, which
// possibly maps to 'abbr' would be) and we can't gather that
// from the metadata as yet.
return FALSE;
}
return (bool) $this->getFieldMetadata()[$fieldName]['options'];
}

/**
* Get the value for the relevant pseudo field.
*
* @param string $realField e.g contribution_status_id
* @param string $pseudoKey e.g name
* @param int|string $fieldValue e.g 1
*
* @return string
* Eg. 'Completed' in the example above.
*
* @internal function will likely be protected soon.
*/
public function getPseudoValue(string $realField, string $pseudoKey, $fieldValue): string {
if ($pseudoKey === 'name') {
$fieldValue = (string) CRM_Core_PseudoConstant::getName($this->getBAOName(), $realField, $fieldValue);
}
if ($pseudoKey === 'label') {
$fieldValue = (string) CRM_Core_PseudoConstant::getLabel($this->getBAOName(), $realField, $fieldValue);
}
return (string) $fieldValue;
}

}

0 comments on commit 742941f

Please sign in to comment.