Browse Source

Meta link headers (#81)

* Adding rel=alternate link headers for metadata REST endpoints

* Missed a few spots in tests still bootstrapping their own REST config.
pull/756/head
dannylamb 7 years ago committed by Jared Whiklo
parent
commit
6e4815ef87
  1. 4
      islandora.services.yml
  2. 145
      src/EventSubscriber/LinkHeaderSubscriber.php
  3. 96
      src/EventSubscriber/MediaLinkHeaderSubscriber.php
  4. 34
      src/EventSubscriber/NodeLinkHeaderSubscriber.php
  5. 140
      tests/src/Functional/IslandoraFunctionalTestBase.php
  6. 19
      tests/src/Functional/MappingUriPredicateReactionTest.php
  7. 15
      tests/src/Functional/MediaLinkHeaderTest.php
  8. 21
      tests/src/Functional/MediaSourceUpdateTest.php
  9. 43
      tests/src/Functional/NodeLinkHeaderTest.php

4
islandora.services.yml

@ -20,12 +20,12 @@ services:
- { name: event_subscriber } - { name: event_subscriber }
islandora.media_link_header_subscriber: islandora.media_link_header_subscriber:
class: Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber class: Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber
arguments: ['@entity_field.manager', '@current_route_match', '@entity_type.manager'] arguments: ['@entity_type.manager', '@entity_field.manager', '@current_route_match', '@access_manager', '@current_user']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
islandora.node_link_header_subscriber: islandora.node_link_header_subscriber:
class: Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber class: Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber
arguments: ['@entity_field.manager', '@current_route_match'] arguments: ['@entity_type.manager', '@entity_field.manager', '@current_route_match', '@access_manager', '@current_user']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
islandora.versioncounter: islandora.versioncounter:

145
src/EventSubscriber/LinkHeaderSubscriber.php

@ -2,8 +2,13 @@
namespace Drupal\islandora\EventSubscriber; namespace Drupal\islandora\EventSubscriber;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Entity\EntityFieldManager; use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
@ -16,6 +21,13 @@ use Symfony\Component\HttpKernel\KernelEvents;
*/ */
abstract class LinkHeaderSubscriber implements EventSubscriberInterface { abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/** /**
* The entity field manager. * The entity field manager.
* *
@ -33,17 +45,45 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
/** /**
* Constructor. * Constructor.
* *
* The access manager.
*
* @var \Drupal\Core\Access\AccessManagerInterface
*/
protected $accessManager;
/**
* Current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* Constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager * @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager
* The entity field manager. * The entity field manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object. * The route match object.
* @param \Drupal\Core\Access\AccessManagerInterface $access_manager
* The access manager.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
*/ */
public function __construct( public function __construct(
EntityTypeManager $entity_type_manager,
EntityFieldManager $entity_field_manager, EntityFieldManager $entity_field_manager,
RouteMatchInterface $route_match RouteMatchInterface $route_match,
AccessManagerInterface $access_manager,
AccountInterface $account
) { ) {
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager; $this->entityFieldManager = $entity_field_manager;
$this->routeMatch = $route_match; $this->routeMatch = $route_match;
$this->accessManager = $access_manager;
$this->account = $account;
} }
/** /**
@ -113,6 +153,109 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
return $object; return $object;
} }
/**
* Generates link headers for each referenced entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* Entity that has reference fields.
*
* @return string[]
* Array of link headers
*/
protected function generateEntityReferenceLinks(EntityInterface $entity) {
// Use the node to add link headers for each entity reference.
$entity_type = $entity->getEntityType()->id();
$bundle = $entity->bundle();
// Get all fields for the entity.
$fields = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
// Strip out everything but entity references that are not base fields.
$entity_reference_fields = array_filter($fields, function ($field) {
return $field->getFieldStorageDefinition()->isBaseField() == FALSE && $field->getType() == "entity_reference";
});
// Collect links for referenced entities.
$links = [];
foreach ($entity_reference_fields as $field_name => $field_definition) {
foreach ($entity->get($field_name)->referencedEntities() as $referencedEntity) {
// Headers are subject to an access check.
if ($referencedEntity->access('view')) {
$entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]);
$field_label = $field_definition->label();
$links[] = "<$entity_url>; rel=\"related\"; title=\"$field_label\"";
}
}
}
return $links;
}
/**
* Generates link headers for REST endpoints.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* Entity that has reference fields.
*
* @return string[]
* Array of link headers
*/
protected function generateRestLinks(EntityInterface $entity) {
$rest_resource_config_storage = $this->entityTypeManager->getStorage('rest_resource_config');
$entity_type = $entity->getEntityType()->id();
$rest_resource_config = $rest_resource_config_storage->load("entity.$entity_type");
$links = [];
$route_name = $this->routeMatch->getRouteName();
if ($rest_resource_config) {
$configuration = $rest_resource_config->get('configuration');
foreach ($configuration['GET']['supported_formats'] as $format) {
switch ($format) {
case 'json':
$mime = 'application/json';
break;
case 'jsonld':
$mime = 'application/ld+json';
break;
case 'hal_json':
$mime = 'application/hal+json';
break;
case 'xml':
$mime = 'application/xml';
break;
default:
continue;
}
$meta_route_name = "rest.entity.$entity_type.GET.$format";
if ($route_name == $meta_route_name) {
continue;
}
$route_params = [$entity_type => $entity->id()];
if (!$this->accessManager->checkNamedRoute($meta_route_name, $route_params, $this->account)) {
continue;
}
$meta_url = Url::fromRoute($meta_route_name, $route_params)
->setAbsolute()
->toString();
$links[] = "<$meta_url?_format=$format>; rel=\"alternate\"; type=\"$mime\"";
}
}
return $links;
}
/** /**
* Adds resource-specific link headers to appropriate responses. * Adds resource-specific link headers to appropriate responses.
* *

96
src/EventSubscriber/MediaLinkHeaderSubscriber.php

@ -2,11 +2,8 @@
namespace Drupal\islandora\EventSubscriber; namespace Drupal\islandora\EventSubscriber;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\media_entity\MediaInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
@ -17,80 +14,77 @@ use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
*/ */
class MediaLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubscriberInterface { class MediaLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubscriberInterface {
/**
* Media storage interface.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $mediaBundleStorage;
/**
* MediaLinkHeaderSubscriber constructor.
*
* @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(
EntityFieldManager $entity_field_manager,
RouteMatchInterface $route_match,
EntityTypeManagerInterface $entity_type_manager) {
$this->mediaBundleStorage = $entity_type_manager->getStorage('media_bundle');
parent::__construct($entity_field_manager, $route_match);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function onResponse(FilterResponseEvent $event) { public function onResponse(FilterResponseEvent $event) {
$response = $event->getResponse(); $response = $event->getResponse();
$entity = $this->getObject($response, 'media'); $media = $this->getObject($response, 'media');
if ($entity === FALSE) { if ($media === FALSE) {
return; return;
} }
$media_bundle = $this->mediaBundleStorage->load($entity->bundle()); $links = array_merge(
$this->generateEntityReferenceLinks($media),
$this->generateRestLinks($media),
$this->generateMediaLinks($media)
);
// Add the link headers to the response.
if (empty($links)) {
return;
}
$response->headers->set('Link', $links, FALSE);
}
/**
* Generates link headers for the described file and source update routes.
*
* @param \Drupal\media_entity\MediaInterface $media
* Media to generate link headers.
*
* @return string[]
* Array of link headers
*/
protected function generateMediaLinks(MediaInterface $media) {
$media_bundle = $this->entityTypeManager->getStorage('media_bundle')->load($media->bundle());
$type_configuration = $media_bundle->getTypeConfiguration(); $type_configuration = $media_bundle->getTypeConfiguration();
$links = [];
$update_route_name = 'islandora.media_source_update';
$update_route_params = ['media' => $media->id()];
if ($this->accessManager->checkNamedRoute($update_route_name, $update_route_params, $this->account)) {
$edit_media_url = Url::fromRoute($update_route_name, $update_route_params)
->setAbsolute()
->toString();
$links[] = "<$edit_media_url>; rel=\"edit-media\"";
}
if (!isset($type_configuration['source_field'])) { if (!isset($type_configuration['source_field'])) {
return; return $links;
} }
$source_field = $type_configuration['source_field']; $source_field = $type_configuration['source_field'];
if (empty($source_field) || if (empty($source_field) ||
!$entity instanceof FieldableEntityInterface || !$media->hasField($source_field)
!$entity->hasField($source_field)
) { ) {
return; return $links;
} }
// Collect file links for the media. // Collect file links for the media.
$links = []; foreach ($media->get($source_field)->referencedEntities() as $referencedEntity) {
foreach ($entity->get($source_field)->referencedEntities() as $referencedEntity) { if ($referencedEntity->access('view')) {
if ($entity->access('view')) {
$file_url = $referencedEntity->url('canonical', ['absolute' => TRUE]); $file_url = $referencedEntity->url('canonical', ['absolute' => TRUE]);
$edit_media_url = Url::fromRoute('islandora.media_source_update', ['media' => $referencedEntity->id()])
->setAbsolute()
->toString();
$links[] = "<$file_url>; rel=\"describes\"; type=\"{$referencedEntity->getMimeType()}\""; $links[] = "<$file_url>; rel=\"describes\"; type=\"{$referencedEntity->getMimeType()}\"";
$links[] = "<$edit_media_url>; rel=\"edit-media\"";
} }
} }
// Exit early if there aren't any. return $links;
if (empty($links)) {
return;
}
// Add the link headers to the response.
$response->headers->set('Link', $links, FALSE);
} }
} }

