You are here

function bat_entity_access_query_alter in Booking and Availability Management Tools for Drupal 8

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

Implements hook_query_alter().

Enforces access control for bat units during database queries.

4 calls to bat_entity_access_query_alter()
bat_event_query_bat_event_access_alter in modules/bat_event/bat_event.module
Implements hook_query_TAG_alter().
bat_event_series_query_bat_event_series_access_alter in modules/bat_event_series/bat_event_series.module
Implements hook_query_TAG_alter().
bat_unit_query_bat_unit_access_alter in modules/bat_unit/bat_unit.module
Implements hook_query_TAG_alter().
bat_unit_query_bat_unit_type_access_alter in modules/bat_unit/bat_unit.module
Implements hook_query_TAG_alter().

File

./bat.module, line 316
Contains bat.module..

Code

function bat_entity_access_query_alter($query, $entity_type, $base_table = NULL, $account = NULL, $op = 'view') {

  // Get the Drupal user account from the query if available, or
  // default to the logged in user if not.
  if (!isset($account) && !($account = $query
    ->getMetaData('account'))) {
    $account = \Drupal::currentUser();
  }

  // Do not apply any conditions for users with administrative view permissions.
  if ($account
    ->hasPermission('bypass ' . $entity_type . ' entities access') || $account
    ->hasPermission($op . ' any ' . $entity_type . ' entity')) {
    return;
  }

  // Get the entity type info array for the current access check and prepare a
  // conditions object.
  $entity_info = \Drupal::entityTypeManager()
    ->getDefinition($entity_type);

  // Prepare an OR container for conditions. Conditions will be added that seek
  // to grant access, meaning any particular type of permission check may grant
  // access even if none of the others apply. At the end of this function, if no
  // conditions have been added to the array, a condition will be added that
  // always returns FALSE (1 = 0).
  $conditions = new Condition('OR');

  // Loop over every possible bundle for the given entity type.
  foreach (\Drupal::service('entity_type.bundle.info')
    ->getBundleInfo($entity_type) as $bundle_name => $bundle_info) {

    // If the user has access to operation entities of the current bundle...
    if ($account
      ->hasPermission($op . ' any ' . $entity_type . ' entity of bundle ' . $bundle_name)) {

      // Add a condition granting access if the entity specified by the view
      // query is of the same bundle.
      $conditions
        ->condition($base_table . '.' . $entity_info
        ->getKey('bundle'), $bundle_name);
    }
    elseif ($account
      ->id() && $entity_info
      ->getKey('uid') !== FALSE && $account
      ->hasPermission($op . ' own ' . $entity_type . ' entities of bundle ' . $bundle_name)) {

      // Add an AND condition group that grants access if the entity specified
      // by the view query matches the same bundle and belongs to the user.
      $c_and = new Condition('AND');
      $conditions
        ->condition($c_and
        ->condition($base_table . '.' . $entity_info
        ->getKey('bundle'), $bundle_name)
        ->condition($base_table . '.' . $entity_info
        ->getKey('uid'), $account
        ->id()));
    }
  }

  // Perform 'operation own' access control for the entity in the query if the
  // user is authenticated.
  if ($account
    ->id() && $account
    ->hasPermission($op . ' own ' . $entity_type . ' entities')) {
    $conditions
      ->condition($base_table . '.' . $entity_info
      ->getKey('uid'), $account
      ->id());
  }

  // Prepare an array of condition alter hooks to invoke and an array of context
  // data for the current query.
  $hooks = [
    'bat_entity_access_' . $op . '_condition_' . $entity_type,
    'bat_entity_access_' . $op . '_condition',
  ];
  $context = [
    'account' => $account,
    'entity_type' => $entity_type,
    'base_table' => $base_table,
  ];

  // Allow other modules to add conditions to the array as necessary.
  \Drupal::moduleHandler()
    ->alter($hooks, $conditions, $context);

  // If we have more than one condition based on the entity access permissions
  // and any hook implementations...
  if (count($conditions)) {

    // Add the conditions to the query.
    $query
      ->condition($conditions);
  }
  else {

    // Otherwise, since we don't have any possible conditions to match against,
    // we falsify this query. View checks are access grants, not access denials.
    $query
      ->where('1 = 0');
  }
}