From 9aea8e14859f3502e257ffea9315ee8d62d04abc Mon Sep 17 00:00:00 2001 From: eileenmcnaugton Date: Mon, 24 Oct 2016 21:50:26 +1300 Subject: [PATCH] CRM-19557 Fix ACL caching function to not use inefficient query for view my contact Conflicts: CRM/Contact/BAO/Contact/Permission.php --- CRM/ACL/API.php | 13 +++++++++---- CRM/Contact/BAO/Contact/Permission.php | 20 +++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/CRM/ACL/API.php b/CRM/ACL/API.php index 113bcce0e9..27ce2b1561 100644 --- a/CRM/ACL/API.php +++ b/CRM/ACL/API.php @@ -84,6 +84,10 @@ class CRM_ACL_API { * @param bool $skipDeleteClause * Don't add delete clause if this is true,. * this means it is handled by generating query + * @param bool $skipOwnContactClause + * Do not add 'OR contact_id = $userID' to the where clause. + * This is a hideously inefficient query and should be avoided + * wherever possible. * * @return string * the group where clause for this user @@ -94,7 +98,8 @@ class CRM_ACL_API { &$whereTables, $contactID = NULL, $onlyDeleted = FALSE, - $skipDeleteClause = FALSE + $skipDeleteClause = FALSE, + $skipOwnContactClause = FALSE ) { // the default value which is valid for the final AND $deleteClause = ' ( 1 ) '; @@ -131,9 +136,9 @@ class CRM_ACL_API { ) ); - // Add permission on self - if ($contactID && (CRM_Core_Permission::check('edit my contact') || - $type == self::VIEW && CRM_Core_Permission::check('view my contact')) + // Add permission on self if we really hate our server or have hardly any contacts. + if (!$skipOwnContactClause && $contactID && (CRM_Core_Permission::check('edit my contact') || + $type == self::VIEW && CRM_Core_Permission::check('view my contact')) ) { $where = "(contact_a.id = $contactID OR ($where))"; } diff --git a/CRM/Contact/BAO/Contact/Permission.php b/CRM/Contact/BAO/Contact/Permission.php index 88767deb9a..ceb765cdad 100644 --- a/CRM/Contact/BAO/Contact/Permission.php +++ b/CRM/Contact/BAO/Contact/Permission.php @@ -103,7 +103,7 @@ class CRM_Contact_BAO_Contact_Permission { SELECT contact_id FROM civicrm_acl_contact_cache {$LEFT_JOIN_DELETED} -WHERE contact_id IN ({$contact_id_list}) +WHERE contact_id IN ({$contact_id_list}) AND user_id = {$contactID} AND operation = '{$operation}' {$AND_CAN_ACCESS_DELETED}"; @@ -211,6 +211,7 @@ WHERE contact_a.id = %1 AND $permission $operationClause = " operation = 'Edit' "; $operation = 'Edit'; } + $queryParams = array(1 => array($userID, 'Integer')); if (!$force) { // skip if already calculated @@ -225,8 +226,7 @@ FROM civicrm_acl_contact_cache WHERE user_id = %1 AND $operationClause "; - $params = array(1 => array($userID, 'Integer')); - $count = CRM_Core_DAO::singleValueQuery($sql, $params); + $count = CRM_Core_DAO::singleValueQuery($sql, $queryParams); if ($count > 0) { $_processed[$type][$userID] = 1; return; @@ -236,7 +236,7 @@ AND $operationClause $tables = array(); $whereTables = array(); - $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, $userID); + $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, $userID, FALSE, FALSE, TRUE); $from = CRM_Contact_BAO_Query::fromClause($whereTables); CRM_Core_DAO::executeQuery(" @@ -247,6 +247,16 @@ SELECT DISTINCT $userID as user_id, contact_a.id as contact_id, '{$operation}' a WHERE $permission AND ac.user_id IS NULL "); + + // Add in a row for the logged in contact. Do not try to combine with the above query or an ugly OR will appear in + // the permission clause. + if (CRM_Core_Permission::check('edit my contact') || + ($type == CRM_Core_Permission::VIEW && CRM_Core_Permission::check('view my contact'))) { + if (!CRM_Core_DAO::executeQuery(" + SELECT count(*) FROM civicrm_acl_contact_cache WHERE user_id = %1 AND contact_id = %1 AND operation = '{$operation}'", $queryParams)) { + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) VALUES(%1, %1, '{$operation}')"); + } + } $_processed[$type][$userID] = 1; } @@ -353,7 +363,7 @@ AND ac.user_id IS NULL $queries[] = " SELECT civicrm_relationship.{$contact_id_column} AS contact_id - FROM civicrm_relationship + FROM civicrm_relationship {$LEFT_JOIN_DELETED} WHERE civicrm_relationship.{$user_id_column} = {$contactID} AND civicrm_relationship.{$contact_id_column} IN ({$contact_id_list}) -- 2.25.1