34
src/EventSubscriber/NodeLinkHeaderSubscriber.php

@ -21,42 +21,22 @@ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubs
public function onResponse(FilterResponseEvent $event) { public function onResponse(FilterResponseEvent $event) {
$response = $event->getResponse(); $response = $event->getResponse();
$entity = $this->getObject($response, 'node'); $node = $this->getObject($response, 'node');
if ($entity === FALSE) { if ($node === FALSE) {
return; return;
} }
// Use the node to add link headers for each entity reference. $links = array_merge(
$bundle = $entity->bundle(); $this->generateEntityReferenceLinks($node),
$this->generateRestLinks($node)
// Get all fields for the entity. );
$fields = $this->entityFieldManager->getFieldDefinitions('node', $bundle);
// Strip out everything but entity references that are not base fields.
$entity_reference_fields = array_filter($fields, function ($field) {
return $field->getFieldStorageDefinition()->isBaseField() == FALSE && $field->getType() == "entity_reference";
});
// Collect links for referenced entities.
$links = [];
foreach ($entity_reference_fields as $field_name => $field_definition) {
foreach ($entity->get($field_name)->referencedEntities() as $referencedEntity) {
// Headers are subject to an access check.
if ($referencedEntity->access('view')) {
$entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]);
$field_label = $field_definition->label();
$links[] = "<$entity_url>; rel=\"related\"; title=\"$field_label\"";
}
}
}
// Exit early if there aren't any. // Add the link headers to the response.
if (empty($links)) { if (empty($links)) {
return; return;
} }
// Add the link headers to the response.
$response->headers->set('Link', $links, FALSE); $response->headers->set('Link', $links, FALSE);
} }

