3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * Trait Civi\Test\ACLPermissionTrait.
17 * Trait for working with ACLs in tests
19 trait ACLPermissionTrait
{
22 * ContactID of allowed Contact
25 protected $allowedContactId = 0;
28 * Array of allowed contactIds
31 protected $allowedContacts = [];
34 * Ids created for the scenario in use.
38 protected $scenarioIDs = [];
41 * All results returned.
43 * @implements CRM_Utils_Hook::aclWhereClause
46 * @param array $tables
47 * @param array $whereTables
48 * @param int $contactID
49 * @param string $where
51 public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
56 * No results returned.
58 * @implements CRM_Utils_Hook::aclWhereClause
61 * @param array $tables
62 * @param array $whereTables
63 * @param int $contactID
64 * @param string $where
66 public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
70 * All but first results returned.
72 * @implements CRM_Utils_Hook::aclWhereClause
75 * @param array $tables
76 * @param array $whereTables
77 * @param int $contactID
78 * @param string $where
80 public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
81 $where = " contact_a.id > 1";
85 * Only specified contact returned.
87 * @implements CRM_Utils_Hook::aclWhereClause
90 * @param array $tables
91 * @param array $whereTables
92 * @param int $contactID
93 * @param string $where
95 public function aclWhereOnlyOne($type, &$tables, &$whereTables, &$contactID, &$where) {
96 $where = " contact_a.id = " . $this->allowedContactId
;
100 * Results after the allowedContact are returned.
102 * @implements CRM_Utils_Hook::aclWhereClause
104 * @param string $type
105 * @param array $tables
106 * @param array $whereTables
107 * @param int $contactID
108 * @param string $where
110 public function aclWhereGreaterThan($type, &$tables, &$whereTables, &$contactID, &$where) {
111 $where = " contact_a.id > " . $this->allowedContactId
;
117 * It is recommended that this helper function is accessed through a scenario function.
119 * @param array $permissionedEntities Array of groups for whom ACLs enable access.
120 * @param string|int $groupAllowedAccess Group permitted to access the permissioned Group
121 * An ID of 0 means that 'Everyone' can access the group.
122 * @param string $operation View|Edit|Create|Delete|Search|All
123 * @param string $entity Group|CustomGroup|Profile|Event
125 * @throws CRM_Core_Exception
127 public function setupCoreACLPermittedAcl($permissionedEntities = [], $groupAllowedAccess = 'Everyone', $operation = 'View', $entity = 'Group') {
128 $tableMap = ['Group' => 'civicrm_saved_search', 'CustomGroup' => 'civicrm_custom_group', 'Profile' => 'civicrm_uf_match', 'Event' => 'civicrm_event'];
129 $entityTable = $tableMap[$entity];
131 $permittedRoleID = ($groupAllowedAccess === 'Everyone') ?
0 : $groupAllowedAccess;
132 if ($permittedRoleID !== 0) {
133 throw new \
CRM_Core_Exception('only handling everyone group as yet');
136 foreach ($permissionedEntities as $permissionedEntityID) {
137 $this->callAPISuccess('Acl', 'create', [
139 'operation' => $operation,
140 'entity_id' => $permittedRoleID,
141 'object_id' => $permissionedEntityID,
142 'object_table' => $entityTable,
148 * Set up a scenario where everyone can access the permissioned group.
150 * A scenario in this class involves multiple defined assets. In this case we create
151 * - a group to which the everyone has permission
152 * - a contact in the group
153 * - a contact not in the group
155 * These are arrayed as follows
156 * $this->scenarioIDs['Contact'] = ['permitted_contact' => x, 'non_permitted_contact' => y]
157 * $this->scenarioIDs['Group'] = ['permitted_group' => x]
159 public function setupScenarioCoreACLEveryonePermittedToGroup() {
160 $this->quickCleanup(['civicrm_acl_cache', 'civicrm_acl_contact_cache']);
161 $this->scenarioIDs
['Group']['permitted_group'] = $this->groupCreate();
162 $this->scenarioIDs
['Contact']['permitted_contact'] = $this->individualCreate();
163 $result = $this->callAPISuccess('GroupContact', 'create', ['group_id' => $this->scenarioIDs
['Group']['permitted_group'], 'contact_id' => $this->scenarioIDs
['Contact']['permitted_contact'], 'status' => 'Added']);
164 $this->scenarioIDs
['Contact']['non_permitted_contact'] = $this->individualCreate();
165 \CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [];
166 $this->setupCoreACLPermittedAcl([$this->scenarioIDs
['Group']['permitted_group']]);
170 * Set up a scenario where everyone can access the permissioned group.
172 * A scenario in this class involves multiple defined assets. In this case we create
173 * - a group to which the everyone has permission
174 * - a contact in the group
175 * - a contact not in the group
177 * These are arrayed as follows
178 * $this->scenarioIDs['Contact'] = ['permitted_contact' => x, 'non_permitted_contact' => y]
179 * $this->scenarioIDs['Group'] = ['permitted_group' => x]
181 public function setupScenarioCoreACLEveryonePermittedToEvent() {
182 $this->quickCleanup(['civicrm_acl_cache', 'civicrm_acl_contact_cache']);
183 $this->scenarioIDs
['Event']['permitted_event'] = $this->eventCreate()['id'];
184 $this->scenarioIDs
['Contact']['permitted_contact'] = $this->individualCreate();
185 \CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= ['view event info'];
186 $this->setupCoreACLPermittedAcl([$this->scenarioIDs
['Event']['permitted_event']], 'Everyone', 'View', 'Event');
190 * Clean up places where permissions get cached.
192 protected function cleanupCachedPermissions() {
193 if (isset(\Civi
::$statics['CRM_Contact_BAO_Contact_Permission'])) {
194 unset(\Civi
::$statics['CRM_Contact_BAO_Contact_Permission']);
196 \CRM_Core_DAO
::executeQuery('TRUNCATE civicrm_acl_contact_cache');