Refactor ActivityTokens to use a trait that can be shared with other entities
authorMatthew Wire <mjw@mjwconsult.co.uk>
Sun, 2 Feb 2020 16:30:39 +0000 (16:30 +0000)
committerMatthew Wire <mjw@mjwconsult.co.uk>
Tue, 4 Feb 2020 22:32:50 +0000 (22:32 +0000)
CRM/Activity/Tokens.php
CRM/Core/TokenTrait.php [new file with mode: 0644]

index 825c120c9890e085260a3c64825b1dc33df1747e..fff8e6224a507fe684cf1465cbf0881d7365ca91 100644 (file)
  */
 class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
 
-  private $basicTokens;
-  private $customFieldTokens;
+  use CRM_Core_TokenTrait;
 
   /**
-   * Mapping from tokenName to api return field
-   * Use lists since we might need multiple fields
-   *
-   * @var array
+   * @return string
    */
-  private static $fieldMapping = [
-    'activity_id' => ['id'],
-    'activity_type' => ['activity_type_id'],
-    'status' => ['status_id'],
-    'campaign' => ['campaign_id'],
-  ];
+  private function getEntityName(): string {
+    return 'activity';
+  }
 
   /**
-   * CRM_Activity_Tokens constructor.
+   * @return string
    */
-  public function __construct() {
-    parent::__construct('activity', array_merge(
-      $this->getBasicTokens(),
-      $this->getCustomFieldTokens()
-    ));
+  private function getEntityTableName(): string {
+    return 'civicrm_activity';
   }
 
   /**
-   * @inheritDoc
+   * @return string
    */
-  public function checkActive(\Civi\Token\TokenProcessor $processor) {
-    return in_array('activityId', $processor->context['schema']) ||
-      (!empty($processor->context['actionMapping'])
-      && $processor->context['actionMapping']->getEntity() === 'civicrm_activity');
+  private function getEntityContextSchema(): string {
+    return 'activityId';
   }
 
   /**
-   * @inheritDoc
+   * Mapping from tokenName to api return field
+   * Use lists since we might need multiple fields
+   *
+   * @var array
    */
-  public function getActiveTokens(\Civi\Token\Event\TokenValueEvent $e) {
-    $messageTokens = $e->getTokenProcessor()->getMessageTokens();
-    if (!isset($messageTokens[$this->entity])) {
-      return NULL;
-    }
-
-    $activeTokens = [];
-    // if message token contains '_\d+_', then treat as '_N_'
-    foreach ($messageTokens[$this->entity] as $msgToken) {
-      if (array_key_exists($msgToken, $this->tokenNames)) {
-        $activeTokens[] = $msgToken;
-      }
-      else {
-        $altToken = preg_replace('/_\d+_/', '_N_', $msgToken);
-        if (array_key_exists($altToken, $this->tokenNames)) {
-          $activeTokens[] = $msgToken;
-        }
-      }
-    }
-    return array_unique($activeTokens);
-  }
+  private static $fieldMapping = [
+    'activity_id' => ['id'],
+    'activity_type' => ['activity_type_id'],
+    'status' => ['status_id'],
+    'campaign' => ['campaign_id'],
+  ];
 
   /**
    * @inheritDoc
    */
   public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent $e) {
-    if ($e->mapping->getEntity() !== 'civicrm_activity') {
+    if ($e->mapping->getEntity() !== $this->getEntityTableName()) {
       return;
     }
 
@@ -105,44 +81,22 @@ class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
     $e->query->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
   }
 
-  /**
-   * Find the fields that we need to get to construct the tokens requested.
-   * @param  array $tokens list of tokens
-   * @return array         list of fields needed to generate those tokens
-   */
-  public function getReturnFields($tokens) {
-    // Make sure we always return something
-    $fields = ['id'];
-
-    foreach (array_intersect($tokens,
-      array_merge(array_keys(self::getBasicTokens()), array_keys(self::getCustomFieldTokens()))
-      ) as $token) {
-      if (isset(self::$fieldMapping[$token])) {
-        $fields = array_merge($fields, self::$fieldMapping[$token]);
-      }
-      else {
-        $fields[] = $token;
-      }
-    }
-    return array_unique($fields);
-  }
-
   /**
    * @inheritDoc
    */
   public function prefetch(\Civi\Token\Event\TokenValueEvent $e) {
-    // Find all the activity IDs
-    $activityIds
+    // Find all the entity IDs
+    $entityIds
       = $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
-      + $e->getTokenProcessor()->getContextValues('activityId');
+      + $e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());
 
-    if (!$activityIds) {
-      return;
+    if (!$entityIds) {
+      return NULL;
     }
 
     // Get data on all activities for basic and customfield tokens
     $activities = civicrm_api3('Activity', 'get', [
-      'id' => ['IN' => $activityIds],
+      'id' => ['IN' => $entityIds],
       'options' => ['limit' => 0],
       'return' => self::getReturnFields($this->activeTokens),
     ]);
@@ -176,9 +130,7 @@ class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
     ];
 
     // Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
-    $activityId = isset($row->context['actionSearchResult']->entityID)
-      ? $row->context['actionSearchResult']->entityID
-      : $row->context['activityId'];
+    $activityId = $row->context['actionSearchResult']->entityID ?? $row->context[$this->getEntityContextSchema()];
 
     $activity = (object) $prefetch['activity'][$activityId];
 
@@ -243,15 +195,4 @@ class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
     return $this->basicTokens;
   }
 
-  /**
-   * Get the tokens for custom fields
-   * @return array token name => token label
-   */
-  protected function getCustomFieldTokens() {
-    if (!isset($this->customFieldTokens)) {
-      $this->customFieldTokens = \CRM_Utils_Token::getCustomFieldTokens('Activity');
-    }
-    return $this->customFieldTokens;
-  }
-
 }
