Fix token metadata to be clearable outside tests
authorEileen McNaughton <emcnaughton@wikimedia.org>
Thu, 14 Oct 2021 20:10:25 +0000 (09:10 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Sat, 23 Oct 2021 00:13:15 +0000 (13:13 +1300)
CRM/Contact/Tokens.php
CRM/Core/EntityTokens.php

index 6fa88a07591b74a5f6ddb89f3ecd89fb5ba2085a..a713d8cc25847b536453324ac85d1304a569cc1e 100644 (file)
@@ -369,37 +369,34 @@ class CRM_Contact_Tokens extends CRM_Core_EntityTokens {
    * @noinspection PhpUnhandledExceptionInspection
    */
   protected function getTokenMetadata(): array {
-    if ($this->tokensMetadata) {
-      return $this->tokensMetadata;
-    }
     if (Civi::cache('metadata')->has($this->getCacheKey())) {
       return Civi::cache('metadata')->get($this->getCacheKey());
     }
     $this->fieldMetadata = (array) civicrm_api4('Contact', 'getfields', ['checkPermissions' => FALSE], 'name');
-    $this->tokensMetadata = $this->getBespokeTokens();
+    $tokensMetadata = $this->getBespokeTokens();
     foreach ($this->fieldMetadata as $field) {
-      $this->addFieldToTokenMetadata($field, $this->getExposedFields());
+      $this->addFieldToTokenMetadata($tokensMetadata, $field, $this->getExposedFields());
     }
 
     foreach ($this->getRelatedEntityTokenMetadata() as $entity => $exposedFields) {
       $apiEntity = ($entity === 'openid') ? 'OpenID' : ucfirst($entity);
       $metadata = (array) civicrm_api4($apiEntity, 'getfields', ['checkPermissions' => FALSE], 'name');
       foreach ($metadata as $field) {
-        $this->addFieldToTokenMetadata($field, $exposedFields, 'primary_' . $entity);
+        $this->addFieldToTokenMetadata($tokensMetadata, $field, $exposedFields, 'primary_' . $entity);
       }
     }
     // Manually add in the abbreviated state province as that maps to
     // what has traditionally been delivered.
-    $this->tokensMetadata['primary_address.state_province_id:abbr'] = $this->tokensMetadata['primary_address.state_province_id:label'];
-    $this->tokensMetadata['primary_address.state_province_id:abbr']['name'] = 'state_province_id:abbr';
-    $this->tokensMetadata['primary_address.state_province_id:abbr']['audience'] = 'user';
+    $tokensMetadata['primary_address.state_province_id:abbr'] = $tokensMetadata['primary_address.state_province_id:label'];
+    $tokensMetadata['primary_address.state_province_id:abbr']['name'] = 'state_province_id:abbr';
+    $tokensMetadata['primary_address.state_province_id:abbr']['audience'] = 'user';
     // Hide the label for now because we are not sure if there are paths
     // where legacy token resolution is in play where this could not be resolved.
-    $this->tokensMetadata['primary_address.state_province_id:label']['audience'] = 'sysadmin';
+    $tokensMetadata['primary_address.state_province_id:label']['audience'] = 'sysadmin';
     // Hide this really obscure one. Just cos it annoys me.
-    $this->tokensMetadata['primary_address.manual_geo_code:label']['audience'] = 'sysadmin';
-    Civi::cache('metadata')->set($this->getCacheKey(), $this->tokensMetadata);
-    return $this->tokensMetadata;
+    $tokensMetadata['primary_address.manual_geo_code:label']['audience'] = 'sysadmin';
+    Civi::cache('metadata')->set($this->getCacheKey(), $tokensMetadata);
+    return $tokensMetadata;
   }
 
   /**
index 7f7b669959e161ca7e14f372fb9ec93e09d9306d..563cc10a4965b48ac3bd61b665feee12782e4231 100644 (file)
@@ -75,23 +75,18 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
    * @return array
    */
   protected function getTokenMetadata(): array {
-    if (empty($this->tokensMetadata)) {
-      $cacheKey = $this->getCacheKey();
-      if (Civi::cache('metadata')->has($cacheKey)) {
-        $this->tokensMetadata = Civi::cache('metadata')->get($cacheKey);
+    $cacheKey = $this->getCacheKey();
+    if (!Civi::cache('metadata')->has($cacheKey)) {
+      $tokensMetadata = $this->getBespokeTokens();
+      foreach ($this->getFieldMetadata() as $field) {
+        $this->addFieldToTokenMetadata($tokensMetadata, $field, $this->getExposedFields());
       }
-      else {
-        $this->tokensMetadata = $this->getBespokeTokens();
-        foreach ($this->getFieldMetadata() as $field) {
-          $this->addFieldToTokenMetadata($field, $this->getExposedFields());
-        }
-        foreach ($this->getHiddenTokens() as $name) {
-          $this->tokensMetadata[$name]['audience'] = 'hidden';
-        }
-        Civi::cache('metadata')->set($cacheKey, $this->tokensMetadata);
+      foreach ($this->getHiddenTokens() as $name) {
+        $tokensMetadata[$name]['audience'] = 'hidden';
       }
+      Civi::cache('metadata')->set($cacheKey, $tokensMetadata);
     }
-    return $this->tokensMetadata;
+    return Civi::cache('metadata')->get($cacheKey);
   }
 
   /**
@@ -597,11 +592,12 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
   /**
    * Add the token to the metadata based on the field spec.
    *
+   * @param array $tokensMetadata
    * @param array $field
    * @param array $exposedFields
    * @param string $prefix
    */
-  protected function addFieldToTokenMetadata(array $field, array $exposedFields, string $prefix = ''): void {
+  protected function addFieldToTokenMetadata(array &$tokensMetadata, array $field, array $exposedFields, string $prefix = ''): void {
     if ($field['type'] !== 'Custom' && !in_array($field['name'], $exposedFields, TRUE)) {
       return;
     }
@@ -623,7 +619,7 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
       $parts = explode(': ', $field['label']);
       $field['title'] = "{$parts[1]} :: {$parts[0]}";
       $tokenName = 'custom_' . $field['custom_field_id'];
-      $this->tokensMetadata[$tokenName] = $field;
+      $tokensMetadata[$tokenName] = $field;
       return;
     }
     $tokenName = $prefix ? ($prefix . '.' . $field['name']) : $field['name'];
@@ -633,21 +629,21 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
         // At the time of writing currency didn't have a label option - this may have changed.
         && !in_array($field['name'], $this->getCurrencyFieldName(), TRUE)
       ) {
-        $this->tokensMetadata[$tokenName . ':label'] = $this->tokensMetadata[$tokenName . ':name'] = $field;
+        $tokensMetadata[$tokenName . ':label'] = $tokensMetadata[$tokenName . ':name'] = $field;
         $fieldLabel = $field['input_attrs']['label'] ?? $field['label'];
-        $this->tokensMetadata[$tokenName . ':label']['name'] = $field['name'] . ':label';
-        $this->tokensMetadata[$tokenName . ':name']['name'] = $field['name'] . ':name';
-        $this->tokensMetadata[$tokenName . ':name']['audience'] = 'sysadmin';
-        $this->tokensMetadata[$tokenName . ':label']['title'] = $fieldLabel;
-        $this->tokensMetadata[$tokenName . ':name']['title'] = ts('Machine name') . ': ' . $fieldLabel;
+        $tokensMetadata[$tokenName . ':label']['name'] = $field['name'] . ':label';
+        $tokensMetadata[$tokenName . ':name']['name'] = $field['name'] . ':name';
+        $tokensMetadata[$tokenName . ':name']['audience'] = 'sysadmin';
+        $tokensMetadata[$tokenName . ':label']['title'] = $fieldLabel;
+        $tokensMetadata[$tokenName . ':name']['title'] = ts('Machine name') . ': ' . $fieldLabel;
         $field['audience'] = 'sysadmin';
       }
       if ($field['data_type'] === 'Boolean') {
-        $this->tokensMetadata[$tokenName . ':label'] = $field;
-        $this->tokensMetadata[$tokenName . ':label']['name'] = $field['name'] . ':label';
+        $tokensMetadata[$tokenName . ':label'] = $field;
+        $tokensMetadata[$tokenName . ':label']['name'] = $field['name'] . ':label';
         $field['audience'] = 'sysadmin';
       }
-      $this->tokensMetadata[$tokenName] = $field;
+      $tokensMetadata[$tokenName] = $field;
     }
   }