diff --git a/ext/search_kit/Civi/Search/SearchDisplayChecks.php b/ext/search_kit/Civi/Search/SearchDisplayChecks.php new file mode 100644 index 000000000000..6ac36c52b936 --- /dev/null +++ b/ext/search_kit/Civi/Search/SearchDisplayChecks.php @@ -0,0 +1,82 @@ + 'runChecks']; + } + + /** + * @see \CRM_Utils_Hook::check() + */ + public function runChecks(&$messages, $statusNames = [], $includeDisabled = FALSE) { + if (!empty($statusNames) && !preg_grep('/^' . preg_quote(static::PREFIX, '/') . '/', $statusNames)) { + return; + } + + $displays = SearchDisplay::get(FALSE) + ->addSelect('id', 'label', 'type', 'settings', 'saved_search_id', 'saved_search_id.api_entity', 'saved_search_id.api_params') + ->execute(); + foreach ($displays as $display) { + $issues = $this->validateSearchDisplay($display['saved_search_id.api_entity'], $display['saved_search_id.api_params'], $display['settings']); + if (!empty($issues)) { + $message = new \CRM_Utils_Check_Message( + static::PREFIX . $display['id'], + '

' . ts('This record appears to have invalid settings:') . '

' . + '', + ts('Search Display "%1" (#%2)', [1 => $display['label'], 2 => $display['id']]), + LogLevel::WARNING, + 'fa-search' + ); + if (!empty($display['saved_search_id'])) { + $message->addAction(ts('Edit search'), FALSE, 'href', [ + 'url' => \Civi::url('backend://civicrm/admin/search#/edit/')->addFragment($display['saved_search_id']), + ]); + } + + $messages[] = $message; + } + } + } + + public function validateSearchDisplay(string $entity, array $params, array $settings): array { + $issues = []; + + $fields = civicrm_api4($entity, 'getFields', ['checkPermissions' => FALSE])->indexBy('name')->getArrayCopy(); + foreach ($settings['columns'] as $column) { + if ($column['type'] !== 'field') { + continue; + } + + // TODO: A better way to validate subfields. For now, we'll just check the first layer. Much better than nothing. + [$key] = preg_split('/[:\.]/', $column['key']); + if (!isset($fields[$key])) { + $issues[] = ts('Unrecognized field "%1"', [1 => htmlentities($column['key'])]); + } + } + + return $issues; + } + +}