From 1be8a0e0c4a5862323429c8388fd0cbbdfea524a Mon Sep 17 00:00:00 2001 From: colemanw Date: Sat, 29 Jul 2023 22:59:21 -0400 Subject: [PATCH] ActionMapping - Use APIv4 SpecProviderInterface to alter metadata for each mapping type --- CRM/Activity/ActionMapping.php | 15 ++++---- CRM/Contact/ActionMapping.php | 16 +++++---- CRM/Contribute/ActionMapping.php | 9 ++--- CRM/Contribute/ActionMapping/ByPage.php | 11 +++--- CRM/Contribute/ActionMapping/ByType.php | 13 ++++--- CRM/Core/BAO/ActionSchedule.php | 4 +-- CRM/Event/ActionMapping.php | 13 +++++-- CRM/Member/ActionMapping.php | 23 ++++++------ Civi/ActionSchedule/MappingBase.php | 10 +++--- Civi/ActionSchedule/MappingInterface.php | 35 +++++-------------- .../Generic/SpecProviderInterface.php | 5 ++- Civi/Api4/Service/Spec/SpecGatherer.php | 2 +- Civi/Schema/Traits/GuiSpecTrait.php | 10 ++++++ .../api/v4/Entity/ActionScheduleTest.php | 18 +++++++++- .../phpunit/api/v4/Spec/SpecGathererTest.php | 2 +- 15 files changed, 102 insertions(+), 84 deletions(-) diff --git a/CRM/Activity/ActionMapping.php b/CRM/Activity/ActionMapping.php index 1e5416bb5d..6d9800e379 100644 --- a/CRM/Activity/ActionMapping.php +++ b/CRM/Activity/ActionMapping.php @@ -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(); } diff --git a/CRM/Contact/ActionMapping.php b/CRM/Contact/ActionMapping.php index cbd92cb975..d8d0ce0b22 100644 --- a/CRM/Contact/ActionMapping.php +++ b/CRM/Contact/ActionMapping.php @@ -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'); } diff --git a/CRM/Contribute/ActionMapping.php b/CRM/Contribute/ActionMapping.php index ed5aaaa631..c986a14051 100644 --- a/CRM/Contribute/ActionMapping.php +++ b/CRM/Contribute/ActionMapping.php @@ -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', []); } diff --git a/CRM/Contribute/ActionMapping/ByPage.php b/CRM/Contribute/ActionMapping/ByPage.php index 11d11bde4b..5cf73dbbb1 100644 --- a/CRM/Contribute/ActionMapping/ByPage.php +++ b/CRM/Contribute/ActionMapping/ByPage.php @@ -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')); } /** diff --git a/CRM/Contribute/ActionMapping/ByType.php b/CRM/Contribute/ActionMapping/ByType.php index 42bf7e5c71..39d8c51654 100644 --- a/CRM/Contribute/ActionMapping/ByType.php +++ b/CRM/Contribute/ActionMapping/ByType.php @@ -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'); } /** diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php index 4eeae87285..761f0f7311 100644 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -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; diff --git a/CRM/Event/ActionMapping.php b/CRM/Event/ActionMapping.php index c9b528c915..7e9acad3ba 100644 --- a/CRM/Event/ActionMapping.php +++ b/CRM/Event/ActionMapping.php @@ -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'); } diff --git a/CRM/Member/ActionMapping.php b/CRM/Member/ActionMapping.php index 99f2e7dfd7..1d5a50aaa8 100644 --- a/CRM/Member/ActionMapping.php +++ b/CRM/Member/ActionMapping.php @@ -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 []; } /** diff --git a/Civi/ActionSchedule/MappingBase.php b/Civi/ActionSchedule/MappingBase.php index 4e7c7978da..63c5cbe748 100644 --- a/Civi/ActionSchedule/MappingBase.php +++ b/Civi/ActionSchedule/MappingBase.php @@ -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); + } + } diff --git a/Civi/ActionSchedule/MappingInterface.php b/Civi/ActionSchedule/MappingInterface.php index c2f0911ae2..509a51ddb0 100644 --- a/Civi/ActionSchedule/MappingInterface.php +++ b/Civi/ActionSchedule/MappingInterface.php @@ -11,11 +11,13 @@ 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. diff --git a/Civi/Api4/Service/Spec/Provider/Generic/SpecProviderInterface.php b/Civi/Api4/Service/Spec/Provider/Generic/SpecProviderInterface.php index 1f2fe6671e..b66fb6d485 100644 --- a/Civi/Api4/Service/Spec/Provider/Generic/SpecProviderInterface.php +++ b/Civi/Api4/Service/Spec/Provider/Generic/SpecProviderInterface.php @@ -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 = []*/); } diff --git a/Civi/Api4/Service/Spec/SpecGatherer.php b/Civi/Api4/Service/Spec/SpecGatherer.php index b59426551a..75222965df 100644 --- a/Civi/Api4/Service/Spec/SpecGatherer.php +++ b/Civi/Api4/Service/Spec/SpecGatherer.php @@ -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); } } diff --git a/Civi/Schema/Traits/GuiSpecTrait.php b/Civi/Schema/Traits/GuiSpecTrait.php index 888c71d2ae..36bd073dc8 100644 --- a/Civi/Schema/Traits/GuiSpecTrait.php +++ b/Civi/Schema/Traits/GuiSpecTrait.php @@ -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 */ diff --git a/tests/phpunit/api/v4/Entity/ActionScheduleTest.php b/tests/phpunit/api/v4/Entity/ActionScheduleTest.php index 570f1f9302..aa76767ba9 100644 --- a/tests/phpunit/api/v4/Entity/ActionScheduleTest.php +++ b/tests/phpunit/api/v4/Entity/ActionScheduleTest.php @@ -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']); + } + } diff --git a/tests/phpunit/api/v4/Spec/SpecGathererTest.php b/tests/phpunit/api/v4/Spec/SpecGathererTest.php index 4aa6cac8c9..4cfe0d9b30 100644 --- a/tests/phpunit/api/v4/Spec/SpecGathererTest.php +++ b/tests/phpunit/api/v4/Spec/SpecGathererTest.php @@ -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]; -- 2.25.1