Mercurial > hg > cmmr2012-drupal-site
diff core/modules/jsonapi/src/Revisions/VersionNegotiator.php @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/jsonapi/src/Revisions/VersionNegotiator.php Thu May 09 15:34:47 2019 +0100 @@ -0,0 +1,112 @@ +<?php + +namespace Drupal\jsonapi\Revisions; + +use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Http\Exception\CacheableBadRequestHttpException; +use Drupal\Core\Http\Exception\CacheableNotFoundHttpException; + +/** + * 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. + * + * @see https://www.drupal.org/project/jsonapi/issues/3032787 + * @see jsonapi.api.php + * + * @see \Drupal\jsonapi\Revisions\VersionNegotiatorInterface + */ +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 { + list($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); + } + +}