Switch contribution action schedule tokens to use advertised tokens for cancel_date...
authorEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 2 Aug 2021 21:09:54 +0000 (09:09 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Tue, 3 Aug 2021 04:59:02 +0000 (16:59 +1200)
Scheduled reminders was working with the incorrect and not advertised variants - this
switches over and upgrades ( a bit precautionary since the removed ones were not
in the widget)

CRM/Contribute/Tokens.php
CRM/Upgrade/Incremental/php/FiveFortyOne.php
tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php

index 52511402d42cc71d32f4f81f376706c459bce9b4..3fe10f3ede2ff96dce671184f38316cb4f09d507 100644 (file)
@@ -28,7 +28,7 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
   /**
    * @return string
    */
-  private function getEntityName(): string {
+  protected function getEntityName(): string {
     return 'contribution';
   }
 
@@ -44,7 +44,7 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
    *
    * @var array
    */
-  protected $entityFieldMetadata = [];
+  protected $fieldMetadata = [];
 
   /**
    * Get a list of tokens whose name and title match the DB fields.
@@ -53,6 +53,8 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
   protected function getPassthruTokens(): array {
     return [
       'contribution_page_id',
+      'source',
+      'id',
       'receive_date',
       'total_amount',
       'fee_amount',
@@ -60,7 +62,7 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
       'trxn_id',
       'invoice_id',
       'currency',
-      'contribution_cancel_date',
+      'cancel_date',
       'receipt_date',
       'thankyou_date',
       'tax_amount',
@@ -75,11 +77,8 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
    */
   protected function getAliasTokens(): array {
     return [
-      'id' => 'contribution_id',
       'payment_instrument' => 'payment_instrument_id',
-      'source' => 'contribution_source',
       'type' => 'financial_type_id',
-      'cancel_date' => 'contribution_cancel_date',
     ];
   }
 
@@ -108,9 +107,9 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
   public function getPseudoTokens(): array {
     $return = [];
     foreach (array_keys($this->getBasicTokens()) as $fieldName) {
-      if (!empty($this->entityFieldMetadata[$fieldName]['pseudoconstant'])) {
-        $return[$fieldName . ':label'] = $this->entityFieldMetadata[$fieldName]['html']['label'];
-        $return[$fieldName . ':name'] = ts('Machine name') . ': ' . $this->entityFieldMetadata[$fieldName]['html']['label'];
+      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;
@@ -120,9 +119,8 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
    * Class constructor.
    */
   public function __construct() {
-    $this->entityFieldMetadata = CRM_Contribute_DAO_Contribution::fields();
     $tokens = CRM_Utils_Array::subset(
-      CRM_Utils_Array::collect('title', $this->entityFieldMetadata),
+      CRM_Utils_Array::collect('title', $this->getFieldMetadata()),
       $this->getPassthruTokens()
     );
     $tokens['id'] = ts('Contribution ID');
@@ -155,7 +153,7 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
       return;
     }
 
-    $fields = CRM_Contribute_DAO_Contribution::fields();
+    $fields = $this->getFieldMetadata();
     foreach ($this->getPassthruTokens() as $token) {
       $e->query->select("e." . $fields[$token]['name'] . " AS contrib_{$token}");
     }
@@ -193,11 +191,30 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
     elseif (in_array($field, array_keys($this->getBasicTokens()))) {
       $row->tokens($entity, $field, $fieldValue);
     }
+    elseif (!array_key_exists($field, CRM_Contribute_BAO_Contribution::fields())) {
+      if ($this->isDateField($field)) {
+        $row->format('text/plain')->tokens($entity, $field, \CRM_Utils_Date::customFormat($fieldValue));
+      }
+      else {
+        $row->format('text/plain')->tokens($entity, $field, $fieldValue);
+      }
+    }
     else {
       $row->dbToken($entity, $field, 'CRM_Contribute_BAO_Contribution', $field, $fieldValue);
     }
   }
 
+  /**
+   * Is the given field a date field.
+   *
+   * @param string $fieldName
+   *
+   * @return bool
+   */
+  public function isDateField($fieldName): bool {
+    return $this->getFieldMetadata()[$fieldName]['type'] === (\CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME);
+  }
+
   /**
    * Get the value for the relevant pseudo field.
    *
@@ -220,4 +237,23 @@ class CRM_Contribute_Tokens extends AbstractTokenSubscriber {
     return (string) $fieldValue;
   }
 
+  /**
+   * Get the metadata for the available fields.
+   *
+   * @return array
+   */
+  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;
+      }
+    }
+    return $this->fieldMetadata;
+  }
+
 }
index aaa958a127934ebb3b2ec85ecf74667003201fa3..700735a4305b2118c07d95b5247b7938445ba757 100644 (file)
@@ -74,6 +74,12 @@ class CRM_Upgrade_Incremental_php_FiveFortyOne extends CRM_Upgrade_Incremental_B
     $this->addTask('Replace contribution status token in action schedule',
       'updateActionScheduleToken', 'contribution.status', 'contribution.contribution_status_id:label', $rev
     );
+    $this->addTask('Replace contribution cancel_date token in action schedule',
+      'updateActionScheduleToken', 'contribution.contribution_cancel_date', 'contribution.cancel_date', $rev
+    );
+    $this->addTask('Replace contribution source token in action schedule',
+      'updateActionScheduleToken', 'contribution.contribution_source', 'contribution.source', $rev
+    );
   }
 
   /**
index 896bc6e490cca56f9c31f479642fb13838631ee7..a512abec1b75634af74af9dc68f1a174ae30f455 100644 (file)
@@ -150,7 +150,7 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
   /**
    * Create a contribution record for Alice with type "Member Dues".
    */
-  public function addAliceDues() {
+  public function addAliceDues(): void {
     $this->ids['Contribution']['alice'] = $this->callAPISuccess('Contribution', 'create', [
       'contact_id' => $this->contacts['alice']['id'],
       'receive_date' => date('Ymd', strtotime($this->targetDate)),
@@ -160,6 +160,8 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
       'fee_amount' => '5',
       'net_amount' => '95',
       'source' => 'SSF',
+      // Having a cancel date is a bit artificial here but we can test it....
+      'cancel_date' => '2021-08-09',
       'contribution_status_id' => 1,
       'soft_credit' => [
         '1' => [
@@ -266,7 +268,8 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
       new style label = {contribution.contribution_status_id:label}
       id {contribution.id}
       contribution_id {contribution.contribution_id} - not valid for action schedule
-    ';
+      cancel date {contribution.cancel_date}
+      source {contribution.source}';
     $this->schedule->save();
     $this->callAPISuccess('job', 'send_reminder', []);
     $expected = [
@@ -277,6 +280,8 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
       'new style label = Completed Label**',
       'id ' . $this->ids['Contribution']['alice'],
       'id  - not valid for action schedule',
+      'cancel date August 9th, 2021 12:00 AM',
+      'source SSF',
     ];
     $this->mut->checkMailLog($expected);