Commit 6e7ed05e authored by Michael Strelan's avatar Michael Strelan Committed by Lee Rowlands
Browse files

Issue #3031271 by mstrelan, larowlan, bbrala, PQ, lois.chabrand, acbramley,...

Issue #3031271 by mstrelan, larowlan, bbrala, PQ, lois.chabrand, acbramley, drs2034, Kristen Pol, Wim Leers, Roensby: Support version negotiation for any entity type (currently only Node & Media are supported)
parent 4ad6f750
Loading
Loading
Loading
Loading
+1 −12
Original line number Diff line number Diff line
@@ -194,18 +194,7 @@ protected function checkRevisionViewAccess(EntityInterface $entity, AccountInter
    assert($entity instanceof RevisionableInterface);
    assert(!$entity->isDefaultRevision(), 'It is not necessary to check revision access when the entity is the default revision.');
    $entity_type = $entity->getEntityType();
    switch ($entity_type->id()) {
      case 'node':
      case 'media':
    $access = $entity->access('view all revisions', $account, TRUE);
        break;

      default:
        $reason = 'Only node and media revisions are supported by JSON:API.';
        $reason .= ' For context, see https://www.drupal.org/project/drupal/issues/2992833#comment-12818258.';
        $reason .= ' To contribute, see https://www.drupal.org/project/drupal/issues/2350939 and https://www.drupal.org/project/drupal/issues/2809177.';
        $access = AccessResult::neutral($reason);
    }
    // Apply content_moderation's additional access logic.
    // @see \Drupal\content_moderation\Access\LatestRevisionCheck::access()
    if ($entity_type->getLinkTemplate('latest-version') && $entity->isLatestRevision() && isset($this->latestRevisionCheck)) {
+1 −3
Original line number Diff line number Diff line
@@ -383,9 +383,7 @@ protected static function isLocatableResourceType(EntityTypeInterface $entity_ty
   *   TRUE if the entity type is versionable, FALSE otherwise.
   */
  protected static function isVersionableResourceType(EntityTypeInterface $entity_type) {
    // @todo: remove the following line and uncomment the next one when revisions have standardized access control. For now, it is unsafe to support all revisionable entity types.
    return in_array($entity_type->id(), ['node', 'media']);
    /* return $entity_type->isRevisionable(); */
    return $entity_type->isRevisionable();
  }

  /**
+1 −10
Original line number Diff line number Diff line
@@ -95,17 +95,8 @@ public function enhance(array $defaults, Request $request) {
      // If the query parameter was provided but the resource type is not
      // versionable, provide a helpful error.
      if ($has_version_param) {
        // Until Drupal core has a generic revision access API, it is only safe
        // to support the `node` and `media` entity types because they are the
        // only // entity types that have revision access checks for forward
        // revisions that are not the default and not the latest revision.
        $cacheability = (new CacheableMetadata())->addCacheContexts(['url.path', static::CACHE_CONTEXT]);
        /* Uncomment the next line and remove the following one when https://www.drupal.org/project/drupal/issues/3002352 lands in core. */
        /* throw new CacheableHttpException($cacheability, 501, 'Resource versioning is not yet supported for this resource type.'); */
        $message = 'JSON:API does not yet support resource versioning for this resource type.';
        $message .= ' For context, see https://www.drupal.org/project/drupal/issues/2992833#comment-12818258.';
        $message .= ' To contribute, see https://www.drupal.org/project/drupal/issues/2350939 and https://www.drupal.org/project/drupal/issues/2809177.';
        throw new CacheableHttpException($cacheability, 501, $message);
        throw new CacheableHttpException($cacheability, 501, 'Resource versioning is not yet supported for this resource type.');
      }
      return $defaults;
    }
+22 −8
Original line number Diff line number Diff line
@@ -32,6 +32,16 @@ class BlockContentTest extends ResourceTestBase {
   */
  protected static $resourceTypeName = 'block_content--basic';

  /**
   * {@inheritdoc}
   */
  protected static $resourceTypeIsVersionable = TRUE;

  /**
   * {@inheritdoc}
   */
  protected static $newRevisionsShouldBeAutomatic = TRUE;

  /**
   * {@inheritdoc}
   *
@@ -66,7 +76,7 @@ public function createEntity() {
      $block_content_type = BlockContentType::create([
        'id' => 'basic',
        'label' => 'basic',
        'revision' => FALSE,
        'revision' => TRUE,
      ]);
      $block_content_type->save();
      block_content_add_body_field($block_content_type->id());
@@ -90,7 +100,11 @@ public function createEntity() {
   * {@inheritdoc}
   */
  protected function getExpectedDocument() {
    $self_url = Url::fromUri('base:/jsonapi/block_content/basic/' . $this->entity->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl();
    $base_url = Url::fromUri('base:/jsonapi/block_content/basic/' . $this->entity->uuid())->setAbsolute();
    $self_url = clone $base_url;
    $version_identifier = 'id:' . $this->entity->getRevisionId();
    $self_url = $self_url->setOption('query', ['resourceVersion' => $version_identifier]);
    $version_query_string = '?resourceVersion=' . urlencode($version_identifier);
    return [
      'jsonapi' => [
        'meta' => [
@@ -101,13 +115,13 @@ protected function getExpectedDocument() {
        'version' => '1.0',
      ],
      'links' => [
        'self' => ['href' => $self_url],
        'self' => ['href' => $base_url->toString()],
      ],
      'data' => [
        'id' => $this->entity->uuid(),
        'type' => 'block_content--basic',
        'links' => [
          'self' => ['href' => $self_url],
          'self' => ['href' => $self_url->toString()],
        ],
        'attributes' => [
          'body' => [
@@ -138,15 +152,15 @@ protected function getExpectedDocument() {
              'type' => 'block_content_type--block_content_type',
            ],
            'links' => [
              'related' => ['href' => $self_url . '/block_content_type'],
              'self' => ['href' => $self_url . '/relationships/block_content_type'],
              'related' => ['href' => $base_url->toString() . '/block_content_type' . $version_query_string],
              'self' => ['href' => $base_url->toString() . '/relationships/block_content_type' . $version_query_string],
            ],
          ],
          'revision_user' => [
            'data' => NULL,
            'links' => [
              'related' => ['href' => $self_url . '/revision_user'],
              'self' => ['href' => $self_url . '/relationships/revision_user'],
              'related' => ['href' => $base_url->toString() . '/revision_user' . $version_query_string],
              'self' => ['href' => $base_url->toString() . '/relationships/revision_user' . $version_query_string],
            ],
          ],
        ],
+14 −5
Original line number Diff line number Diff line
@@ -38,6 +38,11 @@ class MenuLinkContentTest extends ResourceTestBase {
   */
  protected static $resourceTypeName = 'menu_link_content--menu_link_content';

  /**
   * {@inheritdoc}
   */
  protected static $resourceTypeIsVersionable = TRUE;

  /**
   * {@inheritdoc}
   *
@@ -80,7 +85,11 @@ protected function createEntity() {
   * {@inheritdoc}
   */
  protected function getExpectedDocument() {
    $self_url = Url::fromUri('base:/jsonapi/menu_link_content/menu_link_content/' . $this->entity->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl();
    $base_url = Url::fromUri('base:/jsonapi/menu_link_content/menu_link_content/' . $this->entity->uuid())->setAbsolute();
    $self_url = clone $base_url;
    $version_identifier = 'id:' . $this->entity->getRevisionId();
    $self_url = $self_url->setOption('query', ['resourceVersion' => $version_identifier]);
    $version_query_string = '?resourceVersion=' . urlencode($version_identifier);
    return [
      'jsonapi' => [
        'meta' => [
@@ -91,13 +100,13 @@ protected function getExpectedDocument() {
        'version' => '1.0',
      ],
      'links' => [
        'self' => ['href' => $self_url],
        'self' => ['href' => $base_url->toString()],
      ],
      'data' => [
        'id' => $this->entity->uuid(),
        'type' => 'menu_link_content--menu_link_content',
        'links' => [
          'self' => ['href' => $self_url],
          'self' => ['href' => $self_url->toString()],
        ],
        'attributes' => [
          'bundle' => 'menu_link_content',
@@ -130,10 +139,10 @@ protected function getExpectedDocument() {
            'data' => NULL,
            'links' => [
              'related' => [
                'href' => $self_url . '/revision_user',
                'href' => $base_url->toString() . '/revision_user' . $version_query_string,
              ],
              'self' => [
                'href' => $self_url . '/relationships/revision_user',
                'href' => $base_url->toString() . '/relationships/revision_user' . $version_query_string,
              ],
            ],
          ],
Loading