APIv4 - Alter activity links for CiviCase
authorcolemanw <coleman@civicrm.org>
Tue, 28 Nov 2023 03:01:35 +0000 (22:01 -0500)
committercolemanw <coleman@civicrm.org>
Sun, 24 Dec 2023 00:29:21 +0000 (19:29 -0500)
Activities that belong to a case use a differently-structured url.
This adds a handler for it and moves it more appropriately into the
civi_case extension.

CRM/Core/Action.php
Civi/Api4/Service/Links/ContactLinksProvider.php
Civi/Api4/Service/Links/LinksProviderTrait.php [new file with mode: 0644]
ext/civi_case/Civi/Api4/Service/Links/CaseLinksProvider.php [new file with mode: 0644]

index 3adae016f68bda74ceb1adee9576449d8bbb232f..7188b40edc9593a207bd150b8c25a5cadb28a88c 100644 (file)
@@ -76,6 +76,7 @@ class CRM_Core_Action {
     'revert' => self::REVERT,
     'close' => self::CLOSE,
     'reopen' => self::REOPEN,
+    'advanced' => self::ADVANCED,
   ];
 
   private static function getInfo(): array {
index 8bdad79ee015fe94b21eadba55a3ca3d0448fbaa..273eb3b17078ab949f0c0953ade761e5f516f20d 100644 (file)
@@ -20,6 +20,7 @@ use Civi\Core\Event\GenericHookEvent;
  * @internal
  */
 class ContactLinksProvider extends \Civi\Core\Service\AutoSubscriber {
+  use LinksProviderTrait;
 
   public static function getSubscribedEvents(): array {
     return [
@@ -34,19 +35,22 @@ class ContactLinksProvider extends \Civi\Core\Service\AutoSubscriber {
         if (in_array($link['ui_action'], ['view', 'update'], TRUE)) {
           $e->links[$index]['target'] = '';
         }
-        // Unset the generic "add" link and replace it with links per contact-type and sub-type
-        if ($link['ui_action'] === 'add') {
-          $addTemplate = $link;
-          unset($e->links[$index]);
-        }
       }
-      if ($e->entity === 'Contact') {
-        foreach (\CRM_Contact_BAO_ContactType::basicTypes() as $contactType) {
-          self::addLinks($contactType, $addTemplate, $e);
+      // Unset the generic "add" link and replace it with links per contact-type and sub-type
+      $addLinkIndex = self::getActionIndex($e->links, 'add');
+      if ($addLinkIndex !== NULL) {
+        $addTemplate = $e->links[$addLinkIndex];
+        unset($e->links[$addLinkIndex]);
+        // For contact entity, add links for every contact type
+        if ($e->entity === 'Contact') {
+          foreach (\CRM_Contact_BAO_ContactType::basicTypes() as $contactType) {
+            self::addLinks($contactType, $addTemplate, $e);
+          }
+        }
+        // For Individual, Organization, Household entity
+        else {
+          self::addLinks($e->entity, $addTemplate, $e);
         }
-      }
-      else {
-        self::addLinks($e->entity, $addTemplate, $e);
       }
     }
   }
diff --git a/Civi/Api4/Service/Links/LinksProviderTrait.php b/Civi/Api4/Service/Links/LinksProviderTrait.php
new file mode 100644 (file)
index 0000000..b3f88e6
--- /dev/null
@@ -0,0 +1,32 @@
+<?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\Api4\Service\Links;
+
+trait LinksProviderTrait {
+
+  /**
+   * Given a set of links, find the one with the specified ui_action
+   *
+   * @param $links
+   * @param $uiAction
+   * @return int|null
+   */
+  protected static function getActionIndex($links, $uiAction): ?int {
+    foreach ($links as $index => $link) {
+      if (($link['ui_action'] ?? NULL) === $uiAction || str_contains($link['path'] ?? '', "action=$uiAction")) {
+        return $index;
+      }
+    }
+    return NULL;
+  }
+
+}
diff --git a/ext/civi_case/Civi/Api4/Service/Links/CaseLinksProvider.php b/ext/civi_case/Civi/Api4/Service/Links/CaseLinksProvider.php
new file mode 100644 (file)
index 0000000..bf34346
--- /dev/null
@@ -0,0 +1,97 @@
+<?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\Api4\Service\Links;
+
+use Civi\API\Event\RespondEvent;
+use Civi\Api4\Utils\CoreUtil;
+use Civi\Core\Event\GenericHookEvent;
+
+/**
+ * @service
+ * @internal
+ */
+class CaseLinksProvider extends \Civi\Core\Service\AutoSubscriber {
+  use LinksProviderTrait;
+
+  public static function getSubscribedEvents(): array {
+    return [
+      'civi.api4.getLinks' => 'alterCaseLinks',
+      'civi.api.respond' => ['alterActivityLinksResult', -50],
+    ];
+  }
+
+  /**
+   * @param \Civi\Core\Event\GenericHookEvent $e
+   * @return void
+   */
+  public static function alterCaseLinks(GenericHookEvent $e): void {
+    // Tweak case view/edit links
+    if ($e->entity === 'Case') {
+      foreach ($e->links as $index => $link) {
+        // Cases are too cumbersome to view in a popup
+        if (in_array($link['ui_action'], ['view', 'update'], TRUE)) {
+          $e->links[$index]['target'] = '';
+        }
+      }
+    }
+  }
+
+  /**
+   * Customize case activity links
+   *
+   * @param \Civi\API\Event\RespondEvent $e
+   * @return void
+   * @throws \CRM_Core_Exception
+   */
+  public static function alterActivityLinksResult(RespondEvent $e): void {
+    $request = $e->getApiRequest();
+    if ($request['version'] == 4 && $request->getEntityName() === 'Activity' && is_a($request, '\Civi\Api4\Action\GetLinks')) {
+      $activityId = $request->getValue('id');
+      $caseId = $request->getValue('case_id');
+      if (!$caseId && $activityId) {
+        $caseId = \CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseActivity', 'case_id', $activityId, 'activity_id');
+      }
+      if (!$caseId) {
+        return;
+      }
+      $links = (array) $e->getResponse();
+      $viewLinkIndex = self::getActionIndex($links, 'view');
+      $editLinkIndex = self::getActionIndex($links, 'update');
+      $deleteLinkIndex = self::getActionIndex($links, 'delete');
+      // Add link to manage case
+      $links[] = [
+        'ui_action' => 'advanced',
+        'api_action' => 'update',
+        'api_values' => NULL,
+        'entity' => 'Case',
+        'path' => "civicrm/contact/view/case?reset=1&id=$caseId&action=view",
+        'text' => ts('Manage Case'),
+        'icon' => CoreUtil::getInfoItem('Case', 'icon'),
+        'weight' => 80,
+        'target' => NULL,
+      ];
+      $idToken = $activityId ?: '[id]';
+      // Change view/edit/delete links to the CiviCase version
+      if (isset($links[$viewLinkIndex]['path'])) {
+        $links[$viewLinkIndex]['path'] = "civicrm/case/activity/view?reset=1&caseid=$caseId&aid=$idToken";
+      }
+      if (isset($links[$editLinkIndex]['path'])) {
+        $links[$editLinkIndex]['path'] = "civicrm/case/activity?reset=1&caseid=$caseId&id=$idToken&action=update";
+      }
+      if (isset($links[$deleteLinkIndex]['path'])) {
+        $links[$deleteLinkIndex]['path'] = "civicrm/case/activity?reset=1&caseid=$caseId&id=$idToken&action=delete";
+      }
+      $e->getResponse()->exchangeArray(array_values($links));
+    }
+  }
+
+}