From d4d33aad9ee5c4ba141749975eec0cb96f1938bf Mon Sep 17 00:00:00 2001 From: colemanw Date: Mon, 18 Sep 2023 19:08:19 -0400 Subject: [PATCH] Add userId and conditions to hook_civicrm_selectWhereClause signature --- CRM/Activity/BAO/Activity.php | 5 ++-- CRM/Case/BAO/Case.php | 5 ++-- CRM/Case/BAO/CaseContact.php | 3 ++- CRM/Contact/BAO/Contact.php | 5 ++-- CRM/Contact/BAO/Group.php | 5 ++-- CRM/Contact/BAO/RelationshipCache.php | 5 ++-- CRM/Contribute/BAO/ContributionSoft.php | 5 ++-- CRM/Core/BAO/CustomValue.php | 3 ++- CRM/Core/BAO/File.php | 25 ++++++++++--------- CRM/Core/BAO/Note.php | 4 +-- CRM/Core/BAO/UFJoin.php | 5 ++-- CRM/Core/BAO/UFMatch.php | 5 ++-- CRM/Core/BAO/UserJob.php | 5 ++-- CRM/Core/DAO.php | 16 +++++++++--- CRM/Price/BAO/LineItem.php | 5 ++-- CRM/Queue/BAO/Queue.php | 4 +-- CRM/Utils/Hook.php | 13 +++++++--- .../CRM/OAuth/BAO/OAuthContactToken.php | 5 ++-- 18 files changed, 75 insertions(+), 48 deletions(-) diff --git a/CRM/Activity/BAO/Activity.php b/CRM/Activity/BAO/Activity.php index 821034f9a5..5d74041ed6 100644 --- a/CRM/Activity/BAO/Activity.php +++ b/CRM/Activity/BAO/Activity.php @@ -802,10 +802,11 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity { /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; $permittedActivityTypeIDs = self::getPermittedActivityTypes(); if (!empty($conditions['activity_type_id'])) { @@ -827,7 +828,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity { $contactClause = implode(' AND contact_id ', $contactClause); $clauses['id'][] = "IN (SELECT activity_id FROM civicrm_activity_contact WHERE contact_id $contactClause)"; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Case/BAO/Case.php b/CRM/Case/BAO/Case.php index 8ffae031ab..d8aa69d2e8 100644 --- a/CRM/Case/BAO/Case.php +++ b/CRM/Case/BAO/Case.php @@ -3014,10 +3014,11 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')'; /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // We always return an array with these keys, even if they are empty, // because this tells the query builder that we have considered these fields for acls $clauses = [ @@ -3041,7 +3042,7 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')'; ) )"; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Case/BAO/CaseContact.php b/CRM/Case/BAO/CaseContact.php index 5cdd8aa6d3..ba3cccd9ed 100644 --- a/CRM/Case/BAO/CaseContact.php +++ b/CRM/Case/BAO/CaseContact.php @@ -72,10 +72,11 @@ class CRM_Case_BAO_CaseContact extends CRM_Case_DAO_CaseContact implements \Civi /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { return [ // Reuse case acls 'case_id' => CRM_Utils_SQL::mergeSubquery('Case'), diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php index 7fcef7ca85..b9b83e95d8 100644 --- a/CRM/Contact/BAO/Contact.php +++ b/CRM/Contact/BAO/Contact.php @@ -3410,17 +3410,18 @@ LEFT JOIN civicrm_address ON ( civicrm_address.contact_id = civicrm_contact.id ) /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // We always return an array with these keys, even if they are empty, // because this tells the query builder that we have considered these fields for acls $clauses = [ 'id' => (array) CRM_Contact_BAO_Contact_Permission::cacheSubquery(), 'is_deleted' => CRM_Core_Permission::check('access deleted contacts') ? [] : ['!= 1'], ]; - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Contact/BAO/Group.php b/CRM/Contact/BAO/Group.php index cf25ab4c65..3a5b8b7b81 100644 --- a/CRM/Contact/BAO/Group.php +++ b/CRM/Contact/BAO/Group.php @@ -311,17 +311,18 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group { /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; if (!CRM_Core_Permission::check([['edit all contacts', 'view all contacts']])) { $allowedGroups = CRM_Core_Permission::group(NULL, FALSE); $groupsIn = $allowedGroups ? implode(',', array_keys($allowedGroups)) : '0'; $clauses['id'][] = "IN ($groupsIn)"; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Contact/BAO/RelationshipCache.php b/CRM/Contact/BAO/RelationshipCache.php index 37bace2c9d..cc3e2d89a5 100644 --- a/CRM/Contact/BAO/RelationshipCache.php +++ b/CRM/Contact/BAO/RelationshipCache.php @@ -157,17 +157,18 @@ class CRM_Contact_BAO_RelationshipCache extends CRM_Contact_DAO_RelationshipCach /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @return array */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // Permission for this entity depends on access to the two related contacts. $contactClause = CRM_Utils_SQL::mergeSubquery('Contact'); $clauses = [ 'near_contact_id' => $contactClause, 'far_contact_id' => $contactClause, ]; - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Contribute/BAO/ContributionSoft.php b/CRM/Contribute/BAO/ContributionSoft.php index d5203ea5b0..797d3dce9b 100644 --- a/CRM/Contribute/BAO/ContributionSoft.php +++ b/CRM/Contribute/BAO/ContributionSoft.php @@ -647,12 +647,13 @@ class CRM_Contribute_BAO_ContributionSoft extends CRM_Contribute_DAO_Contributio /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses['contribution_id'] = CRM_Utils_SQL::mergeSubquery('Contribution'); - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Core/BAO/CustomValue.php b/CRM/Core/BAO/CustomValue.php index c225665baa..f801e1296f 100644 --- a/CRM/Core/BAO/CustomValue.php +++ b/CRM/Core/BAO/CustomValue.php @@ -213,10 +213,11 @@ class CRM_Core_BAO_CustomValue extends CRM_Core_DAO { /** * ACL clause for an APIv4 custom pseudo-entity (aka multi-record custom group extending Contact). * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @return array */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // To-date, custom-value-based entities are only supported for contacts. // If this changes, $entityName variable contains the name of this custom group, // and could be used to lookup the type of entity this custom group joins to. diff --git a/CRM/Core/BAO/File.php b/CRM/Core/BAO/File.php index 555f15d00c..d0ad6492a3 100644 --- a/CRM/Core/BAO/File.php +++ b/CRM/Core/BAO/File.php @@ -836,25 +836,26 @@ HEREDOC; /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // TODO: This seemded like a good idea... piggybacking off the ACL clause of EntityFile // however that's too restrictive because entityFile ACLs are limited to just attachments, // so this would prevent access to other file fields (e.g. custom fields) // Disabling this function for now by calling the parent instead. - return parent::addSelectWhereClause($entityName, $conditions); - $clauses = [ - 'id' => [], - ]; - // File ACLs are driven by the EntityFile table - $entityFileClause = CRM_Core_DAO_EntityFile::getDynamicFkAclClauses(); - if ($entityFileClause) { - $clauses['id'] = 'IN (SELECT file_id FROM `civicrm_entity_file` WHERE (' . implode(') OR (', $entityFileClause) . '))'; - } - CRM_Utils_Hook::selectWhereClause($this, $clauses); - return $clauses; + return parent::addSelectWhereClause('File', $userId, $conditions); + // $clauses = [ + // 'id' => [], + // ]; + // // File ACLs are driven by the EntityFile table + // $entityFileClause = CRM_Core_DAO_EntityFile::getDynamicFkAclClauses(); + // if ($entityFileClause) { + // $clauses['id'] = 'IN (SELECT file_id FROM `civicrm_entity_file` WHERE (' . implode(') OR (', $entityFileClause) . '))'; + // } + // CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); + // return $clauses; } /** diff --git a/CRM/Core/BAO/Note.php b/CRM/Core/BAO/Note.php index ffd6e3246c..46e7a9052c 100644 --- a/CRM/Core/BAO/Note.php +++ b/CRM/Core/BAO/Note.php @@ -529,7 +529,7 @@ WHERE participant.contact_id = %1 AND note.entity_table = 'civicrm_participant' } } - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; $relatedClauses = self::getDynamicFkAclClauses('entity_table', 'entity_id', $conditions['entity_table'] ?? NULL); if ($relatedClauses) { @@ -546,7 +546,7 @@ WHERE participant.contact_id = %1 AND note.entity_table = 'civicrm_participant' ], ]; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Core/BAO/UFJoin.php b/CRM/Core/BAO/UFJoin.php index 422e6d2e45..b9344ea232 100644 --- a/CRM/Core/BAO/UFJoin.php +++ b/CRM/Core/BAO/UFJoin.php @@ -179,12 +179,13 @@ class CRM_Core_BAO_UFJoin extends CRM_Core_DAO_UFJoin { * Override base method which assumes permissions should be based on entity_table. * * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @return array */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Core/BAO/UFMatch.php b/CRM/Core/BAO/UFMatch.php index 3cffbc2260..5a2406b5c1 100644 --- a/CRM/Core/BAO/UFMatch.php +++ b/CRM/Core/BAO/UFMatch.php @@ -617,13 +617,14 @@ AND domain_id = %4 /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { // Prevent default behavior of joining ACLs onto the contact_id field. $clauses = []; - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Core/BAO/UserJob.php b/CRM/Core/BAO/UserJob.php index 7e99bf6f75..a6ba558f83 100644 --- a/CRM/Core/BAO/UserJob.php +++ b/CRM/Core/BAO/UserJob.php @@ -148,17 +148,18 @@ class CRM_Core_BAO_UserJob extends CRM_Core_DAO_UserJob implements HookInterface * 'view all contacts' etc. * * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; if (!\CRM_Core_Permission::check('administer queues')) { // @todo - the is_template should really be prefixed. We need to add support // for that in the compiler & then this would be `{table}.is_template` $clauses['created_id'] = '= ' . (int) CRM_Core_Session::getLoggedInContactID() . ' OR is_template = 1'; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 289ede21b5..300cc12086 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -3076,13 +3076,17 @@ SELECT contact_id * Name of the entity being queried (for normal BAO files implementing this method, this variable is redundant * as there is a 1-1 relationship between most entities and most BAOs. However the variable is passed in to support * dynamic entities such as ECK). + * @param int|null $userId + * Contact id of the current user. + * This param is more aspirational than functional for now. Someday the API may support checking permissions + * for contacts other than the current user, but at present this is always NULL which defaults to the current user. * @param array $conditions * Contains field/value pairs gleaned from the WHERE clause or ON clause * (depending on how the entity was added to the query). * Can be used for optimization/deduping of clauses. * @return array */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; $fields = $this::getSupportedFields(); foreach ($fields as $fieldName => $field) { @@ -3153,8 +3157,12 @@ SELECT contact_id * * With acls from related entities + additional clauses from hook_civicrm_selectWhereClause * - * @param string $tableAlias - * @param string $entityName + * DO NOT OVERRIDE THIS FUNCTION + * + * @TODO: ADD `final` keyword to function signature + * + * @param string|null $tableAlias + * @param string|null $entityName * @param array $conditions * Values from WHERE or ON clause * @return array @@ -3165,7 +3173,7 @@ SELECT contact_id $entityName = $entityName ?? CRM_Core_DAO_AllCoreTables::getBriefName($bao::class); $finalClauses = []; $fields = static::getSupportedFields(); - $selectWhereClauses = $bao->addSelectWhereClause($entityName, $conditions); + $selectWhereClauses = $bao->addSelectWhereClause($entityName, NULL, $conditions); foreach ($selectWhereClauses as $fieldName => $fieldClauses) { $finalClauses[$fieldName] = NULL; if ($fieldClauses) { diff --git a/CRM/Price/BAO/LineItem.php b/CRM/Price/BAO/LineItem.php index fbc37be9fa..4d4069054a 100644 --- a/CRM/Price/BAO/LineItem.php +++ b/CRM/Price/BAO/LineItem.php @@ -1280,12 +1280,13 @@ WHERE li.contribution_id = %1"; * and membership tables just seem too non-performant. * * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses['contribution_id'] = CRM_Utils_SQL::mergeSubquery('Contribution'); - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Queue/BAO/Queue.php b/CRM/Queue/BAO/Queue.php index af942b9a90..d608767ceb 100644 --- a/CRM/Queue/BAO/Queue.php +++ b/CRM/Queue/BAO/Queue.php @@ -20,13 +20,13 @@ */ class CRM_Queue_BAO_Queue extends CRM_Queue_DAO_Queue implements \Civi\Core\HookInterface { - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; if (!\CRM_Core_Permission::check('administer queues')) { $cid = (int) CRM_Core_Session::getLoggedInContactID(); $clauses['id'] = "IN (SELECT queue_id FROM `civicrm_user_job` WHERE created_id = $cid)"; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } diff --git a/CRM/Utils/Hook.php b/CRM/Utils/Hook.php index 4d5703a546..f6f96425d6 100644 --- a/CRM/Utils/Hook.php +++ b/CRM/Utils/Hook.php @@ -627,13 +627,18 @@ abstract class CRM_Utils_Hook { /** * @param string|CRM_Core_DAO $entity * @param array $clauses - * @return mixed + * @param int|null $userId + * User contact id. NULL == current user. + * @param array $conditions + * Values from WHERE or ON clause */ - public static function selectWhereClause($entity, &$clauses) { + public static function selectWhereClause($entity, array &$clauses, int $userId = NULL, array $conditions = []): void { $entityName = is_object($entity) ? CRM_Core_DAO_AllCoreTables::getBriefName($entity::class) : $entity; $null = NULL; - return self::singleton()->invoke(['entity', 'clauses'], $entityName, $clauses, - $null, $null, $null, $null, + $userId = $userId ?? (int) CRM_Core_Session::getLoggedInContactID(); + self::singleton()->invoke(['entity', 'clauses', 'userId', 'conditions'], + $entityName, $clauses, $userId, $conditions, + $null, $null, 'civicrm_selectWhereClause' ); } diff --git a/ext/oauth-client/CRM/OAuth/BAO/OAuthContactToken.php b/ext/oauth-client/CRM/OAuth/BAO/OAuthContactToken.php index e9f633ea74..46401c6d1f 100644 --- a/ext/oauth-client/CRM/OAuth/BAO/OAuthContactToken.php +++ b/ext/oauth-client/CRM/OAuth/BAO/OAuthContactToken.php @@ -98,10 +98,11 @@ class CRM_OAuth_BAO_OAuthContactToken extends CRM_OAuth_DAO_OAuthContactToken { /** * @param string|null $entityName + * @param int|null $userId * @param array $conditions * @inheritDoc */ - public function addSelectWhereClause(string $entityName = NULL, array $conditions = []): array { + public function addSelectWhereClause(string $entityName = NULL, int $userId = NULL, array $conditions = []): array { $clauses = []; $loggedInContactID = CRM_Core_Session::getLoggedInContactID(); @@ -117,7 +118,7 @@ class CRM_OAuth_BAO_OAuthContactToken extends CRM_OAuth_DAO_OAuthContactToken { else { $clauses['contact_id'][] = "= -1"; } - CRM_Utils_Hook::selectWhereClause($this, $clauses); + CRM_Utils_Hook::selectWhereClause($this, $clauses, $userId, $conditions); return $clauses; } -- 2.25.1