ActionMapping - Use APIv4 SpecProviderInterface to alter metadata for each mapping...
authorcolemanw <coleman@civicrm.org>
Sun, 30 Jul 2023 02:59:21 +0000 (22:59 -0400)
committercolemanw <coleman@civicrm.org>
Wed, 9 Aug 2023 00:54:35 +0000 (20:54 -0400)
15 files changed:
CRM/Activity/ActionMapping.php
CRM/Contact/ActionMapping.php
CRM/Contribute/ActionMapping.php
CRM/Contribute/ActionMapping/ByPage.php
CRM/Contribute/ActionMapping/ByType.php
CRM/Core/BAO/ActionSchedule.php
CRM/Event/ActionMapping.php
CRM/Member/ActionMapping.php
Civi/ActionSchedule/MappingBase.php
Civi/ActionSchedule/MappingInterface.php
Civi/Api4/Service/Spec/Provider/Generic/SpecProviderInterface.php
Civi/Api4/Service/Spec/SpecGatherer.php
Civi/Schema/Traits/GuiSpecTrait.php
tests/phpunit/api/v4/Entity/ActionScheduleTest.php
tests/phpunit/api/v4/Spec/SpecGathererTest.php

index 1e5416bb5db8d145cb7ebca9572769b73fc5fa78..6d9800e37932391f68670cfff0f4c5e103d500f6 100644 (file)
@@ -40,8 +40,13 @@ class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\MappingBase {
     return 'Activity';
   }
 
