You are here

function bat_entity_access in Booking and Availability Management Tools for Drupal 8

Same name and namespace in other branches
  1. 7 bat.module \bat_entity_access()

Implements hook_entity_access().

6 calls to bat_entity_access()
bat_booking_access in modules/bat_booking/bat_booking.module
Determines whether the given user has access to a unit.
bat_event_access in modules/bat_event/bat_event.module
Checks event access for various operations.
bat_event_series_access in modules/bat_event_series/bat_event_series.module
Checks event access for various operations.
bat_type_access in modules/bat_unit/bat_unit.module
Determines whether the given user has access to a type.
bat_unit_access in modules/bat_unit/bat_unit.module
Determines whether the given user has access to a unit.

... See full list

File

./bat.module, line 91
Contains bat.module..

Code

function bat_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
  $rights =& drupal_static(__FUNCTION__, []);
  $entity_type = $entity
    ->getEntityType()
    ->id();
  if (in_array($entity_type, [
    'bat_type_group',
    'bat_unit',
    'bat_unit_type',
    'bat_event',
    'bat_event_series',
    'bat_booking',
  ])) {
    $entity_info = \Drupal::entityTypeManager()
      ->getDefinition($entity_type);
    $cid = $entity
      ->id();

    // If we are creating a new entity make sure we set the type
    // so permissions get applied.
    if ($operation == 'create' && $cid == '') {
      $cid = $entity
        ->getEntityType()
        ->id();
    }

    // If we've already checked access for this entity, user and op, return the
    // cached result.
    if (isset($rights[$account
      ->id()][$cid][$operation])) {
      if ($rights[$account
        ->id()][$cid][$operation]) {
        return AccessResult::allowed();
      }
      else {
        return AccessResult::forbidden();
      }
    }

    // Grant generic administrator level access.
    if ($account
      ->hasPermission('bypass ' . $entity_type . ' entities access')) {
      $rights[$account
        ->id()][$cid][$operation] = TRUE;
      return AccessResult::allowed();
    }
    if ($operation == 'view') {

      // When trying to figure out access to an entity, query the base table
      // using our access control tag.
      // TODO remove incorrect hook test in summer 2020.
      if (Drupal::moduleHandler()
        ->getImplementations('query_' . $entity_type . '_alter') || Drupal::moduleHandler()
        ->getImplementations('query_' . $entity_type . '_access_alter')) {

        // Trigger an error if the deprecated hook is implemented.
        // TODO remove in summer 2020.
        if (Drupal::moduleHandler()
          ->getImplementations('query_' . $entity_type . '_alter')) {
          $message = "The 'query_{$entity_type}_alter' hook has been ";
          $message .= "deprecated, and will be removed in a future release. ";
          $message .= "Please use the 'query_{$entity_type}_access_alter'";
          $message .= " hook instead.";

          // phpcs:ignore
          trigger_error($message, E_USER_DEPRECATED);
        }
        $query = \Drupal::database()
          ->select($entity_info
          ->getBaseTable());
        $query
          ->addExpression('1');
        $result = (bool) $query
          ->addTag($entity_type)
          ->addTag($entity_type . '_access')
          ->addMetaData('account', $account)
          ->condition($entity_info
          ->getKey('id'), $entity
          ->id())
          ->range(0, 1)
          ->execute()
          ->fetchField();
        $rights[$account
          ->id()][$cid][$operation] = $result;
        if ($result) {
          return AccessResult::allowed();
        }
        else {
          return AccessResult::forbidden();
        }
      }
      else {
        $rights[$account
          ->id()][$cid][$operation] = TRUE;
        return AccessResult::allowed();
      }
    }
    else {

      // Non-view operations.
      // First grant access to the entity for the specified operation if no other
      // module denies it and at least one other module says to grant access.
      $access_results = \Drupal::moduleHandler()
        ->invokeAll('bat_entity_access', [
        $entity,
        $operation,
        $account,
      ]);
      if (in_array(FALSE, $access_results, TRUE)) {
        $rights[$account
          ->id()][$cid][$operation] = FALSE;
        return AccessResult::forbidden();
      }
      elseif (in_array(TRUE, $access_results, TRUE)) {
        $rights[$account
          ->id()][$cid][$operation] = TRUE;
        return AccessResult::allowed();
      }

      // Grant access based on entity type and bundle specific permissions with
      // special handling for the create operation since the entity passed in will
      // be initialized without ownership.
      if ($operation == 'create') {
        $access = $account
          ->hasPermission('create ' . $entity_type . ' entities') || $account
          ->hasPermission('create ' . $entity_type . ' entities of bundle ' . $entity
          ->bundle());
        $rights[$account
          ->id()][$cid][$operation] = $access;
        if ($access) {
          return AccessResult::allowed();
        }
        else {
          return AccessResult::forbidden();
        }
      }
      else {

        // Finally perform checks for the rest of operations. Begin by
        // extracting the bundle name from the entity if available.
        $bundle_name = $entity
          ->bundle();

        // For the update and delete operations, first perform the entity type and
        // bundle-level access check for any entity.
        if ($account
          ->hasPermission($operation . ' any ' . $entity_type . ' entity') || $account
          ->hasPermission($operation . ' any ' . $entity_type . ' entity of bundle ' . $bundle_name)) {
          $rights[$account
            ->id()][$cid][$operation] = TRUE;
          return AccessResult::allowed();
        }

        // Then check an authenticated user's access to delete own entities.
        if (method_exists($entity, 'getOwnerId')) {
          if ($account
            ->id() && $entity
            ->getOwnerId() && $entity
            ->getOwnerId() === $account
            ->id()) {
            if ($account
              ->hasPermission($operation . ' own ' . $entity_type . ' entities') || $account
              ->hasPermission($operation . ' own ' . $entity_type . ' entities of bundle ' . $bundle_name)) {
              $rights[$account
                ->id()][$cid][$operation] = TRUE;
              return AccessResult::allowed();
            }
          }
        }
      }
    }
    return AccessResult::forbidden();
  }
}