diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/views/display/RestExport.php b/core/modules/rest/lib/Drupal/rest/Plugin/views/display/RestExport.php index b263f71..f3f918c 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/views/display/RestExport.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/views/display/RestExport.php @@ -7,11 +7,12 @@ namespace Drupal\rest\Plugin\views\display; -use Symfony\Component\HttpFoundation\Response; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\display\PathPluginBase; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\RouteCollection; /** * The plugin that handles Data response callbacks for REST resources. @@ -59,7 +60,7 @@ class RestExport extends PathPluginBase { * * @var string */ - protected $contentType = 'json'; + protected $contentType = NULL; /** * The mime type for the response. @@ -78,13 +79,7 @@ public function initDisplay(ViewExecutable $view, array &$display, array &$optio $negotiation = $container->get('content_negotiation'); $request = $container->get('request'); - $request_content_type = $negotiation->getContentType($request); - // Only use the requested content type if it's not 'html'. If it is then - // default to 'json' to aid debugging. - if ($request_content_type !== 'html') { - $this->setContentType($request_content_type); - } - + $this->setContentType($negotiation->getContentType($request)); $this->setMimeType($request->getMimeType($this->contentType)); } @@ -200,7 +195,33 @@ public function optionsSummary(&$categories, &$options) { unset($options['css_class']); } + /** + * {@inheritdoc} + */ + public function collectRoutes(RouteCollection $collection) { + parent::collectRoutes($collection); + + $style_plugin = $this->getPlugin('style'); + // REST exports should only respond to get methods. + $requirements = array('_method' => 'GET'); + // Only add requirements on formats if some have been configured, otherwise + // Use all available formats. + if (!empty($style_plugin->options['formats'])) { + $formats = $style_plugin->options['formats']; + } + else { + $formats = $style_plugin->getFormats(); + } + + // Format as a string using pipes as a delimeter. + $requirements['_format'] = implode('|', $formats); + + // Add the new requirements to each route. + foreach ($collection as $route) { + $route->addRequirements($requirements); + } + } /** * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute(). diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/views/style/Serializer.php b/core/modules/rest/lib/Drupal/rest/Plugin/views/style/Serializer.php index 8999bf1..e1c45cd 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/views/style/Serializer.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/views/style/Serializer.php @@ -58,7 +58,7 @@ class Serializer extends StylePluginBase { public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { parent::init($view, $display, $options); - $container = drupal_container(); + $container = \Drupal::getContainer(); // Get the serializer service. $this->serializer = $container->get('serializer'); $this->formats = $container->getParameter('serializer.formats'); @@ -84,7 +84,7 @@ public function buildOptionsForm(&$form, &$form_state) { '#type' => 'checkboxes', '#title' => t('Accepted request formats'), '#description' => t('Request formats that will be allowed in responses. If none are selected all formats will be allowed.'), - '#options' => $this->formats, + '#options' => drupal_map_assoc($this->formats), '#default_value' => $this->options['formats'], ); } @@ -103,12 +103,6 @@ public function submitOptionsForm(&$form, &$form_state) { */ public function render() { $rows = array(); - $content_type = $this->displayHandler->getContentType(); - - if (empty($this->view->live_preview) && !empty($formats) && !in_array($content_type, $formats)) { - // @todo throw exception? Alter the response for the view? - return; - } // If the Data Entity row plugin is used, this will be an array of entities // which will pass through Serializer to one of the registered Normalizers, // which will transform it to arrays/scalars. If the Data field row plugin @@ -118,7 +112,17 @@ public function render() { $rows[] = $this->view->rowPlugin->render($row); } - return $this->serializer->serialize($rows, $content_type); + return $this->serializer->serialize($rows, $this->displayHandler->getContentType()); + } + + /** + * Gets a list of all available formats that can be requested. + * + * @return array + * An array of formats. + */ + public function getFormats() { + return $this->formats; } } diff --git a/core/modules/rest/lib/Drupal/rest/Tests/Views/StyleSerializerTest.php b/core/modules/rest/lib/Drupal/rest/Tests/Views/StyleSerializerTest.php index 9c96920..ef85ec1 100644 --- a/core/modules/rest/lib/Drupal/rest/Tests/Views/StyleSerializerTest.php +++ b/core/modules/rest/lib/Drupal/rest/Tests/Views/StyleSerializerTest.php @@ -125,11 +125,40 @@ public function testSerializerResponses() { $expected = $serializer->serialize($entities, 'hal_json'); $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/hal+json')); $this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.'); + } - // Test that the default output will be JSON if html is requested. - $expected = $serializer->serialize($entities, 'json'); - $actual = $this->drupalGet('test/serialize/entity'); - $this->assertIdentical($actual, $expected, 'By default json output is returned.'); + /** + * Tests the response format configuration. + */ + public function testReponseFormatConfiguration() { + $this->drupalLogin($this->adminUser); + + $style_options = 'admin/structure/views/nojs/display/test_serializer_display_field/rest_export_1/style_options'; + + // Select only 'xml' as an accepted format. + $this->drupalPost($style_options, array('style_options[formats][xml]' => 'xml'), t('Apply')); + $this->drupalPost(NULL, array(), t('Save')); + + // Should not return a 406. + $this->drupalGet('test/serialize/field', array(), array('Accept: application/json')); + $this->assertResponse(406, 'A 406 response was returned when JSON was requested.'); + // Should return a 200. + $this->drupalGet('test/serialize/field', array(), array('Accept: application/xml')); + $this->assertResponse(200, 'A 200 response was returned when XML was requested.'); + + // Add 'json' as an accepted format, so we hae multiple. + $this->drupalPost($style_options, array('style_options[formats][json]' => 'json'), t('Apply')); + $this->drupalPost(NULL, array(), t('Save')); + + // Should return a 200. + $this->drupalGet('test/serialize/field', array(), array('Accept: application/json')); + $this->assertResponse(200, 'A 200 response was returned when JSON was requested.'); + // Should return a 200. + $this->drupalGet('test/serialize/field', array(), array('Accept: application/xml')); + $this->assertResponse(200, 'A 200 response was returned when XML was requested'); + // Should not return a 406. + $this->drupalGet('test/serialize/field', array(), array('Accept: application/html')); + $this->assertResponse(406, 'A 406 response was returned when HTML was requested.'); } /**