You are here

function acb_node_grants_alter in Access Control Bridge 8

Same name and namespace in other branches
  1. 7 acb.module \acb_node_grants_alter()

Implements hook_node_grants_alter().

Let Drupal know of the current user's grants. We're using the _alter function because we need existing grants to calculate ours.

File

./acb.module, line 132
Drupal hooks and functions for the acb module.

Code

function acb_node_grants_alter(&$grants, AccountInterface $account, $op) {

  // Split all grants into their respective controlling modules and prepare the array for the recursive cascader.
  $split_grants = [];

  // ACL requires special care. The responsible module can only be determined by using the database.
  if (\Drupal::moduleHandler()
    ->moduleExists('acl')) {
    $acl = db_select('acl')
      ->fields('acl', [
      'acl_id',
      'module',
    ])
      ->execute()
      ->fetchAllAssoc('acl_id');
  }

  // For our ACB grants, we need the 'Edit any domain content' and 'Delete any domain content' permissions to be enabled to
  // enable other modules to control it effectively (due to the AND-logic we're implementing).
  // Add them to the user grants if not already present if Domain Access is active.
  // Additionally, fork $grants so we don't add them permanently to the referenced grants array.
  $acb_grants = $grants;
  if (\Drupal::moduleHandler()
    ->moduleExists('domain_access') && ($op == 'update' || $op == 'delete')) {
    $user = User::load($account
      ->id());
    $domains = \Drupal::service('domain_access.manager')
      ->getAccessValues($user);
    if (!empty($domains)) {
      foreach ($domains as $id) {
        if (abs($id) > 0) {
          $value = $id > 0 ? $id : 0;
          if (!isset($acb_grants['domain_id']) || !in_array($value, $acb_grants['domain_id'])) {
            $acb_grants['domain_id'][] = $value;
          }
        }
      }
    }
  }
  foreach (acb_get_modules() as $module) {

    // ACL requires special care. Extract the ACL ids for the current module.
    if (\Drupal::moduleHandler()
      ->moduleExists('acl')) {
      $entry_storage = [];
      foreach ($acl as $key => $entry) {
        if (acb_is_module_realm($entry->module, $module) === TRUE) {
          $entry_storage[$key] = $entry;
        }
      }
      $acl_current = array_keys($entry_storage);
    }
    foreach ($acb_grants as $realm => $gids) {

      // ACL requires special care. Filter out any ACL entries that were not set by the current module.
      if ($realm == 'acl') {
        $gids = array_intersect($gids, $acl_current);
      }

      // If this realm is originating from the current module (or if ACL has entries), then add the gids.
      if (acb_is_module_realm($realm, $module) === TRUE || $realm == 'acl' && !empty($gids)) {

        // Eventually prepare the module's subarray for pushing.
        if (empty($split_grants[$module])) {
          $split_grants[$module] = [];
        }
        foreach ($gids as $gid) {
          array_push($split_grants[$module], [
            'realm' => $realm,
            'gid' => $gid,
          ]);
        }
      }
    }
  }

  // We keep the existing grants and merge ACB's to support the case where only one module controls the node.
  // Filter out any modules that didn't set grants.
  $grants = array_merge($grants, _acb_cascade_grants(array_filter($split_grants)));
}