From 2a43f31fb73ba130a8b77ce729bba4340839c811 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Mon, 29 Aug 2016 08:04:46 +0100
Subject: [PATCH] Issue #2779807 by jhedstrom: Bring RestExport::buildResponse
 into line with Feed::buildResponse

---
 .../src/Plugin/views/display/RestExport.php   |  9 ++-
 .../rest_test_views/rest_test_views.module    | 21 ++++++
 .../tests/src/Kernel/Views/RestExportTest.php | 69 +++++++++++++++++++
 3 files changed, 97 insertions(+), 2 deletions(-)
 create mode 100644 core/modules/rest/tests/modules/rest_test_views/rest_test_views.module
 create mode 100644 core/modules/rest/tests/src/Kernel/Views/RestExportTest.php

diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php
index cf5e232e1a6e..1a7a7f1a7225 100644
--- a/core/modules/rest/src/Plugin/views/display/RestExport.php
+++ b/core/modules/rest/src/Plugin/views/display/RestExport.php
@@ -353,12 +353,17 @@ public function collectRoutes(RouteCollection $collection) {
   public static function buildResponse($view_id, $display_id, array $args = []) {
     $build = static::buildBasicRenderable($view_id, $display_id, $args);
 
+    // Setup an empty response so headers can be added as needed during views
+    // rendering and processing.
+    $response = new CacheableResponse('', 200);
+    $build['#response'] = $response;
+
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = \Drupal::service('renderer');
 
-    $output = $renderer->renderRoot($build);
+    $output = (string) $renderer->renderRoot($build);
 
-    $response = new CacheableResponse($output, 200);
+    $response->setContent($output);
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
 
diff --git a/core/modules/rest/tests/modules/rest_test_views/rest_test_views.module b/core/modules/rest/tests/modules/rest_test_views/rest_test_views.module
new file mode 100644
index 000000000000..e46d8096e682
--- /dev/null
+++ b/core/modules/rest/tests/modules/rest_test_views/rest_test_views.module
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Test hook implementations for the REST views test module.
+ */
+
+use Drupal\views\ViewExecutable;
+
+/**
+ * Implements hook_views_post_execute().
+ */
+function rest_test_views_views_post_execute(ViewExecutable $view) {
+  // Attach a custom header to the test_data_export view.
+  if ($view->id() === 'test_serializer_display_entity') {
+    if ($value = \Drupal::state()->get('rest_test_views_set_header', FALSE)) {
+      $view->getResponse()->headers->set('Custom-Header', $value);
+    }
+  }
+
+}
diff --git a/core/modules/rest/tests/src/Kernel/Views/RestExportTest.php b/core/modules/rest/tests/src/Kernel/Views/RestExportTest.php
new file mode 100644
index 000000000000..f3a8f04f5272
--- /dev/null
+++ b/core/modules/rest/tests/src/Kernel/Views/RestExportTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\Tests\rest\Kernel\Views;
+
+use Drupal\rest\Plugin\views\display\RestExport;
+use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
+use Drupal\views\Entity\View;
+use Drupal\views\Tests\ViewTestData;
+
+/**
+ * Tests the REST export view display plugin.
+ *
+ * @coversDefaultClass \Drupal\rest\Plugin\views\display\RestExport
+ *
+ * @group rest
+ */
+class RestExportTest extends ViewsKernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = ['test_serializer_display_entity'];
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['rest_test_views', 'serialization', 'rest', 'entity_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp($import_test_views = TRUE) {
+    parent::setUp($import_test_views);
+
+    ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
+    $this->installEntitySchema('entity_test');
+  }
+
+  /**
+   * @covers ::buildResponse
+   */
+  public function testBuildResponse() {
+    /** @var \Drupal\views\Entity\View $view */
+    $view = View::load('test_serializer_display_entity');
+    $display = &$view->getDisplay('rest_export_1');
+
+    $display['display_options']['defaults']['style'] = FALSE;
+    $display['display_options']['style']['type'] = 'serializer';
+    $display['display_options']['style']['options']['formats'] = ['json', 'xml'];
+    $view->save();
+
+    // No custom header should be set yet.
+    $response = RestExport::buildResponse('test_serializer_display_entity', 'rest_export_1', []);
+    $this->assertFalse($response->headers->get('Custom-Header'));
+
+    // Clear render cache.
+    /** @var \Drupal\Core\Cache\MemoryBackend $render_cache */
+    $render_cache = $this->container->get('cache_factory')->get('render');
+    $render_cache->deleteAll();
+
+    // A custom header should now be added.
+    // @see rest_test_views_views_post_execute()
+    $header = $this->randomString();
+    $this->container->get('state')->set('rest_test_views_set_header', $header);
+    $response = RestExport::buildResponse('test_serializer_display_entity', 'rest_export_1', []);
+    $this->assertEquals($header, $response->headers->get('Custom-Header'));
+  }
+
+}
-- 
GitLab