diff --git a/CRM/Core/TokenTrait.php b/CRM/Core/TokenTrait.php
new file mode 100644 (file)
index 0000000..2611015
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+
+trait CRM_Core_TokenTrait {
+
+  private $basicTokens;
+  private $customFieldTokens;
+
+  /**
+   * CRM_Entity_Tokens constructor.
+   */
+  public function __construct() {
+    parent::__construct($this->getEntityName(), array_merge(
+      $this->getBasicTokens(),
+      $this->getCustomFieldTokens()
+    ));
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public function checkActive(\Civi\Token\TokenProcessor $processor) {
+    return in_array($this->getEntityContextSchema(), $processor->context['schema']) ||
+      (!empty($processor->context['actionMapping'])
+        && $processor->context['actionMapping']->getEntity() === $this->getEntityTableName());
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public function getActiveTokens(\Civi\Token\Event\TokenValueEvent $e) {
+    $messageTokens = $e->getTokenProcessor()->getMessageTokens();
+    if (!isset($messageTokens[$this->entity])) {
+      return NULL;
+    }
+
+    $activeTokens = [];
+    // if message token contains '_\d+_', then treat as '_N_'
+    foreach ($messageTokens[$this->entity] as $msgToken) {
+      if (array_key_exists($msgToken, $this->tokenNames)) {
+        $activeTokens[] = $msgToken;
+      }
+      else {
+        $altToken = preg_replace('/_\d+_/', '_N_', $msgToken);
+        if (array_key_exists($altToken, $this->tokenNames)) {
+          $activeTokens[] = $msgToken;
+        }
+      }
+    }
+    return array_unique($activeTokens);
+  }
+
+  /**
+   * Find the fields that we need to get to construct the tokens requested.
+   * @param  array $tokens list of tokens
+   * @return array         list of fields needed to generate those tokens
+   */
+  public function getReturnFields($tokens) {
+    // Make sure we always return something
+    $fields = ['id'];
+
+    foreach (array_intersect($tokens,
+      array_merge(array_keys(self::getBasicTokens()), array_keys(self::getCustomFieldTokens()))
+             ) as $token) {
+      if (isset(self::$fieldMapping[$token])) {
+        $fields = array_merge($fields, self::$fieldMapping[$token]);
+      }
+      else {
+        $fields[] = $token;
+      }
+    }
+    return array_unique($fields);
+  }
+
+  /**
+   * Get the tokens for custom fields
+   * @return array token name => token label
+   */
+  protected function getCustomFieldTokens() {
+    if (!isset($this->customFieldTokens)) {
+      $this->customFieldTokens = \CRM_Utils_Token::getCustomFieldTokens(ucfirst($this->getEntityName()));
+    }
+    return $this->customFieldTokens;
+  }
+
+}