You are here

class VersionNegotiator in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/jsonapi/src/Revisions/VersionNegotiator.php \Drupal\jsonapi\Revisions\VersionNegotiator
  2. 9 core/modules/jsonapi/src/Revisions/VersionNegotiator.php \Drupal\jsonapi\Revisions\VersionNegotiator

Provides a version negotiator manager.

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

Hierarchy

Expanded class hierarchy of VersionNegotiator

See also

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

jsonapi.api.php

\Drupal\jsonapi\Revisions\VersionNegotiatorInterface

1 file declares its use of VersionNegotiator
VersionNegotiatorTest.php in core/modules/jsonapi/tests/src/Kernel/Revisions/VersionNegotiatorTest.php
1 string reference to 'VersionNegotiator'
jsonapi.services.yml in core/modules/jsonapi/jsonapi.services.yml
core/modules/jsonapi/jsonapi.services.yml
1 service uses VersionNegotiator
jsonapi.version_negotiator in core/modules/jsonapi/jsonapi.services.yml
Drupal\jsonapi\Revisions\VersionNegotiator

File

core/modules/jsonapi/src/Revisions/VersionNegotiator.php, line 21

Namespace

Drupal\jsonapi\Revisions
View source
class VersionNegotiator {

  /**
   * The separator between the version negotiator name and the version argument.
   *
   * @var string
   */
  const SEPARATOR = ':';

  /**
   * An array of named version negotiators.
   *
   * @var \Drupal\jsonapi\Revisions\VersionNegotiatorInterface[]
   */
  protected $negotiators = [];

  /**
   * Adds a version negotiator.
   *
   * @param \Drupal\jsonapi\Revisions\VersionNegotiatorInterface $version_negotiator
   *   The version negotiator.
   * @param string $negotiator_name
   *   The name of the negotiation strategy used by the version negotiator.
   */
  public function addVersionNegotiator(VersionNegotiatorInterface $version_negotiator, $negotiator_name) {
    assert(strpos(get_class($version_negotiator), 'Drupal\\jsonapi\\') === 0, 'Version negotiators are not a public API.');
    $this->negotiators[$negotiator_name] = $version_negotiator;
  }

  /**
   * Gets a negotiated entity revision.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   * @param string $resource_version_identifier
   *   A value used to derive a revision for the given entity.
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   The loaded revision.
   *
   * @throws \Drupal\Core\Http\Exception\CacheableNotFoundHttpException
   *   When the revision does not exist.
   * @throws \Drupal\Core\Http\Exception\CacheableBadRequestHttpException
   *   When the revision ID cannot be negotiated.
   */
  public function getRevision(EntityInterface $entity, $resource_version_identifier) {
    try {
      [
        $version_negotiator_name,
        $version_argument,
      ] = explode(VersionNegotiator::SEPARATOR, $resource_version_identifier, 2);
      if (!isset($this->negotiators[$version_negotiator_name])) {
        static::throwBadRequestHttpException($resource_version_identifier);
      }
      return $this->negotiators[$version_negotiator_name]
        ->getRevision($entity, $version_argument);
    } catch (VersionNotFoundException $exception) {
      static::throwNotFoundHttpException($entity, $resource_version_identifier);
    } catch (InvalidVersionIdentifierException $exception) {
      static::throwBadRequestHttpException($resource_version_identifier);
    }
  }

  /**
   * Throws a cacheable error exception.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity for which a revision was requested.
   * @param string $resource_version_identifier
   *   The user input for the revision negotiation.
   *
   * @throws \Drupal\Core\Http\Exception\CacheableNotFoundHttpException
   */
  protected static function throwNotFoundHttpException(EntityInterface $entity, $resource_version_identifier) {
    $cacheability = CacheableMetadata::createFromObject($entity)
      ->addCacheContexts([
      'url.path',
      'url.query_args:' . ResourceVersionRouteEnhancer::RESOURCE_VERSION_QUERY_PARAMETER,
    ]);
    $reason = sprintf('The requested version, identified by `%s`, could not be found.', $resource_version_identifier);
    throw new CacheableNotFoundHttpException($cacheability, $reason);
  }

  /**
   * Throws a cacheable error exception.
   *
   * @param string $resource_version_identifier
   *   The user input for the revision negotiation.
   *
   * @throws \Drupal\Core\Http\Exception\CacheableBadRequestHttpException
   */
  protected static function throwBadRequestHttpException($resource_version_identifier) {
    $cacheability = (new CacheableMetadata())
      ->addCacheContexts([
      'url.query_args:' . ResourceVersionRouteEnhancer::RESOURCE_VERSION_QUERY_PARAMETER,
    ]);
    $message = sprintf('An invalid resource version identifier, `%s`, was provided.', $resource_version_identifier);
    throw new CacheableBadRequestHttpException($cacheability, $message);
  }

}

Members