Search ext: Add settingsCallback to searchAdmin module
authorColeman Watts <coleman@civicrm.org>
Tue, 13 Oct 2020 21:47:38 +0000 (17:47 -0400)
committerColeman Watts <coleman@civicrm.org>
Wed, 14 Oct 2020 18:19:21 +0000 (14:19 -0400)
ext/search/CRM/Search/Page/Admin.php
ext/search/Civi/Search/Admin.php [new file with mode: 0644]
ext/search/ang/searchAdmin.ang.php
ext/search/ang/searchAdmin.module.js
ext/search/ang/searchAdmin/crmSearch.component.js
ext/search/ang/searchAdmin/crmSearchClause.component.js
ext/search/ang/searchAdmin/crmSearchFunction.component.js

index c1d06ab0f83b76c69423617fdaa68ef3b159be4d..cfded724aae7010c913750772c08fa2cbec63dfd 100644 (file)
  * Angular base page for search admin
  */
 class CRM_Search_Page_Admin extends CRM_Core_Page {
-  /**
-   * @var string[]
-   */
-  private $loadOptions = ['id', 'name', 'label', 'description', 'color', 'icon'];
-
-  /**
-   * @var array
-   */
-  private $schema = [];
 
   /**
    * @var string[]
@@ -30,25 +21,22 @@ class CRM_Search_Page_Admin extends CRM_Core_Page {
 
   public function run() {
     $breadCrumb = [
-      'title' => ts('Search'),
+      'title' => ts('Search Kit'),
       'url' => CRM_Utils_System::url('civicrm/search'),
     ];
     CRM_Utils_System::appendBreadCrumb([$breadCrumb]);
 
-    $this->getSchema();
+    $schema = \Civi\Search\Admin::getSchema();
 
     // If user does not have permission to search any entity, bye bye.
-    if (!$this->allowedEntities) {
+    if (!$schema) {
       CRM_Utils_System::permissionDenied();
     }
 
     // Add client-side vars for the search UI
     $vars = [
-      'operators' => CRM_Utils_Array::makeNonAssociative($this->getOperators()),
-      'schema' => $this->schema,
-      'links' => $this->getLinks(),
-      'loadOptions' => $this->loadOptions,
-      'functions' => CRM_Api4_Page_Api4Explorer::getSqlFunctions(),
+      'schema' => $schema,
+      'links' => \Civi\Search\Admin::getLinks(array_column($schema, 'name')),
     ];
 
     Civi::resources()
@@ -66,82 +54,4 @@ class CRM_Search_Page_Admin extends CRM_Core_Page {
     parent::run();
   }
 
-  /**
-   * @return string[]
-   */
-  private function getOperators() {
-    return [
-      '=' => '=',
-      '!=' => '≠',
-      '>' => '>',
-      '<' => '<',
-      '>=' => '≥',
-      '<=' => '≤',
-      'CONTAINS' => ts('Contains'),
-      'IN' => ts('Is In'),
-      'NOT IN' => ts('Not In'),
-      'LIKE' => ts('Is Like'),
-      'NOT LIKE' => ts('Not Like'),
-      'BETWEEN' => ts('Is Between'),
-      'NOT BETWEEN' => ts('Not Between'),
-      'IS NULL' => ts('Is Null'),
-      'IS NOT NULL' => ts('Not Null'),
-    ];
-  }
-
-  /**
-   * Populates $this->schema & $this->allowedEntities
-   */
-  private function getSchema() {
-    $schema = \Civi\Api4\Entity::get()
-      ->addSelect('name', 'title', 'titlePlural', 'description', 'icon')
-      ->addWhere('name', '!=', 'Entity')
-      ->addOrderBy('titlePlural')
-      ->setChain([
-        'get' => ['$name', 'getActions', ['where' => [['name', '=', 'get']]], ['params']],
-      ])->execute();
-    $getFields = ['name', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize', 'fk_entity'];
-    foreach ($schema as $entity) {
-      // Skip if entity doesn't have a 'get' action or the user doesn't have permission to use get
-      if ($entity['get']) {
-        // Get fields and pre-load options for certain prominent entities
-        $loadOptions = in_array($entity['name'], ['Contact', 'Group']) ? $this->loadOptions : FALSE;
-        if ($loadOptions) {
-          $entity['optionsLoaded'] = TRUE;
-        }
-        $entity['fields'] = civicrm_api4($entity['name'], 'getFields', [
-          'select' => $getFields,
-          'where' => [['permission', 'IS NULL']],
-          'orderBy' => ['label'],
-          'loadOptions' => $loadOptions,
-        ]);
-        // Get the names of params this entity supports (minus some obvious ones)
-        $params = $entity['get'][0];
-        CRM_Utils_Array::remove($params, 'checkPermissions', 'debug', 'chain', 'language');
-        unset($entity['get']);
-        $this->schema[] = ['params' => array_keys($params)] + array_filter($entity);
-        $this->allowedEntities[] = $entity['name'];
-      }
-    }
-  }
-
-  /**
-   * @return array
-   */
-  private function getLinks() {
-    $results = [];
-    $keys = array_flip(['alias', 'entity', 'joinType']);
-    foreach (civicrm_api4('Entity', 'getLinks', ['where' => [['entity', 'IN', $this->allowedEntities]]], ['entity' => 'links']) as $entity => $links) {
-      $entityLinks = [];
-      foreach ($links as $link) {
-        if (!empty($link['entity']) && in_array($link['entity'], $this->allowedEntities)) {
-          // Use entity.alias as array key to avoid duplicates
-          $entityLinks[$link['entity'] . $link['alias']] = array_intersect_key($link, $keys);
-        }
-      }
-      $results[$entity] = array_values($entityLinks);
-    }
-    return array_filter($results);
-  }
-
 }
diff --git a/ext/search/Civi/Search/Admin.php b/ext/search/Civi/Search/Admin.php
new file mode 100644 (file)
index 0000000..6ddc792
--- /dev/null
@@ -0,0 +1,105 @@
+<?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\Search;
+
+/**
+ * Class Admin
+ * @package Civi\Search
+ */
+class Admin {
+
+  /**
+   * @return array
+   */
+  public static function getAdminSettings():array {
+    return [
+      'operators' => \CRM_Utils_Array::makeNonAssociative(self::getOperators()),
+      'functions' => \CRM_Api4_Page_Api4Explorer::getSqlFunctions(),
+    ];
+  }
+
+  /**
+   * @return string[]
+   */
+  public static function getOperators():array {
+    return [
+      '=' => '=',
+      '!=' => '≠',
+      '>' => '>',
+      '<' => '<',
+      '>=' => '≥',
+      '<=' => '≤',
+      'CONTAINS' => ts('Contains'),
+      'IN' => ts('Is In'),
+      'NOT IN' => ts('Not In'),
+      'LIKE' => ts('Is Like'),
+      'NOT LIKE' => ts('Not Like'),
+      'BETWEEN' => ts('Is Between'),
+      'NOT BETWEEN' => ts('Not Between'),
+      'IS NULL' => ts('Is Null'),
+      'IS NOT NULL' => ts('Not Null'),
+    ];
+  }
+
+  /**
+   * Fetch all entities the current user has permission to `get`
+   */
+  public static function getSchema() {
+    $schema = [];
+    $entities = \Civi\Api4\Entity::get()
+      ->addSelect('name', 'title', 'titlePlural', 'description', 'icon')
+      ->addWhere('name', '!=', 'Entity')
+      ->addOrderBy('titlePlural')
+      ->setChain([
+        'get' => ['$name', 'getActions', ['where' => [['name', '=', 'get']]], ['params']],
+      ])->execute();
+    $getFields = ['name', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize', 'fk_entity'];
+    foreach ($entities as $entity) {
+      // Skip if entity doesn't have a 'get' action or the user doesn't have permission to use get
+      if ($entity['get']) {
+        $entity['fields'] = civicrm_api4($entity['name'], 'getFields', [
+          'select' => $getFields,
+          'where' => [['permission', 'IS NULL']],
+          'orderBy' => ['label'],
+        ]);
+        $params = $entity['get'][0];
+        // Entity must support at least these params or it is too weird for search kit
+        if (!array_diff(['select', 'where', 'orderBy', 'limit', 'offset'], array_keys($params))) {
+          \CRM_Utils_Array::remove($params, 'checkPermissions', 'debug', 'chain', 'language', 'select', 'where', 'orderBy', 'limit', 'offset');
+          unset($entity['get']);
+          $schema[] = ['params' => array_keys($params)] + array_filter($entity);
+        }
+      }
+    }
+    return $schema;
+  }
+
+  /**
+   * @return array
+   */
+  public static function getLinks($allowedEntities) {
+    $results = [];
+    $keys = array_flip(['alias', 'entity', 'joinType']);
+    foreach (civicrm_api4('Entity', 'getLinks', ['where' => [['entity', 'IN', $allowedEntities]]], ['entity' => 'links']) as $entity => $links) {
+      $entityLinks = [];
+      foreach ($links as $link) {
+        if (!empty($link['entity']) && in_array($link['entity'], $allowedEntities)) {
+          // Use entity.alias as array key to avoid duplicates
+          $entityLinks[$link['entity'] . $link['alias']] = array_intersect_key($link, $keys);
+        }
+      }
+      $results[$entity] = array_values($entityLinks);
+    }
+    return array_filter($results);
+  }
+
+}
index 1c60e31ee5978808e32935d9a24f3d4060886148..f07fc61de275f719d1f12d7c525a66758086a19c 100644 (file)
@@ -14,4 +14,5 @@ return [
   ],
   'basePages' => [],
   'requires' => ['crmUi', 'crmUtil', 'ngRoute', 'crmRouteBinder', 'ui.sortable', 'ui.bootstrap', 'dialogService', 'api4', 'searchActions'],
+  'settingsFactory' => ['\Civi\Search\Admin', 'getAdminSettings'],
 ];
index 7132e7eb6fca3f72bf84a06155cccd4cbac1c71f..cdb1562baa36914206d91d70d3ba6df9bde6cbf6 100644 (file)
           if (bracketPos >= 0) {
             var parsed = expr.substr(bracketPos).match(/[ ]?([A-Z]+[ ]+)?([\w.:]+)/);
             fieldName = parsed[2];
-            result.fn = _.find(CRM.vars.search.functions, {name: expr.substring(0, bracketPos)});
+            result.fn = _.find(CRM.searchAdmin.functions, {name: expr.substring(0, bracketPos)});
             result.modifier = _.trim(parsed[1]);
           }
           result.field = expr ? getField(fieldName, searchEntity) : undefined;
index 7ebea92db2d90b0d358bbf8ed3660fee4f6b8bf2..19e049ee81f6ff28f30149abc42d60b6f2f7c8b0 100644 (file)
         function enqueue(entity) {
           entity.optionsLoaded = false;
           entities[entity.name] = [entity.name, 'getFields', {
-            loadOptions: CRM.vars.search.loadOptions,
+            loadOptions: ['id', 'name', 'label', 'description', 'color', 'icon'],
             where: [['options', '!=', false]],
             select: ['options']
           }, {name: 'options'}];
index 3258d57bfcc450ac71cdbb6bc1b5f80c48a2c774..884eae6bf53b04846a32c0f0dc78fae7144c7fc6 100644 (file)
@@ -16,7 +16,7 @@
       var ts = $scope.ts = CRM.ts(),
         ctrl = this;
       this.conjunctions = {AND: ts('And'), OR: ts('Or'), NOT: ts('Not')};
-      this.operators = CRM.vars.search.operators;
+      this.operators = CRM.searchAdmin.operators;
       this.sortOptions = {
         axis: 'y',
         connectWith: '.api4-clause-group-sortable',
index 2b8448b55d95eaf86951507791e951c42b4340b2..4ac5870576b649af31787e289399ddfb88063092 100644 (file)
@@ -12,7 +12,7 @@
         ctrl = this;
 
       this.$onInit = function() {
-        ctrl.functions = formatForSelect2(_.where(CRM.vars.search.functions, {category: ctrl.cat}), 'name', 'title');
+        ctrl.functions = formatForSelect2(_.where(CRM.searchAdmin.functions, {category: ctrl.cat}), 'name', 'title');
         var fieldInfo = searchMeta.parseExpr(ctrl.expr);
         ctrl.path = fieldInfo.path + fieldInfo.suffix;
         ctrl.field = fieldInfo.field;
@@ -22,7 +22,7 @@
       };
 
       function initFunction() {
-        ctrl.fnInfo = _.find(CRM.vars.search.functions, {name: ctrl.fn});
+        ctrl.fnInfo = _.find(CRM.searchAdmin.functions, {name: ctrl.fn});
         if (ctrl.fnInfo && _.includes(ctrl.fnInfo.params[0].prefix, 'DISTINCT')) {
           ctrl.modifierAllowed = true;
         }