Skip to content



This hook is called when composing the ACL to restrict access to civicrm entities (civicrm groups, profiles and events).


In order to use this hook you must uncheck "View All Contacts" AND "Edit All Contacts" in Drupal Permissions for the user role you want to limit. You can then go into CiviCRM and grant permission to Edit or View "All Contacts" or "Certain Groups". See the Forum Topic at:,14595.0.html for more information.


If you're looking to control access to CiviCRM contacts, use hook_civicrm_aclWhereClause.


This hook only work with the entities that the core ACL system works with. To apply access control restrictions to other entities e.g Mailing, use hook_civicrm_selectWhereClause


hook_civicrm_aclGroup($type, $contactID, $tableName, &$allGroups, &$currentGroups)


  • $type - the type of permission needed
  • $contactID - the contactID for whom the check is made
  • $tableName - the tableName which is being permissioned
  • $allGroups - the set of all the objects for the above table
  • $currentGroups - the set of objects that are currently permissioned for this contact. This array will be modified by the hook


  • null - the return value is ignored


From the multisite extension:

 * Implements ACLGroup hook().
 * aclGroup function returns a list of groups which are either children of the
 * domain group id or connected to the same organisation as the domain Group ID
 * @param string $type
 * @param int $contactID
 * @param string $tableName
 * @param array $allGroups
 * @param array $currentGroups
 * @throws \CiviCRM_API3_Exception
function multisite_civicrm_aclGroup($type, $contactID, $tableName, &$allGroups, &$currentGroups) {

  // only process civicrm_group
  // NOTE: Before CiviCRM 5.64 'civicrm_group' was 'civicrm_saved_search' instead.
  if ($tableName != 'civicrm_group') {
  $isEnabled = civicrm_api('setting', 'getvalue', [
      'version' => 3,
      'name' => 'is_enabled',
      'group' => 'Multi Site Preferences',
  $groupID = _multisite_get_domain_group();
  // If multisite is not enabled, or if a domain group is not selected, then we default to all groups allowed
  if (!$isEnabled || !$groupID) {
    $currentGroups = array_keys($allGroups);
  if (!CRM_Core_Permission::check('list all groups in domain') && !_multisite_add_permissions($type)) {
  $currentGroups = array_merge($currentGroups ?? [], _multisite_get_all_child_groups($groupID, FALSE));
  $currentGroups = array_merge($currentGroups, _multisite_get_domain_groups($groupID));
  $disabledGroups = [];
  $disabled = civicrm_api3('group', 'get', [
    'is_active' => 0,
    'check_permissions' => FALSE,
    'return' => 'id',
    'sequential' => 1,
    'options' => ['limit' => 0],
  foreach ($disabled['values'] as $group) {
    $disabledGroups[] = (int) $group['id'];
  if (!empty($allGroups)) {
    //all groups is empty if we really mean all groups but if a filter like 'is_disabled' is already applied
    // it is populated, ajax calls from Manage Groups will leave empty but calls from New Mailing pass in a filtered list
    $originalCurrentGroups = $currentGroups;
    $currentGroups = array_intersect($currentGroups, array_keys($allGroups));
    $currentGroups = array_merge($currentGroups, array_intersect($originalCurrentGroups, $disabledGroups));