Commit 488116d7 authored by catch's avatar catch

Issue #2352155 by Wim Leers: Remove HtmlFragment/HtmlPage.

parent 9f035188
......@@ -25,7 +25,6 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Site\Settings;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
// Change the directory to the Drupal root.
chdir('..');
......@@ -150,7 +149,7 @@ function authorize_access_allowed() {
if (!empty($output)) {
$response->headers->set('Content-Type', 'text/html; charset=utf-8');
$response->setContent(DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array(
$response->setContent(\Drupal::service('bare_html_page_renderer')->renderMaintenancePage($output, $page_title, array(
'#show_messages' => $show_messages,
)));
$response->send();
......
......@@ -650,15 +650,34 @@ services:
class: Drupal\Core\EventSubscriber\RouteMethodSubscriber
tags:
- { name: event_subscriber }
controller.page:
class: Drupal\Core\Controller\HtmlPageController
arguments: ['@controller_resolver', '@title_resolver', '@render_html_renderer']
controller.ajax:
class: Drupal\Core\Controller\AjaxController
arguments: ['@controller_resolver', '@element_info']
controller.dialog:
class: Drupal\Core\Controller\DialogController
arguments: ['@controller_resolver', '@title_resolver']
# Main content view subscriber plus the renderers it uses.
main_content_view_subscriber:
class: Drupal\Core\EventSubscriber\MainContentViewSubscriber
arguments: ['@class_resolver', '@current_route_match', '%main_content_renderers%']
tags:
- { name: event_subscriber }
main_content_renderer.html:
class: Drupal\Core\Render\MainContent\HtmlRenderer
arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler']
tags:
- { name: render.main_content_renderer, format: html }
main_content_renderer.ajax:
class: Drupal\Core\Render\MainContent\AjaxRenderer
arguments: ['@element_info']
tags:
- { name: render.main_content_renderer, format: drupal_ajax }
main_content_renderer.dialog:
class: Drupal\Core\Render\MainContent\DialogRenderer
arguments: ['@title_resolver']
tags:
- { name: render.main_content_renderer, format: drupal_dialog }
main_content_renderer.modal:
class: Drupal\Core\Render\MainContent\ModalRenderer
arguments: ['@title_resolver']
tags:
- { name: render.main_content_renderer, format: drupal_modal }
router_listener:
class: Symfony\Component\HttpKernel\EventListener\RouterListener
tags:
......@@ -671,19 +690,8 @@ services:
tags:
- { name: event_subscriber }
arguments: ['@content_negotiation', '@title_resolver']
html_view_subscriber:
class: Drupal\Core\EventSubscriber\HtmlViewSubscriber
tags:
- { name: event_subscriber }
arguments: ['@html_fragment_renderer', '@html_page_renderer']
render_html_renderer:
class: Drupal\Core\Page\RenderHtmlRenderer
arguments: ['@url_generator']
html_fragment_renderer:
class: Drupal\Core\Page\DefaultHtmlFragmentRenderer
arguments: ['@language_manager']
html_page_renderer:
class: Drupal\Core\Page\DefaultHtmlPageRenderer
bare_html_page_renderer:
class: Drupal\Core\Render\BareHtmlPageRenderer
private_key:
class: Drupal\Core\PrivateKey
arguments: ['@state']
......@@ -732,7 +740,7 @@ services:
arguments: ['@state', '@current_user']
maintenance_mode_subscriber:
class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user']
arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer']
tags:
- { name: event_subscriber }
path_subscriber:
......@@ -777,7 +785,7 @@ services:
class: Drupal\Core\EventSubscriber\DefaultExceptionSubscriber
tags:
- { name: event_subscriber }
arguments: ['@html_fragment_renderer', '@html_page_renderer', '@config.factory']
arguments: ['@config.factory', '@bare_html_page_renderer']
exception.logger:
class: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber
tags:
......
......@@ -19,7 +19,6 @@
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Batch\Percentage;
use Drupal\Core\Form\FormState;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
......@@ -136,7 +135,7 @@ function _batch_progress_page() {
// additional HTML output by PHP shows up inside the page rather than below
// it. While this causes invalid HTML, the same would be true if we didn't,
// as content is not allowed to appear after </html> anyway.
$fallback = DefaultHtmlPageRenderer::renderPage($fallback, $current_set['title'], 'maintenance', array(
$fallback = \Drupal::service('bare_html_page_renderer')->renderMaintenancePage($fallback, $current_set['title'], array(
'#show_messages' => FALSE,
));
list($fallback) = explode('<!--partial-->', $fallback);
......
......@@ -1117,9 +1117,6 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE, $theme_add_css = TRUE)
'#type' => 'styles',
'#items' => $css,
);
if (!empty($setting)) {
$styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting);
}
return drupal_render($styles);
}
......@@ -2261,39 +2258,6 @@ function drupal_page_set_cache(Response $response, Request $request) {
\Drupal::cache('render')->set($cid, $response, $expire, $tags);
}
/**
* Sets the main page content value for later use.
*
* Given the nature of the Drupal page handling, this will be called once with
* a string or array. We store that and return it later as the block is being
* displayed.
*
* @param $content
* A string or renderable array representing the body of the page.
*
* @return
* If called without $content, a renderable array representing the body of
* the page.
*/
function drupal_set_page_content($content = NULL) {
$content_block = &drupal_static(__FUNCTION__, NULL);
$main_content_display = &drupal_static('system_main_content_added', FALSE);
// Filter out each empty value, though allow '0' and 0, which would be
// filtered out by empty().
if ($content !== NULL && $content !== '') {
$content_block = (is_array($content) ? $content : array('main' => array('#markup' => $content)));
}
else {
// Indicate that the main content has been requested. We assume that
// the module requesting the content will be adding it to the page.
// A module can indicate that it does not handle the content by setting
// the static variable back to FALSE after calling this function.
$main_content_display = TRUE;
return $content_block;
}
}
/**
* Pre-render callback: Renders a link into #markup.
*
......@@ -2398,111 +2362,6 @@ function drupal_pre_render_links($element) {
return $element;
}
/**
* Processes the page render array, enhancing it as necessary.
*
* @param $page
* A string or array representing the content of a page. The array consists of
* the following keys:
* - #type: Value is always 'page'. This pushes the theming through
* the page template (required).
* - #show_messages: Suppress drupal_get_message() items. Used by Batch
* API (optional).
*
* @return array
* The processed render array for the page.
*
* @see hook_page_attachments()
* @see hook_page_attachments_alter()
* @see hook_page_top()
* @see hook_page_bottom()
* @see element_info()
*/
function drupal_prepare_page($page) {
$main_content_display = &drupal_static('system_main_content_added', FALSE);
// Pull out the page title to set it back later.
if (is_array($page) && isset($page['#title'])) {
$title = $page['#title'];
}
// Allow menu callbacks to return strings or arbitrary arrays to render.
// If the array returned is not of #type page directly, we need to fill
// in the page with defaults.
if (is_string($page) || (is_array($page) && (!isset($page['#type']) || ($page['#type'] != 'page')))) {
drupal_set_page_content($page);
$page = element_info('page');
}
// Modules can add attachments.
$attachments = [];
foreach (\Drupal::moduleHandler()->getImplementations('page_attachments') as $module) {
$function = $module . '_page_attachments';
$function($attachments);
}
if (array_diff(array_keys($attachments), ['#attached', '#post_render_cache']) !== []) {
throw new \LogicException('Only #attached and #post_render_cache may be set in hook_page_attachments().');
}
// Modules and themes can alter page attachments.
\Drupal::moduleHandler()->alter('page_attachments', $attachments);
\Drupal::theme()->alter('page_attachments', $attachments);
if (array_diff(array_keys($attachments), ['#attached', '#post_render_cache']) !== []) {
throw new \LogicException('Only #attached and #post_render_cache may be set in hook_page_attachments_alter().');
}
if (isset($attachments['#attached'])) {
$page['#attached'] = $attachments['#attached'];
}
if (isset($attachments['#post_render_cache'])) {
$page['#post_render_cache'] = $attachments['#post_render_cache'];
}
// Modules can add renderable arrays to the top and bottom of the page.
$pseudo_page_top = [];
$pseudo_page_bottom = [];
foreach (\Drupal::moduleHandler()->getImplementations('page_top') as $module) {
$function = $module . '_page_top';
$function($pseudo_page_top);
}
foreach (\Drupal::moduleHandler()->getImplementations('page_bottom') as $module) {
$function = $module . '_page_bottom';
$function($pseudo_page_bottom);
}
if (!empty($pseudo_page_top)) {
$page['page_top'] = $pseudo_page_top;
}
if (!empty($pseudo_page_bottom)) {
$page['page_bottom'] = $pseudo_page_bottom;
}
// @todo Clean this up as part of https://www.drupal.org/node/2352155.
if (\Drupal::moduleHandler()->moduleExists('block')) {
_block_page_build($page);
// Find all non-empty page regions, and add a theme wrapper function that
// allows them to be consistently themed.
$regions = system_region_list(\Drupal::theme()->getActiveTheme()->getName());
foreach (array_keys($regions) as $region) {
if (!empty($page[$region])) {
$page[$region]['#theme_wrappers'][] = 'region';
$page[$region]['#region'] = $region;
}
}
}
// If no module has taken care of the main content, add it to the page now.
// This allows the site to still be usable even if no modules that
// control page regions (for example, the Block module) are enabled.
if (!$main_content_display) {
$page['content']['system_main'] = drupal_set_page_content();
}
// Set back the previously stored title.
if (isset($title)) {
$page['#title'] = $title;
}
return $page;
}
/**
* Renders final HTML given a structured array tree.
*
......
......@@ -8,7 +8,6 @@
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Utility\Error;
use Symfony\Component\HttpFoundation\Response;
......@@ -236,7 +235,7 @@ function _drupal_log_error($error, $fatal = FALSE) {
install_display_output($output, $GLOBALS['install_state']);
}
else {
$output = DefaultHtmlPageRenderer::renderPage($message, 'Error');
$output = \Drupal::service('bare_html_page_renderer')->renderMaintenancePage($message, 'Error');
}
$response = new Response($output, 500);
......
......@@ -14,7 +14,6 @@
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Site\Settings;
use Drupal\Core\StringTranslation\Translator\FileTranslation;
use Drupal\Core\Extension\ExtensionDiscovery;
......@@ -934,7 +933,7 @@ function install_display_output($output, $install_state) {
'ETag' => '"' . REQUEST_TIME . '"',
);
$response->headers->add($default_headers);
$response->setContent(DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'install', $regions));
$response->setContent(\Drupal::service('bare_html_page_renderer')->renderInstallPage($output, $output['#title'], $regions));
$response->send();
exit;
}
......
......@@ -110,13 +110,15 @@
* class and method. Page controller classes do not necessarily need to
* implement any particular interface or extend any particular base class. The
* only requirement is that the method specified in your *.routing.yml file
* return one of the following, depending on whether you specified _content or
* _controller in the routing file defaults section:
* returns:
* - A render array (see the
* @link theme_render Theme and render topic @endlink for more information),
* if _content is used in the routing file.
* - A \Drupal\Core\Page\HtmlFragmentInterface object (fragment or page), if
* _content is used in the routing file.
* This render array is then rendered in the requested format (HTML, dialog,
* modal, AJAX are supported by default). In the case of HTML, it will be
* surrounded by blocks by default: the Block module is enabled by default,
* and hence its Page Display Variant that surrounds the main content with
* blocks is also used by default.
* - A \Symfony\Component\HttpFoundation\Response object, if _controller is
* used in the routing file.
* As a note, if your module registers multiple simple routes, it is usual
......
......@@ -18,8 +18,6 @@
use Drupal\Core\Config\StorageException;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionNameLengthException;
use Drupal\Core\Page\LinkElement;
use Drupal\Core\Page\MetaElement;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Theme\ThemeSettings;
use Drupal\Component\Utility\NestedArray;
......@@ -1646,22 +1644,37 @@ function drupal_pre_render_html(array $element) {
* - page: A render element representing the page.
*/
function template_preprocess_html(&$variables) {
/** @var $page \Drupal\Core\Page\HtmlPage */
$page = $variables['page_object'];
$variables['page'] = $variables['html']['page'];
unset($variables['html']['page']);
$variables['page_top'] = NULL;
if (isset($variables['html']['page_top'])) {
$variables['page_top'] = $variables['html']['page_top'];
unset($variables['html']['page_top']);
}
$variables['page_bottom'] = NULL;
if (isset($variables['html']['page_bottom'])) {
$variables['page_bottom'] = $variables['html']['page_bottom'];
unset($variables['html']['page_bottom']);
}
$variables['html_attributes'] = $page->getHtmlAttributes();
$variables['attributes'] = $page->getBodyAttributes();
$variables['page'] = $page;
$variables['html_attributes'] = new Attribute();
// HTML element attributes.
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
$variables['html_attributes']['lang'] = $language_interface->getId();
$variables['html_attributes']['dir'] = $language_interface->getDirection();
// Compile a list of classes that are going to be applied to the body element.
// This allows advanced theming based on context (home page, node of certain
// type, etc.).
$body_classes = $variables['attributes']['class'];
if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
$variables['attributes']['class'][] = 'db-offline';
}
// Add a class that tells us whether the page is viewed by an authenticated
// user.
if ($variables['logged_in']) {
$body_classes[] = 'user-logged-in';
$variables['attributes']['class'][] = 'user-logged-in';
}
// Add a class that tells us what path the page is located make it possible
// to theme the page depending on the current path (e.g. node, admin, user,
......@@ -1669,20 +1682,18 @@ function template_preprocess_html(&$variables) {
$path = \Drupal::request()->getPathInfo();
if (drupal_is_front_page()) {
$body_classes[] = 'path-frontpage';
$variables['attributes']['class'][] = 'path-frontpage';
}
else {
$segment = explode('/', $path);
$body_classes[] = 'path-' . drupal_html_class($segment[1]);
$variables['attributes']['class'][] = 'path-' . drupal_html_class($segment[1]);
}
$variables['attributes']['class'] = $body_classes;
$site_config = \Drupal::config('system.site');
// Construct page title.
if ($page->hasTitle()) {
if (!empty($variables['page']['#title'])) {
$head_title = array(
'title' => SafeMarkup::set(trim(strip_tags($page->getTitle()))),
'title' => SafeMarkup::set(trim(strip_tags($variables['page']['#title']))),
'name' => String::checkPlain($site_config->get('name')),
);
}
......@@ -1710,35 +1721,27 @@ function template_preprocess_html(&$variables) {
}
$variables['head_title'] = SafeMarkup::set($output);
// @todo Remove drupal_*_html_head() and refactor accordingly.
$html_heads = drupal_get_html_head(FALSE);
uasort($html_heads, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
foreach ($html_heads as $name => $tag) {
if ($tag['#tag'] == 'link') {
$link = new LinkElement($name, isset($tag['#attributes']['content']) ? $tag['#attributes']['content'] : NULL, $tag['#attributes']);
if (!empty($tag['#noscript'])) {
$link->setNoScript();
}
$page->addLinkElement($link);
}
elseif ($tag['#tag'] == 'meta') {
$metatag = new MetaElement(NULL, $tag['#attributes']);
if (!empty($tag['#noscript'])) {
$metatag->setNoScript();
}
$page->addMetaElement($metatag);
}
// Collect all attachments. This must happen in the preprocess function for
// #type => html, to ensure that attachments added in #pre_render callbacks
// for #type => html are included.
$attached = $variables['html']['#attached'];
$attached = drupal_merge_attached($attached, $variables['page']['#attached']);
if (isset($variables['page_top'])) {
$attached = drupal_merge_attached($attached, $variables['page_top']['#attached']);
}
// Add favicon.
if (theme_get_setting('features.favicon')) {
$url = UrlHelper::stripDangerousProtocols(theme_get_setting('favicon.url'));
$link = new LinkElement($url, 'shortcut icon', ['type' => theme_get_setting('favicon.mimetype')]);
$page->addLinkElement($link);
if (isset($variables['page_bottom'])) {
$attached = drupal_merge_attached($attached, $variables['page_bottom']['#attached']);
}
$variables['page_top'][] = array('#markup' => $page->getBodyTop());
$variables['page_bottom'][] = array('#markup' => $page->getBodyBottom());
// Render the attachments into HTML markup to be used directly in the template
// for #type => html: html.html.twig.
$all_attached = ['#attached' => $attached];
drupal_process_attached($all_attached);
$variables['styles'] = drupal_get_css();
$variables['scripts'] = drupal_get_js();
$variables['scripts_bottom'] = drupal_get_js('footer');
$variables['head'] = drupal_get_html_head(FALSE);
}
/**
......@@ -1749,8 +1752,6 @@ function template_preprocess_html(&$variables) {
* Most themes use their own copy of page.html.twig. The default is located
* inside "modules/system/page.html.twig". Look in there for the full list of
* variables.
*
* @see DefaultHtmlFragmentRenderer::render()
*/
function template_preprocess_page(&$variables) {
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
......@@ -1890,15 +1891,6 @@ function template_preprocess_maintenance_page(&$variables) {
// @todo Rename the templates to page--maintenance + page--install.
template_preprocess_page($variables);
$page_object = $variables['page']['#page'];
$attributes = $page_object->getBodyAttributes();
$classes = $attributes['class'];
$classes[] = 'maintenance-page';
if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
$classes[] = 'db-offline';
}
$attributes['class'] = $classes;
// @see system_page_attachments()
$variables['#attached']['library'][] = 'core/normalize';
$variables['#attached']['library'][] = 'system/maintenance';
......@@ -1918,12 +1910,6 @@ function template_preprocess_maintenance_page(&$variables) {
function template_preprocess_install_page(&$variables) {
template_preprocess_maintenance_page($variables);
$page_object = $variables['page']['#page'];
$attributes = $page_object->getBodyAttributes();
$classes = $attributes['class'];
$classes[] = 'install-page';
$attributes['class'] = $classes;
// Override the site name that is displayed on the page, since Drupal is
// still in the process of being installed.
$distribution_name = String::checkPlain(drupal_install_profile_distribution_name());
......@@ -2161,7 +2147,7 @@ function drupal_common_theme() {
return array(
// From theme.inc.
'html' => array(
'variables' => array('page_object' => NULL),
'render element' => 'html',
),
'page' => array(
'render element' => 'page',
......
<?php
/**
* @file
* Contains \Drupal\Core\Controller\DialogController.
*/
namespace Drupal\Core\Controller;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenDialogCommand;
use Drupal\Core\Page\HtmlPage;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Defines a default controller for dialog requests.
*/
class DialogController {
/**
* The controller resolver service.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
*/
protected $controllerResolver;
/**
* The title resolver.
*
* @var \Drupal\Core\Controller\TitleResolver
*/
protected $titleResolver;
/**
* Constructs a new DialogController.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver service.
* @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
* The title resolver.
*/
public function __construct(ControllerResolverInterface $controller_resolver, TitleResolverInterface $title_resolver) {
$this->controllerResolver = $controller_resolver;
$this->titleResolver = $title_resolver;
}
/**
* Displays content in a modal dialog.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param mixed $_content
* A controller definition string, or a callable object/closure.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* AjaxResponse to return the content wrapper in a modal dialog.
*/
public function modal(Request $request, RouteMatchInterface $route_match, $_content) {
return $this->dialog($request, $route_match, $_content, TRUE);
}
/**
* Displays content in a dialog.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param mixed $_content
* A controller definition string, or a callable object/closure.
* @param bool $modal
* (optional) TRUE to render a modal dialog. Defaults to FALSE.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* AjaxResponse to return the content wrapper in a dialog.
*/
public function dialog(Request $request, RouteMatchInterface $route_match, $_content, $modal = FALSE) {
$page_content = $this->getContentResult($request, $_content);
// Allow controllers to return a HtmlPage or a Response object directly.
if ($page_content instanceof HtmlPage) {
$page_content = $page_content->getContent();
}
if ($page_content instanceof Response) {
$page_content = $page_content->getContent();
}
// Most controllers return a render array, but some return a string.
if (!is_array($page_content)) {
$page_content = array(
'#markup' => $page_content,
);
}
$content = drupal_render_root($page_content);
drupal_process_attached($page_content);
$title = isset($page_content['#title']) ? $page_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject());
$response = new AjaxResponse();
// Fetch any modal options passed in from data-dialog-options.
$options = $request->request->get('dialogOptions', array());
// Set modal flag and re-use the modal ID.
if ($modal) {
$options['modal'] = TRUE;
$target = '#drupal-modal';
}
else {
// Generate the target wrapper for the dialog.
if (isset($options['target'])) {
// If the target was nominated in the incoming options, use that.
$target = $options['target'];
// Ensure the target includes the #.
if (substr($target, 0, 1) != '#') {
$target = '#' . $target;
}
// This shouldn't be passed on to jQuery.ui.dialog.
unset($options['target']);
}
else {
// Generate a target based on the route id.
$route_name = $route_match->getRouteName();
$target = '#' . drupal_html_id("drupal-dialog-$route_name");
}
}
$response->addCommand(new OpenDialogCommand($target, $title, $content, $options));
return $response;
}
/**
* Returns the result of invoking the sub-controller.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
* @param mixed $controller_definition
* A controller definition string, or a callable object/closure.
*
* @return mixed
* The result of invoking the controller. Render arrays, strings, HtmlPage,
* and HtmlFragment objects are possible.
*/
public function getContentResult(Request $request, $controller_definition) {
if ($controller_definition instanceof \Closure) {
$callable = $controller_definition;
}
else {
$callable = $this->controllerResolver->getControllerFromDefinition($controller_definition);
}
$arguments = $this->controllerResolver->getArguments($request, $callable);
$page_content = call_user_func_array($callable, $arguments);
return $page_content;
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Controller\HtmlControllerBase.
*/
namespace Drupal\Core\Controller;
use Drupal\Core\Page\HtmlFragment;
use Drupal\Core\Page\RenderHtmlRendererInterface;
use Drupal\Core\Utility\Title;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Base class for HTML page-generating controllers.
*/
class HtmlControllerBase {