Merge branch '5.31' into master
authorColeman Watts <coleman@civicrm.org>
Thu, 29 Oct 2020 21:19:51 +0000 (17:19 -0400)
committerColeman Watts <coleman@civicrm.org>
Thu, 29 Oct 2020 21:19:51 +0000 (17:19 -0400)
1  2 
ext/search/Civi/Search/Admin.php
ext/search/ang/searchActions/SaveSmartGroup.ctrl.js
ext/search/ang/searchActions/crmSearchActionUpdate.html
ext/search/ang/searchActions/crmSearchActions.component.js
ext/search/ang/searchAdmin/crmSearch.component.js
ext/search/ang/searchAdmin/crmSearch.html
tests/phpunit/api/v4/Entity/ConformanceTest.php

index 4cbc53d1145448c6846a1261e29d77b72c251fef,0000000000000000000000000000000000000000..a0de3e6059a827fdd1dc68a227007e0b3a5d4a83
mode 100644,000000..100644
--- /dev/null
@@@ -1,105 -1,0 +1,105 @@@
-       ->addSelect('name', 'title', 'titlePlural', 'description', 'icon')
 +<?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()
-       ->addOrderBy('titlePlural')
++      ->addSelect('name', 'title', 'title_plural', 'description', 'icon')
 +      ->addWhere('name', '!=', 'Entity')
++      ->addOrderBy('title_plural')
 +      ->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' => [['name', 'NOT IN', ['api_key', 'hash']]],
 +          '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 a7bfb3cef55f7a9d922724b5494b0a150bce312f,0d00f1bb2c2bd7f47956b72f36919d5f7f1123f9..2638d5c2bbbaef3178cd72424128a8bedfbd3f9b
@@@ -7,30 -7,15 +7,30 @@@
        refresh: '&',
        ids: '<'
      },
 -    templateUrl: '~/search/crmSearchActions.html',
 +    templateUrl: '~/searchActions/crmSearchActions.html',
      controller: function($scope, crmApi4, dialogService, searchMeta) {
        var ts = $scope.ts = CRM.ts(),
 -        ctrl = this;
 +        ctrl = this,
 +        initialized = false,
 +        unwatchIDs = $scope.$watch('$ctrl.ids.length', watchIDs);
  
 -      this.$onInit = function() {
 +      function watchIDs() {
 +        if (ctrl.ids && ctrl.ids.length && !initialized) {
 +          unwatchIDs();
 +          initialized = true;
 +          initialize();
 +        }
 +      }
 +
 +      function initialize() {
-         var entityTitle = searchMeta.getEntity(ctrl.entity).titlePlural;
+         var entityTitle = searchMeta.getEntity(ctrl.entity).title_plural;
 -        if (!ctrl.actions) {
 -          var actions = _.transform(_.cloneDeep(CRM.vars.search.actions), function (actions, action) {
 +        crmApi4(ctrl.entity, 'getActions', {
 +          where: [['name', 'IN', ['update', 'delete']]],
 +        }, ['name']).then(function(allowed) {
 +          _.each(allowed, function(action) {
 +            CRM.searchActions.tasks[action].entities.push(ctrl.entity);
 +          });
 +          var actions = _.transform(_.cloneDeep(CRM.searchActions.tasks), function(actions, action) {
              if (_.includes(action.entities, ctrl.entity)) {
                action.title = action.title.replace('%1', entityTitle);
                actions.push(action);