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