3 class CRM_Search_Page_Build
extends CRM_Core_Page
{
7 private $loadOptions = ['id', 'name', 'label', 'description', 'color', 'icon'];
17 private $allowedEntities = [];
19 public function run() {
21 'title' => ts('Search'),
22 'url' => CRM_Utils_System
::url('civicrm/search'),
24 CRM_Utils_System
::appendBreadCrumb([$breadCrumb]);
28 // If user does not have permission to search any entity, bye bye.
29 if (!$this->allowedEntities
) {
30 CRM_Utils_System
::permissionDenied();
33 // Add client-side vars for the search UI
35 'operators' => \CRM_Core_DAO
::acceptedSQLOperators(),
36 'schema' => $this->schema
,
37 'links' => $this->getLinks(),
38 'loadOptions' => $this->loadOptions
,
39 'actions' => $this->getActions(),
40 'functions' => CRM_Api4_Page_Api4Explorer
::getSqlFunctions(),
44 ->addPermissions(['edit groups', 'administer reserved groups'])
45 ->addVars('search', $vars);
47 // Load angular module
48 $loader = new Civi\Angular\
AngularLoader();
49 $loader->setModules(['search']);
50 $loader->setPageName('civicrm/search');
52 'defaultRoute' => '/Contact',
59 * Populates $this->schema & $this->allowedEntities
61 private function getSchema() {
62 $schema = \Civi\Api4\Entity
::get()
63 ->addSelect('name', 'title', 'description', 'icon')
64 ->addWhere('name', '!=', 'Entity')
67 'get' => ['$name', 'getActions', ['where' => [['name', '=', 'get']]], ['params']],
69 $getFields = ['name', 'title', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize'];
70 foreach ($schema as $entity) {
71 // Skip if entity doesn't have a 'get' action or the user doesn't have permission to use get
73 // Get fields and pre-load options for certain prominent entities
74 $loadOptions = in_array($entity['name'], ['Contact', 'Group']) ?
$this->loadOptions
: FALSE;
76 $entity['optionsLoaded'] = TRUE;
78 $entity['fields'] = civicrm_api4($entity['name'], 'getFields', [
79 'select' => $getFields,
80 'where' => [['permission', 'IS NULL']],
81 'orderBy' => ['title'],
82 'loadOptions' => $loadOptions,
84 // Get the names of params this entity supports (minus some obvious ones)
85 $params = $entity['get'][0];
86 CRM_Utils_Array
::remove($params, 'checkPermissions', 'debug', 'chain', 'language');
87 unset($entity['get']);
88 $this->schema
[] = ['params' => array_keys($params)] +
array_filter($entity);
89 $this->allowedEntities
[] = $entity['name'];
97 private function getLinks() {
99 $keys = array_flip(['alias', 'entity', 'joinType']);
100 foreach (civicrm_api4('Entity', 'getLinks', ['where' => [['entity', 'IN', $this->allowedEntities
]]], ['entity' => 'links']) as $entity => $links) {
102 foreach ($links as $link) {
103 if (!empty($link['entity']) && in_array($link['entity'], $this->allowedEntities
)) {
104 // Use entity.alias as array key to avoid duplicates
105 $entityLinks[$link['entity'] . $link['alias']] = array_intersect_key($link, $keys);
108 $results[$entity] = array_values($entityLinks);
110 return array_filter($results);
116 private function getActions() {
117 // Note: the placeholder %1 will be replaced with entity name on the clientside
120 'title' => ts('Export %1'),
121 'icon' => 'fa-file-excel-o',
122 'entities' => array_keys(CRM_Export_BAO_Export
::getComponents()),
124 'path' => "'civicrm/export/standalone'",
125 'query' => "{entity: entity, id: ids.join(',')}",
129 'title' => ts('Update %1'),
132 'uiDialog' => ['templateUrl' => '~/search/crmSearchActions/crmSearchActionUpdate.html'],
135 'title' => ts('Delete %1'),
136 'icon' => 'fa-trash',
138 'uiDialog' => ['templateUrl' => '~/search/crmSearchActions/crmSearchActionDelete.html'],
142 // Check permissions for update & delete actions
143 foreach ($this->allowedEntities
as $entity) {
144 $result = civicrm_api4($entity, 'getActions', [
145 'where' => [['name', 'IN', ['update', 'delete']]],
147 foreach ($result as $action) {
148 // Contacts have their own delete action
149 if (!($entity === 'Contact' && $action === 'delete')) {
150 $actions[$action]['entities'][] = $entity;
155 // Add contact tasks which support standalone mode (with a 'url' property)
156 $contactTasks = CRM_Contact_Task
::permissionedTaskTitles(CRM_Core_Permission
::getPermission());
157 foreach (CRM_Contact_Task
::tasks() as $id => $task) {
158 if (isset($contactTasks[$id]) && !empty($task['url'])) {
159 $actions['contact.' . $id] = [
160 'title' => $task['title'],
161 'entities' => ['Contact'],
162 'icon' => $task['icon'] ??
'fa-gear',
164 'path' => "'{$task['url']}'",
165 'query' => "{cids: ids.join(',')}",