diff --git a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php index f6957086d079..3e6450edde21 100644 --- a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php +++ b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php @@ -373,6 +373,9 @@ private function formatLinksColumn($column, $data): array { $out['text'] = $this->replaceTokens($column['text'], $data, 'view'); } foreach ($column['links'] as $item) { + if (!$this->checkLinkCondition($item, $data)) { + continue; + } $path = $this->replaceTokens($this->getLinkPath($item, $data), $data, 'url'); if ($path) { $link = [ @@ -390,6 +393,30 @@ private function formatLinksColumn($column, $data): array { return $out; } + /** + * Check if a link should be shown based on its conditions. + * + * Given a link, check if it is set to be displayed conditionally. + * If so, evaluate the condition, else return TRUE. + * + * @param array $item + * @param array $data + * @return bool + */ + private function checkLinkCondition(array $item, array $data): bool { + if (empty($item['condition'][0]) || empty($item['condition'][1])) { + return TRUE; + } + $op = $item['condition'][1]; + if ($item['condition'][0] === 'check user permission') { + if (!empty($item['condition'][2]) && !\CRM_Core_Permission::check($item['condition'][2])) { + return $op !== '='; + } + return TRUE; + } + return ArrayQueryActionTrait::filterCompare($data, $item['condition']); + } + /** * @param array $link * @param array $data diff --git a/ext/search_kit/Civi/Search/Admin.php b/ext/search_kit/Civi/Search/Admin.php index 2fb9d9f49782..e6346394119c 100644 --- a/ext/search_kit/Civi/Search/Admin.php +++ b/ext/search_kit/Civi/Search/Admin.php @@ -30,11 +30,12 @@ class Admin { public static function getAdminSettings():array { $schema = self::getSchema(); $extensions = \CRM_Extension_System::singleton()->getMapper(); - return [ + $data = [ 'schema' => self::addImplicitFKFields($schema), 'joins' => self::getJoins($schema), 'pseudoFields' => AbstractRunAction::getPseudoFields(), 'operators' => \CRM_Utils_Array::makeNonAssociative(self::getOperators()), + 'permissions' => [], 'functions' => self::getSqlFunctions(), 'displayTypes' => Display::getDisplayTypes(['id', 'name', 'label', 'description', 'icon']), 'styles' => \CRM_Utils_Array::makeNonAssociative(self::getStyles()), @@ -49,6 +50,19 @@ public static function getAdminSettings():array { ->addWhere('used_for', 'CONTAINS', 'civicrm_saved_search') ->execute(), ]; + $perms = \Civi\Api4\Permission::get() + ->addWhere('group', 'IN', ['civicrm', 'cms']) + ->addWhere('is_active', '=', 1) + ->setOrderBy(['title' => 'ASC']) + ->execute(); + foreach ($perms as $perm) { + $data['permissions'][] = [ + 'id' => $perm['name'], + 'text' => $perm['title'], + 'description' => $perm['description'] ?? NULL, + ]; + } + return $data; } /** diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js index 6623f2933dcf..524eb5f6b547 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js @@ -8,11 +8,26 @@ apiParams: '<', links: '<' }, + require: { + crmSearchAdmin: '^crmSearchAdmin' + }, templateUrl: '~/crmSearchAdmin/crmSearchAdminLinkGroup.html', controller: function ($scope, $element, $timeout, searchMeta) { var ts = $scope.ts = CRM.ts('org.civicrm.search_kit'), ctrl = this, - linkProps = ['path', 'entity', 'action', 'join', 'target', 'icon', 'text', 'style']; + linkProps = ['path', 'entity', 'action', 'join', 'target', 'icon', 'text', 'style', 'condition']; + + var permissionOperators = [ + {key: '=', value: ts('Has')}, + {key: '!=', value: ts('Lacks')} + ]; + + this.getOperators = function(clause) { + if (clause[0] === 'check user permission') { + return permissionOperators; + } + return CRM.crmSearchAdmin.operators; + }; this.styles = CRM.crmSearchAdmin.styles; @@ -20,6 +35,26 @@ return _.findWhere(this.styles, {key: item.style}); }; + this.getField = searchMeta.getField; + + this.fields = function() { + var selectFields = ctrl.crmSearchAdmin.getSelectFields(); + var permissionField = [{ + text: ts('Current User Permission'), + id: 'check user permission', + description: ts('Check permission of logged-in user') + }]; + return {results: permissionField.concat(selectFields)}; + }; + + this.onChangeCondition = function(item) { + if (item.condition[0]) { + item.condition[1] = '='; + } else { + item.condition = []; + } + }; + this.sortableOptions = { containment: 'tbody', direction: 'vertical', @@ -32,23 +67,31 @@ } }; + this.permissions = CRM.crmSearchAdmin.permissions; + $scope.pickIcon = function(index) { searchMeta.pickIcon().then(function(icon) { ctrl.group[index].icon = icon; }); }; + function setDefaults(item, newValue) { + _.each(linkProps, function(prop) { + item[prop] = newValue[prop] || (prop === 'condition' ? [] : ''); + }); + } + this.addItem = function(item) { - ctrl.group.push(_.pick(item, linkProps)); + var newItem = _.pick(item, linkProps); + setDefaults(newItem, newItem); + ctrl.group.push(newItem); }; this.onChangeLink = function(item, newValue) { if (newValue.path === 'civicrm/') { newValue = JSON.parse(this.default); } - _.each(linkProps, function(prop) { - item[prop] = newValue[prop] || ''; - }); + setDefaults(item, newValue); }; this.serialize = JSON.stringify; @@ -58,11 +101,15 @@ style: 'default', text: ts('Link'), icon: 'fa-external-link', + condition: [], path: 'civicrm/' }); var defaultLinks = _.filter(ctrl.links, function(link) { return !link.join; }); + _.each(ctrl.group, function(item) { + setDefaults(item, item); + }); if (!ctrl.group.length) { if (defaultLinks.length) { _.each(defaultLinks, ctrl.addItem); diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html index fc67712617b1..86af85b40480 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html @@ -6,6 +6,7 @@