Commit 118a4a02 authored by catch's avatar catch

Issue #2166195 by dawehner, Crell: Split HtmlPageRenderer in twain.

parent 4b4ef377
......@@ -435,10 +435,12 @@ services:
class: Drupal\Core\EventSubscriber\HtmlViewSubscriber
tags:
- { name: event_subscriber }
arguments: ['@html_page_renderer']
arguments: ['@html_fragment_renderer', '@html_page_renderer']
html_fragment_renderer:
class: Drupal\Core\Page\DefaultHtmlFragmentRenderer
arguments: ['@language_manager']
html_page_renderer:
class: Drupal\Core\Page\DefaultHtmlPageRenderer
arguments: ['@language_manager']
private_key:
class: Drupal\Core\PrivateKey
arguments: ['@state']
......@@ -533,7 +535,7 @@ services:
arguments: ['@config.storage', '@config.storage.snapshot']
exception_controller:
class: Drupal\Core\Controller\ExceptionController
arguments: ['@content_negotiation', '@string_translation', '@title_resolver', '@html_page_renderer']
arguments: ['@content_negotiation', '@string_translation', '@title_resolver', '@html_page_renderer', '@html_fragment_renderer']
calls:
- [setContainer, ['@service_container']]
exception_listener:
......
......@@ -44,7 +44,14 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
*
* @var \Drupal\Core\Page\HtmlPageRendererInterface
*/
protected $renderer;
protected $htmlPageRenderer;
/**
* The fragment rendering service.
*
* @var \Drupal\Core\Page\HtmlFragmentRendererInterface
*/
protected $fragmentRenderer;
/**
* Constructor.
......@@ -58,11 +65,14 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
* The title resolver.
* @param \Drupal\Core\Page\HtmlPageRendererInterface $renderer
* The page renderer.
* @param \Drupal\Core\Page\HtmlFragmentRendererInterface $fragment_renderer
* The fragment rendering service.
*/
public function __construct(ContentNegotiation $negotiation, TranslationInterface $translation_manager, TitleResolverInterface $title_resolver, HtmlPageRendererInterface $renderer) {
public function __construct(ContentNegotiation $negotiation, TranslationInterface $translation_manager, TitleResolverInterface $title_resolver, HtmlPageRendererInterface $renderer, $fragment_renderer) {
parent::__construct($translation_manager, $title_resolver);
$this->negotiation = $negotiation;
$this->renderer = $renderer;
$this->htmlPageRenderer = $renderer;
$this->fragmentRenderer = $fragment_renderer;
}
/**
......@@ -164,8 +174,8 @@ public function on403Html(FlattenException $exception, Request $request) {
);
$fragment = $this->createHtmlFragment($page_content, $request);
$page = $this->renderer->render($fragment, 403);
$response = new Response($this->renderer->renderPage($page), $page->getStatusCode());
$page = $this->fragmentRenderer->render($fragment, 403);
$response = new Response($this->htmlPageRenderer->render($page), $page->getStatusCode());
return $response;
}
......@@ -241,8 +251,8 @@ public function on404Html(FlattenException $exception, Request $request) {
);
$fragment = $this->createHtmlFragment($page_content, $request);
$page = $this->renderer->render($fragment, 404);
$response = new Response($this->renderer->renderPage($page), $page->getStatusCode());
$page = $this->fragmentRenderer->render($fragment, 404);
$response = new Response($this->htmlPageRenderer->render($page), $page->getStatusCode());
return $response;
}
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Page\HtmlFragment;
use Drupal\Core\Page\HtmlPage;
use Drupal\Core\Page\HtmlFragmentRendererInterface;
use Drupal\Core\Page\HtmlPageRendererInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
......@@ -20,21 +21,31 @@
*/
class HtmlViewSubscriber implements EventSubscriberInterface {
/**
* The fragment rendering service.
*
* @var \Drupal\Core\Page\HtmlFragmentRendererInterface
*/
protected $fragmentRenderer;
/**
* The page rendering service.
*
* @var \Drupal\Core\Page\HtmlPageRendererInterface
*/
protected $renderer;
protected $pageRenderer;
/**
* Constructs a new HtmlViewSubscriber.
*
* @param \Drupal\Core\Page\HtmlPageRendererInterface $renderer
* @param \Drupal\Core\Page\HtmlFragmentRendererInterface $fragment_renderer
* The fragment rendering service.
* @param \Drupal\Core\Page\HtmlPageRendererInterface $page_renderer
* The page rendering service.
*/
public function __construct(HtmlPageRendererInterface $renderer) {
$this->renderer = $renderer;
public function __construct(HtmlFragmentRendererInterface $fragment_renderer, HtmlPageRendererInterface $page_renderer) {
$this->fragmentRenderer = $fragment_renderer;
$this->pageRenderer = $page_renderer;
}
/**
......@@ -46,7 +57,7 @@ public function __construct(HtmlPageRendererInterface $renderer) {
public function onHtmlFragment(GetResponseForControllerResultEvent $event) {
$fragment = $event->getControllerResult();
if ($fragment instanceof HtmlFragment && !$fragment instanceof HtmlPage) {
$page = $this->renderer->render($fragment);
$page = $this->fragmentRenderer->render($fragment);
$event->setControllerResult($page);
}
}
......@@ -64,7 +75,7 @@ public function onHtmlPage(GetResponseForControllerResultEvent $event) {
// so as to not cause issues with Response. This also allows renderPage
// to return an object implementing __toString(), but that is not
// recommended.
$response = new Response((string) $this->renderer->renderPage($page), $page->getStatusCode());
$response = new Response((string) $this->pageRenderer->render($page), $page->getStatusCode());
if ($tags = $page->getCacheTags()) {
$response->headers->set('cache_tags', serialize($tags));
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Page\DefaultHtmlFragmentRenderer
*/
namespace Drupal\Core\Page;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
/**
* Default page rendering engine.
*/
class DefaultHtmlFragmentRenderer implements HtmlFragmentRendererInterface {
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManager
*/
protected $languageManager;
/**
* Constructs a new DefaultHtmlPageRenderer.
*
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager service.
*/
public function __construct(LanguageManager $language_manager) {
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public function render(HtmlFragment $fragment, $status_code = 200) {
// Converts the given HTML fragment which represents the main content region
// of the page into a render array.
$page_content['main'] = array(
'#markup' => $fragment->getContent(),
'#cache' => array('tags' => $fragment->getCacheTags()),
);
$page_content['#title'] = $fragment->getTitle();
// Build the full page array by calling drupal_prepare_page(), which invokes
// hook_page_build(). This adds the other regions to the page.
$page_array = drupal_prepare_page($page_content);
// Collect cache tags for all the content in all the regions on the page.
$tags = drupal_render_collect_cache_tags($page_array);
// Build the HtmlPage object.
$page = new HtmlPage('', array('tags' => $tags), $fragment->getTitle());
$page = $this->preparePage($page, $page_array);
$page->setBodyTop(drupal_render($page_array['page_top']));
$page->setBodyBottom(drupal_render($page_array['page_bottom']));
$page->setContent(drupal_render($page_array));
$page->setStatusCode($status_code);
return $page;
}
/**
* Enhances a page object based on a render array.
*
* @param \Drupal\Core\Page\HtmlPage $page
* The page object to enhance.
* @param array $page_array
* The page array to extract onto the page object.
*
* @return \Drupal\Core\Page\HtmlPage
* The modified page object.
*/
public function preparePage(HtmlPage $page, &$page_array) {
// @todo Remove this one drupal_get_title() has been eliminated.
if (!$page->hasTitle()) {
$title = drupal_get_title();
// drupal_set_title() already ensured security, so not letting the
// title pass through would cause double escaping.
$page->setTitle($title, PASS_THROUGH);
}
$page_array['#page'] = $page;
// HTML element attributes.
$language_interface = $this->languageManager->getCurrentLanguage();
$html_attributes = $page->getHtmlAttributes();
$html_attributes['lang'] = $language_interface->id;
$html_attributes['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
return $page;
}
}
......@@ -7,65 +7,15 @@
namespace Drupal\Core\Page;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
/**
* Default page rendering engine.
*/
class DefaultHtmlPageRenderer implements HtmlPageRendererInterface {
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManager
*/
protected $languageManager;
/**
* Constructs a new DefaultHtmlPageRenderer.
*
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager service.
*/
public function __construct(LanguageManager $language_manager) {
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public function render(HtmlFragment $fragment, $status_code = 200) {
// Converts the given HTML fragment which represents the main content region
// of the page into a render array.
$page_content['main'] = array(
'#markup' => $fragment->getContent(),
'#cache' => array('tags' => $fragment->getCacheTags()),
);
$page_content['#title'] = $fragment->getTitle();
// Build the full page array by calling drupal_prepare_page(), which invokes
// hook_page_build(). This adds the other regions to the page.
$page_array = drupal_prepare_page($page_content);
// Collect cache tags for all the content in all the regions on the page.
$tags = drupal_render_collect_cache_tags($page_array);
// Build the HtmlPage object.
$page = new HtmlPage('', array('tags' => $tags), $fragment->getTitle());
$page = $this->preparePage($page, $page_array);
$page->setBodyTop(drupal_render($page_array['page_top']));
$page->setBodyBottom(drupal_render($page_array['page_bottom']));
$page->setContent(drupal_render($page_array));
$page->setStatusCode($status_code);
return $page;
}
/**
* {@inheritdoc}
*/
public function renderPage(HtmlPage $page) {
public function render(HtmlPage $page) {
$render = array(
'#theme' => 'html',
'#page_object' => $page,
......@@ -73,35 +23,4 @@ public function renderPage(HtmlPage $page) {
return drupal_render($render);
}
/**
* Enhances a page object based on a render array.
*
* @param \Drupal\Core\Page\HtmlPage $page
* The page object to enhance.
* @param array $page_array
* The page array to extract onto the page object.
*
* @return \Drupal\Core\Page\HtmlPage
* The modified page object.
*/
public function preparePage(HtmlPage $page, &$page_array) {
// @todo Remove this one drupal_get_title() has been eliminated.
if (!$page->hasTitle()) {
$title = drupal_get_title();
// drupal_set_title() already ensured security, so not letting the
// title pass through would cause double escaping.
$page->setTitle($title, PASS_THROUGH);
}
$page_array['#page'] = $page;
// HTML element attributes.
$language_interface = $this->languageManager->getCurrentLanguage();
$html_attributes = $page->getHtmlAttributes();
$html_attributes['lang'] = $language_interface->id;
$html_attributes['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
return $page;
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Page\HtmlFragmentRendererInterface
*/
namespace Drupal\Core\Page;
/**
* Interface for HTML Fragment Renderers.
*
* An HTML Fragment Renderer is responsible for translating an HtmlFragment
* object into an HtmlPage object.
*/
interface HtmlFragmentRendererInterface {
/**
* Renders an HtmlFragment into an HtmlPage.
*
* An HtmlFragment represents only a portion of an HTML page, along with
* some attached information (assets, metatags, etc.) An HtmlPage represents
* an entire page. This method will create an HtmlPage containing the
* metadata from the fragment and using the body of the fragment as the main
* content region of the page.
*
* @param \Drupal\Core\Page\HtmlFragment $fragment
* The HTML fragment object to convert up to a page.
* @param int $status_code
* (optional) The status code of the page. May be any legal HTTP response
* code. Default is 200 OK.
*
* @return \Drupal\Core\Page\HtmlPage
* An HtmlPage object derived from the provided fragment.
*/
public function render(HtmlFragment $fragment, $status_code = 200);
}
......@@ -10,31 +10,11 @@
/**
* Interface for HTML Page Renderers.
*
* An HTML Page Renderer is responsible for translating an HtmlFragment object
* into an HtmlPage object, and from a page object into a string.
* An HTML Page Renderer is responsible for translating an HtmlPage object
* into a string.
*/
interface HtmlPageRendererInterface {
/**
* Renders an HtmlFragment into an HtmlPage.
*
* An HtmlFragment represents only a portion of an HTML page, along with
* some attached information (assets, metatags, etc.) An HtmlPage represents
* an entire page. This method will create an HtmlPage containing the
* metadata from the fragment and using the body of the fragment as the main
* content region of the page.
*
* @param \Drupal\Core\Page\HtmlFragment $fragment
* The HTML fragment object to convert up to a page.
* @param int $status_code
* (optional) The status code of the page. May be any legal HTTP response
* code. Default is 200 OK.
*
* @return \Drupal\Core\Page\HtmlPage
* An HtmlPage object derived from the provided fragment.
*/
public function render(HtmlFragment $fragment, $status_code = 200);
/**
* Renders an HtmlPage object to an HTML string.
*
......@@ -44,6 +24,6 @@ public function render(HtmlFragment $fragment, $status_code = 200);
* @return string
* A complete HTML page as a string.
*/
public function renderPage(HtmlPage $page);
public function render(HtmlPage $page);
}
......@@ -9,7 +9,7 @@
use Drupal\Core\Controller\TitleResolverInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Page\DefaultHtmlFragmentRenderer;
use Drupal\Core\Page\HtmlPage;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -23,11 +23,11 @@
class BatchController implements ContainerInjectionInterface {
/**
* The HTML page renderer.
* The fragment rendering service.
*
* @var \Drupal\Core\Page\DefaultHtmlPageRenderer
* @var \Drupal\Core\Page\DefaultHtmlFragmentRenderer
*/
protected $htmlPageRenderer;
protected $fragmentRenderer;
/**
* The title resolver.
......@@ -39,13 +39,13 @@ class BatchController implements ContainerInjectionInterface {
/**
* Constructs a new BatchController.
*
* @param \Drupal\Core\Page\DefaultHtmlPageRenderer $html_page_renderer
* The HTML page renderer.
* @param \Drupal\Core\Page\DefaultHtmlFragmentRenderer $html_fragment_renderer
* The fragment rendering service.
* @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
* The title resolver.
*/
public function __construct(DefaultHtmlPageRenderer $html_page_renderer, TitleResolverInterface $title_resolver) {
$this->htmlPageRenderer = $html_page_renderer;
public function __construct(DefaultHtmlFragmentRenderer $html_fragment_renderer, TitleResolverInterface $title_resolver) {
$this->fragmentRenderer = $html_fragment_renderer;
$this->titleResolver = $title_resolver;
}
......@@ -54,7 +54,7 @@ public function __construct(DefaultHtmlPageRenderer $html_page_renderer, TitleRe
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('html_page_renderer'),
$container->get('html_fragment_renderer'),
$container->get('title_resolver')
);
}
......@@ -106,7 +106,7 @@ public function render(array $output, $status_code = 200) {
$page_array = drupal_prepare_page($output);
$page = $this->htmlPageRenderer->preparePage($page, $page_array);
$page = $this->fragmentRenderer->preparePage($page, $page_array);
$page->setBodyTop(drupal_render($page_array['page_top']));
$page->setBodyBottom(drupal_render($page_array['page_bottom']));
......
......@@ -36,7 +36,8 @@ public function test405HTML() {
$exception = new \Exception('Test exception');
$flat_exception = FlattenException::create($exception, 405);
$translation_manager = $this->getStringTranslationStub();
$renderer = $this->getMock('Drupal\Core\Page\HtmlPageRendererInterface');
$html_page_renderer = $this->getMock('Drupal\Core\Page\HtmlPageRendererInterface');
$html_fragment_renderer = $this->getMock('Drupal\Core\Page\HtmlFragmentRendererInterface');
$title_resolver = $this->getMock('Drupal\Core\Controller\TitleResolverInterface');
$content_negotiation = $this->getMock('Drupal\Core\ContentNegotiation');
......@@ -44,7 +45,7 @@ public function test405HTML() {
->method('getContentType')
->will($this->returnValue('html'));
$exception_controller = new ExceptionController($content_negotiation, $translation_manager, $title_resolver, $renderer);
$exception_controller = new ExceptionController($content_negotiation, $translation_manager, $title_resolver, $html_page_renderer, $html_fragment_renderer);
$response = $exception_controller->execute($flat_exception, new Request());
$this->assertEquals($response->getStatusCode(), 405, 'HTTP status of response is correct.');
$this->assertEquals($response->getContent(), 'Method Not Allowed', 'HTTP response body is correct.');
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment