SearchKit - Preprocess links only once; use api getLinks action
authorcolemanw <coleman@civicrm.org>
Tue, 19 Dec 2023 15:33:41 +0000 (10:33 -0500)
committercolemanw <coleman@civicrm.org>
Sun, 24 Dec 2023 00:29:21 +0000 (19:29 -0500)
Before: Links were being preprocessed by the getLinkInfo() function once-per-link-per-row.

After: Links preprocessed once-per-link. New API action used.

ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php
ext/search_kit/Civi/Api4/Action/SearchDisplay/Run.php

index 32d00aaead1a4f53d51511e7741b138ca0c44cb0..936eae620e9ef98337a6c91de3666874e0d6bfcc 100644 (file)
@@ -508,7 +508,6 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
   }
 
   protected function formatLink(array $link, array $data, string $text = NULL, $index = 0): ?array {
-    $link = $this->getLinkInfo($link);
     if (!$this->checkLinkAccess($link, $data, $index)) {
       return NULL;
     }
@@ -663,10 +662,30 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
   }
 
   /**
-   * @param array{path: string, entity: string, action: string, task: string, join: string, target: string, style: string, title: string, text: string} $link
-   * @return array{path: string, entity: string, action: string, task: string, join: string, target: string, style: string, title: string, text: string, prefix: string}
+   * Fills in info about each link in the search display.
    */
-  private function getLinkInfo(array $link): array {
+  protected function preprocessLinks(): void {
+    foreach ($this->display['settings']['columns'] as &$column) {
+      if (!empty($column['link'])) {
+        $this->preprocessLink($column['link']);
+      }
+      if (!empty($column['links'])) {
+        foreach ($column['links'] as &$link) {
+          $this->preprocessLink($link);
+        }
+      }
+    }
+    if (!empty($this->display['settings']['toolbar'])) {
+      foreach ($this->display['settings']['toolbar'] as &$button) {
+        $this->preprocessLink($button);
+      }
+    }
+  }
+
+  /**
+   * @param array{path: string, entity: string, action: string, task: string, join: string, target: string, style: string, title: string, text: string, prefix: string} $link
+   */
+  private function preprocessLink(array &$link): void {
     $link += [
       'path' => '',
       'target' => '',
@@ -687,8 +706,15 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
         $link['prefix'] = $link['join'] . '.';
       }
       // Get path from action
-      if (!$link['path'] && !empty($link['action'])) {
-        $link['path'] = CoreUtil::getInfoItem($entity, 'paths')[$link['action']] ?? NULL;
+      if (!empty($link['action'])) {
+        $getLinks = civicrm_api4($entity, 'getLinks', [
+          'checkPermissions' => FALSE,
+          'where' => [
+            ['ui_action', '=', $link['action']],
+          ],
+        ]);
+        $link['path'] = $getLinks[0]['path'] ?? NULL;
+        $link['entity'] = $getLinks[0]['entity'] ?? NULL;
         // This is a bit clunky, the function_join_field gets un-munged later by $this->getJoinFromAlias()
         if ($this->canAggregate($link['prefix'] . $idKey)) {
           $link['prefix'] = 'GROUP_CONCAT_' . str_replace('.', '_', $link['prefix']);
@@ -724,7 +750,6 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
       }
       $link['key'] = $link['prefix'] . $idKey;
     }
-    return $link;
   }
 
   /**
@@ -734,7 +759,6 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
    * @return array
    */
   private function getLinkTokens(array $link): array {
-    $link = $this->getLinkInfo($link);
     $tokens = [];
     if (!$link['path'] && !empty($link['task'])) {
       $tokens[] = $link['prefix'] . $this->getIdKeyName($link['entity']);
index 7c6e9d8b5ab1f7aad1f94ca912b816d474a8b02a..01d587fa22a79b8a60b03aaf899fadecd05a8635 100644 (file)
@@ -44,6 +44,7 @@ class Run extends AbstractRunAction {
     // Pager can operate in "page" mode for traditional pager, or "scroll" mode for infinite scrolling
     $pagerMode = NULL;
 
+    $this->preprocessLinks();
     $this->augmentSelectClause($apiParams);
     $this->applyFilters();