From 1dc6a54d9240e7ec6a38ae485429e2d47394e07f Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Thu, 22 Jun 2023 16:23:39 -0700 Subject: [PATCH] Move customSearch smart group sql generation to legacycustomsearches extension --- CRM/Contact/BAO/GroupContactCache.php | 57 +++++-------------- CRM/Utils/Hook.php | 32 +++++++++++ .../legacycustomsearches.php | 35 ++++++++++++ 3 files changed, 81 insertions(+), 43 deletions(-) diff --git a/CRM/Contact/BAO/GroupContactCache.php b/CRM/Contact/BAO/GroupContactCache.php index 8fc361e64b..f29a782746 100644 --- a/CRM/Contact/BAO/GroupContactCache.php +++ b/CRM/Contact/BAO/GroupContactCache.php @@ -532,41 +532,6 @@ ORDER BY gc.contact_id, g.children return "SELECT $addSelect, `$idField` AS contact_id FROM ($sql) api_query"; } - /** - * Get sql from a custom search. - * - * We split it up and store custom class - * so temp tables are not destroyed if they are used - * - * @param array $savedSearch - * @param int $groupID - * - * @return string - * @throws \CRM_Core_Exception - */ - protected static function getCustomSearchSQL(array $savedSearch, int $groupID) { - $savedSearchID = $savedSearch['id']; - $excludeClause = "NOT IN ( - SELECT contact_id FROM civicrm_group_contact - WHERE civicrm_group_contact.status = 'Removed' - AND civicrm_group_contact.group_id = $groupID )"; - $addSelect = "$groupID AS group_id"; - $ssParams = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); - // CRM-7021 rectify params to what proximity search expects if there is a value for prox_distance - if (!empty($ssParams)) { - CRM_Contact_BAO_ProximityQuery::fixInputParams($ssParams); - } - $searchSQL = CRM_Contact_BAO_SearchCustom::customClass($ssParams['customSearchID'], $savedSearchID)->contactIDs(); - $searchSQL = str_replace('ORDER BY contact_a.id ASC', '', $searchSQL); - if (strpos($searchSQL, 'WHERE') === FALSE) { - $searchSQL .= " WHERE contact_a.id $excludeClause"; - } - else { - $searchSQL .= " AND contact_a.id $excludeClause"; - } - return preg_replace("/^\s*SELECT /", "SELECT $addSelect, ", $searchSQL); - } - /** * Get array of sql from a saved query object group. * @@ -797,14 +762,20 @@ ORDER BY gc.contact_id, g.children ->execute() ->first(); - if ($savedSearch['api_entity']) { - $sql = self::getApiSQL($savedSearch, $groupID); - } - elseif (!empty($savedSearch['search_custom_id'])) { - $sql = self::getCustomSearchSQL($savedSearch, $groupID); - } - else { - $sql = self::getQueryObjectSQL($savedSearch, $groupID); + $sql = ''; + CRM_Utils_Hook::buildGroupContactCache($savedSearch, $groupID, $sql); + if (!$sql) { + if ($savedSearch['api_entity']) { + $sql = self::getApiSQL($savedSearch, $groupID); + } + elseif (!empty($savedSearch['search_custom_id'])) { + Group::update(FALSE)->addWhere('id', '=', $groupID)->setValues(['is_active' => FALSE])->execute(); + CRM_Core_Session::setStatus(ts('Invalid group %1 found and disabled'), [1 => $groupID]); + return; + } + else { + $sql = self::getQueryObjectSQL($savedSearch, $groupID); + } } } diff --git a/CRM/Utils/Hook.php b/CRM/Utils/Hook.php index a03e2fbccb..9403947013 100644 --- a/CRM/Utils/Hook.php +++ b/CRM/Utils/Hook.php @@ -1768,6 +1768,38 @@ abstract class CRM_Utils_Hook { ); } + /** + * Build the group contact cache for the relevant group. + * + * This hook allows a listener to specify the sql to be used to build a group in + * the group contact cache. + * + * If sql is altered then the api / bao query methods of building the cache will not + * be called. + * + * An example of the sql it might be set to is: + * + * SELECT 7 AS group_id, contact_a.id as contact_id + * FROM civicrm_contact contact_a + * WHERE contact_a.contact_type = 'Household' AND contact_a.household_name LIKE '%' AND ( 1 ) ORDER BY contact_a.id + * AND contact_a.id + * NOT IN ( + * SELECT contact_id FROM civicrm_group_contact + * WHERE civicrm_group_contact.status = 'Removed' + * AND civicrm_group_contact.group_id = 7 ) + * + * @param array $savedSearch + * @param int $groupID + * @param string $sql + */ + public static function buildGroupContactCache(array $savedSearch, int $groupID, string &$sql): void { + $null = NULL; + self::singleton()->invoke(['savedSearch', 'groupID', 'sql'], $savedSearch, $groupID, + $sql, $null, $null, $null, + 'civicrm_buildGroupContactCache' + ); + } + /** * (EXPERIMENTAL) Scan extensions for a list of auto-registered interfaces. * diff --git a/ext/legacycustomsearches/legacycustomsearches.php b/ext/legacycustomsearches/legacycustomsearches.php index 9d16959ce5..056049c041 100644 --- a/ext/legacycustomsearches/legacycustomsearches.php +++ b/ext/legacycustomsearches/legacycustomsearches.php @@ -31,3 +31,38 @@ function legacycustomsearches_civicrm_install() { function legacycustomsearches_civicrm_enable() { _legacycustomsearches_civix_civicrm_enable(); } + +/** + * Determine the sql + * @param array $savedSearch + * @param int $groupID + * @param string $sql + * + * @throws \CRM_Core_Exception + */ +function legacycustomsearches_civicrm_buildGroupContactCache(array $savedSearch, int $groupID, string &$sql): void { + if (empty($savedSearch['search_custom_id'])) { + return; + } + $savedSearchID = $savedSearch['id']; + $excludeClause = " + NOT IN ( + SELECT contact_id FROM civicrm_group_contact + WHERE civicrm_group_contact.status = 'Removed' + AND civicrm_group_contact.group_id = $groupID )"; + $addSelect = "$groupID AS group_id"; + $ssParams = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); + // CRM-7021 rectify params to what proximity search expects if there is a value for prox_distance + if (!empty($ssParams)) { + CRM_Contact_BAO_ProximityQuery::fixInputParams($ssParams); + } + $searchSQL = CRM_Contact_BAO_SearchCustom::customClass($ssParams['customSearchID'], $savedSearchID)->contactIDs(); + $searchSQL = str_replace('ORDER BY contact_a.id ASC', '', $searchSQL); + if (strpos($searchSQL, 'WHERE') === FALSE) { + $searchSQL .= " WHERE contact_a.id $excludeClause"; + } + else { + $searchSQL .= " AND contact_a.id $excludeClause"; + } + $sql = preg_replace("/^\s*SELECT /", "SELECT $addSelect, ", $searchSQL); +} -- 2.25.1