You are here

protected function JsonapiResourceController::ensureValidResponseDataResourceTypes in JSON:API Resources 8

Ensures that resource object responses contain only declared data.

JSON:API resources routes must either declare the `_jsonapi_resource_types` route default or provide their own implementation of \Drupal\jsonapi_resource\Resource\ResourceBase::getRouteResourceTypes(). By doing so, modules like JSON:API Schema and OpenAPI will be able to provide accurate schema information. Additionally, this ensures a good DX for client developers because query parameters like `filter` and `include` can be automatically validated.

Parameters

\Drupal\jsonapi\ResourceResponse $response: A JSON:API resource response object.

\Symfony\Component\HttpFoundation\Request $request: A request object.

Throws

\Drupal\jsonapi_resources\Exception\ResourceImplementationException Thrown if the response contains resource type data that is not declared by the resource processor.

1 call to JsonapiResourceController::ensureValidResponseDataResourceTypes()
JsonapiResourceController::processRequest in src/Unstable/Controller/JsonapiResourceController.php
Processes a request and returns a JSON:API ResourceResponse.

File

src/Unstable/Controller/JsonapiResourceController.php, line 111

Class

JsonapiResourceController
An interstitial controller between raw requests & JSON:API resource objects.

Namespace

Drupal\jsonapi_resources\Unstable\Controller

Code

protected function ensureValidResponseDataResourceTypes(ResourceResponse $response, Request $request) {
  $document = $response
    ->getResponseData();
  if ($response
    ->getStatusCode() === 204) {
    if ($document !== NULL) {
      throw new ResourceImplementationException('HTTP 204 responses should not have content.');
    }
  }
  else {
    assert($document instanceof JsonApiDocumentTopLevel);
    $data = $document
      ->getData();

    // Only resource object responses need to be validated.
    if ($data instanceof ResourceObjectData) {

      // Ensure that every object's resource type is declared as a route
      // resource type.
      foreach ($data as $object) {
        assert($object instanceof ResourceIdentifierInterface);
        $allowed = array_reduce($request->attributes
          ->get('resource_types', []), static function ($allowed, ResourceType $resource_type) use ($object) {
          return $allowed ?: $object
            ->getResourceType()
            ->getTypeName() === $resource_type
            ->getTypeName();
        }, FALSE);
        if (!$allowed) {
          throw new \LogicException('This resource attempted to serve data that contains unsupported resource types.');
        }
      }
    }
  }
}