3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
37 class CRM_ACL_BAO_ACL
extends CRM_ACL_DAO_ACL
{
41 static $_entityTable = NULL;
42 static $_objectTable = NULL;
43 static $_operation = NULL;
45 static $_fieldKeys = NULL;
48 * Get ACL entity table.
52 public static function entityTable() {
53 if (!self
::$_entityTable) {
54 self
::$_entityTable = array(
55 'civicrm_contact' => ts('Contact'),
56 'civicrm_acl_role' => ts('ACL Role'),
59 return self
::$_entityTable;
65 public static function objectTable() {
66 if (!self
::$_objectTable) {
67 self
::$_objectTable = array(
68 'civicrm_contact' => ts('Contact'),
69 'civicrm_group' => ts('Group'),
70 'civicrm_saved_search' => ts('Contact Group'),
71 'civicrm_admin' => ts('Import'),
74 return self
::$_objectTable;
80 public static function operation() {
81 if (!self
::$_operation) {
82 self
::$_operation = array(
85 'Create' => ts('Create'),
86 'Delete' => ts('Delete'),
87 'Search' => ts('Search'),
91 return self
::$_operation;
95 * Construct a WHERE clause to handle permissions to $object_*
99 * @param array $tables
100 * Any tables that may be needed in the FROM.
101 * @param string $operation
102 * The operation being attempted.
103 * @param string $object_table
104 * The table of the object in question.
105 * @param int $object_id
106 * The ID of the object in question.
108 * If it's a grant/revoke operation, the ACL ID.
109 * @param bool $acl_role
110 * For grant operations, this flag determines if we're granting a single acl (false) or an entire group.
113 * The WHERE clause, or 0 on failure
115 public static function permissionClause(
116 &$tables, $operation,
117 $object_table = NULL, $object_id = NULL,
118 $acl_id = NULL, $acl_role = FALSE
120 CRM_Core_Error
::deprecatedFunctionWarning('unknown - this is really old & not used in core');
121 $dao = new CRM_ACL_DAO_ACL();
124 'ACL' => self
::getTableName(),
125 'ACLRole' => 'civicrm_acl_role',
126 'ACLEntityRole' => CRM_ACL_DAO_EntityRole
::getTableName(),
127 'Contact' => CRM_Contact_DAO_Contact
::getTableName(),
128 'Group' => CRM_Contact_DAO_Group
::getTableName(),
129 'GroupContact' => CRM_Contact_DAO_GroupContact
::getTableName(),
132 $contact_id = CRM_Core_Session
::getLoggedInContactID();
134 $where = " {$t['ACL']}.operation = '" . CRM_Utils_Type
::escape($operation, 'String') . "'";
136 /* Include clause if we're looking for a specific table/id permission */
138 if (!empty($object_table)) {
139 $where .= " AND ( {$t['ACL']}.object_table IS null
140 OR ({$t['ACL']}.object_table = '" . CRM_Utils_Type
::escape($object_table, 'String') . "'";
141 if (!empty($object_id)) {
142 $where .= " AND ({$t['ACL']}.object_id IS null
143 OR {$t['ACL']}.object_id = " . CRM_Utils_Type
::escape($object_id, 'Integer') . ')';
148 /* Include clause if we're granting an ACL or ACL Role */
150 if (!empty($acl_id)) {
151 $where .= " AND ({$t['ACL']}.acl_id IS null
152 OR {$t['ACL']}.acl_id = " . CRM_Utils_Type
::escape($acl_id, 'Integer') . ')';
154 $where .= " AND {$t['ACL']}.acl_table = '{$t['ACLRole']}'";
157 $where .= " AND {$t['ACL']}.acl_table = '{$t['ACL']}'";
163 /* Query for permissions granted to all contacts in the domain */
165 $query[] = "SELECT {$t['ACL']}.*, 0 as override
168 WHERE {$t['ACL']}.entity_table = '{$t['Domain']}'
171 /* Query for permissions granted to all contacts through an ACL group */
173 $query[] = "SELECT {$t['ACL']}.*, 0 as override
176 INNER JOIN {$t['ACLEntityRole']}
177 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
178 AND {$t['ACL']}.entity_id =
179 {$t['ACLEntityRole']}.acl_role_id)
181 INNER JOIN {$t['ACLRole']}
182 ON {$t['ACL']}.entity_id =
185 WHERE {$t['ACLEntityRole']}.entity_table =
187 AND {$t['ACLRole']}.is_active = 1
190 /* Query for permissions granted directly to the contact */
192 $query[] = "SELECT {$t['ACL']}.*, 1 as override
195 INNER JOIN {$t['Contact']}
196 ON ({$t['ACL']}.entity_table = '{$t['Contact']}'
197 AND {$t['ACL']}.entity_id = {$t['Contact']}.id)
199 WHERE {$t['Contact']}.id = $contact_id
202 /* Query for permissions granted to the contact through an ACL group */
204 $query[] = "SELECT {$t['ACL']}.*, 1 as override
207 INNER JOIN {$t['ACLEntityRole']}
208 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
209 AND {$t['ACL']}.entity_id =
210 {$t['ACLEntityRole']}.acl_role_id)
212 INNER JOIN {$t['ACLRole']}
213 ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
215 WHERE {$t['ACLEntityRole']}.entity_table =
217 AND {$t['ACLRole']}.is_active = 1
218 AND {$t['ACLEntityRole']}.entity_id = $contact_id
221 /* Query for permissions granted to the contact through a group */
223 $query[] = "SELECT {$t['ACL']}.*, 0 as override
226 INNER JOIN {$t['GroupContact']}
227 ON ({$t['ACL']}.entity_table = '{$t['Group']}'
228 AND {$t['ACL']}.entity_id =
229 {$t['GroupContact']}.group_id)
232 AND {$t['GroupContact']}.contact_id = $contact_id
233 AND {$t['GroupContact']}.status = 'Added')";
235 /* Query for permissions granted through an ACL group to a Contact
238 $query[] = "SELECT {$t['ACL']}.*, 0 as override
241 INNER JOIN {$t['ACLEntityRole']}
242 ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
243 AND {$t['ACL']}.entity_id =
244 {$t['ACLEntityRole']}.acl_role_id)
246 INNER JOIN {$t['ACLRole']}
247 ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
249 INNER JOIN {$t['GroupContact']}
250 ON ({$t['ACLEntityRole']}.entity_table =
252 AND {$t['ACLEntityRole']}.entity_id =
253 {$t['GroupContact']}.group_id)
256 AND {$t['ACLRole']}.is_active = 1
257 AND {$t['GroupContact']}.contact_id = $contact_id
258 AND {$t['GroupContact']}.status = 'Added'";
260 $union = '(' . implode(') UNION DISTINCT (', $query) . ')';
268 while ($dao->fetch()) {
269 /* Instant bypass for the following cases:
270 * 1) the rule governs all tables
271 * 2) the rule governs all objects in the table in question
272 * 3) the rule governs the specific object we want
275 if (empty($dao->object_table
) ||
276 ($dao->object_table
== $object_table
277 && (empty($dao->object_id
)
278 ||
$dao->object_id
== $object_id
285 /* Otherwise try to generate a clause for this rule */
287 $clause = self
::getClause(
288 $dao->object_table
, $dao->object_id
, $tables
291 /* If the clause returned is null, then the rule is a blanket
292 * (id is null) on a table other than the one we're interested
295 if (empty($clause)) {
300 /* Now we figure out if this is an allow or deny rule, and possibly
301 * a contact-level override */
309 if ($dao->override
) {
310 $override[] = $clause;
315 $allows = '(' . implode(' OR ', $allow) . ')';
316 $denies = '(' . implode(' OR ', $deny) . ')';
317 if (!empty($override)) {
318 $denies = '(NOT (' . implode(' OR ', $override) . ") AND $denies)";
321 return "($allows AND NOT $denies)";
325 * Given a table and id pair, return the filter clause
327 * @param string $table
328 * The table owning the object.
330 * The ID of the object.
331 * @param array $tables
332 * Tables that will be needed in the FROM.
334 * @return string|null
335 * WHERE-style clause to filter results,
336 * or null if $table or $id is null
338 public static function getClause($table, $id, &$tables) {
339 $table = CRM_Utils_Type
::escape($table, 'String');
340 $id = CRM_Utils_Type
::escape($id, 'Integer');
341 $whereTables = array();
343 $ssTable = CRM_Contact_BAO_SavedSearch
::getTableName();
348 elseif ($table == $ssTable) {
349 return CRM_Contact_BAO_SavedSearch
::whereClause($id, $tables, $whereTables);
351 elseif (!empty($id)) {
352 $tables[$table] = TRUE;
353 return "$table.id = $id";
359 * Construct an associative array of an ACL rule's properties
361 * @param string $format
362 * Sprintf format for array.
363 * @param bool $hideEmpty
364 * Only return elements that have a value set.
367 * Assoc. array of the ACL rule's properties
369 public function toArray($format = '%s', $hideEmpty = FALSE) {
372 if (!self
::$_fieldKeys) {
373 $fields = CRM_ACL_DAO_ACL
::fields();
374 self
::$_fieldKeys = array_keys($fields);
377 foreach (self
::$_fieldKeys as $field) {
378 $result[$field] = $this->$field;
384 * Retrieve ACLs for a contact or group. Note that including a contact id
385 * without a group id will return those ACL rules which are granted
386 * directly to the contact, but not those granted to the contact through
387 * any/all of his group memberships.
389 * @param int $contact_id
390 * ID of a contact to search for.
391 * @param int $group_id
392 * ID of a group to search for.
393 * @param bool $aclRoles
394 * Should we include ACL Roles.
397 * Array of assoc. arrays of ACL rules
399 public static function &getACLs($contact_id = NULL, $group_id = NULL, $aclRoles = FALSE) {
402 if (empty($contact_id)) {
406 $contact_id = CRM_Utils_Type
::escape($contact_id, 'Integer');
408 $group_id = CRM_Utils_Type
::escape($group_id, 'Integer');
411 $rule = new CRM_ACL_BAO_ACL();
413 $acl = self
::getTableName();
414 $contact = CRM_Contact_BAO_Contact
::getTableName();
415 $c2g = CRM_Contact_BAO_GroupContact
::getTableName();
416 $group = CRM_Contact_BAO_Group
::getTableName();
418 $query = " SELECT $acl.*
421 if (!empty($group_id)) {
422 $query .= " INNER JOIN $c2g
423 ON $acl.entity_id = $c2g.group_id
424 WHERE $acl.entity_table = '$group'
425 AND $acl.is_active = 1
426 AND $c2g.group_id = $group_id";
428 if (!empty($contact_id)) {
429 $query .= " AND $c2g.contact_id = $contact_id
430 AND $c2g.status = 'Added'";
434 if (!empty($contact_id)) {
435 $query .= " WHERE $acl.entity_table = '$contact'
436 AND $acl.entity_id = $contact_id";
440 $rule->query($query);
442 while ($rule->fetch()) {
443 $results[$rule->id
] = $rule->toArray();
447 $results +
= self
::getACLRoles($contact_id, $group_id);
454 * Get all of the ACLs through ACL groups.
456 * @param int $contact_id
457 * ID of a contact to search for.
458 * @param int $group_id
459 * ID of a group to search for.
462 * Array of assoc. arrays of ACL rules
464 public static function &getACLRoles($contact_id = NULL, $group_id = NULL) {
465 $contact_id = CRM_Utils_Type
::escape($contact_id, 'Integer');
467 $group_id = CRM_Utils_Type
::escape($group_id, 'Integer');
470 $rule = new CRM_ACL_BAO_ACL();
472 $acl = self
::getTableName();
473 $aclRole = 'civicrm_acl_role';
474 $aclRoleJoin = CRM_ACL_DAO_EntityRole
::getTableName();
475 $contact = CRM_Contact_BAO_Contact
::getTableName();
476 $c2g = CRM_Contact_BAO_GroupContact
::getTableName();
477 $group = CRM_Contact_BAO_Group
::getTableName();
479 $query = " SELECT $acl.*
481 INNER JOIN civicrm_option_group og
482 ON og.name = 'acl_role'
483 INNER JOIN civicrm_option_value ov
484 ON $acl.entity_table = '$aclRole'
485 AND ov.option_group_id = og.id
486 AND $acl.entity_id = ov.value";
488 if (!empty($group_id)) {
489 $query .= " INNER JOIN $c2g
490 ON $acl.entity_id = $c2g.group_id
491 WHERE $acl.entity_table = '$group'
492 AND $acl.is_active = 1
493 AND $c2g.group_id = $group_id";
495 if (!empty($contact_id)) {
496 $query .= " AND $c2g.contact_id = $contact_id
497 AND $c2g.status = 'Added'";
501 if (!empty($contact_id)) {
502 $query .= " WHERE $acl.entity_table = '$contact'
503 AND $acl.is_active = 1
504 AND $acl.entity_id = $contact_id";
510 $rule->query($query);
512 while ($rule->fetch()) {
513 $results[$rule->id
] = $rule->toArray();
520 * Get all ACLs granted to a contact through all group memberships.
522 * @param int $contact_id
524 * @param bool $aclRoles
525 * Include ACL Roles?.
528 * Assoc array of ACL rules
530 public static function &getGroupACLs($contact_id, $aclRoles = FALSE) {
531 $contact_id = CRM_Utils_Type
::escape($contact_id, 'Integer');
533 $rule = new CRM_ACL_BAO_ACL();
535 $acl = self
::getTableName();
536 $c2g = CRM_Contact_BAO_GroupContact
::getTableName();
537 $group = CRM_Contact_BAO_Group
::getTableName();
545 ON $acl.entity_id = $c2g.group_id
546 WHERE $acl.entity_table = '$group'
547 AND $c2g.contact_id = $contact_id
548 AND $c2g.status = 'Added'";
550 $rule->query($query);
552 while ($rule->fetch()) {
553 $results[$rule->id
] = $rule->toArray();
558 $results +
= self
::getGroupACLRoles($contact_id);
565 * Get all of the ACLs for a contact through ACL groups owned by Contact.
568 * @param int $contact_id
569 * ID of a contact to search for.
572 * Array of assoc. arrays of ACL rules
574 public static function &getGroupACLRoles($contact_id) {
575 $contact_id = CRM_Utils_Type
::escape($contact_id, 'Integer');
577 $rule = new CRM_ACL_BAO_ACL();
579 $acl = self
::getTableName();
580 $aclRole = 'civicrm_acl_role';
582 $aclER = CRM_ACL_DAO_EntityRole
::getTableName();
583 $c2g = CRM_Contact_BAO_GroupContact
::getTableName();
584 $group = CRM_Contact_BAO_Group
::getTableName();
586 $query = " SELECT $acl.*
588 INNER JOIN civicrm_option_group og
589 ON og.name = 'acl_role'
590 INNER JOIN civicrm_option_value ov
591 ON $acl.entity_table = '$aclRole'
592 AND ov.option_group_id = og.id
593 AND $acl.entity_id = ov.value
596 ON $aclER.acl_role_id = $acl.entity_id
597 AND $aclER.is_active = 1
599 ON $aclER.entity_id = $c2g.group_id
600 AND $aclER.entity_table = 'civicrm_group'
601 WHERE $acl.entity_table = '$aclRole'
602 AND $acl.is_active = 1
603 AND $c2g.contact_id = $contact_id
604 AND $c2g.status = 'Added'";
608 $rule->query($query);
610 while ($rule->fetch()) {
611 $results[$rule->id
] = $rule->toArray();
614 // also get all acls for "Any Role" case
615 // and authenticated User Role if present
617 $session = CRM_Core_Session
::singleton();
618 if ($session->get('ufID') > 0) {
625 WHERE $acl.entity_id IN ( $roles )
626 AND $acl.entity_table = 'civicrm_acl_role'
629 $rule->query($query);
630 while ($rule->fetch()) {
631 $results[$rule->id
] = $rule->toArray();
638 * Get all ACLs owned by a given contact, including domain and group-level.
640 * @param int $contact_id
644 * Assoc array of ACL rules
646 public static function &getAllByContact($contact_id) {
649 /* First, the contact-specific ACLs, including ACL Roles */
650 $result +
= self
::getACLs($contact_id, NULL, TRUE);
652 /* Then, all ACLs granted through group membership */
653 $result +
= self
::getGroupACLs($contact_id, TRUE);
659 * @param array $params
661 * @return CRM_ACL_DAO_ACL
663 public static function create(&$params) {
664 $dao = new CRM_ACL_DAO_ACL();
665 $dao->copyValues($params);
671 * @param array $params
674 public static function retrieve(&$params, &$defaults) {
675 CRM_Core_DAO
::commonRetrieve('CRM_ACL_DAO_ACL', $params, $defaults);
679 * Update the is_active flag in the db.
682 * Id of the database record.
683 * @param bool $is_active
684 * Value we want to set the is_active field.
687 * true if we found and updated the object, else false
689 public static function setIsActive($id, $is_active) {
690 // note this also resets any ACL cache
691 CRM_Core_BAO_Cache
::deleteGroup('contact fields');
693 return CRM_Core_DAO
::setFieldValue('CRM_ACL_DAO_ACL', $id, 'is_active', $is_active);
698 * @param int $contactID
702 public static function check($str, $contactID) {
704 $acls = CRM_ACL_BAO_Cache
::build($contactID);
706 $aclKeys = array_keys($acls);
707 $aclKeys = implode(',', $aclKeys);
709 if (empty($aclKeys)) {
715 FROM civicrm_acl_cache c, civicrm_acl a
716 WHERE c.acl_id = a.id
718 AND a.object_table = %1
719 AND a.id IN ( $aclKeys )
721 $params = array(1 => array($str, 'String'));
723 $count = CRM_Core_DAO
::singleValueQuery($query, $params);
724 return ($count) ?
TRUE : FALSE;
730 * @param $whereTables
731 * @param int $contactID
733 * @return null|string
735 public static function whereClause($type, &$tables, &$whereTables, $contactID = NULL) {
736 $acls = CRM_ACL_BAO_Cache
::build($contactID);
742 $aclKeys = array_keys($acls);
743 $aclKeys = implode(',', $aclKeys);
746 SELECT a.operation, a.object_id
747 FROM civicrm_acl_cache c, civicrm_acl a
748 WHERE c.acl_id = a.id
750 AND a.object_table = 'civicrm_saved_search'
751 AND a.id IN ( $aclKeys )
755 $dao = CRM_Core_DAO
::executeQuery($query);
757 // do an or of all the where clauses u see
759 while ($dao->fetch()) {
760 // make sure operation matches the type TODO
761 if (self
::matchType($type, $dao->operation
)) {
762 if (!$dao->object_id
) {
764 $whereClause = ' ( 1 ) ';
767 $ids[] = $dao->object_id
;
772 $ids = implode(',', $ids);
776 WHERE g.id IN ( $ids )
779 $dao = CRM_Core_DAO
::executeQuery($query);
781 $groupContactCacheClause = FALSE;
782 while ($dao->fetch()) {
783 $groupIDs[] = $dao->id
;
785 if (($dao->saved_search_id ||
$dao->children ||
$dao->parents
) &&
786 $dao->cache_date
== NULL
788 CRM_Contact_BAO_GroupContactCache
::load($dao);
789 $groupContactCacheClause = " UNION SELECT contact_id FROM civicrm_group_contact_cache WHERE group_id IN (" . implode(', ', $groupIDs) . ")";
797 SELECT contact_id FROM civicrm_group_contact WHERE group_id IN (" . implode(', ', $groupIDs) . ") AND status = 'Added'
798 $groupContactCacheClause
805 if (!empty($clauses)) {
806 $whereClause = ' ( ' . implode(' OR ', $clauses) . ' ) ';
809 // call the hook to get additional whereClauses
810 CRM_Utils_Hook
::aclWhereClause($type, $tables, $whereTables, $contactID, $whereClause);
812 if (empty($whereClause)) {
813 $whereClause = ' ( 0 ) ';
821 * @param int $contactID
822 * @param string $tableName
823 * @param null $allGroups
824 * @param null $includedGroups
828 public static function group(
831 $tableName = 'civicrm_saved_search',
833 $includedGroups = NULL
835 $userCacheKey = "{$contactID}_{$type}_{$tableName}_" . CRM_Core_Config
::domainID() . '_' . md5(implode(',', array_merge((array) $allGroups, (array) $includedGroups)));
836 if (empty(Civi
::$statics[__CLASS__
]['permissioned_groups'])) {
837 Civi
::$statics[__CLASS__
]['permissioned_groups'] = array();
839 if (!empty(Civi
::$statics[__CLASS__
]['permissioned_groups'][$userCacheKey])) {
840 return Civi
::$statics[__CLASS__
]['permissioned_groups'][$userCacheKey];
843 $acls = CRM_ACL_BAO_Cache
::build($contactID);
847 $aclKeys = array_keys($acls);
848 $aclKeys = implode(',', $aclKeys);
850 $cacheKey = CRM_Core_BAO_Cache
::cleanKey("$tableName-$aclKeys");
851 $cache = CRM_Utils_Cache
::singleton();
852 $ids = $cache->get($cacheKey);
856 SELECT a.operation, a.object_id
857 FROM civicrm_acl_cache c, civicrm_acl a
858 WHERE c.acl_id = a.id
860 AND a.object_table = %1
861 AND a.id IN ( $aclKeys )
862 GROUP BY a.operation,a.object_id
865 $params = array(1 => array($tableName, 'String'));
866 $dao = CRM_Core_DAO
::executeQuery($query, $params);
867 while ($dao->fetch()) {
868 if ($dao->object_id
) {
869 if (self
::matchType($type, $dao->operation
)) {
870 $ids[] = $dao->object_id
;
874 // this user has got the permission for all objects of this type
875 // check if the type matches
876 if (self
::matchType($type, $dao->operation
)) {
877 foreach ($allGroups as $id => $dontCare) {
884 $cache->set($cacheKey, $ids);
888 if (empty($ids) && !empty($includedGroups) &&
889 is_array($includedGroups)
891 $ids = $includedGroups;
895 if (!empty($allGroups)) {
896 $groupWhere = " AND id IN (" . implode(',', array_keys($allGroups)) . ")";
898 // Contacts create hidden groups from search results. They should be able to retrieve their own.
899 $ownHiddenGroupsList = CRM_Core_DAO
::singleValueQuery("
900 SELECT GROUP_CONCAT(id) FROM civicrm_group WHERE is_hidden =1 AND created_id = $contactID
903 if ($ownHiddenGroupsList) {
904 $ownHiddenGroups = explode(',', $ownHiddenGroupsList);
905 $ids = array_merge((array) $ids, $ownHiddenGroups);
910 CRM_Utils_Hook
::aclGroup($type, $contactID, $tableName, $allGroups, $ids);
911 Civi
::$statics[__CLASS__
]['permissioned_groups'][$userCacheKey] = $ids;
921 public static function matchType($type, $operation) {
923 switch ($operation) {
929 if ($type == CRM_ACL_API
::VIEW
) {
935 if ($type == CRM_ACL_API
::VIEW ||
$type == CRM_ACL_API
::EDIT
) {
941 if ($type == CRM_ACL_API
::CREATE
) {
947 if ($type == CRM_ACL_API
::DELETE
) {
953 if ($type == CRM_ACL_API
::SEARCH
) {
962 * Delete ACL records.
965 * ID of the ACL record to be deleted.
968 public static function del($aclId) {
969 // delete all entries from the acl cache
970 CRM_ACL_BAO_Cache
::resetCache();
972 $acl = new CRM_ACL_DAO_ACL();