diff --git a/core/lib/Drupal/Core/EventSubscriber/LegacyControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/LegacyControllerSubscriber.php index f088f7ef2e2e7373761dd317e7bdefe406d6ccba..7009eff9154ed3128de8e40cbbe9491d8f5c0894 100644 --- a/core/lib/Drupal/Core/EventSubscriber/LegacyControllerSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/LegacyControllerSubscriber.php @@ -36,11 +36,18 @@ class LegacyControllerSubscriber implements EventSubscriberInterface { * The Event to process. */ public function onKernelControllerLegacy(FilterControllerEvent $event) { - $router_item = $event->getRequest()->attributes->get('drupal_menu_item'); + $request = $event->getRequest(); + $router_item = $request->attributes->get('drupal_menu_item'); $controller = $event->getController(); // This BC logic applies only to functions. Otherwise, skip it. if (is_string($controller) && function_exists($controller)) { + // Flag this as a legacy request. We need to use this for subrequest + // handling so that we can treat older page callbacks and new routes + // differently. + // @todo Remove this line as soon as possible. + $request->attributes->set('_legacy', TRUE); + $new_controller = function() use ($router_item) { return call_user_func_array($router_item['page_callback'], $router_item['page_arguments']); }; diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php index cb3aeeaaa6eb733aeb84fceed17c6b928c5106ff..e88525e7ed4fbc3c09a480b88bdeef69d771eece 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php @@ -45,14 +45,14 @@ public function __construct(ContentNegotiation $negotiation) { */ public function onView(GetResponseForControllerResultEvent $event) { + $request = $event->getRequest(); + // For a master request, we process the result and wrap it as needed. // For a subrequest, all we want is the string value. We assume that // is just an HTML string from a controller, so wrap that into a response // object. The subrequest's response will get dissected and placed into // the larger page as needed. if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { - $request = $event->getRequest(); - $method = 'on' . $this->negotiation->getContentType($request); if (method_exists($this, $method)) { @@ -62,7 +62,9 @@ public function onView(GetResponseForControllerResultEvent $event) { $event->setResponse(new Response('Unsupported Media Type', 415)); } } - else { + elseif ($request->attributes->get('_legacy')) { + // This is an old hook_menu-based subrequest, which means we assume + // the body is supposed to be the complete page. $page_result = $event->getControllerResult(); if (!is_array($page_result)) { $page_result = array( @@ -71,6 +73,18 @@ public function onView(GetResponseForControllerResultEvent $event) { } $event->setResponse(new Response(drupal_render_page($page_result))); } + else { + // This is a new-style Symfony-esque subrequest, which means we assume + // the body is not supposed to be a complete page but just a page + // fragment. + $page_result = $event->getControllerResult(); + if (!is_array($page_result)) { + $page_result = array( + '#markup' => $page_result, + ); + } + $event->setResponse(new Response(drupal_render($page_result))); + } } public function onJson(GetResponseForControllerResultEvent $event) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php index f5b4a1893f4d22f73b89576b06b6e1a333a70f27..413737516ac386c437737fab06fbc240227ed875 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php @@ -43,7 +43,14 @@ public function testCanRoute() { public function testDefaultController() { $this->drupalGet('router_test/test2'); $this->assertRaw('test2', 'The correct string was returned because the route was successful.'); + + // Confirm that the page wrapping is being added, so we're not getting a + // raw body returned. $this->assertRaw('</html>', 'Page markup was found.'); + + // In some instances, the subrequest handling may get confused and render + // a page inception style. This test verifies that is not happening. + $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -53,7 +60,14 @@ public function testControllerPlaceholders() { $value = $this->randomName(); $this->drupalGet('router_test/test3/' . $value); $this->assertRaw($value, 'The correct string was returned because the route was successful.'); + + // Confirm that the page wrapping is being added, so we're not getting a + // raw body returned. $this->assertRaw('</html>', 'Page markup was found.'); + + // In some instances, the subrequest handling may get confused and render + // a page inception style. This test verifies that is not happening. + $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -62,7 +76,14 @@ public function testControllerPlaceholders() { public function testControllerPlaceholdersDefaultValues() { $this->drupalGet('router_test/test4'); $this->assertRaw('narf', 'The correct string was returned because the route was successful.'); + + // Confirm that the page wrapping is being added, so we're not getting a + // raw body returned. $this->assertRaw('</html>', 'Page markup was found.'); + + // In some instances, the subrequest handling may get confused and render + // a page inception style. This test verifies that is not happening. + $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } }