You are here

function gnode_node_grants in Group 7

Implements hook_node_grants().

See also

gnode_node_access_records().

File

modules/gnode/gnode.node_access.inc, line 16
Hooks and functions used in compliance mode.

Code

function gnode_node_grants($account, $op) {

  // Provide the master grant for users who can bypass group access.
  if (user_access('bypass group access')) {
    return array(
      'gnode_bypass' => array(
        GNODE_MASTER_GRANT_ID,
      ),
    );
  }

  // Initialize a grant array for members and one for anonymous/outsider users.
  $grants_m = $grants_ao = array();

  // Gather the machine names of all node types.
  $node_types = array_keys(node_type_get_types());

  // If the user could not bypass group access, we need to check their access
  // for every single group. Because loading every group would incur a massive
  // performance hit, we only load those groups the user is a member of.
  foreach (GroupMembership::getByActiveStatus($account->uid) as $group_membership) {

    // Add the groups the user is a member of to use later on.
    $member_gids[] = $gid = $group_membership->gid;

    // See whether the user has all permissions for this group.
    $group_administrator = $group_membership
      ->hasPermission('administer group');
    foreach ($node_types as $node_type) {
      switch ($op) {
        case 'view':

          // Allow the user to view published content of this type.
          if ($group_administrator || $group_membership
            ->hasPermission("view {$node_type} node")) {
            $grants_m["gnode:{$node_type}"][] = $gid;
          }

          // Allow the user to view unpublished content of this type.
          if ($group_administrator || $group_membership
            ->hasPermission("view unpublished {$node_type} node")) {
            $grants_m["gnode_unpublished:{$node_type}"][] = $gid;
          }
          break;
        case 'update':
        case 'delete':

          // If you can act on any node, there's no need for the author grant.
          if ($group_administrator || $group_membership
            ->hasPermission("{$op} any {$node_type} node")) {
            $grants_m["gnode:{$node_type}"][] = $gid;
          }
          elseif ($group_membership
            ->hasPermission("{$op} own {$node_type} node")) {
            $grants_m["gnode_author:{$account->uid}:{$node_type}"][] = $gid;
          }
          break;
      }
    }
  }

  // All other groups have the benefit of sharing the same permission set among
  // all anonymous or authenticated users per group type. We can therefore know
  // the user's permissions for all groups of the same type they aren't part of.
  $query = db_select('groups', 'g')
    ->fields('g', array(
    'gid',
    'type',
  ));
  if (!empty($member_gids)) {
    $query
      ->condition('gid', $member_gids, 'NOT IN');
  }
  foreach ($query
    ->execute() as $record) {
    $gids_per_group_type[$record->type][] = $record->gid;
  }
  foreach (group_types() as $name => $group_type) {

    // If we could not retrieve any group IDs, skip to the next group type.
    if (empty($gids_per_group_type[$name])) {
      continue;
    }

    // Get the IDs of all the groups the user is not part of for the group type.
    $gids = $gids_per_group_type[$name];

    // Grab the anonymous or outsider permissions for the group type depending
    // on the user's account status (anonymous or authenticated).
    $permissions = $account->uid == 0 ? $group_type->anonymous_permissions : $group_type->outsider_permissions;

    // See whether the user has all permissions for this group type.
    $group_administrator = in_array('administer group', $permissions, TRUE);
    foreach ($node_types as $node_type) {
      switch ($op) {
        case 'view':

          // Allow the user to view published content of this type.
          if ($group_administrator || in_array("view {$node_type} node", $permissions, TRUE)) {
            $grants_ao["gnode:{$node_type}"][] = $gids;
          }

          // Allow the user to view unpublished content of this type.
          if ($group_administrator || in_array("view unpublished {$node_type} node", $permissions, TRUE)) {
            $grants_ao["gnode_unpublished:{$node_type}"][] = $gids;
          }
          break;
        case 'update':
        case 'delete':

          // If you can act on any node, there's no need for the author grant.
          if ($group_administrator || in_array("{$op} any {$node_type} node", $permissions, TRUE)) {
            $grants_ao["gnode:{$node_type}"][] = $gids;
          }
          elseif (in_array("{$op} own {$node_type} node", $permissions, TRUE)) {
            $grants_ao["gnode_author:{$account->uid}:{$node_type}"][] = $gids;
          }
          break;
      }
    }
  }

  // The code above populated the anonymous/outsider grants by adding the group
  // IDs per group type. We need to combine this into one big list of group IDs
  // per entry in the $grants_ao array.
  foreach ($grants_ao as $key => $grants_per_group_type) {
    $grants_ao[$key] = array_reduce($grants_per_group_type, 'array_merge', array());
  }

  // Recursively merge the member grants with the anonymous/outsider grants.
  return array_merge_recursive($grants_m, $grants_ao);
}