ActionMapping - Improve class structure
authorcolemanw <coleman@civicrm.org>
Tue, 18 Jul 2023 00:27:51 +0000 (20:27 -0400)
committercolemanw <coleman@civicrm.org>
Tue, 18 Jul 2023 00:39:29 +0000 (20:39 -0400)
Completes the refactoring that began with https://github.com/civicrm/civicrm-core/pull/6687
Fully migrates from the old model based on the civicrm_action_mapping table
(dropped in https://github.com/civicrm/civicrm-core/pull/26646)
by removing all references to that structure and fully embracing the object-model.
New common base-class added to make it eaiser to implement MappingInterface.

15 files changed:
CRM/Activity/ActionMapping.php
CRM/Contact/ActionMapping.php
CRM/Contribute/ActionMapping.php [new file with mode: 0644]
CRM/Contribute/ActionMapping/ByPage.php
CRM/Contribute/ActionMapping/ByType.php
CRM/Event/ActionMapping.php
CRM/Event/ActionMapping/ByEvent.php [new file with mode: 0644]
CRM/Event/ActionMapping/ByTemplate.php [new file with mode: 0644]
CRM/Event/ActionMapping/ByType.php [new file with mode: 0644]
CRM/Member/ActionMapping.php
Civi/ActionSchedule/Mapping.php [deleted file]
Civi/ActionSchedule/MappingBase.php [new file with mode: 0644]
Civi/ActionSchedule/MappingInterface.php
Civi/Core/Container.php
tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php

index 5618a2eb1534a3ead1819420951b930b6fd00fd3..91f46b5bb530970dcdfca6d2c47d9e8fe2307e17 100644 (file)
 
 
 /**
- * Class CRM_Activity_ActionMapping
- *
  * This defines the scheduled-reminder functionality for Activities.
  * It is useful for, e.g., sending a reminder based on scheduled
  * date or other custom dates on the activity record.
  */
-class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\Mapping {
+class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\MappingBase {
 
   /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Activity" mapping.
-   *
-   * Note: This value is chosen to match legacy DB IDs.
+   * Note: This value is an integer for legacy reasons; but going forward any new
+   * action mapping classes should return a string from `getId` instead of using a constant.
    */
   const ACTIVITY_MAPPING_ID = 1;
 
-  /**
-   * Register Activity-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(CRM_Activity_ActionMapping::create([
-      'id' => CRM_Activity_ActionMapping::ACTIVITY_MAPPING_ID,
-      'entity' => 'civicrm_activity',
-      'entity_label' => ts('Activity'),
-      'entity_value' => 'activity_type',
-      'entity_value_label' => ts('Activity Type'),
-      'entity_status' => 'activity_status',
-      'entity_status_label' => ts('Activity Status'),
-      'entity_date_start' => 'activity_date_time',
-    ]));
+  public function getId() {
+    return self::ACTIVITY_MAPPING_ID;
+  }
+
+  public function getEntityName(): string {
+    return 'Activity';
+  }
+
+  public function getValueHeader(): string {
+    return ts('Activity Type');
+  }
+
+  public function getValueLabels(): array {
+    // CRM-20510: Include CiviCampaign activity types along with CiviCase IF component is enabled
+    $activityTypes = \CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE);
+    asort($activityTypes);
+    return $activityTypes;
+  }
+
+  public function getStatusHeader(): string {
+    return ts('Activity Status');
+  }
+
+  public function getStatusLabels($value): array {
+    return CRM_Core_PseudoConstant::activityStatus();
+  }
+
+  public function getDateFields(): array {
+    return [
+      'activity_date_time' => ts('Activity Date'),
+    ];
   }
 
   /**
@@ -60,7 +71,7 @@ class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\Mapping {
    *   array(string $value => string $label).
    *   Ex: array('assignee' => 'Activity Assignee').
    */
-  public function getRecipientTypes() {
+  public function getRecipientTypes(): array {
     return \CRM_Core_OptionGroup::values('activity_contacts');
   }
 
@@ -78,11 +89,11 @@ class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @return \CRM_Utils_SQL_Select
    * @see RecipientBuilder
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
-    $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
+    $query = \CRM_Utils_SQL_Select::from("{$this->getEntityTable()} e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_activity e';
     $query['casContactIdField'] = 'r.contact_id';
     $query['casEntityIdField'] = 'e.id';
@@ -117,12 +128,4 @@ class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\Mapping {
     return $query;
   }
 
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  public function sendToAdditional($entityId): bool {
-    return TRUE;
-  }
-
 }
index ea96b5da7863645e387c72106fbb3b7d4fa47fe4..281da12a2f918e3d727f6f9497113d0ace62eaa4 100644 (file)
 
 
 /**
- * Class CRM_Contact_ActionMapping
- *
  * This defines the scheduled-reminder functionality for contact
  * entities. It is useful for, e.g., sending a reminder based on
  * birth date, modification date, or other custom dates on
  * the contact record.
  */
-class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\Mapping {
+class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\MappingBase {
 
   /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Contact" mapping.
-   *
-   * Note: This value is chosen to match legacy DB IDs.
+   * Note: This value is an integer for legacy reasons; but going forward any new
+   * action mapping classes should return a string from `getId` instead of using a constant.
    */
   const CONTACT_MAPPING_ID = 6;
 
-  /**
-   * Register Contact-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(CRM_Contact_ActionMapping::create([
-      'id' => CRM_Contact_ActionMapping::CONTACT_MAPPING_ID,
-      'entity' => 'civicrm_contact',
-      'entity_label' => ts('Contact'),
-      'entity_value' => 'civicrm_contact',
-      'entity_value_label' => ts('Date Field'),
-      'entity_status' => 'contact_date_reminder_options',
-      'entity_status_label' => ts('Annual Options'),
-      'entity_date_start' => 'date_field',
-    ]));
+  public function getId() {
+    return self::CONTACT_MAPPING_ID;
+  }
+
+  public function getEntityName(): string {
+    return 'Contact';
+  }
+
+  public function getValueHeader(): string {
+    return ts('Date Field');
+  }
+
+  public function getValueLabels(): array {
+    $allCustomFields = \CRM_Core_BAO_CustomField::getFields('');
+    $dateFields = [
+      'birth_date' => ts('Birth Date'),
+      'created_date' => ts('Created Date'),
+      'modified_date' => ts('Modified Date'),
+    ];
+    foreach ($allCustomFields as $fieldID => $field) {
+      if ($field['data_type'] == 'Date') {
+        $dateFields["custom_$fieldID"] = $field['label'];
+      }
+    }
+    return $dateFields;
+  }
+
+  public function getStatusHeader(): string {
+    return ts('Annual Options');
+  }
+
+  public function getStatusLabels($value): array {
+    return CRM_Core_OptionGroup::values('contact_date_reminder_options');
+  }
+
+  public function getDateFields(): array {
+    return [
+      'date_field' => ts('Date Field'),
+    ];
   }
 
   private $contactDateFields = [
@@ -61,7 +80,7 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\Mapping {
    *   Array (string $code => string $message).
    *   List of error messages.
    */
-  public function validateSchedule($schedule) {
+  public function validateSchedule($schedule): array {
     $errors = [];
     if (CRM_Utils_System::isNull($schedule->entity_value) || $schedule->entity_value === '0') {
       $errors['entity'] = ts('Please select a specific date field.');
@@ -90,7 +109,7 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @throws \CRM_Core_Exception
    * @see RecipientBuilder
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
@@ -101,7 +120,7 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\Mapping {
     }
     elseif (in_array($selectedValues[0], $this->contactDateFields)) {
       $dateDBField = $selectedValues[0];
-      $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
+      $query = \CRM_Utils_SQL_Select::from("{$this->getEntityTable()} e")->param($defaultParams);
       $query->param([
         'casAddlCheckFrom' => 'civicrm_contact e',
         'casContactIdField' => 'e.id',
@@ -139,12 +158,4 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\Mapping {
     return $query;
   }
 
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  public function sendToAdditional($entityId): bool {
-    return TRUE;
-  }
-
 }
diff --git a/CRM/Contribute/ActionMapping.php b/CRM/Contribute/ActionMapping.php
new file mode 100644 (file)
index 0000000..ed5aaaa
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+
+/**
+ * This defines the scheduled-reminder functionality for contribution
+ * entities. It is useful for sending a reminder based on:
+ *  - The receipt-date, cancel-date, or thankyou-date.
+ *  - The type of contribution.
+ * @service
+ * @internal
+ */
+abstract class CRM_Contribute_ActionMapping extends \Civi\ActionSchedule\MappingBase {
+
+  public function getEntityName(): string {
+    return 'Contribution';
+  }
+
+  public function getStatusHeader(): string {
+    return ts('Contribution Status');
+  }
+
+  /**
+   * Get a list of status options.
+   *
+   * @param string|int $value
+   * @return array
+   * @throws CRM_Core_Exception
+   */
+  public function getStatusLabels($value): array {
+    return CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'get', []);
+  }
+
+  public function getDateFields(): array {
+    return [
+      'receive_date' => ts('Receive Date'),
+      'cancel_date' => ts('Cancel Date'),
+      'receipt_date' => ts('Receipt Date'),
+      'thankyou_date' => ts('Thank You Date'),
+    ];
+  }
+
+}
index b975b8098dd58e6eedd342cee4e263586f2bf1c3..f332d6f1e90a329acd5c2d7b26b6119ff9ffb482 100644 (file)
  *  - The receipt-date, cancel-date, or thankyou-date.
  *  - The page on which the contribution was made.
  */
-class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\MappingInterface {
-
-  /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Contribution Page" mapping.
-   */
-  const MAPPING_ID = 'contribpage';
-
-  /**
-   * Register Activity-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(new static());
-  }
-
-  /**
-   * @return mixed
-   */
-  public function getId() {
-    return self::MAPPING_ID;
-  }
+class CRM_Contribute_ActionMapping_ByPage extends CRM_Contribute_ActionMapping {
 
   /**
    * @return string
    */
-  public function getEntityTable(): string {
-    return 'civicrm_contribution';
-  }
-
-  public function getEntityName(): string {
-    return 'Contribution';
+  public function getId() {
+    return 'contribpage';
   }
 
   /**
@@ -58,7 +32,7 @@ class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\Mappin
    *
    * @return string
    */
-  public function getLabel() {
+  public function getLabel(): string {
     return ts('Contribution Page');
   }
 
@@ -67,19 +41,10 @@ class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\Mappin
    *
    * @return string
    */
-  public function getValueHeader() {
+  public function getValueHeader(): string {
     return ts('Contribution Page');
   }
 
-  /**
-   * Get a printable label to use as the header on the 'status' filter.
-   *
-   * @return string
-   */
-  public function getStatusHeader() {
-    return ts('Contribution Status');
-  }
-
   /**
    * Get a list of value options.
    *
@@ -88,84 +53,10 @@ class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\Mappin
    *   Ex: array(123 => 'Phone Call', 456 => 'Meeting').
    * @throws CRM_Core_Exception
    */
-  public function getValueLabels() {
+  public function getValueLabels(): array {
     return CRM_Contribute_BAO_Contribution::buildOptions('contribution_page_id', 'get', []);
   }
 
-  /**
-   * Get a list of status options.
-   *
-   * @param string|int $value
-   *   The list of status options may be contingent upon the selected filter value.
-   *   This is the selected filter value.
-   * @return array
-   *   Array(string $value => string $label).
-   *   Ex: Array(123 => 'Completed', 456 => 'Scheduled').
-   * @throws CRM_Core_Exception
-   */
-  public function getStatusLabels($value) {
-    return CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'get', []);
-  }
-
-  /**
-   * Get a list of available date fields.
-   *
-   * @return array
-   *   Array(string $fieldName => string $fieldLabel).
-   */
-  public function getDateFields() {
-    return [
-      'receive_date' => ts('Receive Date'),
-      'cancel_date' => ts('Cancel Date'),
-      'receipt_date' => ts('Receipt Date'),
-      'thankyou_date' => ts('Thank You Date'),
-    ];
-  }
-
-  /**
-   * Get a list of recipient types.
-   *
-   * Note: A single schedule may filter on *zero* or *one* recipient types.
-   * When an admin chooses a value, it's stored in $schedule->recipient.
-   *
-   * @return array
-   *   array(string $value => string $label).
-   *   Ex: array('assignee' => 'Activity Assignee').
-   */
-  public function getRecipientTypes() {
-    return [];
-  }
-
-  /**
-   * Get a list of recipients which match the given type.
-   *
-   * Note: A single schedule may filter on *multiple* recipients.
-   * When an admin chooses value(s), it's stored in $schedule->recipient_listing.
-   *
-   * @param string $recipientType
-   *   Ex: 'participant_role'.
-   * @return array
-   *   Array(mixed $name => string $label).
-   *   Ex: array(1 => 'Attendee', 2 => 'Volunteer').
-   * @see getRecipientTypes
-   */
-  public function getRecipientListing($recipientType) {
-    return [];
-  }
-
-  /**
-   * Determine whether a schedule based on this mapping is sufficiently
-   * complete.
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   * @return array
-   *   Array (string $code => string $message).
-   *   List of error messages.
-   */
-  public function validateSchedule($schedule) {
-    return [];
-  }
-
   /**
    * Generate a query to locate contacts who match the given
    * schedule.
@@ -179,7 +70,7 @@ class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\Mappin
    * @see RecipientBuilder
    * @throws CRM_Core_Exception
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
@@ -208,24 +99,4 @@ class CRM_Contribute_ActionMapping_ByPage implements \Civi\ActionSchedule\Mappin
     return $query;
   }
 
-  /**
-   * Determine whether a schedule based on this mapping should
-   * reset the reminder state if the trigger date changes.
-   *
-   * @return bool
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   */
-  public function resetOnTriggerDateChange($schedule) {
-    return FALSE;
-  }
-
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  public function sendToAdditional($entityId): bool {
-    return TRUE;
-  }
-
 }
index 688f8c753a67d3175b291828fcf1800ad1e62248..27f0c4818462a6a221962d88400d0ef77c7cef96 100644 (file)
  *  - The receipt-date, cancel-date, or thankyou-date.
  *  - The type of contribution.
  */
-class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\MappingInterface {
-
-  /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Contribution Page" mapping.
-   */
-  const MAPPING_ID = 'contribtype';
-
-  /**
-   * Register Activity-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(new static());
-  }
-
-  /**
-   * @return mixed
-   */
-  public function getId() {
-    return self::MAPPING_ID;
-  }
-
-  /**
-   * @return string
-   */
-  public function getEntityTable(): string {
-    return 'civicrm_contribution';
-  }
+class CRM_Contribute_ActionMapping_ByType extends CRM_Contribute_ActionMapping {
 
   /**
    * @return string
    */
-  public function getEntityName(): string {
-    return 'Contribution';
+  public function getId() {
+    return 'contribtype';
   }
 
   /**
@@ -61,7 +32,7 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    *
    * @return string
    */
-  public function getLabel() {
+  public function getLabel(): string {
     return ts('Contribution Type');
   }
 
@@ -70,19 +41,10 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    *
    * @return string
    */
-  public function getValueHeader() {
+  public function getValueHeader(): string {
     return ts('Financial Type');
   }
 
-  /**
-   * Get a printable label to use as the header on the 'status' filter.
-   *
-   * @return string
-   */
-  public function getStatusHeader() {
-    return ts('Contribution Status');
-  }
-
   /**
    * Get a list of value options.
    *
@@ -91,40 +53,10 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    *   Ex: array(123 => 'Phone Call', 456 => 'Meeting').
    * @throws CRM_Core_Exception
    */
-  public function getValueLabels() {
+  public function getValueLabels(): array {
     return CRM_Contribute_BAO_Contribution::buildOptions('financial_type_id', 'get', []);
   }
 
-  /**
-   * Get a list of status options.
-   *
-   * @param string|int $value
-   *   The list of status options may be contingent upon the selected filter value.
-   *   This is the selected filter value.
-   * @return array
-   *   Array(string $value => string $label).
-   *   Ex: Array(123 => 'Completed', 456 => 'Scheduled').
-   * @throws CRM_Core_Exception
-   */
-  public function getStatusLabels($value) {
-    return CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'get', []);
-  }
-
-  /**
-   * Get a list of available date fields.
-   *
-   * @return array
-   *   Array(string $fieldName => string $fieldLabel).
-   */
-  public function getDateFields() {
-    return [
-      'receive_date' => ts('Receive Date'),
-      'cancel_date' => ts('Cancel Date'),
-      'receipt_date' => ts('Receipt Date'),
-      'thankyou_date' => ts('Thank You Date'),
-    ];
-  }
-
   /**
    * Get a list of recipient types.
    *
@@ -135,7 +67,7 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    *   array(string $value => string $label).
    *   Ex: array('assignee' => 'Activity Assignee').
    */
-  public function getRecipientTypes() {
+  public function getRecipientTypes(): array {
     return [
       'soft_credit_type' => ts('Soft Credit Role'),
     ];
@@ -154,7 +86,7 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    *   Ex: array(1 => 'Attendee', 2 => 'Volunteer').
    * @see getRecipientTypes
    */
-  public function getRecipientListing($recipientType) {
+  public function getRecipientListing($recipientType): array {
     switch ($recipientType) {
       case 'soft_credit_type':
         return \CRM_Core_OptionGroup::values('soft_credit_type', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name');
@@ -164,19 +96,6 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
     }
   }
 
-  /**
-   * Determine whether a schedule based on this mapping is sufficiently
-   * complete.
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   * @return array
-   *   Array (string $code => string $message).
-   *   List of error messages.
-   */
-  public function validateSchedule($schedule) {
-    return [];
-  }
-
   /**
    * Generate a query to locate contacts who match the given
    * schedule.
@@ -190,7 +109,7 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
    * @see RecipientBuilder
    * @throws CRM_Core_Exception
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
@@ -230,24 +149,4 @@ class CRM_Contribute_ActionMapping_ByType implements \Civi\ActionSchedule\Mappin
     return $query;
   }
 
-  /**
-   * Determine whether a schedule based on this mapping should
-   * reset the reminder state if the trigger date changes.
-   *
-   * @return bool
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   */
-  public function resetOnTriggerDateChange($schedule) {
-    return FALSE;
-  }
-
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  public function sendToAdditional($entityId): bool {
-    return TRUE;
-  }
-
 }
index c474a8dba6aaf87b5afd7ffaf7a5533fd66bdebd..1aa9057f69cd575b78a0b0ae06048b1f271534bb 100644 (file)
 use Civi\ActionSchedule\RecipientBuilder;
 
 /**
- * Class CRM_Event_ActionMapping
- *
- * This defines the scheduled-reminder functionality for CiviEvent
- * participants. It allows one to target messages on the
- * event's start-date/end-date, with additional filtering by
- * event-type, event-template, or event-id.
+ * Shared scheduled-reminder functionality for CiviEvent participants.
  */
-class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
+abstract class CRM_Event_ActionMapping extends \Civi\ActionSchedule\MappingBase {
 
   /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Event Type" mapping.
-   *
-   * Note: This value is chosen to match legacy DB IDs.
+   * Note: These values are integers for legacy reasons; but going forward any new
+   * action mapping classes should return a string from `getId` instead of using a constant.
    */
   const EVENT_TYPE_MAPPING_ID = 2;
   const EVENT_NAME_MAPPING_ID = 3;
   const EVENT_TPL_MAPPING_ID = 5;
 
-  /**
-   * Register CiviEvent-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(CRM_Event_ActionMapping::create([
-      'id' => CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID,
-      'entity' => 'civicrm_participant',
-      'entity_label' => ts('Event Type'),
-      'entity_value' => 'event_type',
-      'entity_value_label' => ts('Event Type'),
-      'entity_status' => 'civicrm_participant_status_type',
-      'entity_status_label' => ts('Participant Status'),
-    ]));
-    $registrations->register(CRM_Event_ActionMapping::create([
-      'id' => CRM_Event_ActionMapping::EVENT_NAME_MAPPING_ID,
-      'entity' => 'civicrm_participant',
-      'entity_label' => ts('Event Name'),
-      'entity_value' => 'civicrm_event',
-      'entity_value_label' => ts('Event Name'),
-      'entity_status' => 'civicrm_participant_status_type',
-      'entity_status_label' => ts('Participant Status'),
-    ]));
-    $registrations->register(CRM_Event_ActionMapping::create([
-      'id' => CRM_Event_ActionMapping::EVENT_TPL_MAPPING_ID,
-      'entity' => 'civicrm_participant',
-      'entity_label' => ts('Event Template'),
-      'entity_value' => 'event_template',
-      'entity_value_label' => ts('Event Template'),
-      'entity_status' => 'civicrm_participant_status_type',
-      'entity_status_label' => ts('Participant Status'),
-    ]));
+  public function getEntityName(): string {
+    return 'Participant';
+  }
+
+  public function getStatusHeader(): string {
+    return ts('Participant Status');
+  }
+
+  public function getStatusLabels($value): array {
+    return CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label');
   }
 
   /**
@@ -72,7 +42,7 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @return array
    *   Array(string $fieldName => string $fieldLabel).
    */
-  public function getDateFields() {
+  public function getDateFields(): array {
     return [
       'start_date' => ts('Event Start'),
       'end_date' => ts('Event End'),
@@ -91,7 +61,7 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
    *   array(string $value => string $label).
    *   Ex: array('assignee' => 'Activity Assignee').
    */
-  public function getRecipientTypes() {
+  public function getRecipientTypes(): array {
     return \CRM_Core_OptionGroup::values('event_contacts', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name');
   }
 
@@ -108,7 +78,7 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
    *   Ex: array(1 => 'Attendee', 2 => 'Volunteer').
    * @see getRecipientTypes
    */
-  public function getRecipientListing($recipientType) {
+  public function getRecipientListing($recipientType): array {
     switch ($recipientType) {
       case 'participant_role':
         return \CRM_Event_PseudoConstant::participantRole();
@@ -131,11 +101,11 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @return \CRM_Utils_SQL_Select
    * @see RecipientBuilder
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
-    $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
+    $query = \CRM_Utils_SQL_Select::from("{$this->getEntityTable()} e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_event r';
     $query['casContactIdField'] = 'e.contact_id';
     $query['casEntityIdField'] = 'e.id';
@@ -162,12 +132,12 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
     // build where clause
     // FIXME: This handles scheduled reminder of type "Event Name" and "Event Type", gives incorrect result on "Event Template".
     if (!empty($selectedValues)) {
-      $valueField = ($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? 'event_type_id' : 'id';
+      $valueField = ($this->getId() == self::EVENT_TYPE_MAPPING_ID) ? 'event_type_id' : 'id';
       $query->where("r.{$valueField} IN (@selectedValues)")
         ->param('selectedValues', $selectedValues);
     }
     else {
-      $query->where(($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? "r.event_type_id IS NULL" : "r.id IS NULL");
+      $query->where(($this->getId() == self::EVENT_TYPE_MAPPING_ID) ? "r.event_type_id IS NULL" : "r.id IS NULL");
     }
 
     $query->where('r.is_active = 1');
@@ -197,7 +167,7 @@ class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping {
    */
   public function sendToAdditional($entityId): bool {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($entityId);
-    switch ($this->id) {
+    switch ($this->getId()) {
       case self::EVENT_TYPE_MAPPING_ID:
         $valueTable = 'e';
         $valueField = 'event_type_id';
diff --git a/CRM/Event/ActionMapping/ByEvent.php b/CRM/Event/ActionMapping/ByEvent.php
new file mode 100644 (file)
index 0000000..ddb8107
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * This defines the scheduled-reminder functionality for CiviEvent
+ * participants with filtering by event-type.
+ */
+class CRM_Event_ActionMapping_ByEvent extends CRM_Event_ActionMapping {
+
+  public function getId() {
+    return self::EVENT_NAME_MAPPING_ID;
+  }
+
+  public function getLabel(): string {
+    return ts('Event Name');
+  }
+
+  public function getValueLabels(): array {
+    return CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
+  }
+
+}
diff --git a/CRM/Event/ActionMapping/ByTemplate.php b/CRM/Event/ActionMapping/ByTemplate.php
new file mode 100644 (file)
index 0000000..7ee4744
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * This defines the scheduled-reminder functionality for CiviEvent
+ * participants with filtering by event-type.
+ */
+class CRM_Event_ActionMapping_ByTemplate extends CRM_Event_ActionMapping {
+
+  public function getId() {
+    return self::EVENT_TPL_MAPPING_ID;
+  }
+
+  public function getLabel(): string {
+    return ts('Event Template');
+  }
+
+  public function getValueLabels(): array {
+    return \Civi\Api4\Event::get(FALSE)
+      ->addWhere('is_template', '=', TRUE)
+      ->addWhere('is_active', '=', TRUE)
+      ->execute()
+      ->indexBy('id')
+      ->column('template_title');
+  }
+
+}
diff --git a/CRM/Event/ActionMapping/ByType.php b/CRM/Event/ActionMapping/ByType.php
new file mode 100644 (file)
index 0000000..fdba67d
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * This defines the scheduled-reminder functionality for CiviEvent
+ * participants with filtering by event-type.
+ */
+class CRM_Event_ActionMapping_ByType extends CRM_Event_ActionMapping {
+
+  public function getId() {
+    return self::EVENT_TYPE_MAPPING_ID;
+  }
+
+  public function getLabel(): string {
+    return ts('Event Type');
+  }
+
+  public function getValueLabels(): array {
+    return CRM_Event_PseudoConstant::eventType();
+  }
+
+}
index aa40f00bb7c2f3aaa94ac89f69d1ab6a5115e21b..e81824d490a97d9b5a1a43e1ad525b3e726c89b0 100644 (file)
 
 
 /**
- * Class CRM_Member_ActionMapping
- *
  * This defines the scheduled-reminder functionality for CiviMember
  * memberships. It allows one to target reminders based on join date
  * or end date, with additional filtering based on membership-type.
  */
-class CRM_Member_ActionMapping extends \Civi\ActionSchedule\Mapping {
+class CRM_Member_ActionMapping extends \Civi\ActionSchedule\MappingBase {
 
   /**
-   * The value for civicrm_action_schedule.mapping_id which identifies the
-   * "Membership Type" mapping.
-   *
-   * Note: This value is chosen to match legacy DB IDs.
+   * Note: This value is an integer for legacy reasons; but going forward any new
+   * action mapping classes should return a string from `getId` instead of using a constant.
    */
   const MEMBERSHIP_TYPE_MAPPING_ID = 4;
 
-  /**
-   * Register CiviMember-related action mappings.
-   *
-   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
-   */
-  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) {
-    $registrations->register(CRM_Member_ActionMapping::create([
-      'id' => CRM_Member_ActionMapping::MEMBERSHIP_TYPE_MAPPING_ID,
-      'entity' => 'civicrm_membership',
-      'entity_label' => ts('Membership'),
-      'entity_value' => 'civicrm_membership_type',
-      'entity_value_label' => ts('Membership Type'),
-      'entity_status' => 'auto_renew_options',
-      'entity_status_label' => ts('Auto Renew Options'),
-    ]));
+  public function getId() {
+    return self::MEMBERSHIP_TYPE_MAPPING_ID;
+  }
+
+  public function getEntityName(): string {
+    return 'Membership';
+  }
+
+  public function getValueHeader(): string {
+    return ts('Membership Type');
+  }
+
+  public function getValueLabels(): array {
+    return CRM_Member_PseudoConstant::membershipType();
+  }
+
+  public function getStatusHeader(): string {
+    return ts('Auto Renew Options');
+  }
+
+  public function getStatusLabels($value): array {
+    if ($value && \CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $value, 'auto_renew')) {
+      return \CRM_Core_OptionGroup::values('auto_renew_options');
+    }
+    else {
+      return [];
+    }
   }
 
   /**
@@ -50,7 +58,7 @@ class CRM_Member_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @return array
    *   Array(string $fieldName => string $fieldLabel).
    */
-  public function getDateFields() {
+  public function getDateFields(): array {
     return [
       'join_date' => ts('Member Since'),
       'start_date' => ts('Membership Start Date'),
@@ -71,11 +79,11 @@ class CRM_Member_ActionMapping extends \Civi\ActionSchedule\Mapping {
    * @return \CRM_Utils_SQL_Select
    * @see RecipientBuilder
    */
-  public function createQuery($schedule, $phase, $defaultParams) {
+  public function createQuery($schedule, $phase, $defaultParams): CRM_Utils_SQL_Select {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
 
-    $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
+    $query = \CRM_Utils_SQL_Select::from("{$this->getEntityTable()} e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_membership e';
     $query['casContactIdField'] = 'e.contact_id';
     $query['casEntityIdField'] = 'e.id';
@@ -159,7 +167,7 @@ class CRM_Member_ActionMapping extends \Civi\ActionSchedule\Mapping {
    *
    * @param \CRM_Core_DAO_ActionSchedule $schedule
    */
-  public function resetOnTriggerDateChange($schedule) {
+  public function resetOnTriggerDateChange($schedule): bool {
     if ($schedule->absolute_date !== NULL) {
       return FALSE;
     }
@@ -168,12 +176,4 @@ class CRM_Member_ActionMapping extends \Civi\ActionSchedule\Mapping {
     }
   }
 
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  public function sendToAdditional($entityId): bool {
-    return TRUE;
-  }
-
 }
diff --git a/Civi/ActionSchedule/Mapping.php b/Civi/ActionSchedule/Mapping.php
deleted file mode 100644 (file)
index aeea266..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-<?php
-/*
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC. All rights reserved.                        |
- |                                                                    |
- | This work is published under the GNU AGPLv3 license with some      |
- | permitted exceptions and without any warranty. For full license    |
- | and copyright information, see https://civicrm.org/licensing       |
- +--------------------------------------------------------------------+
- */
-
-namespace Civi\ActionSchedule;
-
-/**
- * Class Mapping
- * @package Civi\ActionSchedule
- *
- * This is the initial implementation of MappingInterface; it was
- * constructed by cutting out swaths from CRM_Core_BAO_ActionSchedule.
- * New implementers should consider implementing MappingInterface on
- * their own.
- *
- * Background: The original designers of ActionMappings intended that
- * one could create and configure new mappings through the database.
- * To, e.g., define the filtering options for CiviEvent, you
- * would insert a record in "civicrm_action_mapping" with fields like
- * "entity" (a table name, eg "civicrm_event"), "entity_value" (an
- * option-group name, eg "event_types").
- *
- * Unfortunately, the metadata in "civicrm_action_mapping" proved
- * inadequate and was not updated to cope. Instead, a number
- * of work-arounds for specific entities were hard-coded into
- * the core action-scheduling code. Ultimately, to add a new
- * mapping type, one needed to run around and patch a dozen
- * places.
- *
- * The new MappingInterface makes no pretense of database-driven
- * configuration. The dozen places have been consolidated and
- * replaced with functions in MappingInterface.
- * The unused `civicrm_action_mapping` table has been dropped.
- *
- * This "Mapping" implementation is a refactoring of the old
- * hard-coded bits. Internally, it uses the concepts from
- * "civicrm_action_mapping". The resulting code is more
- * convoluted than a clean implementation of MappingInterface, but
- * it strictly matches the old behavior (based on logging/comparing
- * the queries produced through ActionScheduleTest).
- */
-abstract class Mapping implements MappingInterface {
-
-  private static $fields = [
-    'id',
-    'entity',
-    'entity_label',
-    'entity_value',
-    'entity_value_label',
-    'entity_status',
-    'entity_status_label',
-    'entity_date_start',
-    'entity_date_end',
-  ];
-
-  /**
-   * Create mapping.
-   *
-   * @param array $params
-   *
-   * @return static
-   */
-  public static function create($params) {
-    return new static($params);
-  }
-
-  /**
-   * Class constructor.
-   *
-   * @param array $params
-   */
-  public function __construct($params) {
-    foreach (self::$fields as $field) {
-      if (isset($params[$field])) {
-        $this->{$field} = $params[$field];
-      }
-    }
-  }
-
-  protected $id;
-
-  /**
-   * The basic entity to query (table name).
-   *
-   * @var string
-   *   Ex: 'civicrm_activity', 'civicrm_event'.
-   */
-  protected $entity;
-
-  /**
-   * The basic entity to query (label).
-   *
-   * @var string
-   *   Ex: 'Activity', 'Event'
-   */
-  private $entity_label;
-
-  /**
-   * Level 1 filter -- the field/option-list to filter on.
-   *
-   * @var string
-   *   Ex: 'activity_type', 'civicrm_event', 'event_template'.
-   */
-  private $entity_value;
-
-  /**
-   * Level 1 filter -- The field label.
-   *
-   * @var string
-   *   Ex: 'Activity Type', 'Event Name', 'Event Template'.
-   */
-  private $entity_value_label;
-
-  /**
-   * Level 2 filter -- the field/option-list to filter on.
-   * @var string
-   *   Ex: 'activity_status, 'civicrm_participant_status_type', 'auto_renew_options'.
-   */
-  private $entity_status;
-
-  /**
-   * Level 2 filter -- the field label.
-   * @var string
-   *   Ex: 'Activity Status', 'Participant Status', 'Auto Rewnewal Options'.
-   */
-  private $entity_status_label;
-
-  /**
-   * Date filter -- the field name.
-   * @var string|null
-   *   Ex: 'event_start_date'
-   */
-  private $entity_date_start;
-
-  /**
-   * Date filter -- the field name.
-   * @var string|null
-   *   Ex: 'event_end_date'.
-   */
-  private $entity_date_end;
-
-  /**
-   * @return mixed
-   */
-  public function getId() {
-    return $this->id;
-  }
-
-  /**
-   * @return string
-   */
-  public function getEntityTable(): string {
-    return $this->entity;
-  }
-
-  public function getEntityName(): string {
-    return \CRM_Core_DAO_AllCoreTables::getEntityNameForTable($this->getEntityTable());
-  }
-
-  /**
-   * Get a printable label for this mapping type.
-   *
-   * @return string
-   */
-  public function getLabel() {
-    return $this->entity_label;
-  }
-
-  /**
-   * Get a printable label to use a header on the 'value' filter.
-   *
-   * @return string
-   */
-  public function getValueHeader() {
-    return $this->entity_value_label;
-  }
-
-  /**
-   * Get a printable label to use a header on the 'status' filter.
-   *
-   * @return string
-   */
-  public function getStatusHeader() {
-    return $this->entity_status_label;
-  }
-
-  /**
-   * Get a list of value options.
-   *
-   * @return array
-   *   Array(string $value => string $label).
-   *   Ex: array(123 => 'Phone Call', 456 => 'Meeting').
-   */
-  public function getValueLabels() {
-    return self::getValueLabelMap($this->entity_value);
-  }
-
-  /**
-   * Get a list of status options.
-   *
-   * @param string|int $value
-   *   The list of status options may be contingent upon the selected filter value.
-   *   This is the selected filter value.
-   * @return array
-   *   Array(string $value => string $label).
-   *   Ex: Array(123 => 'Completed', 456 => 'Scheduled').
-   */
-  public function getStatusLabels($value) {
-    if ($this->entity_status === 'auto_renew_options') {
-      if ($value && \CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $value, 'auto_renew')) {
-        return \CRM_Core_OptionGroup::values('auto_renew_options');
-      }
-      else {
-        return [];
-      }
-    }
-    return self::getValueLabelMap($this->entity_status);
-  }
-
-  /**
-   * Get a list of available date fields.
-   *
-   * @return array
-   *   Array(string $fieldName => string $fieldLabel).
-   */
-  public function getDateFields() {
-    $dateFieldLabels = [];
-    if (!empty($this->entity_date_start)) {
-      $dateFieldLabels[$this->entity_date_start] = ucwords(str_replace('_', ' ', $this->entity_date_start));
-    }
-    if (!empty($this->entity_date_end)) {
-      $dateFieldLabels[$this->entity_date_end] = ucwords(str_replace('_', ' ', $this->entity_date_end));
-    }
-    return $dateFieldLabels;
-  }
-
-  /**
-   * Get a list of recipient types.
-   *
-   * Note: A single schedule may filter on *zero* or *one* recipient types.
-   * When an admin chooses a value, it's stored in $schedule->recipient.
-   *
-   * @return array
-   *   array(string $value => string $label).
-   *   Ex: array('assignee' => 'Activity Assignee').
-   */
-  public function getRecipientTypes() {
-    return [];
-  }
-
-  /**
-   * Get a list of recipients which match the given type.
-   *
-   * Note: A single schedule may filter on *multiple* recipients.
-   * When an admin chooses value(s), it's stored in $schedule->recipient_listing.
-   *
-   * @param string $recipientType
-   *   Ex: 'participant_role'.
-   * @return array
-   *   Array(mixed $name => string $label).
-   *   Ex: array(1 => 'Attendee', 2 => 'Volunteer').
-   * @see getRecipientTypes
-   */
-  public function getRecipientListing($recipientType) {
-    return [];
-  }
-
-  protected static function getValueLabelMap($name) {
-    static $valueLabelMap = NULL;
-    if ($valueLabelMap === NULL) {
-      // CRM-20510: Include CiviCampaign activity types along with CiviCase IF component is enabled
-      $valueLabelMap['activity_type'] = \CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE);
-      asort($valueLabelMap['activity_type']);
-
-      $valueLabelMap['activity_status'] = \CRM_Core_PseudoConstant::activityStatus();
-      $valueLabelMap['event_type'] = \CRM_Event_PseudoConstant::eventType();
-      $valueLabelMap['civicrm_event'] = \CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
-      $valueLabelMap['civicrm_participant_status_type'] = \CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label');
-      $valueLabelMap['event_template'] = \Civi\Api4\Event::get(FALSE)
-        ->addWhere('is_template', '=', TRUE)
-        ->addWhere('is_active', '=', TRUE)
-        ->execute()
-        ->indexBy('id')
-        ->column('template_title');
-      $valueLabelMap['auto_renew_options'] = \CRM_Core_OptionGroup::values('auto_renew_options');
-      $valueLabelMap['contact_date_reminder_options'] = \CRM_Core_OptionGroup::values('contact_date_reminder_options');
-      $valueLabelMap['civicrm_membership_type'] = \CRM_Member_PseudoConstant::membershipType();
-
-      $allCustomFields = \CRM_Core_BAO_CustomField::getFields('');
-      $dateFields = [
-        'birth_date' => ts('Birth Date'),
-        'created_date' => ts('Created Date'),
-        'modified_date' => ts('Modified Date'),
-      ];
-      foreach ($allCustomFields as $fieldID => $field) {
-        if ($field['data_type'] == 'Date') {
-          $dateFields["custom_$fieldID"] = $field['label'];
-        }
-      }
-      $valueLabelMap['civicrm_contact'] = $dateFields;
-    }
-
-    return $valueLabelMap[$name];
-  }
-
-  /**
-   * Determine whether a schedule based on this mapping is sufficiently
-   * complete.
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   * @return array
-   *   Array (string $code => string $message).
-   *   List of error messages.
-   */
-  public function validateSchedule($schedule) {
-    return [];
-  }
-
-  /**
-   * Generate a query to locate contacts who match the given
-   * schedule.
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   * @param string $phase
-   *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
-   * @param array $defaultParams
-   * @return \CRM_Utils_SQL_Select
-   */
-  abstract public function createQuery($schedule, $phase, $defaultParams);
-
-  /**
-   * Determine whether a schedule based on this mapping should
-   * reset the reminder state if the trigger date changes.
-   *
-   * @return bool
-   *
-   * @param \CRM_Core_DAO_ActionSchedule $schedule
-   */
-  public function resetOnTriggerDateChange($schedule) {
-    return FALSE;
-  }
-
-  /**
-   * Determine whether a schedule based on this mapping should
-   * send to additional contacts.
-   */
-  abstract public function sendToAdditional($entityId): bool;
-
-}
diff --git a/Civi/ActionSchedule/MappingBase.php b/Civi/ActionSchedule/MappingBase.php
new file mode 100644 (file)
index 0000000..cf4f997
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\ActionSchedule;
+
+use Civi\Api4\Utils\CoreUtil;
+
+/**
+ * Base implementation of MappingInterface.
+ *
+ * Extend this class to register a new type of ActionSchedule mapping.
+ * Note: When choosing a value to return from `getId()`, use a "machine name" style string.
+ */
+abstract class MappingBase implements MappingInterface {
+
+  /**
+   * Register this action mapping type with CRM_Core_BAO_ActionSchedule.
+   *
+   * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
+   */
+  public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations): void {
+    $registrations->register(new static());
+  }
+
+  public function getEntityTable(): string {
+    return \CRM_Core_DAO_AllCoreTables::getTableForEntityName($this->getEntityName());
+  }
+
+  /**
+   * Deprecated ambiguously-named function.
+   * @deprecated
+   * @return string
+   */
+  public function getEntity(): string {
+    \CRM_Core_Error::deprecatedFunctionWarning('getEntityTable');
+    return $this->getEntityTable();
+  }
+
+  public function getLabel(): string {
+    return CoreUtil::getInfoItem($this->getEntityName(), 'title');
+  }
+
+  public function getValueHeader(): string {
+    return $this->getLabel();
+  }
+
+  public function getRecipientListing($recipientType): array {
+    return [];
+  }
+
+  public function getRecipientTypes(): array {
+    return [];
+  }
+
+  public function validateSchedule($schedule): array {
+    return [];
+  }
+
+  public function getDateFields(): array {
+    return [];
+  }
+
+  public function resetOnTriggerDateChange($schedule): bool {
+    return FALSE;
+  }
+
+  public function sendToAdditional($entityId): bool {
+    return TRUE;
+  }
+
+}
index 62e530bf87915dfad2f4f84486111a1693dae8ec..42fe2e8a1f32efe62026617e765680248ba784ab 100644 (file)
@@ -18,7 +18,10 @@ namespace Civi\ActionSchedule;
 interface MappingInterface {
 
   /**
-   * @return mixed
+   * Unique identifier of this mapping type.
+   *
+   * Should return a "machine name" style string (older implementations return an int -- don't follow their example).
+   * @return string|int
    */
   public function getId();
 
@@ -35,25 +38,23 @@ interface MappingInterface {
   public function getEntityName(): string;
 
   /**
-   * Get a printable label for this mapping type.
-   *
+   * Label of this mapping type as shown in the "Entity" dropdown-select on the form.
    * @return string
    */
   public function getLabel();
 
   /**
-   * Get a printable label to use as the header on the 'value' filter.
-   *
+   * Label of the primary filter field on the form, e.g. "Activity Type"
    * @return string
    */
-  public function getValueHeader();
+  public function getValueHeader(): string;
 
   /**
    * Get a printable label to use as the header on the 'status' filter.
    *
    * @return string
    */
-  public function getStatusHeader();
+  public function getStatusHeader(): string;
 
   /**
    * Get a list of value options.
@@ -62,7 +63,7 @@ interface MappingInterface {
    *   Array(string $value => string $label).
    *   Ex: array(123 => 'Phone Call', 456 => 'Meeting').
    */
-  public function getValueLabels();
+  public function getValueLabels(): array;
 
   /**
    * Get a list of status options.
@@ -74,7 +75,7 @@ interface MappingInterface {
    *   Array(string $value => string $label).
    *   Ex: Array(123 => 'Completed', 456 => 'Scheduled').
    */
-  public function getStatusLabels($value);
+  public function getStatusLabels($value): array;
 
   /**
    * Get a list of available date fields.
@@ -82,7 +83,7 @@ interface MappingInterface {
    * @return array
    *   Array(string $fieldName => string $fieldLabel).
    */
-  public function getDateFields();
+  public function getDateFields(): array;
 
   /**
    * Get a list of recipient types.
@@ -94,7 +95,7 @@ interface MappingInterface {
    *   array(string $value => string $label).
    *   Ex: array('assignee' => 'Activity Assignee').
    */
-  public function getRecipientTypes();
+  public function getRecipientTypes(): array;
 
   /**
    * Get a list of recipients which match the given type.
@@ -109,7 +110,7 @@ interface MappingInterface {
    *   Ex: array(1 => 'Attendee', 2 => 'Volunteer').
    * @see getRecipientTypes
    */
-  public function getRecipientListing($recipientType);
+  public function getRecipientListing($recipientType): array;
 
   /**
    * Determine whether a schedule based on this mapping is sufficiently
@@ -120,7 +121,7 @@ interface MappingInterface {
    *   Array (string $code => string $message).
    *   List of error messages.
    */
-  public function validateSchedule($schedule);
+  public function validateSchedule($schedule): array;
 
   /**
    * Generate a query to locate contacts who match the given
@@ -134,7 +135,7 @@ interface MappingInterface {
    * @return \CRM_Utils_SQL_Select
    * @see RecipientBuilder
    */
-  public function createQuery($schedule, $phase, $defaultParams);
+  public function createQuery($schedule, $phase, $defaultParams): \CRM_Utils_SQL_Select;
 
   /**
    * Determine whether a schedule based on this mapping should
@@ -144,7 +145,7 @@ interface MappingInterface {
    *
    * @param \CRM_Core_DAO_ActionSchedule $schedule
    */
-  public function resetOnTriggerDateChange($schedule);
+  public function resetOnTriggerDateChange($schedule): bool;
 
   /**
    * Determine whether a schedule based on this mapping should
index e4ec975ee0017ec51c94559e05f3d17a63187e7a..245c3b835e4574e668b1d3e792a54086f9ac3398 100644 (file)
@@ -481,7 +481,9 @@ class Container {
     $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Contact_ActionMapping', 'onRegisterActionMappings']);
     $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Contribute_ActionMapping_ByPage', 'onRegisterActionMappings']);
     $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Contribute_ActionMapping_ByType', 'onRegisterActionMappings']);
-    $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Event_ActionMapping', 'onRegisterActionMappings']);
+    $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Event_ActionMapping_ByType', 'onRegisterActionMappings']);
+    $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Event_ActionMapping_ByEvent', 'onRegisterActionMappings']);
+    $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Event_ActionMapping_ByTemplate', 'onRegisterActionMappings']);
     $dispatcher->addListener('civi.actionSchedule.getMappings', ['CRM_Member_ActionMapping', 'onRegisterActionMappings']);
 
     return $dispatcher;
index efd9027dd4cb5f16ff8beced0ddb69ec346d4c5e..f33292c618b39f4dc2aa418c8405d29316dcd702 100644 (file)
@@ -229,7 +229,7 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
    * Schedule message delivery for contributions of type "Member Dues".
    */
   public function scheduleForDues() {
-    $this->schedule->mapping_id = CRM_Contribute_ActionMapping_ByType::MAPPING_ID;
+    $this->schedule->mapping_id = 'contribtype';
     $this->schedule->start_action_date = 'receive_date';
     $this->schedule->entity_value = CRM_Utils_Array::implodePadded([1]);
     $this->schedule->entity_status = CRM_Utils_Array::implodePadded([1]);
@@ -239,7 +239,7 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
    * Schedule message delivery for contributions of type "Donation".
    */
   public function scheduleForDonation() {
-    $this->schedule->mapping_id = CRM_Contribute_ActionMapping_ByType::MAPPING_ID;
+    $this->schedule->mapping_id = 'contribtype';
     $this->schedule->start_action_date = 'receive_date';
     $this->schedule->entity_value = CRM_Utils_Array::implodePadded([2]);
     $this->schedule->entity_status = CRM_Utils_Array::implodePadded(NULL);
@@ -249,7 +249,7 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
    * Schedule message delivery for any contribution, regardless of type.
    */
   public function scheduleForAny() {
-    $this->schedule->mapping_id = CRM_Contribute_ActionMapping_ByType::MAPPING_ID;
+    $this->schedule->mapping_id = 'contribtype';
     $this->schedule->start_action_date = 'receive_date';
     $this->schedule->entity_value = CRM_Utils_Array::implodePadded(NULL);
     $this->schedule->entity_status = CRM_Utils_Array::implodePadded(NULL);
@@ -259,7 +259,7 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
    * Schedule message delivery to the 'soft credit' assignee.
    */
   public function scheduleForSoftCreditor() {
-    $this->schedule->mapping_id = CRM_Contribute_ActionMapping_ByType::MAPPING_ID;
+    $this->schedule->mapping_id = 'contribtype';
     $this->schedule->start_action_date = 'receive_date';
     $this->schedule->entity_value = CRM_Utils_Array::implodePadded(NULL);
     $this->schedule->entity_status = CRM_Utils_Array::implodePadded(NULL);