isLocatable example


  protected static function buildLinksFromEntity(ResourceType $resource_type, EntityInterface $entity, LinkCollection $links) {
    if ($resource_type->isLocatable() && !$resource_type->isInternal()) {
      $self_url = Url::fromRoute(Routes::getRouteName($resource_type, 'individual')['entity' => $entity->uuid()]);
      if ($resource_type->isVersionable()) {
        assert($entity instanceof RevisionableInterface);
        if (!$links->hasLinkWithKey('self')) {
          // If the resource is versionable, the `self` link should be the exact           // link for the represented version. This helps a client track           // revision changes and to disambiguate resource objects with the same           // `type` and `id` in a `version-history` collection.           $self_with_version_url = $self_url->setOption('query', [JsonApiSpec::VERSION_QUERY_PARAMETER => 'id:' . $entity->getRevisionId()]);
          $links = $links->withLink('self', new Link(new CacheableMetadata()$self_with_version_url, 'self'));
        }
        
$cacheability = (new CacheableMetadata())
      ->addCacheContexts(['user.roles:authenticated'])
      ->addCacheTags(['jsonapi_resource_types']);

    // Only build URLs for exposed resources.     $resources = array_filter($this->resourceTypeRepository->all()function D$resource) {
      return !$resource->isInternal();
    });

    $self_link = new Link(new CacheableMetadata(), Url::fromRoute('jsonapi.resource_list'), 'self');
    $urls = array_reduce($resourcesfunction DLinkCollection $carry, ResourceType $resource_type) {
      if ($resource_type->isLocatable() || $resource_type->isMutable()) {
        $route_suffix = $resource_type->isLocatable() ? 'collection' : 'collection.post';
        $url = Url::fromRoute(sprintf('jsonapi.%s.%s', $resource_type->getTypeName()$route_suffix))->setAbsolute();
        // Using a resource type name in place of a link relation type is not         // technically valid. However, since it matches the link key, it will         // not actually be serialized since the rel is omitted if it matches the         // link key; because of that no client can rely on it. Once an extension         // relation type is implemented for links to a collection, that should         // be used instead. Unfortunately, the `collection` link relation type         // would not be semantically correct since it would imply that the         // entrypoint is a *member* of the link target.         // @todo: implement an extension relation type to signal that this is a primary collection resource.
/** * {@inheritdoc} */
  protected function createResourceType(EntityTypeInterface $entity_type$bundle) {
    $resource_type = parent::createResourceType($entity_type$bundle);
    return new CountableResourceType(
      $resource_type->getEntityTypeId(),
      $resource_type->getBundle(),
      $resource_type->getDeserializationTargetClass(),
      $resource_type->isInternal(),
      $resource_type->isLocatable(),
      $resource_type->isMutable(),
      $resource_type->isVersionable(),
      $resource_type->getFields(),
      $resource_type->getTypeName()
    );
  }

}


    $parsed_entity->save();

    // Build response object.     $resource_object = ResourceObject::createFromEntity($resource_type$parsed_entity);
    $primary_data = new ResourceObjectData([$resource_object], 1);
    $response = $this->buildWrappedResponse($primary_data$request$this->getIncludes($request$primary_data), 201);

    // According to JSON:API specification, when a new entity was created     // we should send "Location" header to the frontend.     if ($resource_type->isLocatable()) {
      $url = $resource_object->toUrl()->setAbsolute()->toString(TRUE);
      $response->headers->set('Location', $url->getGeneratedUrl());
    }

    // Return response object with updated headers info.     return $response;
  }

  /** * Patches an individual entity. * * @param \Drupal\jsonapi\ResourceType\ResourceType $resource_type * The JSON:API resource type for the request to be served. * @param \Drupal\Core\Entity\EntityInterface $entity * The loaded entity. * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * * @return \Drupal\jsonapi\ResourceResponse * The response. * * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * Thrown when the selected entity does not match the id in th payload. * @throws \Drupal\jsonapi\Exception\UnprocessableHttpEntityException * Thrown when the patched entity does not pass validation. */

  protected static function buildLinkCollectionFromEntityReferenceField(ResourceObject $context, EntityReferenceFieldItemListInterface $field, LinkCollection $links) {
    $context_resource_type = $context->getResourceType();
    $public_field_name = $context_resource_type->getPublicName($field->getName());
    if ($context_resource_type->isLocatable() && !$context_resource_type->isInternal()) {
      $context_is_versionable = $context_resource_type->isVersionable();
      if (!$links->hasLinkWithKey('self')) {
        $route_name = Routes::getRouteName($context_resource_type, "$public_field_name.relationship.get");
        $self_link = Url::fromRoute($route_name['entity' => $context->getId()]);
        if ($context_is_versionable) {
          $self_link->setOption('query', [JsonApiSpec::VERSION_QUERY_PARAMETER => $context->getVersionIdentifier()]);
        }
        $links = $links->withLink('self', new Link(new CacheableMetadata()$self_link, 'self'));
      }
      $has_non_internal_resource_type = array_reduce($context_resource_type->getRelatableResourceTypesByField($public_field_name)function D$carry, ResourceType $target) {
        return $carry ?: !$target->isInternal();
      },
    // - to first test all mistakes a developer might make, and assert that the     // error responses provide a good DX     // - to eventually result in a well-formed request that succeeds.     $url = Url::fromRoute(sprintf('jsonapi.%s.collection.post', static::$resourceTypeName));
    $request_options = [];
    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
    $request_options = NestedArray::mergeDeep($request_options$this->getAuthenticationRequestOptions());

    // DX: 405 when read-only mode is enabled.     $response = $this->request('POST', $url$request_options);
    $this->assertResourceErrorResponse(405, sprintf("JSON:API is configured to accept only read operations. Site administrators can configure this at %s.", Url::fromUri('base:/admin/config/services/jsonapi')->setAbsolute()->toString(TRUE)->getGeneratedUrl())$url$response);
    if ($this->resourceType->isLocatable()) {
      $this->assertSame(['GET']$response->getHeader('Allow'));
    }
    else {
      $this->assertSame(['']$response->getHeader('Allow'));
    }

    $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);

    // DX: 415 when no Content-Type request header.     $response = $this->request('POST', $url$request_options);
    $this->assertSame(415, $response->getStatusCode());

    

  public static function getRelationshipLinks(ResourceObject $relationship_context, ResourceTypeRelationship $resource_relationship) {
    $resource_type = $relationship_context->getResourceType();
    if ($resource_type->isInternal() || !$resource_type->isLocatable()) {
      return [];
    }
    $public_field_name = $resource_relationship->getPublicName();
    $relationship_route_name = Routes::getRouteName($resource_type, "$public_field_name.relationship.get");
    $links = [
      'self' => Url::fromRoute($relationship_route_name['entity' => $relationship_context->getId()]),
    ];
    if (static::hasNonInternalResourceType($resource_type->getRelatableResourceTypesByField($public_field_name))) {
      $related_route_name = Routes::getRouteName($resource_type, "$public_field_name.related");
      $links['related'] = Url::fromRoute($related_route_name['entity' => $relationship_context->getId()]);
    }
    

  protected static function getRoutesForResourceType(ResourceType $resource_type$path_prefix) {
    // Internal resources have no routes.     if ($resource_type->isInternal()) {
      return new RouteCollection();
    }

    $routes = new RouteCollection();

    // Collection route like `/jsonapi/node/article`.     if ($resource_type->isLocatable()) {
      $collection_route = new Route("/{$resource_type->getPath()}");
      $collection_route->addDefaults([RouteObjectInterface::CONTROLLER_NAME => static::CONTROLLER_SERVICE_NAME . ':getCollection']);
      $collection_route->setMethods(['GET']);
      // Allow anybody access because "view" and "view label" access are checked       // in the controller.       $collection_route->setRequirement('_access', 'TRUE');
      $routes->add(static::getRouteName($resource_type, 'collection')$collection_route);
    }

    // Creation route.     if ($resource_type->isMutable()) {
      
Home | Imprint | This part of the site doesn't use cookies.