From b8ecfad280bda11c5d90f7f029651926c74b63ad Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Tue, 13 Sep 2022 17:08:03 -0400 Subject: [PATCH] SearchKit - Improve metadata for ContactType & add standalone path to edit form Giving the listing page and the edit form seperate url paths allow each to be replaced incrimentally by the civicrm_admin_ui extension. --- CRM/Admin/Form/ContactType.php | 7 +++++++ CRM/Admin/Page/ContactType.php | 5 ++--- CRM/Contact/BAO/ContactType.php | 20 +++++++++++++++++++ CRM/Contact/DAO/ContactType.php | 13 +++++++++++- CRM/Core/xml/Menu/Admin.xml | 5 +++++ CRM/Utils/Check/Component/ContactTypes.php | 2 +- Civi/Api4/ContactType.php | 2 +- Civi/Api4/Generic/DAODeleteAction.php | 4 +++- .../SearchDisplay/AbstractRunAction.php | 11 ++++++---- xml/schema/Contact/ContactType.xml | 5 +++++ 10 files changed, 63 insertions(+), 11 deletions(-) diff --git a/CRM/Admin/Form/ContactType.php b/CRM/Admin/Form/ContactType.php index 386bd4785c..676a7e4e97 100644 --- a/CRM/Admin/Form/ContactType.php +++ b/CRM/Admin/Form/ContactType.php @@ -20,6 +20,13 @@ */ class CRM_Admin_Form_ContactType extends CRM_Admin_Form { + public function preProcess(): void { + CRM_Utils_Request::retrieve('action', 'String', $this); + CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, 0); + $this->set('BAOName', 'CRM_Contact_BAO_ContactType'); + parent::preProcess(); + } + /** * Build the form object. */ diff --git a/CRM/Admin/Page/ContactType.php b/CRM/Admin/Page/ContactType.php index be396a9709..593c583f3c 100644 --- a/CRM/Admin/Page/ContactType.php +++ b/CRM/Admin/Page/ContactType.php @@ -50,7 +50,7 @@ class CRM_Admin_Page_ContactType extends CRM_Core_Page_Basic { self::$_links = [ CRM_Core_Action::UPDATE => [ 'name' => ts('Edit'), - 'url' => 'civicrm/admin/options/subtype', + 'url' => 'civicrm/admin/options/subtype/edit', 'qs' => 'action=update&id=%%id%%&reset=1', 'title' => ts('Edit Contact Type'), ], @@ -66,7 +66,7 @@ class CRM_Admin_Page_ContactType extends CRM_Core_Page_Basic { ], CRM_Core_Action::DELETE => [ 'name' => ts('Delete'), - 'url' => 'civicrm/admin/options/subtype', + 'url' => 'civicrm/admin/options/subtype/edit', 'qs' => 'action=delete&id=%%id%%', 'title' => ts('Delete Contact Type'), ], @@ -81,7 +81,6 @@ class CRM_Admin_Page_ContactType extends CRM_Core_Page_Basic { public function run() { $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 0); $this->assign('action', $action); - $id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, 0); if (!$action) { $this->browse(); } diff --git a/CRM/Contact/BAO/ContactType.php b/CRM/Contact/BAO/ContactType.php index dfafc2c0c7..dcf4150abd 100644 --- a/CRM/Contact/BAO/ContactType.php +++ b/CRM/Contact/BAO/ContactType.php @@ -886,4 +886,24 @@ WHERE ($subtypeClause)"; return $contactTypes; } + /** + * @param string $entityName + * @param string $action + * @param array $record + * @param $userID + * @return bool + * @see CRM_Core_DAO::checkAccess + */ + public static function _checkAccess(string $entityName, string $action, array $record, $userID): bool { + // Only records with a parent may be deleted + if ($action === 'delete') { + if (!array_key_exists('parent_id', $record)) { + $record['parent_id'] = CRM_Core_DAO::getFieldValue(parent::class, $record['id'], 'parent_id'); + } + return (bool) $record['parent_id']; + } + // Gatekeeper permissions suffice for everything else + return TRUE; + } + } diff --git a/CRM/Contact/DAO/ContactType.php b/CRM/Contact/DAO/ContactType.php index 0ae0d52748..6d795d0493 100644 --- a/CRM/Contact/DAO/ContactType.php +++ b/CRM/Contact/DAO/ContactType.php @@ -6,7 +6,7 @@ * * Generated from xml/schema/CRM/Contact/ContactType.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:13c81c203681009e8f71fd8387ebdbc2) + * (GenCodeChecksum:9858d69cd4bfdc5a3ce45c77eecd1145) */ /** @@ -30,6 +30,17 @@ class CRM_Contact_DAO_ContactType extends CRM_Core_DAO { */ public static $_log = FALSE; + /** + * Paths for accessing this entity in the UI. + * + * @var string[] + */ + protected static $_paths = [ + 'add' => 'civicrm/admin/options/subtype/edit?action=add&reset=1', + 'update' => 'civicrm/admin/options/subtype/edit?action=update&id=[id]&reset=1', + 'delete' => 'civicrm/admin/options/subtype/edit?action=delete&id=[id]&reset=1', + ]; + /** * Contact Type ID * diff --git a/CRM/Core/xml/Menu/Admin.xml b/CRM/Core/xml/Menu/Admin.xml index 596018228a..030b2b03d9 100644 --- a/CRM/Core/xml/Menu/Admin.xml +++ b/CRM/Core/xml/Menu/Admin.xml @@ -125,6 +125,11 @@ Customize Data and Screens 40 + + civicrm/admin/options/subtype/edit + Edit Contact Type + CRM_Admin_Form_ContactType + civicrm/admin/options/gender Gender Options diff --git a/CRM/Utils/Check/Component/ContactTypes.php b/CRM/Utils/Check/Component/ContactTypes.php index bfd2983d1f..ebeee75f9d 100644 --- a/CRM/Utils/Check/Component/ContactTypes.php +++ b/CRM/Utils/Check/Component/ContactTypes.php @@ -41,7 +41,7 @@ class CRM_Utils_Check_Component_ContactTypes extends CRM_Utils_Check_Component { 'fa-picture-o' ); foreach ($contactTypesWithImages as $contactType) { - $message->addAction($contactType['label'], FALSE, 'href', ['path' => 'civicrm/admin/options/subtype', 'query' => ['action' => 'update', 'id' => $contactType['id'], 'reset' => 1]], 'fa-pencil'); + $message->addAction($contactType['label'], FALSE, 'href', ['path' => 'civicrm/admin/options/subtype/edit', 'query' => ['action' => 'update', 'id' => $contactType['id'], 'reset' => 1]], 'fa-pencil'); } $messages[] = $message; } diff --git a/Civi/Api4/ContactType.php b/Civi/Api4/ContactType.php index e949845613..cf478def15 100644 --- a/Civi/Api4/ContactType.php +++ b/Civi/Api4/ContactType.php @@ -21,7 +21,7 @@ namespace Civi\Api4; * * @see https://docs.civicrm.org/user/en/latest/organising-your-data/contacts/#contact-subtypes * @see \Civi\Api4\Contact - * @searchable none + * @searchable secondary * @since 5.19 * @package Civi\Api4 */ diff --git a/Civi/Api4/Generic/DAODeleteAction.php b/Civi/Api4/Generic/DAODeleteAction.php index 3dbab24757..cd7a32fc1d 100644 --- a/Civi/Api4/Generic/DAODeleteAction.php +++ b/Civi/Api4/Generic/DAODeleteAction.php @@ -36,8 +36,10 @@ class DAODeleteAction extends AbstractBatchAction { $items = $this->getBatchRecords(); if ($this->getCheckPermissions()) { + $idField = CoreUtil::getIdFieldName($this->getEntityName()); foreach ($items as $key => $item) { - if (!CoreUtil::checkAccessRecord($this, $item, \CRM_Core_Session::getLoggedInContactID() ?: 0)) { + // Don't pass the entire item because only the id is a trusted value + if (!CoreUtil::checkAccessRecord($this, [$idField => $item[$idField]], \CRM_Core_Session::getLoggedInContactID() ?: 0)) { throw new UnauthorizedException("ACL check failed"); } $items[$key]['check_permissions'] = TRUE; diff --git a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php index 6d417c4baf..b06f67c819 100644 --- a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php +++ b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php @@ -509,18 +509,21 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction { if ($prefix) { $path = str_replace('[', '[' . $prefix, $path); } - // Check access for edit/update links + // Check access for edit/update/delete links // (presumably if a record is shown in SearchKit the user already has view access, and the check is expensive) if ($path && isset($data) && !in_array($link['action'], ['view', 'preview'], TRUE)) { $id = $data[$prefix . $idKey] ?? NULL; $id = is_array($id) ? $id[$index] ?? NULL : $id; if ($id) { + $values = [$idField => $id]; + // If not aggregated, add other values to help checkAccess be efficient + if (!is_array($data[$prefix . $idKey])) { + $values += \CRM_Utils_Array::filterByPrefix($data, $prefix); + } $access = civicrm_api4($link['entity'], 'checkAccess', [ // Fudge links with funny action names to check 'update' 'action' => $link['action'] === 'delete' ? 'delete' : 'update', - 'values' => [ - $idField => $id, - ], + 'values' => $values, ], 0)['access']; if (!$access) { return NULL; diff --git a/xml/schema/Contact/ContactType.xml b/xml/schema/Contact/ContactType.xml index b9fe0b75b5..aec9c423fa 100644 --- a/xml/schema/Contact/ContactType.xml +++ b/xml/schema/Contact/ContactType.xml @@ -6,6 +6,11 @@ civicrm_contact_type Provide type information for contacts 3.1 + + civicrm/admin/options/subtype/edit?action=add&reset=1 + civicrm/admin/options/subtype/edit?action=update&id=[id]&reset=1 + civicrm/admin/options/subtype/edit?action=delete&id=[id]&reset=1 + id Contact Type ID -- 2.25.1