You are here

class RelationshipFieldAccess in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/jsonapi/src/Access/RelationshipFieldAccess.php \Drupal\jsonapi\Access\RelationshipFieldAccess

Defines a class to check access to related and relationship routes.

@internal JSON:API maintains no PHP API. The API is the HTTP API. This class may change at any time and could break any dependencies on it.

Hierarchy

Expanded class hierarchy of RelationshipFieldAccess

See also

https://www.drupal.org/project/drupal/issues/3032787

jsonapi.api.php

1 file declares its use of RelationshipFieldAccess
Routes.php in core/modules/jsonapi/src/Routing/Routes.php
1 string reference to 'RelationshipFieldAccess'
jsonapi.services.yml in core/modules/jsonapi/jsonapi.services.yml
core/modules/jsonapi/jsonapi.services.yml
1 service uses RelationshipFieldAccess
access_check.jsonapi.relationship_field_access in core/modules/jsonapi/jsonapi.services.yml
Drupal\jsonapi\Access\RelationshipFieldAccess

File

core/modules/jsonapi/src/Access/RelationshipFieldAccess.php, line 26

Namespace

Drupal\jsonapi\Access
View source
class RelationshipFieldAccess implements AccessInterface {

  /**
   * The route requirement key for this access check.
   *
   * @var string
   */
  const ROUTE_REQUIREMENT_KEY = '_jsonapi_relationship_field_access';

  /**
   * The JSON:API entity access checker.
   *
   * @var \Drupal\jsonapi\Access\EntityAccessChecker
   */
  protected $entityAccessChecker;

  /**
   * RelationshipFieldAccess constructor.
   *
   * @param \Drupal\jsonapi\Access\EntityAccessChecker $entity_access_checker
   *   The JSON:API entity access checker.
   */
  public function __construct(EntityAccessChecker $entity_access_checker) {
    $this->entityAccessChecker = $entity_access_checker;
  }

  /**
   * Checks access to the relationship field on the given route.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming HTTP request object.
   * @param \Symfony\Component\Routing\Route $route
   *   The route to check against.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The currently logged in account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(Request $request, Route $route, AccountInterface $account) {
    $relationship_field_name = $route
      ->getRequirement(static::ROUTE_REQUIREMENT_KEY);
    $field_operation = $request
      ->isMethodCacheable() ? 'view' : 'edit';
    $entity_operation = $request
      ->isMethodCacheable() ? 'view' : 'update';
    if ($resource_type = $request
      ->get(Routes::RESOURCE_TYPE_KEY)) {
      assert($resource_type instanceof ResourceType);
      $entity = $request
        ->get('entity');
      $internal_name = $resource_type
        ->getInternalName($relationship_field_name);
      if ($entity instanceof FieldableEntityInterface && $entity
        ->hasField($internal_name)) {
        $entity_access = $this->entityAccessChecker
          ->checkEntityAccess($entity, $entity_operation, $account);
        $field_access = $entity
          ->get($internal_name)
          ->access($field_operation, $account, TRUE);

        // Ensure that access is respected for different entity revisions.
        $access_result = $entity_access
          ->andIf($field_access);
        if (!$access_result
          ->isAllowed()) {
          $reason = "The current user is not allowed to {$field_operation} this relationship.";
          $access_reason = $access_result instanceof AccessResultReasonInterface ? $access_result
            ->getReason() : NULL;
          $detailed_reason = empty($access_reason) ? $reason : $reason . " {$access_reason}";
          $access_result
            ->setReason($detailed_reason);
          if ($request
            ->isMethodCacheable()) {
            throw new CacheableAccessDeniedHttpException(CacheableMetadata::createFromObject($access_result), $detailed_reason);
          }
        }
        return $access_result;
      }
    }
    return AccessResult::neutral();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
RelationshipFieldAccess::$entityAccessChecker protected property The JSON:API entity access checker.
RelationshipFieldAccess::access public function Checks access to the relationship field on the given route.
RelationshipFieldAccess::ROUTE_REQUIREMENT_KEY constant The route requirement key for this access check.
RelationshipFieldAccess::__construct public function RelationshipFieldAccess constructor.