You are here

public function AccessChecker::isAccessAllowed in Permissions by Term 8

Same name and namespace in other branches
  1. 8.2 modules/permissions_by_entity/src/Service/AccessChecker.php \Drupal\permissions_by_entity\Service\AccessChecker::isAccessAllowed()

Checks if a user is allowed to access a fieldable entity.

Parameters

\Drupal\Core\Entity\FieldableEntityInterface $entity: A fieldable entity.

bool|int $uid: (Optional) Defaults to the uid of the current user.

Return value

bool TRUE if access is allowed, otherwise FALSE. TRUE if access is allowed, otherwise FALSE.

Overrides AccessCheckerInterface::isAccessAllowed

File

modules/permissions_by_entity/src/Service/AccessChecker.php, line 71

Class

AccessChecker
Class AccessChecker.

Namespace

Drupal\permissions_by_entity\Service

Code

public function isAccessAllowed(FieldableEntityInterface $entity, $uid = FALSE) {

  // Iterate over the fields the entity contains.
  foreach ($entity
    ->getFields() as $field) {

    // We only need to check for entity reference fields
    // which references to a taxonomy term.
    if ($field
      ->getFieldDefinition()
      ->getType() == 'entity_reference' && $field
      ->getFieldDefinition()
      ->getSetting('target_type') == 'taxonomy_term') {

      // Iterate over each referenced taxonomy term.

      /** @var \Drupal\Core\Field\FieldItemInterface $item */
      foreach ($field
        ->getValue() as $item) {

        // Let "Permissions By Term" do the actual check.
        if (!empty($item['target_id']) && !$this
          ->isAccessAllowedByDatabase($item['target_id'], $uid, $entity
          ->language()
          ->getId())) {

          // Return that the user is not allowed to access this entity.
          return FALSE;
        }
      }
    }

    // Check if the field contains another fieldable entity,
    // that we need to check.
    if ($field->entity && $field->entity instanceof FieldableEntityInterface) {

      // We need to iterate over the entities.
      $num_values = $field
        ->count();
      if ($num_values > 0) {

        // Iterate over the field values.
        for ($i = 0; $i < $num_values; $i++) {

          // Get the value of the current field index.
          $field_value = $field
            ->get($i);

          // If the value is null or empty we continue with the next index of
          // the loop.
          if (!$field_value) {
            continue;
          }

          // Get the field entity.
          $field_entity = $field_value->entity;

          // If the field entity is null we also continue with the next index
          // of the loop.
          if (!$field_entity) {
            continue;
          }

          // It is possible, that the referenced field entity creates a
          // circular dependency to the current entity. This will cause
          // memory limit exhausted errors because there is no way out for
          // the script. To avoid this, we need to be able to imagine if we
          // already checked this field entity before. If so, we ignore this
          // field entity, if not we can securely do a recursive call.
          //
          // Using own method to avoid "max nesting level error" trying to
          // check if the field entity is stored in the entitiesChecked array.
          if ($this->checkedEntityCache
            ->isChecked($field_entity)) {
            continue;
          }
          else {

            // Add the current entity to the list of checked entities.
            $this->checkedEntityCache
              ->add($field_entity);
          }

          // Do a recursive call to check if the user is allowed to access
          // this entity.
          if (!$this
            ->isAccessAllowed($field_entity, $uid)) {

            // Dispatch an event to allow subscribers
            // to do something in this case.
            $this->event
              ->setIndex($i);
            $this->event
              ->setField($field);
            $this->event
              ->setEntity($field_entity);
            $this->event
              ->setUid($uid);
            $this->eventDispatcher
              ->dispatch(PermissionsByEntityEvents::ENTITY_FIELD_VALUE_ACCESS_DENIED_EVENT, $this->event);
            $i = $this->event
              ->getIndex();
          }
        }
      }
    }
  }
  return TRUE;
}