From 8badd1d83698ed502d86a50202619b04ed3f5c8f Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 8 Oct 2021 15:23:59 -0400 Subject: [PATCH] APIv4 - Use event instead of hardcoded list to resolve entityName to className Typically an APIv4 entity name and class name are the same, e.g. the "Contact" entity has the class `Civi\Api4\Contact`. However, there are a few oddballs (CiviCase, CustomValue) and other extensions may introduce their own oddball entities; this event allows them to do so. --- Civi/API/Request.php | 18 +++--- Civi/Api4/Event/CreateApi4RequestEvent.php | 56 +++++++++++++++++++ .../CreateApi4RequestSubscriber.php | 52 +++++++++++++++++ Civi/Api4/Utils/CoreUtil.php | 13 ++--- 4 files changed, 120 insertions(+), 19 deletions(-) create mode 100644 Civi/Api4/Event/CreateApi4RequestEvent.php create mode 100644 Civi/Api4/Event/Subscriber/CreateApi4RequestSubscriber.php diff --git a/Civi/API/Request.php b/Civi/API/Request.php index 5ad9b9d219..4c9a6d5fc0 100644 --- a/Civi/API/Request.php +++ b/Civi/API/Request.php @@ -10,7 +10,7 @@ */ namespace Civi\API; -use Civi\Api4\Utils\CoreUtil; +use Civi\Api4\Event\CreateApi4RequestEvent; /** * Class Request @@ -45,17 +45,13 @@ class Request { ]; case 4: - // For custom pseudo-entities - if (strpos($entity, 'Custom_') === 0) { - $apiRequest = \Civi\Api4\CustomValue::$action(substr($entity, 7)); - } - else { - $callable = [CoreUtil::getApiClass($entity), $action]; - if (!is_callable($callable)) { - throw new \Civi\API\Exception\NotImplementedException("API ($entity, $action) does not exist (join the API team and implement it!)"); - } - $apiRequest = call_user_func($callable); + $e = new CreateApi4RequestEvent($entity); + \Civi::dispatcher()->dispatch('civi.api4.createRequest', $e); + $callable = [$e->className, $action]; + if (!$e->className || !is_callable($callable)) { + throw new \Civi\API\Exception\NotImplementedException("API ($entity, $action) does not exist (join the API team and implement it!)"); } + $apiRequest = call_user_func_array($callable, $e->args); foreach ($params as $name => $param) { $setter = 'set' . ucfirst($name); $apiRequest->$setter($param); diff --git a/Civi/Api4/Event/CreateApi4RequestEvent.php b/Civi/Api4/Event/CreateApi4RequestEvent.php new file mode 100644 index 0000000000..7a77989609 --- /dev/null +++ b/Civi/Api4/Event/CreateApi4RequestEvent.php @@ -0,0 +1,56 @@ +entityName = $entityName; + } + +} diff --git a/Civi/Api4/Event/Subscriber/CreateApi4RequestSubscriber.php b/Civi/Api4/Event/Subscriber/CreateApi4RequestSubscriber.php new file mode 100644 index 0000000000..45cf5dd146 --- /dev/null +++ b/Civi/Api4/Event/Subscriber/CreateApi4RequestSubscriber.php @@ -0,0 +1,52 @@ + [ + ['onApiRequestCreate', Events::W_LATE], + ], + ]; + } + + /** + * @param \Civi\Api4\Event\CreateApi4RequestEvent $event + */ + public function onApiRequestCreate(\Civi\Api4\Event\CreateApi4RequestEvent $event) { + if (strpos($event->entityName, 'Custom_') === 0) { + $groupName = substr($event->entityName, 7); + if (CoreUtil::isCustomEntity($groupName)) { + $event->className = 'Civi\Api4\CustomValue'; + $event->args = [$groupName]; + } + } + // Because "Case" is a reserved php keyword + $className = 'Civi\Api4\\' . ($event->entityName === 'Case' ? 'CiviCase' : $event->entityName); + if (class_exists($className)) { + $event->className = $className; + } + } + +} diff --git a/Civi/Api4/Utils/CoreUtil.php b/Civi/Api4/Utils/CoreUtil.php index 9643585769..1dbf631603 100644 --- a/Civi/Api4/Utils/CoreUtil.php +++ b/Civi/Api4/Utils/CoreUtil.php @@ -13,6 +13,7 @@ namespace Civi\Api4\Utils; use Civi\API\Request; +use Civi\Api4\Event\CreateApi4RequestEvent; use CRM_Core_DAO_AllCoreTables as AllCoreTables; class CoreUtil { @@ -43,13 +44,9 @@ class CoreUtil { * @return string|\Civi\Api4\Generic\AbstractEntity */ public static function getApiClass($entityName) { - if (strpos($entityName, 'Custom_') === 0) { - $groupName = substr($entityName, 7); - return self::isCustomEntity($groupName) ? 'Civi\Api4\CustomValue' : NULL; - } - // Because "Case" is a reserved php keyword - $className = 'Civi\Api4\\' . ($entityName === 'Case' ? 'CiviCase' : $entityName); - return class_exists($className) ? $className : NULL; + $e = new CreateApi4RequestEvent($entityName); + \Civi::dispatcher()->dispatch('civi.api4.createRequest', $e); + return $e->className; } /** @@ -164,7 +161,7 @@ class CoreUtil { * @return bool * @throws \CRM_Core_Exception */ - private static function isCustomEntity($customGroupName) { + public static function isCustomEntity($customGroupName) { return $customGroupName && \CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupName, 'is_multiple', 'name'); } -- 2.25.1