140
tests/src/Functional/IslandoraFunctionalTestBase.php

@ -4,6 +4,8 @@ namespace Drupal\Tests\islandora\Functional;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\rest\Entity\RestResourceConfig;
use Drupal\rest\RestResourceConfigInterface;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\TestFileCreationTrait;
@ -38,6 +40,144 @@ class IslandoraFunctionalTestBase extends BrowserTestBase {
$this->container->get('entity_type.manager')->getStorage('context')->load('media')->delete(); $this->container->get('entity_type.manager')->getStorage('context')->load('media')->delete();
$this->container->get('entity_type.manager')->getStorage('context')->load('file')->delete(); $this->container->get('entity_type.manager')->getStorage('context')->load('file')->delete();
// Set up basic REST config.
// Delete the node rest config that's bootstrapped with Drupal.
$this->container->get('entity_type.manager')->getStorage('rest_resource_config')->load('entity.node')->delete();
// Create our own for Nodes, Media, and Files.
$this->container->get('entity_type.manager')->getStorage('rest_resource_config')->create([
'id' => 'entity.node',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => [
'cookie',
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
'jsonld',
],
],
'POST' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'DELETE' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'PATCH' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
],
])->save();
$this->container->get('entity_type.manager')->getStorage('rest_resource_config')->create([
'id' => 'entity.media',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => [
'cookie',
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
'jsonld',
],
],
'POST' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'DELETE' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'PATCH' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
],
])->save();
RestResourceConfig::create([
'id' => 'entity.file',
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
'configuration' => [
'GET' => [
'supported_auth' => [
'cookie',
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
'jsonld',
],
],
'POST' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'DELETE' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
'PATCH' => [
'supported_auth' => [
'basic_auth',
'jwt_auth',
],
'supported_formats' => [
'json',
],
],
],
])->save();
// Create a test content type. // Create a test content type.
$test_type = $this->container->get('entity_type.manager')->getStorage('node_type')->create([ $test_type = $this->container->get('entity_type.manager')->getStorage('node_type')->create([
'type' => 'test_type', 'type' => 'test_type',

19
tests/src/Functional/MappingUriPredicateReactionTest.php

@ -33,25 +33,6 @@ class MappingUriPredicateReactionTest extends IslandoraFunctionalTestBase {
]) ])
->save(); ->save();
$resourceConfigStorage = $this->container
->get('entity_type.manager')
->getStorage('rest_resource_config');
// There is already a setting for entity.node, so delete it.
$resourceConfigStorage
->delete($resourceConfigStorage
->loadMultiple(['entity.node']));
// Create it new.
$resourceConfigStorage->create([
'id' => 'entity.node',
'granularity' => 'resource',
'configuration' => [
'methods' => ['GET'],
'authentication' => ['basic_auth', 'cookie'],
'formats' => ['jsonld'],
],
'status' => TRUE,
])->save(TRUE);
$this->container->get('router.builder')->rebuildIfNeeded(); $this->container->get('router.builder')->rebuildIfNeeded();
} }