-  public function getValueHeader(): string {
-    return ts('Activity Type');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    $spec->getFieldByName('entity_value')
+      ->setLabel(ts('Activity Type'));
+    $spec->getFieldByName('entity_status')
+      ->setLabel(ts('Activity Status'));
+    $spec->getFieldByName('recipient')
+      ->setLabel(ts('Recipients'));
   }
 
   public function getValueLabels(): array {
@@ -51,11 +56,7 @@ class CRM_Activity_ActionMapping extends \Civi\ActionSchedule\MappingBase {
     return $activityTypes;
   }
 
-  public function getStatusHeader(): string {
-    return ts('Activity Status');
-  }
-
-  public function getStatusLabels($value): array {
+  public function getStatusLabels(?array $entityValue): array {
     return CRM_Core_PseudoConstant::activityStatus();
   }
 
index cbd92cb975ae6a0774bb34b3ab48ddbe79f64e81..d8d0ce0b2232f0346be5ec8487346fbc699daa82 100644 (file)
@@ -36,8 +36,14 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\MappingBase {
     return 'Contact';
   }
 
-  public function getValueHeader(): string {
-    return ts('Date Field');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    $spec->getFieldByName('entity_value')
+      ->setLabel(ts('Date Field'))
+      ->setInputAttr('multiple', FALSE);
+    $spec->getFieldByName('entity_status')
+      ->setLabel(ts('Annual Options'))
+      ->setInputAttr('multiple', FALSE)
+      ->setRequired(TRUE);
   }
 
   public function getValueLabels(): array {
@@ -55,11 +61,7 @@ class CRM_Contact_ActionMapping extends \Civi\ActionSchedule\MappingBase {
     return $dateFields;
   }
 
-  public function getStatusHeader(): string {
-    return ts('Annual Options');
-  }
-
-  public function getStatusLabels($value): array {
+  public function getStatusLabels(?array $entityValue): array {
     return CRM_Core_OptionGroup::values('contact_date_reminder_options');
   }
 
index ed5aaaa631862aed5152e40121772c1bab25dc9a..c986a140516a78a43cdd0dc3d80ac64d63f17cdd 100644 (file)
@@ -24,18 +24,19 @@ abstract class CRM_Contribute_ActionMapping extends \Civi\ActionSchedule\Mapping
     return 'Contribution';
   }
 
-  public function getStatusHeader(): string {
-    return ts('Contribution Status');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    $spec->getFieldByName('entity_status')
+      ->setLabel(ts('Contribution Status'));
   }
 
   /**
    * Get a list of status options.
    *
-   * @param string|int $value
+   * @param array|null $entityValue
    * @return array
    * @throws CRM_Core_Exception
    */
-  public function getStatusLabels($value): array {
+  public function getStatusLabels(?array $entityValue): array {
     return CRM_Contribute_BAO_Contribution::buildOptions('contribution_status_id', 'get', []);
   }
 
index 11d11bde4b038708b34bc45754eea2e9c76d52e4..5cf73dbbb1c0be124f7cff888e3c65adbfd4973d 100644 (file)
@@ -36,13 +36,10 @@ class CRM_Contribute_ActionMapping_ByPage extends CRM_Contribute_ActionMapping {
     return ts('Contribution Page');
   }
 
-  /**
-   * Get a printable label to use as the header on the 'value' filter.
-   *
-   * @return string
-   */
-  public function getValueHeader(): string {
-    return ts('Contribution Page');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    parent::modifySpec($spec);
+    $spec->getFieldByName('entity_value')
+      ->setLabel(ts('Contribution Page'));
   }
 
   /**
index 42bf7e5c719566b4ce769373c762d8c1c38c769a..39d8c516548d41f669d3c8cac1ef1737f23ebc78 100644 (file)
@@ -36,13 +36,12 @@ class CRM_Contribute_ActionMapping_ByType extends CRM_Contribute_ActionMapping {
     return ts('Contribution Type');
   }
 
-  /**
-   * Get a printable label to use as the header on the 'value' filter.
-   *
-   * @return string
-   */
-  public function getValueHeader(): string {
-    return ts('Financial Type');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    parent::modifySpec($spec);
+    $spec->getFieldByName('entity_value')
+      ->setLabel(ts('Financial Type'));
+    $spec->getFieldByName('recipient_listing')
+      ->setRequired($spec->getValue('limit_to') && $spec->getValue('recipient') === 'soft_credit_type');
   }
 
   /**
index 4eeae8728557a152a5e7809adabd1a771abef782..761f0f7311e03f785f667e2e96b439eb488a0089 100644 (file)
@@ -129,7 +129,7 @@ class CRM_Core_BAO_ActionSchedule extends CRM_Core_DAO_ActionSchedule implements
     if (!$values['mapping_id']) {
       return [];
     }
-    return self::getMapping($values['mapping_id'])->getStatusLabels($values['entity_value']);
+    return self::getMapping($values['mapping_id'])->getStatusLabels((array) $values['entity_value']);
   }
 
   /**
@@ -268,7 +268,7 @@ FROM civicrm_action_schedule cas
         explode(CRM_Core_DAO::VALUE_SEPARATOR, $dao->entityValueIds)
       ));
       $list[$dao->id]['status'] = implode(', ', CRM_Utils_Array::subset(
-        $filterMapping->getStatusLabels($dao->entityValueIds),
+        $filterMapping->getStatusLabels($list[$dao->id]['entity_value']),
         explode(CRM_Core_DAO::VALUE_SEPARATOR, $dao->entityStatusIds)
       ));
       $list[$dao->id]['is_repeat'] = $dao->is_repeat;
index c9b528c9150504ab8f1bc2c6cd49b390ebf1ab66..7e9acad3ba9d1fd8f6b218a43d04c0242a4490af 100644 (file)
@@ -28,11 +28,18 @@ abstract class CRM_Event_ActionMapping extends \Civi\ActionSchedule\MappingBase
     return 'Participant';
   }
 
-  public function getStatusHeader(): string {
-    return ts('Participant Status');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    $spec->getFieldByName('entity_value')
+      ->setLabel($this->getLabel());
+    $spec->getFieldByName('entity_status')
+      ->setLabel(ts('Participant Status'));
+    $spec->getFieldByName('recipient')
+      ->setLabel(ts('Recipients'));
+    $spec->getFieldByName('recipient_listing')
+      ->setRequired($spec->getValue('recipient') === 'participant_role');
   }
 
-  public function getStatusLabels($value): array {
+  public function getStatusLabels(?array $entityValue): array {
     return CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label');
   }
 
index 99f2e7dfd77271da023317e05f3ec23625824ed6..1d5a50aaa8d47cfd9c2771b24aa2a9d93c47aa4d 100644 (file)
@@ -35,25 +35,24 @@ class CRM_Member_ActionMapping extends \Civi\ActionSchedule\MappingBase {
     return 'Membership';
   }
 
-  public function getValueHeader(): string {
-    return ts('Membership Type');
+  public function modifySpec(\Civi\Api4\Service\Spec\RequestSpec $spec) {
+    $spec->getFieldByName('entity_value')
+      ->setLabel(ts('Membership Type'));
+    $spec->getFieldByName('entity_status')
+      ->setLabel(ts('Auto Renew Options'));
   }
 
   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 [];
+  public function getStatusLabels(?array $entityValue): array {
+    foreach ($entityValue ?? [] as $membershipType) {
+      if (\CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $membershipType, 'auto_renew')) {
+        return \CRM_Core_OptionGroup::values('auto_renew_options');
+      }
     }
+    return [];
   }
 
   /**
index 4e7c7978dad8580704b867014e4f336a1a187ef9..63c5cbe7481aafd06330384040c97a5464645f28 100644 (file)
@@ -59,10 +59,6 @@ abstract class MappingBase extends AutoSubscriber implements MappingInterface {
     return CoreUtil::getInfoItem($this->getEntityName(), 'title');
   }
 
-  public function getValueHeader(): string {
-    return $this->getLabel();
-  }
-
   public static function getLimitToOptions(): array {
     return [
       [
@@ -109,4 +105,10 @@ abstract class MappingBase extends AutoSubscriber implements MappingInterface {
     return TRUE;
   }
 
+  final public function applies(string $entity, string $action, array $values = []) {
+    return $entity === 'ActionSchedule' &&
+      in_array($action, ['create', 'get', 'update', 'save'], TRUE) &&
+      $this->getId() == ($values['mapping_id'] ?? NULL);
+  }
+
 }
index c2f0911ae2a940acea6a4e25447bdf381be68cc0..509a51ddb051bb6a3178a72b2824cdb896cb1a51 100644 (file)
 
 namespace Civi\ActionSchedule;
 
+use Civi\Api4\Service\Spec\Provider\Generic\SpecProviderInterface;
+
 /**
  * Interface MappingInterface
  * @package Civi\ActionSchedule
  */
-interface MappingInterface {
+interface MappingInterface extends SpecProviderInterface {
 
   /**
    * Unique identifier of this mapping type.
@@ -53,38 +55,17 @@ interface MappingInterface {
   public function getLabel();
 
   /**
-   * Label of the primary filter field on the form, e.g. "Activity Type"
-   * @return string
-   */
-  public function getValueHeader(): string;
-
-  /**
-   * Get a printable label to use as the header on the 'status' filter.
-   *
-   * @return string
-   */
-  public function getStatusHeader(): string;
-
-  /**
-   * Get a list of value options.
-   *
-   * @return array
-   *   Array(string $value => string $label).
-   *   Ex: array(123 => 'Phone Call', 456 => 'Meeting').
+   * Get option list for the `entity_value` field.
    */
   public function getValueLabels(): array;
 
   /**
-   * Get a list of status options.
+   * Get option list for the `entity_status` field.
    *
-   * @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').
+   * @param array|null $entityValue
+   *   Selected value(s) of the `entity_value` field.
    */
-  public function getStatusLabels($value): array;
+  public function getStatusLabels(?array $entityValue): array;
 
   /**
    * Get a list of available date fields.
index 1f2fe6671e8853a4f2de84c9d70351f1e1ed707c..b66fb6d4851aa77074f201e7fdab180f1d400323 100644 (file)
@@ -29,9 +29,12 @@ interface SpecProviderInterface {
   /**
    * @param string $entity
    * @param string $action
+   * Optional @param array $values
+   *   $values from the api getFields request.
+   *   This param works but has not been added to the interface for the sake of backward-compatability.
    *
    * @return bool
    */
-  public function applies($entity, $action);
+  public function applies(string $entity, string $action/*, array $values = []*/);
 
 }
index b59426551af56f077d9922b97700c16c2139b363..75222965df62150e7845a063714feb19abd6a39d 100644 (file)
@@ -66,7 +66,7 @@ class SpecGatherer extends AutoService {
     }
 
     foreach ($this->specProviders as $provider) {
-      if ($provider->applies($entity, $action)) {
+      if ($provider->applies($entity, $action, $specification->getValues())) {
         $provider->modifySpec($specification);
       }
     }
index 888c71d2aec5f4fbdd9df8f1f33a5cefab5addca..36bd073dc8b2267b45f857a8329107e2d990ca24 100644 (file)
@@ -100,6 +100,16 @@ trait GuiSpecTrait {
     return $this;
   }
 
+  /**
+   * @param string $attrName
+   * @param $attrValue
+   * @return $this
+   */
+  public function setInputAttr(string $attrName, $attrValue) {
+    $this->inputAttrs[$attrName] = $attrValue;
+    return $this;
+  }
+
   /**
    * @return bool
    */
index 570f1f9302a4b8dc91df61090e4190786ecbdc91..aa76767ba9f1b86f90be757f1d6ec6024780a76c 100644 (file)
@@ -22,7 +22,7 @@ use Civi\Api4\ActionSchedule;
  */
 class ActionScheduleTest extends Api4TestBase {
 
-  public function testGetOptionsBasic() {
+  public function testGetOptionsBasic(): void {
     $fields = ActionSchedule::getFields(FALSE)
       ->setLoadOptions(['id', 'name', 'label'])
       ->execute()
@@ -44,4 +44,20 @@ class ActionScheduleTest extends Api4TestBase {
     $this->assertEquals('add', $fields['limit_to']['options'][1]['name']);
   }
 
+  public function testGetFieldsForActivity(): void {
+    $fields = ActionSchedule::getFields(FALSE)
+      ->setLoadOptions(TRUE)
+      ->addValue('mapping_id:name', 'activity_type')
+      ->execute()
+      ->indexBy('name');
+
+    $this->assertEquals('Activity Type', $fields['entity_value']['label']);
+    $this->assertContains('Meeting', $fields['entity_value']['options']);
+    $this->assertEquals('Activity Status', $fields['entity_status']['label']);
+    $this->assertContains('Scheduled', $fields['entity_status']['options']);
+    $this->assertArrayHasKey('activity_date_time', $fields['start_action_date']['options']);
+    $this->assertArrayHasKey('1', $fields['limit_to']['options']);
+    $this->assertArrayNotHasKey('2', $fields['limit_to']['options']);
+  }
+
 }
index 4aa6cac8c988059ab86d0e0e899161faad9270da..4cfe0d9b30fde5249eb95dd1a41b1b50f543ac93 100644 (file)
@@ -51,7 +51,7 @@ class SpecGathererTest extends Api4TestBase {
     $gather = new SpecGatherer();
 
     $provider = $this->prophesize(SpecProviderInterface::class);
-    $provider->applies('Contact', 'create')->willReturn(TRUE);
+    $provider->applies('Contact', 'create', [])->willReturn(TRUE);
     $provider->modifySpec(Argument::any())->will(function ($args) {
       /** @var \Civi\Api4\Service\Spec\RequestSpec $spec */
       $spec = $args[0];