Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
6a488035 TO |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
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 | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
19 | * Access Control List | |
20 | */ | |
21 | class CRM_ACL_BAO_ACL extends CRM_ACL_DAO_ACL { | |
db01bf2f | 22 | /** |
23 | * @var string | |
24 | */ | |
683bf891 SL |
25 | public static $_entityTable = NULL; |
26 | public static $_objectTable = NULL; | |
27 | public static $_operation = NULL; | |
6a488035 | 28 | |
683bf891 | 29 | public static $_fieldKeys = NULL; |
6a488035 | 30 | |
28518c90 | 31 | /** |
3819f101 | 32 | * Get ACL entity table. |
0677f5a4 | 33 | * @deprecated |
28518c90 EM |
34 | * @return array|null |
35 | */ | |
00be9182 | 36 | public static function entityTable() { |
9bd90abd | 37 | CRM_Core_Error::deprecatedFunctionWarning('unused function to be removed'); |
6a488035 | 38 | if (!self::$_entityTable) { |
cf0d1c08 | 39 | self::$_entityTable = [ |
6a488035 TO |
40 | 'civicrm_contact' => ts('Contact'), |
41 | 'civicrm_acl_role' => ts('ACL Role'), | |
cf0d1c08 | 42 | ]; |
6a488035 TO |
43 | } |
44 | return self::$_entityTable; | |
45 | } | |
46 | ||
28518c90 EM |
47 | /** |
48 | * @return array|null | |
0677f5a4 | 49 | * @deprecated |
28518c90 | 50 | */ |
00be9182 | 51 | public static function objectTable() { |
9bd90abd | 52 | CRM_Core_Error::deprecatedFunctionWarning('unused function to be removed'); |
6a488035 | 53 | if (!self::$_objectTable) { |
cf0d1c08 | 54 | self::$_objectTable = [ |
6a488035 TO |
55 | 'civicrm_contact' => ts('Contact'), |
56 | 'civicrm_group' => ts('Group'), | |
57 | 'civicrm_saved_search' => ts('Contact Group'), | |
6a488035 | 58 | 'civicrm_admin' => ts('Import'), |
cf0d1c08 | 59 | ]; |
6a488035 TO |
60 | } |
61 | return self::$_objectTable; | |
62 | } | |
63 | ||
28518c90 | 64 | /** |
9bd90abd | 65 | * Available operations for pseudoconstant. |
66 | * | |
67 | * @return array | |
28518c90 | 68 | */ |
00be9182 | 69 | public static function operation() { |
6a488035 | 70 | if (!self::$_operation) { |
cf0d1c08 | 71 | self::$_operation = [ |
6a488035 TO |
72 | 'View' => ts('View'), |
73 | 'Edit' => ts('Edit'), | |
74 | 'Create' => ts('Create'), | |
75 | 'Delete' => ts('Delete'), | |
76 | 'Search' => ts('Search'), | |
77 | 'All' => ts('All'), | |
cf0d1c08 | 78 | ]; |
6a488035 TO |
79 | } |
80 | return self::$_operation; | |
81 | } | |
82 | ||
6a488035 TO |
83 | /** |
84 | * Given a table and id pair, return the filter clause | |
85 | * | |
b758c7d5 TO |
86 | * @param string $table |
87 | * The table owning the object. | |
88 | * @param int $id | |
89 | * The ID of the object. | |
90 | * @param array $tables | |
91 | * Tables that will be needed in the FROM. | |
0677f5a4 | 92 | * @deprecated |
6a488035 | 93 | * |
72b3a70c CW |
94 | * @return string|null |
95 | * WHERE-style clause to filter results, | |
16b10e64 | 96 | * or null if $table or $id is null |
03149bb2 | 97 | * |
98 | * @throws \CRM_Core_Exception | |
6a488035 TO |
99 | */ |
100 | public static function getClause($table, $id, &$tables) { | |
9bd90abd | 101 | CRM_Core_Error::deprecatedFunctionWarning('unused function to be removed'); |
353ffa53 TO |
102 | $table = CRM_Utils_Type::escape($table, 'String'); |
103 | $id = CRM_Utils_Type::escape($id, 'Integer'); | |
cf0d1c08 | 104 | $whereTables = []; |
6a488035 TO |
105 | |
106 | $ssTable = CRM_Contact_BAO_SavedSearch::getTableName(); | |
107 | ||
108 | if (empty($table)) { | |
109 | return NULL; | |
110 | } | |
111 | elseif ($table == $ssTable) { | |
112 | return CRM_Contact_BAO_SavedSearch::whereClause($id, $tables, $whereTables); | |
113 | } | |
114 | elseif (!empty($id)) { | |
115 | $tables[$table] = TRUE; | |
116 | return "$table.id = $id"; | |
117 | } | |
118 | return NULL; | |
119 | } | |
120 | ||
121 | /** | |
122 | * Construct an associative array of an ACL rule's properties | |
123 | * | |
b758c7d5 TO |
124 | * @param string $format |
125 | * Sprintf format for array. | |
126 | * @param bool $hideEmpty | |
127 | * Only return elements that have a value set. | |
6a488035 | 128 | * |
a6c01b45 CW |
129 | * @return array |
130 | * Assoc. array of the ACL rule's properties | |
6a488035 | 131 | */ |
100b0ec6 | 132 | public function toArray($format = '%s', $hideEmpty = FALSE) { |
cf0d1c08 | 133 | $result = []; |
6a488035 TO |
134 | |
135 | if (!self::$_fieldKeys) { | |
136 | $fields = CRM_ACL_DAO_ACL::fields(); | |
137 | self::$_fieldKeys = array_keys($fields); | |
138 | } | |
139 | ||
140 | foreach (self::$_fieldKeys as $field) { | |
141 | $result[$field] = $this->$field; | |
142 | } | |
143 | return $result; | |
144 | } | |
145 | ||
146 | /** | |
147 | * Retrieve ACLs for a contact or group. Note that including a contact id | |
148 | * without a group id will return those ACL rules which are granted | |
149 | * directly to the contact, but not those granted to the contact through | |
150 | * any/all of his group memberships. | |
151 | * | |
b758c7d5 TO |
152 | * @param int $contact_id |
153 | * ID of a contact to search for. | |
6a488035 | 154 | * |
a6c01b45 CW |
155 | * @return array |
156 | * Array of assoc. arrays of ACL rules | |
03149bb2 | 157 | * |
158 | * @throws \CRM_Core_Exception | |
6a488035 | 159 | */ |
2ee636aa | 160 | protected static function getACLs(int $contact_id) { |
cf0d1c08 | 161 | $results = []; |
6a488035 | 162 | |
6a488035 TO |
163 | $rule = new CRM_ACL_BAO_ACL(); |
164 | ||
6a488035 | 165 | $contact = CRM_Contact_BAO_Contact::getTableName(); |
6a488035 | 166 | |
20095057 | 167 | $query = " SELECT acl.* |
d340e675 | 168 | FROM civicrm_acl acl |
2ee636aa | 169 | WHERE acl.entity_table = '$contact' |
170 | AND acl.entity_id = $contact_id"; | |
6a488035 TO |
171 | |
172 | $rule->query($query); | |
173 | ||
174 | while ($rule->fetch()) { | |
175 | $results[$rule->id] = $rule->toArray(); | |
176 | } | |
177 | ||
4c8054c4 | 178 | $results += self::getACLRoles($contact_id); |
6a488035 TO |
179 | |
180 | return $results; | |
181 | } | |
182 | ||
183 | /** | |
d2e5d2ce | 184 | * Get all of the ACLs through ACL groups. |
6a488035 | 185 | * |
b758c7d5 TO |
186 | * @param int $contact_id |
187 | * ID of a contact to search for. | |
6a488035 | 188 | * |
a6c01b45 CW |
189 | * @return array |
190 | * Array of assoc. arrays of ACL rules | |
03149bb2 | 191 | * |
192 | * @throws \CRM_Core_Exception | |
6a488035 | 193 | */ |
9bd90abd | 194 | protected static function getACLRoles($contact_id = NULL) { |
6a488035 | 195 | $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer'); |
6a488035 TO |
196 | |
197 | $rule = new CRM_ACL_BAO_ACL(); | |
198 | ||
353ffa53 | 199 | $contact = CRM_Contact_BAO_Contact::getTableName(); |
6a488035 | 200 | |
99f37ee2 | 201 | $query = 'SELECT acl.* FROM civicrm_acl acl'; |
202 | $where = ['acl.entity_table = "civicrm_acl_role" AND acl.entity_id IN (' . implode(',', array_keys(CRM_Core_OptionGroup::values('acl_role'))) . ')']; | |
6a488035 | 203 | |
b0854786 | 204 | if (!empty($contact_id)) { |
99f37ee2 | 205 | $where[] = " acl.entity_table = '$contact' AND acl.is_active = 1 AND acl.entity_id = $contact_id"; |
6a488035 TO |
206 | } |
207 | ||
cf0d1c08 | 208 | $results = []; |
6a488035 | 209 | |
99f37ee2 | 210 | $rule->query($query . ' WHERE ' . implode(' AND ', $where)); |
6a488035 TO |
211 | |
212 | while ($rule->fetch()) { | |
a5611c8e | 213 | $results[$rule->id] = $rule->toArray(); |
6a488035 TO |
214 | } |
215 | ||
216 | return $results; | |
217 | } | |
218 | ||
219 | /** | |
d2e5d2ce | 220 | * Get all ACLs granted to a contact through all group memberships. |
6a488035 | 221 | * |
b758c7d5 TO |
222 | * @param int $contact_id |
223 | * The contact's ID. | |
224 | * @param bool $aclRoles | |
225 | * Include ACL Roles?. | |
6a488035 | 226 | * |
a6c01b45 CW |
227 | * @return array |
228 | * Assoc array of ACL rules | |
03149bb2 | 229 | * @throws \CRM_Core_Exception |
6a488035 | 230 | */ |
9bd90abd | 231 | protected static function getGroupACLs($contact_id, $aclRoles = FALSE) { |
6a488035 TO |
232 | $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer'); |
233 | ||
234 | $rule = new CRM_ACL_BAO_ACL(); | |
235 | ||
353ffa53 TO |
236 | $c2g = CRM_Contact_BAO_GroupContact::getTableName(); |
237 | $group = CRM_Contact_BAO_Group::getTableName(); | |
cf0d1c08 | 238 | $results = []; |
6a488035 TO |
239 | |
240 | if ($contact_id) { | |
241 | $query = " | |
20095057 | 242 | SELECT acl.* |
d340e675 | 243 | FROM civicrm_acl acl |
20095057 | 244 | INNER JOIN $c2g group_contact |
245 | ON acl.entity_id = group_contact.group_id | |
246 | WHERE acl.entity_table = '$group' | |
247 | AND group_contact.contact_id = $contact_id | |
248 | AND group_contact.status = 'Added'"; | |
6a488035 TO |
249 | |
250 | $rule->query($query); | |
251 | ||
252 | while ($rule->fetch()) { | |
79380078 | 253 | $results[$rule->id] = $rule->toArray(); |
6a488035 TO |
254 | } |
255 | } | |
256 | ||
257 | if ($aclRoles) { | |
258 | $results += self::getGroupACLRoles($contact_id); | |
259 | } | |
260 | ||
261 | return $results; | |
262 | } | |
263 | ||
264 | /** | |
d2e5d2ce | 265 | * Get all of the ACLs for a contact through ACL groups owned by Contact. |
6a488035 TO |
266 | * groups. |
267 | * | |
b758c7d5 TO |
268 | * @param int $contact_id |
269 | * ID of a contact to search for. | |
6a488035 | 270 | * |
a6c01b45 CW |
271 | * @return array |
272 | * Array of assoc. arrays of ACL rules | |
03149bb2 | 273 | * @throws \CRM_Core_Exception |
6a488035 | 274 | */ |
9bd90abd | 275 | protected static function getGroupACLRoles($contact_id) { |
6a488035 TO |
276 | $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer'); |
277 | ||
278 | $rule = new CRM_ACL_BAO_ACL(); | |
279 | ||
6a488035 TO |
280 | $aclRole = 'civicrm_acl_role'; |
281 | ||
6a488035 | 282 | $aclER = CRM_ACL_DAO_EntityRole::getTableName(); |
353ffa53 | 283 | $c2g = CRM_Contact_BAO_GroupContact::getTableName(); |
6a488035 | 284 | |
20095057 | 285 | $query = " SELECT acl.* |
d340e675 | 286 | FROM civicrm_acl acl |
6a488035 TO |
287 | INNER JOIN civicrm_option_group og |
288 | ON og.name = 'acl_role' | |
289 | INNER JOIN civicrm_option_value ov | |
20095057 | 290 | ON acl.entity_table = '$aclRole' |
6a488035 | 291 | AND ov.option_group_id = og.id |
20095057 | 292 | AND acl.entity_id = ov.value |
6a488035 TO |
293 | AND ov.is_active = 1 |
294 | INNER JOIN $aclER | |
20095057 | 295 | ON $aclER.acl_role_id = acl.entity_id |
6a488035 TO |
296 | AND $aclER.is_active = 1 |
297 | INNER JOIN $c2g | |
298 | ON $aclER.entity_id = $c2g.group_id | |
299 | AND $aclER.entity_table = 'civicrm_group' | |
20095057 | 300 | WHERE acl.entity_table = '$aclRole' |
301 | AND acl.is_active = 1 | |
6a488035 TO |
302 | AND $c2g.contact_id = $contact_id |
303 | AND $c2g.status = 'Added'"; | |
304 | ||
cf0d1c08 | 305 | $results = []; |
6a488035 TO |
306 | |
307 | $rule->query($query); | |
308 | ||
309 | while ($rule->fetch()) { | |
39eb89f4 | 310 | $results[$rule->id] = $rule->toArray(); |
6a488035 TO |
311 | } |
312 | ||
313 | // also get all acls for "Any Role" case | |
314 | // and authenticated User Role if present | |
315 | $roles = "0"; | |
316 | $session = CRM_Core_Session::singleton(); | |
317 | if ($session->get('ufID') > 0) { | |
318 | $roles .= ",2"; | |
319 | } | |
320 | ||
321 | $query = " | |
20095057 | 322 | SELECT acl.* |
d340e675 | 323 | FROM civicrm_acl acl |
20095057 | 324 | WHERE acl.entity_id IN ( $roles ) |
325 | AND acl.entity_table = 'civicrm_acl_role' | |
6a488035 TO |
326 | "; |
327 | ||
328 | $rule->query($query); | |
329 | while ($rule->fetch()) { | |
330 | $results[$rule->id] = $rule->toArray(); | |
331 | } | |
332 | ||
333 | return $results; | |
334 | } | |
335 | ||
336 | /** | |
337 | * Get all ACLs owned by a given contact, including domain and group-level. | |
338 | * | |
b758c7d5 TO |
339 | * @param int $contact_id |
340 | * The contact ID. | |
6a488035 | 341 | * |
a6c01b45 CW |
342 | * @return array |
343 | * Assoc array of ACL rules | |
03149bb2 | 344 | * |
345 | * @throws \CRM_Core_Exception | |
6a488035 | 346 | */ |
03149bb2 | 347 | public static function getAllByContact($contact_id) { |
cf0d1c08 | 348 | $result = []; |
6a488035 TO |
349 | |
350 | /* First, the contact-specific ACLs, including ACL Roles */ | |
2ee636aa | 351 | if ($contact_id) { |
352 | $result += self::getACLs((int) $contact_id); | |
353 | } | |
6a488035 TO |
354 | |
355 | /* Then, all ACLs granted through group membership */ | |
356 | $result += self::getGroupACLs($contact_id, TRUE); | |
357 | ||
358 | return $result; | |
359 | } | |
360 | ||
28518c90 | 361 | /** |
c490a46a | 362 | * @param array $params |
28518c90 EM |
363 | * |
364 | * @return CRM_ACL_DAO_ACL | |
365 | */ | |
03149bb2 | 366 | public static function create($params) { |
6a488035 TO |
367 | $dao = new CRM_ACL_DAO_ACL(); |
368 | $dao->copyValues($params); | |
369 | $dao->save(); | |
1fe97a01 | 370 | return $dao; |
6a488035 TO |
371 | } |
372 | ||
28518c90 | 373 | /** |
c490a46a | 374 | * @param array $params |
03149bb2 | 375 | * @param array $defaults |
28518c90 | 376 | */ |
00be9182 | 377 | public static function retrieve(&$params, &$defaults) { |
6a488035 TO |
378 | CRM_Core_DAO::commonRetrieve('CRM_ACL_DAO_ACL', $params, $defaults); |
379 | } | |
380 | ||
381 | /** | |
fe482240 | 382 | * Update the is_active flag in the db. |
6a488035 | 383 | * |
b758c7d5 TO |
384 | * @param int $id |
385 | * Id of the database record. | |
386 | * @param bool $is_active | |
387 | * Value we want to set the is_active field. | |
6a488035 | 388 | * |
8a4fede3 | 389 | * @return bool |
390 | * true if we found and updated the object, else false | |
6a488035 | 391 | */ |
00be9182 | 392 | public static function setIsActive($id, $is_active) { |
9cdf85c1 | 393 | Civi::cache('fields')->flush(); |
5e601882 SL |
394 | // reset ACL and system caches. |
395 | CRM_Core_BAO_Cache::resetCaches(); | |
6a488035 TO |
396 | |
397 | return CRM_Core_DAO::setFieldValue('CRM_ACL_DAO_ACL', $id, 'is_active', $is_active); | |
398 | } | |
399 | ||
28518c90 EM |
400 | /** |
401 | * @param $str | |
100fef9d | 402 | * @param int $contactID |
28518c90 EM |
403 | * |
404 | * @return bool | |
405 | */ | |
00be9182 | 406 | public static function check($str, $contactID) { |
6a488035 TO |
407 | |
408 | $acls = CRM_ACL_BAO_Cache::build($contactID); | |
409 | ||
410 | $aclKeys = array_keys($acls); | |
411 | $aclKeys = implode(',', $aclKeys); | |
412 | ||
413 | if (empty($aclKeys)) { | |
414 | return FALSE; | |
415 | } | |
416 | ||
6a488035 TO |
417 | $query = " |
418 | SELECT count( a.id ) | |
419 | FROM civicrm_acl_cache c, civicrm_acl a | |
420 | WHERE c.acl_id = a.id | |
421 | AND a.is_active = 1 | |
422 | AND a.object_table = %1 | |
423 | AND a.id IN ( $aclKeys ) | |
424 | "; | |
cf0d1c08 | 425 | $params = [1 => [$str, 'String']]; |
6a488035 TO |
426 | |
427 | $count = CRM_Core_DAO::singleValueQuery($query, $params); | |
1699214f | 428 | return (bool) $count; |
6a488035 TO |
429 | } |
430 | ||
28518c90 EM |
431 | /** |
432 | * @param $type | |
433 | * @param $tables | |
434 | * @param $whereTables | |
100fef9d | 435 | * @param int $contactID |
28518c90 EM |
436 | * |
437 | * @return null|string | |
438 | */ | |
199761b4 | 439 | public static function whereClause($type, &$tables, &$whereTables, $contactID = NULL) { |
6a488035 | 440 | $acls = CRM_ACL_BAO_Cache::build($contactID); |
6a488035 TO |
441 | |
442 | $whereClause = NULL; | |
cf0d1c08 | 443 | $clauses = []; |
6a488035 TO |
444 | |
445 | if (!empty($acls)) { | |
446 | $aclKeys = array_keys($acls); | |
447 | $aclKeys = implode(',', $aclKeys); | |
448 | ||
449 | $query = " | |
450 | SELECT a.operation, a.object_id | |
451 | FROM civicrm_acl_cache c, civicrm_acl a | |
452 | WHERE c.acl_id = a.id | |
453 | AND a.is_active = 1 | |
454 | AND a.object_table = 'civicrm_saved_search' | |
455 | AND a.id IN ( $aclKeys ) | |
456 | ORDER BY a.object_id | |
457 | "; | |
458 | ||
459 | $dao = CRM_Core_DAO::executeQuery($query); | |
460 | ||
461 | // do an or of all the where clauses u see | |
cf0d1c08 | 462 | $ids = []; |
6a488035 TO |
463 | while ($dao->fetch()) { |
464 | // make sure operation matches the type TODO | |
465 | if (self::matchType($type, $dao->operation)) { | |
466 | if (!$dao->object_id) { | |
cf0d1c08 | 467 | $ids = []; |
6a488035 TO |
468 | $whereClause = ' ( 1 ) '; |
469 | break; | |
470 | } | |
471 | $ids[] = $dao->object_id; | |
472 | } | |
473 | } | |
474 | ||
475 | if (!empty($ids)) { | |
476 | $ids = implode(',', $ids); | |
477 | $query = " | |
478 | SELECT g.* | |
479 | FROM civicrm_group g | |
480 | WHERE g.id IN ( $ids ) | |
481 | AND g.is_active = 1 | |
482 | "; | |
353ffa53 | 483 | $dao = CRM_Core_DAO::executeQuery($query); |
1bcdee33 | 484 | $groupIDs = []; |
485 | $groupContactCacheClause = FALSE; | |
6a488035 | 486 | while ($dao->fetch()) { |
1bcdee33 | 487 | $groupIDs[] = $dao->id; |
6a488035 | 488 | |
1d902030 | 489 | if (($dao->saved_search_id || $dao->children || $dao->parents)) { |
490 | if ($dao->cache_date == NULL) { | |
491 | CRM_Contact_BAO_GroupContactCache::load($dao); | |
492 | } | |
1bcdee33 | 493 | $groupContactCacheClause = " UNION SELECT contact_id FROM civicrm_group_contact_cache WHERE group_id IN (" . implode(', ', $groupIDs) . ")"; |
6a488035 | 494 | } |
6a488035 | 495 | |
6a488035 TO |
496 | } |
497 | ||
1bcdee33 | 498 | if ($groupIDs) { |
499 | $clauses[] = "( | |
500 | `contact_a`.id IN ( | |
501 | SELECT contact_id FROM civicrm_group_contact WHERE group_id IN (" . implode(', ', $groupIDs) . ") AND status = 'Added' | |
502 | $groupContactCacheClause | |
503 | ) | |
504 | )"; | |
6a488035 TO |
505 | } |
506 | } | |
507 | } | |
508 | ||
509 | if (!empty($clauses)) { | |
510 | $whereClause = ' ( ' . implode(' OR ', $clauses) . ' ) '; | |
511 | } | |
512 | ||
513 | // call the hook to get additional whereClauses | |
514 | CRM_Utils_Hook::aclWhereClause($type, $tables, $whereTables, $contactID, $whereClause); | |
515 | ||
199761b4 | 516 | if (empty($whereClause)) { |
6a488035 TO |
517 | $whereClause = ' ( 0 ) '; |
518 | } | |
519 | ||
520 | return $whereClause; | |
521 | } | |
522 | ||
28518c90 | 523 | /** |
c490a46a | 524 | * @param int $type |
100fef9d | 525 | * @param int $contactID |
28518c90 EM |
526 | * @param string $tableName |
527 | * @param null $allGroups | |
528 | * @param null $includedGroups | |
529 | * | |
530 | * @return array | |
531 | */ | |
e6a83034 TO |
532 | public static function group( |
533 | $type, | |
100b0ec6 TO |
534 | $contactID = NULL, |
535 | $tableName = 'civicrm_saved_search', | |
536 | $allGroups = NULL, | |
6a488035 TO |
537 | $includedGroups = NULL |
538 | ) { | |
e3ad0182 | 539 | $userCacheKey = "{$contactID}_{$type}_{$tableName}_" . CRM_Core_Config::domainID() . '_' . md5(implode(',', array_merge((array) $allGroups, (array) $includedGroups))); |
540 | if (empty(Civi::$statics[__CLASS__]['permissioned_groups'])) { | |
cf0d1c08 | 541 | Civi::$statics[__CLASS__]['permissioned_groups'] = []; |
e3ad0182 | 542 | } |
543 | if (!empty(Civi::$statics[__CLASS__]['permissioned_groups'][$userCacheKey])) { | |
544 | return Civi::$statics[__CLASS__]['permissioned_groups'][$userCacheKey]; | |
545 | } | |
6a488035 | 546 | |
8aace6af | 547 | if ($allGroups == NULL) { |
887688b9 | 548 | $allGroups = CRM_Contact_BAO_Contact::buildOptions('group_id', NULL, ['onlyActive' => FALSE]); |
8aace6af JG |
549 | } |
550 | ||
6a488035 TO |
551 | $acls = CRM_ACL_BAO_Cache::build($contactID); |
552 | ||
cf0d1c08 | 553 | $ids = []; |
6a488035 TO |
554 | if (!empty($acls)) { |
555 | $aclKeys = array_keys($acls); | |
556 | $aclKeys = implode(',', $aclKeys); | |
557 | ||
77f080cb | 558 | $cacheKey = CRM_Utils_Cache::cleanKey("$tableName-$aclKeys"); |
557f8c17 ARW |
559 | $cache = CRM_Utils_Cache::singleton(); |
560 | $ids = $cache->get($cacheKey); | |
561 | if (!$ids) { | |
cf0d1c08 | 562 | $ids = []; |
557f8c17 | 563 | $query = " |
6a488035 TO |
564 | SELECT a.operation, a.object_id |
565 | FROM civicrm_acl_cache c, civicrm_acl a | |
566 | WHERE c.acl_id = a.id | |
567 | AND a.is_active = 1 | |
568 | AND a.object_table = %1 | |
569 | AND a.id IN ( $aclKeys ) | |
570 | GROUP BY a.operation,a.object_id | |
571 | ORDER BY a.object_id | |
572 | "; | |
cf0d1c08 | 573 | $params = [1 => [$tableName, 'String']]; |
557f8c17 ARW |
574 | $dao = CRM_Core_DAO::executeQuery($query, $params); |
575 | while ($dao->fetch()) { | |
576 | if ($dao->object_id) { | |
577 | if (self::matchType($type, $dao->operation)) { | |
578 | $ids[] = $dao->object_id; | |
579 | } | |
6a488035 | 580 | } |
557f8c17 ARW |
581 | else { |
582 | // this user has got the permission for all objects of this type | |
583 | // check if the type matches | |
584 | if (self::matchType($type, $dao->operation)) { | |
585 | foreach ($allGroups as $id => $dontCare) { | |
586 | $ids[] = $id; | |
587 | } | |
6a488035 | 588 | } |
557f8c17 | 589 | break; |
6a488035 | 590 | } |
6a488035 | 591 | } |
557f8c17 | 592 | $cache->set($cacheKey, $ids); |
6a488035 TO |
593 | } |
594 | } | |
595 | ||
b1f4e637 RN |
596 | if (empty($ids) && !empty($includedGroups) && |
597 | is_array($includedGroups) | |
598 | ) { | |
599 | $ids = $includedGroups; | |
600 | } | |
e3ad0182 | 601 | if ($contactID) { |
54d93c06 | 602 | $groupWhere = ''; |
603 | if (!empty($allGroups)) { | |
604 | $groupWhere = " AND id IN (" . implode(',', array_keys($allGroups)) . ")"; | |
605 | } | |
e3ad0182 | 606 | // Contacts create hidden groups from search results. They should be able to retrieve their own. |
607 | $ownHiddenGroupsList = CRM_Core_DAO::singleValueQuery(" | |
608 | SELECT GROUP_CONCAT(id) FROM civicrm_group WHERE is_hidden =1 AND created_id = $contactID | |
54d93c06 | 609 | $groupWhere |
e3ad0182 | 610 | "); |
611 | if ($ownHiddenGroupsList) { | |
612 | $ownHiddenGroups = explode(',', $ownHiddenGroupsList); | |
54d93c06 | 613 | $ids = array_merge((array) $ids, $ownHiddenGroups); |
e3ad0182 | 614 | } |
615 | ||
616 | } | |
b1f4e637 | 617 | |
6a488035 | 618 | CRM_Utils_Hook::aclGroup($type, $contactID, $tableName, $allGroups, $ids); |
e3ad0182 | 619 | Civi::$statics[__CLASS__]['permissioned_groups'][$userCacheKey] = $ids; |
6a488035 TO |
620 | return $ids; |
621 | } | |
622 | ||
28518c90 | 623 | /** |
c490a46a | 624 | * @param int $type |
28518c90 EM |
625 | * @param $operation |
626 | * | |
627 | * @return bool | |
628 | */ | |
9bd90abd | 629 | protected static function matchType($type, $operation) { |
6a488035 TO |
630 | $typeCheck = FALSE; |
631 | switch ($operation) { | |
632 | case 'All': | |
633 | $typeCheck = TRUE; | |
634 | break; | |
635 | ||
636 | case 'View': | |
637 | if ($type == CRM_ACL_API::VIEW) { | |
638 | $typeCheck = TRUE; | |
639 | } | |
640 | break; | |
641 | ||
642 | case 'Edit': | |
643 | if ($type == CRM_ACL_API::VIEW || $type == CRM_ACL_API::EDIT) { | |
644 | $typeCheck = TRUE; | |
645 | } | |
646 | break; | |
647 | ||
648 | case 'Create': | |
649 | if ($type == CRM_ACL_API::CREATE) { | |
650 | $typeCheck = TRUE; | |
651 | } | |
652 | break; | |
653 | ||
654 | case 'Delete': | |
655 | if ($type == CRM_ACL_API::DELETE) { | |
656 | $typeCheck = TRUE; | |
657 | } | |
658 | break; | |
659 | ||
660 | case 'Search': | |
661 | if ($type == CRM_ACL_API::SEARCH) { | |
662 | $typeCheck = TRUE; | |
663 | } | |
664 | break; | |
665 | } | |
666 | return $typeCheck; | |
667 | } | |
668 | ||
669 | /** | |
d2e5d2ce | 670 | * Delete ACL records. |
6a488035 | 671 | * |
b758c7d5 TO |
672 | * @param int $aclId |
673 | * ID of the ACL record to be deleted. | |
6a488035 | 674 | * |
6a488035 | 675 | */ |
00be9182 | 676 | public static function del($aclId) { |
6a488035 TO |
677 | // delete all entries from the acl cache |
678 | CRM_ACL_BAO_Cache::resetCache(); | |
679 | ||
680 | $acl = new CRM_ACL_DAO_ACL(); | |
681 | $acl->id = $aclId; | |
682 | $acl->delete(); | |
683 | } | |
96025800 | 684 | |
6a488035 | 685 | } |