15
tests/src/Functional/MediaLinkHeaderTest.php

@ -33,6 +33,21 @@ class MediaLinkHeaderTest extends IslandoraFunctionalTestBase {
$this->validateLinkHeaderWithUrl('edit-media', $urls['file']['rest'], '', '') == 1, $this->validateLinkHeaderWithUrl('edit-media', $urls['file']['rest'], '', '') == 1,
"Malformed 'edit-media' link header" "Malformed 'edit-media' link header"
); );
// Check for links to REST endpoints for metadata.
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=json", NULL, 'application/json') == 1,
"Media must have link header pointing to json REST endpoint."
);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=jsonld", NULL, 'application/ld+json') == 1,
"Media must have link header pointing to jsonld REST endpoint."
);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=xml", NULL, 'application/xml') == 0,
"Media must not have link header pointing to disabled xml REST endpoint."
);
} }
} }

21
tests/src/Functional/MediaSourceUpdateTest.php

@ -11,27 +11,6 @@ use Drupal\Core\Url;
*/ */
class MediaSourceUpdateTest extends IslandoraFunctionalTestBase { class MediaSourceUpdateTest extends IslandoraFunctionalTestBase {
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$media_rest_resource = $this->container->get('entity_type.manager')->getStorage('rest_resource_config')->create([
'id' => 'entity.media',
'granularity' => 'resource',
'configuration' => [
'methods' => ['GET'],
'authentication' => ['basic_auth'],
'formats' => ['json'],
],
'status' => TRUE,
]);
$media_rest_resource->save(TRUE);
$this->container->get('router.builder')->rebuildIfNeeded();
}
/** /**
* @covers \Drupal\islandora\Controller\MediaSourceController::put * @covers \Drupal\islandora\Controller\MediaSourceController::put
*/ */

43
tests/src/Functional/RelatedLinkHeaderTest.php → tests/src/Functional/NodeLinkHeaderTest.php

@ -10,7 +10,7 @@ use Drupal\Tests\media_entity\Functional\MediaEntityFunctionalTestTrait;
* *
* @group islandora * @group islandora
*/ */
class RelatedLinkHeaderTest extends IslandoraFunctionalTestBase { class NodeLinkHeaderTest extends IslandoraFunctionalTestBase {
use EntityReferenceTestTrait; use EntityReferenceTestTrait;
use MediaEntityFunctionalTestTrait; use MediaEntityFunctionalTestTrait;
@ -92,23 +92,23 @@ class RelatedLinkHeaderTest extends IslandoraFunctionalTestBase {
/** /**
* @covers \Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber::onResponse * @covers \Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber::onResponse
*/ */
public function testRelatedLinkHeader() { public function testNodeLinkHeaders() {
// Create a test user that can see media. // Create a test user that can see media.
$account = $this->drupalCreateUser([ $account = $this->drupalCreateUser([
'view media', 'view media',
]); ]);
$this->drupalLogin($account); $this->drupalLogin($account);
// Visit the other, there should not be a header since it does not even // Visit the other, there should not be a related header since it does not
// have the field. // even have the field.
$this->drupalGet('node/' . $this->other->id()); $this->drupalGet('node/' . $this->other->id());
$this->assertTrue( $this->assertTrue(
$this->doesNotHaveLinkHeader('related'), $this->doesNotHaveLinkHeader('related'),
"Node that does not have entity reference field must not return related link header." "Node that does not have entity reference field must not return related link header."
); );
// Visit the referenced node, there should not be a header since its // Visit the referenced node, there should not be a related header since
// entity reference field is empty. // its entity reference field is empty.
$this->drupalGet('node/' . $this->referenced->id()); $this->drupalGet('node/' . $this->referenced->id());
$this->assertTrue( $this->assertTrue(
$this->doesNotHaveLinkHeader('related'), $this->doesNotHaveLinkHeader('related'),
@ -127,12 +127,41 @@ class RelatedLinkHeaderTest extends IslandoraFunctionalTestBase {
"Malformed related link header" "Malformed related link header"
); );
// Check for links to REST endpoints for metadata.
$entity_url = $this->referencer->toUrl('canonical', ['absolute' => TRUE])
->toString();
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 1,
"Node must have link header pointing to json REST endpoint."
);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1,
"Node must have link header pointing to jsonld REST endpoint."
);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=xml", NULL, 'application/xml') == 0,
"Node must not have link header pointing to disabled xml REST endpoint."
);
// Check that the current representation is not advertised when visitng
// a REST endpoint (e.g. the json link header doesn't appear when you're
// visiting the ?_format=json endpoint).
$this->drupalGet('node/' . $this->referencer->id(), ['query' => ['_format' => 'json']]);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 0,
"Node must not have link header pointing to json REST endpoint when vising the json REST endpoint."
);
$this->assertTrue(
$this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1,
"Node must have link header pointing to jsonld REST endpoint when visiting the json REST endpoint."
);
// Log in as anonymous. // Log in as anonymous.
$account = $this->drupalCreateUser(); $account = $this->drupalCreateUser();
$this->drupalLogin($account); $this->drupalLogin($account);
// Visit the referencer. It should return a rel="related" link header // Visit the referencer. It should return a rel="related" link header
// for both the referenced node and media entity. // for both the referenced node bun not the media entity b/c permissions.
$this->drupalGet('node/' . $this->referencer->id()); $this->drupalGet('node/' . $this->referencer->id());
$this->assertTrue( $this->assertTrue(
$this->validateLinkHeaderWithEntity('related', $this->referenced, 'Referenced Entity') == 1, $this->validateLinkHeaderWithEntity('related', $this->referenced, 'Referenced Entity') == 1,
Loading…
Cancel
Save