diff --git a/core/lib/Drupal/Core/Entity/Controller/EntityController.php b/core/lib/Drupal/Core/Entity/Controller/EntityController.php index 2ecc637..ebee7cc 100644 --- a/core/lib/Drupal/Core/Entity/Controller/EntityController.php +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php @@ -230,18 +230,6 @@ public function title(RouteMatchInterface $route_match, EntityInterface $_entity } /** - * Provides a generic callback for Configuration Entities. - * - * @return array - * An empty render array. - */ - public function configController() { - // Configuration entities do not have common view concept so default to an - // empty array. - return []; - } - - /** * Provides a generic edit title callback. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match diff --git a/core/lib/Drupal/Core/Entity/Routing/EmptyRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/EmptyRouteProvider.php deleted file mode 100644 index a5926bf..0000000 --- a/core/lib/Drupal/Core/Entity/Routing/EmptyRouteProvider.php +++ /dev/null @@ -1,40 +0,0 @@ -getLinkTemplate('canonical')) { - $entity_type_id = $entity_type->id(); - $route = new Route($link_template); - $route - ->setDefault('_controller', '\Drupal\Core\Entity\Controller\EntityController::configController') - ->setRequirement('_entity_access', "{$entity_type_id}.view") - ->setOption('parameters', [ - $entity_type_id => ['type' => 'entity:' . $entity_type_id], - ]); - $routes->add("entity.{$entity_type_id}.canonical", $route); - } - return $routes; - } - -} diff --git a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php index 14e70cd..3e007b1 100644 --- a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php @@ -21,9 +21,6 @@ * "delete" = "Drupal\Core\Entity\EntityDeleteForm" * }, * "access" = "Drupal\config_test\ConfigTestAccessControlHandler", - * "route_provider" = { - * "default" = "\Drupal\Core\Entity\Routing\EmptyRouteProvider", - * }, * }, * config_prefix = "dynamic", * entity_keys = { @@ -32,7 +29,6 @@ * "status" = "status" * }, * links = { - * "canonical" = "/config_test/{config_test}", * "edit-form" = "/admin/structure/config_test/manage/{config_test}", * "delete-form" = "/admin/structure/config_test/manage/{config_test}/delete", * "enable" = "/admin/structure/config_test/manage/{config_test}/enable", diff --git a/core/modules/rest/src/Tests/ReadTest.php b/core/modules/rest/src/Tests/ReadTest.php index 30f1644..33547bf 100644 --- a/core/modules/rest/src/Tests/ReadTest.php +++ b/core/modules/rest/src/Tests/ReadTest.php @@ -4,6 +4,7 @@ use Drupal\Component\Serialization\Json; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Url; /** @@ -26,7 +27,7 @@ class ReadTest extends RESTTestBase { public function testRead() { // @todo Expand this at least to users. // Define the entity types we want to test. - $entity_types = array('entity_test', 'node', 'config_test'); + $entity_types = ['entity_test', 'node', 'config_test']; foreach ($entity_types as $entity_type) { $this->enableService('entity:' . $entity_type, 'GET'); // Create a user account that has the required permissions to read @@ -40,13 +41,12 @@ public function testRead() { $entity = $this->entityCreate($entity_type); $entity->save(); // Read it over the REST API. - $response = $this->httpRequest($entity->urlInfo('canonical')->setRouteParameter('_format', $this->defaultFormat), 'GET'); + $response = $this->httpRequest($this->getReadUrl($entity), 'GET'); $this->assertResponse('200', 'HTTP response code is correct.'); $this->assertHeader('content-type', $this->defaultMimeType); $data = Json::decode($response); // Only assert one example property here, other properties should be // checked in serialization tests. - if ($entity instanceof ConfigEntityInterface) { $this->assertEqual($data['uuid'], $entity->uuid(), 'Entity UUID is correct'); } @@ -55,23 +55,26 @@ public function testRead() { } // Try to read the entity with an unsupported mime format. - $response = $this->httpRequest($entity->urlInfo('canonical')->setRouteParameter('_format', 'wrongformat'), 'GET'); + $this->httpRequest($this->getReadUrl($entity, 'wrongformat'), 'GET'); $this->assertResponse(406); $this->assertHeader('Content-type', 'application/json'); // Try to read an entity that does not exist. - $response = $this->httpRequest(Url::fromUri('base://' . $entity_type . '/9999', ['query' => ['_format' => $this->defaultFormat]]), 'GET'); + $response = $this->httpRequest($this->getReadUrl($entity, $this->defaultFormat, 9999), 'GET'); $this->assertResponse(404); switch ($entity_type) { case 'node': $path = '/node/{node}'; break; + case 'entity_test': $path = '/entity_test/{entity_test}'; break; + case 'config_test': - $path = '/config_test/{config_test}'; + $path = '/entity/config_test/{config_test}'; break; + default: throw new \RuntimeException('This entity type is not supported'); } @@ -84,7 +87,7 @@ public function testRead() { if ($entity_type == 'entity_test') { $entity->field_test_text->value = 'no access value'; $entity->save(); - $response = $this->httpRequest($entity->urlInfo('canonical')->setRouteParameter('_format', $this->defaultFormat), 'GET'); + $response = $this->httpRequest($this->getReadUrl($entity), 'GET'); $this->assertResponse(200); $this->assertHeader('content-type', $this->defaultMimeType); $data = Json::decode($response); @@ -93,23 +96,32 @@ public function testRead() { // Try to read an entity without proper permissions. $this->drupalLogout(); - $response = $this->httpRequest($entity->urlInfo('canonical')->setRouteParameter('_format', $this->defaultFormat), 'GET'); + $response = $this->httpRequest($this->getReadUrl($entity), 'GET'); $this->assertResponse(403); $this->assertIdentical('{"message":""}', $response); } // Try to read a resource which is not REST API enabled. $account = $this->drupalCreateUser(); $this->drupalLogin($account); - $response = $this->httpRequest($account->urlInfo('canonical')->setRouteParameter('_format', $this->defaultFormat), 'GET'); - // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical, - // non-REST route a match, but a lower quality one: no format restrictions - // means there's always a match and hence when there is no matching REST - // route, the non-REST route is used, but can't render into - // application/hal+json, so it returns a 406. - $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.'); - $this->assertEqual($response, Json::encode([ - 'message' => 'Not acceptable format: hal_json', - ])); + $response = $this->httpRequest($this->getReadUrl($entity), 'GET'); + + if ($entity->hasLinkTemplate('canonical')) { + // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical, + // non-REST route a match, but a lower quality one: no format restrictions + // means there's always a match and hence when there is no matching REST + // route, the non-REST route is used, but can't render into + // application/hal+json, so it returns a 406. + $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.'); + $this->assertEqual($response, Json::encode([ + 'message' => 'Not acceptable format: hal_json', + ])); + } + else { + // If there is not canonical link template we will get a 403 error. + // @todo Is this correct response? Why not a 404? + $this->assertResponse('403'); + } + } /** @@ -130,8 +142,50 @@ public function testResourceStructure() { $entity->save(); // Read it over the REST API. - $response = $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', 'json'), 'GET'); + $this->httpRequest($this->getReadUrl($entity, 'json'), 'GET'); $this->assertResponse('200', 'HTTP response code is correct.'); } + /** + * Gets the read URL object for the entity. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to get the url for. + * @param string $format + * The format for the URL. + * @param string $entity_id + * The entity id to use in the URL. + * Defaults to the entity's id if know given. + * + * @return \Drupal\Core\Url + * The URL object. + */ + protected function getReadUrl(EntityInterface $entity, $format = NULL, $entity_id = NULL) { + if (!$format) { + $format = $this->defaultFormat; + } + if (!$entity_id) { + $entity_id = $entity->id(); + } + $entity_type = $entity->getEntityTypeId(); + if ($entity->hasLinkTemplate('canonical')) { + $url = $entity->toUrl('canonical'); + } + else { + $route_name = 'rest.entity.' . $entity_type . ".GET."; + // If testing unsupported format don't use the format to construct route + // name. This would give a route not found exception. + if ($format == 'wrongformat') { + $route_name .= $this->defaultFormat; + } + else { + $route_name .= $format; + } + $url = Url::fromRoute($route_name); + } + $url->setRouteParameter($entity_type, $entity_id); + $url->setRouteParameter('_format', $format); + return $url; + } + }