annotate core/modules/jsonapi/src/Revisions/VersionNegotiator.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@18 1 <?php
Chris@18 2
Chris@18 3 namespace Drupal\jsonapi\Revisions;
Chris@18 4
Chris@18 5 use Drupal\Core\Cache\CacheableMetadata;
Chris@18 6 use Drupal\Core\Entity\EntityInterface;
Chris@18 7 use Drupal\Core\Http\Exception\CacheableBadRequestHttpException;
Chris@18 8 use Drupal\Core\Http\Exception\CacheableNotFoundHttpException;
Chris@18 9
Chris@18 10 /**
Chris@18 11 * Provides a version negotiator manager.
Chris@18 12 *
Chris@18 13 * @internal JSON:API maintains no PHP API since its API is the HTTP API. This
Chris@18 14 * class may change at any time and this will break any dependencies on it.
Chris@18 15 *
Chris@18 16 * @see https://www.drupal.org/project/jsonapi/issues/3032787
Chris@18 17 * @see jsonapi.api.php
Chris@18 18 *
Chris@18 19 * @see \Drupal\jsonapi\Revisions\VersionNegotiatorInterface
Chris@18 20 */
Chris@18 21 class VersionNegotiator {
Chris@18 22
Chris@18 23 /**
Chris@18 24 * The separator between the version negotiator name and the version argument.
Chris@18 25 *
Chris@18 26 * @var string
Chris@18 27 */
Chris@18 28 const SEPARATOR = ':';
Chris@18 29
Chris@18 30 /**
Chris@18 31 * An array of named version negotiators.
Chris@18 32 *
Chris@18 33 * @var \Drupal\jsonapi\Revisions\VersionNegotiatorInterface[]
Chris@18 34 */
Chris@18 35 protected $negotiators = [];
Chris@18 36
Chris@18 37 /**
Chris@18 38 * Adds a version negotiator.
Chris@18 39 *
Chris@18 40 * @param \Drupal\jsonapi\Revisions\VersionNegotiatorInterface $version_negotiator
Chris@18 41 * The version negotiator.
Chris@18 42 * @param string $negotiator_name
Chris@18 43 * The name of the negotiation strategy used by the version negotiator.
Chris@18 44 */
Chris@18 45 public function addVersionNegotiator(VersionNegotiatorInterface $version_negotiator, $negotiator_name) {
Chris@18 46 assert(strpos(get_class($version_negotiator), 'Drupal\\jsonapi\\') === 0, 'Version negotiators are not a public API.');
Chris@18 47 $this->negotiators[$negotiator_name] = $version_negotiator;
Chris@18 48 }
Chris@18 49
Chris@18 50 /**
Chris@18 51 * Gets a negotiated entity revision.
Chris@18 52 *
Chris@18 53 * @param \Drupal\Core\Entity\EntityInterface $entity
Chris@18 54 * The entity.
Chris@18 55 * @param string $resource_version_identifier
Chris@18 56 * A value used to derive a revision for the given entity.
Chris@18 57 *
Chris@18 58 * @return \Drupal\Core\Entity\EntityInterface
Chris@18 59 * The loaded revision.
Chris@18 60 *
Chris@18 61 * @throws \Drupal\Core\Http\Exception\CacheableNotFoundHttpException
Chris@18 62 * When the revision does not exist.
Chris@18 63 * @throws \Drupal\Core\Http\Exception\CacheableBadRequestHttpException
Chris@18 64 * When the revision ID cannot be negotiated.
Chris@18 65 */
Chris@18 66 public function getRevision(EntityInterface $entity, $resource_version_identifier) {
Chris@18 67 try {
Chris@18 68 list($version_negotiator_name, $version_argument) = explode(VersionNegotiator::SEPARATOR, $resource_version_identifier, 2);
Chris@18 69 if (!isset($this->negotiators[$version_negotiator_name])) {
Chris@18 70 static::throwBadRequestHttpException($resource_version_identifier);
Chris@18 71 }
Chris@18 72 return $this->negotiators[$version_negotiator_name]->getRevision($entity, $version_argument);
Chris@18 73 }
Chris@18 74 catch (VersionNotFoundException $exception) {
Chris@18 75 static::throwNotFoundHttpException($entity, $resource_version_identifier);
Chris@18 76 }
Chris@18 77 catch (InvalidVersionIdentifierException $exception) {
Chris@18 78 static::throwBadRequestHttpException($resource_version_identifier);
Chris@18 79 }
Chris@18 80 }
Chris@18 81
Chris@18 82 /**
Chris@18 83 * Throws a cacheable error exception.
Chris@18 84 *
Chris@18 85 * @param \Drupal\Core\Entity\EntityInterface $entity
Chris@18 86 * The entity for which a revision was requested.
Chris@18 87 * @param string $resource_version_identifier
Chris@18 88 * The user input for the revision negotiation.
Chris@18 89 *
Chris@18 90 * @throws \Drupal\Core\Http\Exception\CacheableNotFoundHttpException
Chris@18 91 */
Chris@18 92 protected static function throwNotFoundHttpException(EntityInterface $entity, $resource_version_identifier) {
Chris@18 93 $cacheability = CacheableMetadata::createFromObject($entity)->addCacheContexts(['url.path', 'url.query_args:' . ResourceVersionRouteEnhancer::RESOURCE_VERSION_QUERY_PARAMETER]);
Chris@18 94 $reason = sprintf('The requested version, identified by `%s`, could not be found.', $resource_version_identifier);
Chris@18 95 throw new CacheableNotFoundHttpException($cacheability, $reason);
Chris@18 96 }
Chris@18 97
Chris@18 98 /**
Chris@18 99 * Throws a cacheable error exception.
Chris@18 100 *
Chris@18 101 * @param string $resource_version_identifier
Chris@18 102 * The user input for the revision negotiation.
Chris@18 103 *
Chris@18 104 * @throws \Drupal\Core\Http\Exception\CacheableBadRequestHttpException
Chris@18 105 */
Chris@18 106 protected static function throwBadRequestHttpException($resource_version_identifier) {
Chris@18 107 $cacheability = (new CacheableMetadata())->addCacheContexts(['url.query_args:' . ResourceVersionRouteEnhancer::RESOURCE_VERSION_QUERY_PARAMETER]);
Chris@18 108 $message = sprintf('An invalid resource version identifier, `%s`, was provided.', $resource_version_identifier);
Chris@18 109 throw new CacheableBadRequestHttpException($cacheability, $message);
Chris@18 110 }
Chris@18 111
Chris@18 112 }