diff --git a/core/core.services.yml b/core/core.services.yml index 79f1fc1..4e2eb06 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -302,6 +302,7 @@ services: arguments: [16] mime_type_matcher: class: Drupal\Core\Routing\MimeTypeMatcher + arguments: ['@content_negotiation'] tags: - { name: route_filter } paramconverter_manager: diff --git a/core/lib/Drupal/Core/LegacyUrlMatcher.php b/core/lib/Drupal/Core/LegacyUrlMatcher.php index 39692c6..6ac6eeb 100644 --- a/core/lib/Drupal/Core/LegacyUrlMatcher.php +++ b/core/lib/Drupal/Core/LegacyUrlMatcher.php @@ -134,7 +134,7 @@ public function matchRequest(Request $request) { * @param string $path * The path being looked up by */ - public function matchDrupalItem($path) { + protected function matchDrupalItem($path) { // For now we can just proxy our procedural method. At some point this will // become more complicated because we'll need to get back candidates for a // path and them resolve them based on things like method and scheme which @@ -151,7 +151,7 @@ public function matchDrupalItem($path) { * @return * An array of parameters. */ - public function convertDrupalItem($router_item) { + protected function convertDrupalItem($router_item) { $route = array( '_controller' => $router_item['page_callback'] ); diff --git a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php index 3e35d55..36d313f 100644 --- a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php +++ b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php @@ -7,16 +7,33 @@ namespace Drupal\Core\Routing; +use Drupal\Core\ContentNegotiation; +use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; use Symfony\Component\Routing\RouteCollection; -use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface; /** * This class filters routes based on the media type in HTTP Accept headers. */ class MimeTypeMatcher implements RouteFilterInterface { + /** + * The content negotiation library. + * + * @var \Drupal\Core\ContentNegotiation + */ + protected $contentNegotiation; + + /** + * Constructs a new MimeTypeMatcher. + * + * @param \Drupal\Core\ContentNegotiation $cotent_negotiation + * The content negotiation library. + */ + public function __construct(ContentNegotiation $content_negotiation) { + $this->contentNegotiation = $content_negotiation; + } /** * Implements \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface::filter() @@ -26,11 +43,7 @@ public function filter(RouteCollection $collection, Request $request) { // @todo replace by proper content negotiation library. $acceptable_mime_types = $request->getAcceptableContentTypes(); $acceptable_formats = array_map(array($request, 'getFormat'), $acceptable_mime_types); - $negotiation = new \Drupal\Core\ContentNegotiation(); - $primary_format = $negotiation->getContentType($request); - - // @todo this does not work because the routing system only hands us 3 REST - // routes for /node/{node}. Where is the usual node route for the HTML page? + $primary_format = $this->contentNegotiation->getContentType($request); // Collect a list of routes that match the primary request content type. $primary_matches = new RouteCollection(); diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php index 3a48c83..5a79ea8 100644 --- a/core/lib/Drupal/Core/Routing/RouteProvider.php +++ b/core/lib/Drupal/Core/Routing/RouteProvider.php @@ -11,7 +11,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use \Drupal\Core\Database\Connection; @@ -100,25 +99,6 @@ public function getRouteCollectionForRequest(Request $request) { $collection = $this->getRoutesByPath($path); - // Add legacy route for MimeTypeMatcher. - $legacy_url_matcher = \Drupal::service('legacy_url_matcher'); - // Add flag so legacy route won't be added once again. This is needed to avoid - // getting to nesting level error. Error happens because in menu_get_item() we - // call menu_item_route_access() that runs - // Drupal::service('router.dynamic')->matchRequest($request) that gets - // to this method again. - $flag = &drupal_static(__FUNCTION__); - if (empty($flag) && $router_item = $legacy_url_matcher->matchDrupalItem($request->attributes->get('system_path'))) { - $flag = TRUE; - $route = new Route($router_item['path'], array( - '_controller' => $router_item['page_callback'], - ), array( - '_format' => 'html', - )); - - $collection->add('legacy.route', $route); - } - if (!count($collection)) { throw new ResourceNotFoundException(String::format("The route for '@path' could not be found", array('@path' => $path))); } diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php b/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php index fa22dfd..2b9abd7 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php @@ -75,8 +75,16 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { 'label' => $entity_info['label'], ); // Use the entity links as REST URL patterns if available. - $this->derivatives[$entity_type]['links']['canonical'] = isset($entity_info['links']['canonical']) ? $entity_info['links']['canonical'] : "/entity/$entity_type/{id}"; $this->derivatives[$entity_type]['links']['drupal:create'] = isset($entity_info['links']['drupal:create']) ? $entity_info['links']['drupal:create'] : "/entity/$entity_type"; + // Replace the default cannonical link pattern with a version that + // directly uses the entity type, because we don't want to hand 2 + // parameters to the entity resource plugin. + if ($entity_info['links']['canonical'] == '/entity/{entityType}/{id}') { + $this->derivatives[$entity_type]['links']['canonical'] = "/entity/$entity_type/{id}"; + } + else { + $this->derivatives[$entity_type]['links']['canonical'] = $entity_info['links']['canonical']; + } $this->derivatives[$entity_type] += $base_plugin_definition; } diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php index f19e3e2..a482b7d 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php @@ -46,6 +46,7 @@ class EntityResource extends ResourceBase { * @throws \Symfony\Component\HttpKernel\Exception\HttpException */ public function get($entity) { + $id = $entity; if (is_scalar($entity)) { $definition = $this->getPluginDefinition(); $entity = entity_load($definition['entity_type'], $entity); diff --git a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php index d6fc9f9..8d88ab1 100644 --- a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php +++ b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php @@ -295,4 +295,19 @@ protected function entityPermissions($entity_type, $operation) { } } } + + /** + * Returns the base URI path of an entity type. + * + * @param type $entity_type + * @return string + */ + protected function entityBasePath($entity_type) { + switch ($entity_type) { + case 'entity_test': + return 'entity/entity_test'; + case 'node': + return 'node'; + } + } } diff --git a/core/modules/rest/lib/Drupal/rest/Tests/ReadTest.php b/core/modules/rest/lib/Drupal/rest/Tests/ReadTest.php index 7c84cfd..1052c2c 100644 --- a/core/modules/rest/lib/Drupal/rest/Tests/ReadTest.php +++ b/core/modules/rest/lib/Drupal/rest/Tests/ReadTest.php @@ -51,7 +51,7 @@ public function testRead() { $entity = $this->entityCreate($entity_type); $entity->save(); // Read it over the REST API. - $response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); + $response = $this->httpRequest($this->entityBasePath($entity_type) . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse('200', 'HTTP response code is correct.'); $this->assertHeader('content-type', $this->defaultMimeType); $data = drupal_json_decode($response); @@ -60,11 +60,11 @@ public function testRead() { $this->assertEqual($data['uuid'][0]['value'], $entity->uuid(), 'Entity UUID is correct'); // Try to read the entity with an unsupported mime format. - $response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, 'application/wrongformat'); + $response = $this->httpRequest($this->entityBasePath($entity_type) . '/' . $entity->id(), 'GET', NULL, 'application/wrongformat'); $this->assertResponse(406); // Try to read an entity that does not exist. - $response = $this->httpRequest('entity/' . $entity_type . '/9999', 'GET', NULL, $this->defaultMimeType); + $response = $this->httpRequest($this->entityBasePath($entity_type) . '/9999', 'GET', NULL, $this->defaultMimeType); $this->assertResponse(404); $decoded = drupal_json_decode($response); $this->assertEqual($decoded['error'], 'Entity with ID 9999 not found', 'Response message is correct.'); @@ -75,7 +75,7 @@ public function testRead() { if ($entity_type == 'entity_test') { $entity->field_test_text->value = 'no access value'; $entity->save(); - $response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); + $response = $this->httpRequest($this->entityBasePath($entity_type) . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse(200); $this->assertHeader('content-type', $this->defaultMimeType); $data = drupal_json_decode($response); @@ -84,7 +84,7 @@ public function testRead() { // Try to read an entity without proper permissions. $this->drupalLogout(); - $response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); + $response = $this->httpRequest($this->entityBasePath($entity_type) . '/' . $entity->id(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse(403); $this->assertNull(drupal_json_decode($response), 'No valid JSON found.'); }