From c36d6d9d589656557b1afca8ae18198ab58c1dc3 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 27 Dec 2021 15:39:58 -0500 Subject: [PATCH] Catch and log nonexistent groups instead of a fatal error When a contact layout is set to filter on one or more groups, and the group is subsequently deleted, it leaves the layout in an unstable state. This catches and logs the error instead of triggering a fatal. --- CRM/Contactlayout/BAO/ContactLayout.php | 28 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/CRM/Contactlayout/BAO/ContactLayout.php b/CRM/Contactlayout/BAO/ContactLayout.php index c6d2046..bea6c17 100644 --- a/CRM/Contactlayout/BAO/ContactLayout.php +++ b/CRM/Contactlayout/BAO/ContactLayout.php @@ -36,7 +36,7 @@ public static function getLayout($cid, $uid = NULL) { $get->addClause('OR', $subClauses); foreach ($get->execute() as $layout) { - if (self::userIsIn($uid, $layout['groups'])) { + if (self::checkGroupFilter($uid, $layout)) { self::loadBlocks($layout, $contact['contact_type']); return $layout; } @@ -48,22 +48,34 @@ public static function getLayout($cid, $uid = NULL) { * Check if the user matches the group filter for a layout * * @param int $uid - * @param array|null $groups + * @param array $layout * * @return bool */ - private static function userIsIn($uid, $groups) { + private static function checkGroupFilter($uid, $layout) { // If no group filter, any user matches - if (!$groups) { + if (empty($layout['groups'])) { + return TRUE; + } + // Convert group names to ids, and verify groups exist + $groupIds = (array) civicrm_api4('Group', 'get', [ + 'where' => [['name', 'IN', $layout['groups']]], + ], ['name' => 'id']); + + // In case groups used by this layout have been deleted + if (count($groupIds) < count($layout['groups'])) { + Civi::log()->warning(sprintf('ContactLayout "%s" cannot filter on nonexistent group "%s".', + $layout['label'], + implode('" and "', array_diff($layout['groups'], array_keys($groupIds))) + )); + } + if (!$groupIds) { + // Can't filter if the groups don't exist. return TRUE; } - $groupIds = array_map(function($groupName) { - return CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupName, 'id', 'name'); - }, $groups); return (bool) \Civi\Api4\Contact::get(FALSE) ->addSelect('id') ->addWhere('id', '=', $uid) - // TODO: Change this back to ('groups:name', 'IN', $groups) when fixed upstream ->addWhere('groups', 'IN', $groupIds) ->execute()->count(); }