summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwebchick2014-04-04 04:41:54 (GMT)
committerwebchick2014-04-04 04:41:54 (GMT)
commit4f4b457d6b4ccba10c6faaa618a2f16b61f253df (patch)
treedac99df80168bff1f64e417e7add1aa585c8c0a7 /core
parent3a27db99bb9d19a5368f959349aa4a19d5725b37 (diff)
Revert "Issue #2218039 by sun, dawehner: Render the maintenance/install page like any other HTML page."
Broke update.php. This reverts commit 10b038906621c45e7aa638733d0994cad3ebab6d.
Diffstat (limited to 'core')
-rw-r--r--core/authorize.php11
-rw-r--r--core/includes/batch.inc11
-rw-r--r--core/includes/errors.inc8
-rw-r--r--core/includes/install.core.inc18
-rw-r--r--core/includes/theme.inc181
-rw-r--r--core/includes/theme.maintenance.inc8
-rw-r--r--core/includes/update.inc13
-rw-r--r--core/lib/Drupal/Core/Controller/ExceptionController.php12
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php14
-rw-r--r--core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php83
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php244
-rw-r--r--core/modules/system/templates/install-page.html.twig31
-rw-r--r--core/modules/system/templates/maintenance-page.html.twig17
-rw-r--r--core/themes/bartik/bartik.theme3
-rw-r--r--core/themes/bartik/templates/maintenance-page.html.twig21
-rw-r--r--core/themes/seven/seven.theme16
-rw-r--r--core/themes/seven/templates/install-page.html.twig30
-rw-r--r--core/themes/seven/templates/maintenance-page.html.twig29
-rw-r--r--core/themes/seven/templates/page.html.twig4
-rw-r--r--core/update.php15
20 files changed, 514 insertions, 255 deletions
diff --git a/core/authorize.php b/core/authorize.php
index 086802e..97fbe24 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -21,7 +21,6 @@
*/
use Drupal\Component\Utility\Settings;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
// Change the directory to the Drupal root.
chdir('..');
@@ -156,7 +155,13 @@ else {
if (!empty($output)) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
- print DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array(
+ $maintenance_page = array(
+ '#page' => array(
+ '#title' => $page_title,
+ ),
+ '#theme' => 'maintenance_page',
+ '#content' => $output,
'#show_messages' => $show_messages,
- ));
+ );
+ print drupal_render($maintenance_page);
}
diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index 153a7de..daa7b2f 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -16,7 +16,6 @@
use Drupal\Component\Utility\Timer;
use Drupal\Core\Batch\Percentage;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -122,14 +121,18 @@ function _batch_progress_page() {
// the error message.
ob_start();
$fallback = $current_set['error_message'] . '<br />' . $batch['error_message'];
+ $fallback = array(
+ '#theme' => 'maintenance_page',
+ '#title' => $current_set['title'],
+ '#content' => $fallback,
+ '#show_messages' => FALSE,
+ );
// We strip the end of the page using a marker in the template, so any
// 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(
- '#show_messages' => FALSE,
- ));
+ $fallback = drupal_render($fallback);
list($fallback) = explode('<!--partial-->', $fallback);
print $fallback;
diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index 56cf71a..56c276f 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -5,7 +5,6 @@
* Functions for error handling.
*/
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Utility\Error;
use Drupal\Component\Utility\String;
use Symfony\Component\HttpFoundation\Response;
@@ -232,7 +231,12 @@ function _drupal_log_error($error, $fatal = FALSE) {
install_display_output($output, $GLOBALS['install_state']);
}
else {
- $output = DefaultHtmlPageRenderer::renderPage($message, 'Error');
+ $output = array(
+ '#theme' => 'maintenance_page',
+ '#title' => 'Error',
+ '#content' => $message,
+ );
+ $output = drupal_render($output);
}
$response = new Response($output, 500);
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index a2ef2c1..aa158a2 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -14,7 +14,6 @@ use Drupal\Core\Installer\Exception\InstallerException;
use Drupal\Core\Installer\Exception\NoProfilesException;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\StringTranslation\Translator\FileTranslation;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\DependencyInjection\ContainerBuilder;
@@ -904,7 +903,6 @@ function install_display_output($output, $install_state) {
// Only show the task list if there is an active task; otherwise, the page
// request has ended before tasks have even been started, so there is nothing
// meaningful to show.
- $regions = array();
if (isset($install_state['active_task'])) {
// Let the theming function know when every step of the installation has
// been completed.
@@ -914,10 +912,20 @@ function install_display_output($output, $install_state) {
'#items' => install_tasks_to_display($install_state),
'#active' => $active_task,
);
- $regions['sidebar_first'] = $task_list;
+ drupal_add_region_content('sidebar_first', drupal_render($task_list));
}
-
- print DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'install', $regions);
+ $install_page = array(
+ '#theme' => 'install_page',
+ // $output has to be rendered here, because the install page template is not
+ // wrapped into the html template, which means that any #attached libraries
+ // in $output will not be loaded, because the wrapping HTML has been printed
+ // already.
+ '#content' => drupal_render($output),
+ );
+ if (isset($output['#title'])) {
+ $install_page['#page']['#title'] = $output['#title'];
+ }
+ print drupal_render($install_page);
exit;
}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index c51867e..c63f679 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2073,26 +2073,16 @@ function template_preprocess_page(&$variables) {
$variables['base_path'] = base_path();
$variables['front_page'] = url();
+ $variables['feed_icons'] = drupal_get_feeds();
$variables['language'] = $language_interface;
$variables['language']->dir = $language_interface->direction ? 'rtl' : 'ltr';
$variables['logo'] = theme_get_setting('logo.url');
+ $variables['main_menu'] = theme_get_setting('features.main_menu') ? menu_main_menu() : array();
+ $variables['secondary_menu'] = theme_get_setting('features.secondary_menu') ? menu_secondary_menu() : array();
+ $variables['action_links'] = menu_get_local_actions();
$variables['site_name'] = (theme_get_setting('features.name') ? String::checkPlain($site_config->get('name')) : '');
$variables['site_slogan'] = (theme_get_setting('features.slogan') ? filter_xss_admin($site_config->get('slogan')) : '');
-
- if (!defined('MAINTENANCE_MODE')) {
- $variables['main_menu'] = theme_get_setting('features.main_menu') ? menu_main_menu() : array();
- $variables['secondary_menu'] = theme_get_setting('features.secondary_menu') ? menu_secondary_menu() : array();
- $variables['action_links'] = menu_get_local_actions();
- $variables['tabs'] = menu_local_tabs();
- $variables['feed_icons'] = drupal_get_feeds();
- }
- else {
- $variables['main_menu'] = array();
- $variables['secondary_menu'] = array();
- $variables['action_links'] = array();
- $variables['tabs'] = array();
- $variables['feed_icons'] = '';
- }
+ $variables['tabs'] = menu_local_tabs();
// Pass the main menu and secondary menu to the template as render arrays.
if (!empty($variables['main_menu'])) {
@@ -2133,12 +2123,10 @@ function template_preprocess_page(&$variables) {
// re-use the cache of an already retrieved menu containing the active link
// for the current page.
// @see menu_tree_page_data()
- if (!defined('MAINTENANCE_MODE')) {
- $variables['breadcrumb'] = array(
- '#theme' => 'breadcrumb',
- '#breadcrumb' => \Drupal::service('breadcrumb')->build(\Drupal::request()->attributes->all()),
- );
- }
+ $variables['breadcrumb'] = array(
+ '#theme' => 'breadcrumb',
+ '#breadcrumb' => \Drupal::service('breadcrumb')->build(\Drupal::request()->attributes->all()),
+ );
}
/**
@@ -2216,6 +2204,12 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
*
* Default template: maintenance-page.html.twig.
*
+ * The variables array generated here is a mirror of
+ * template_preprocess_page(). This preprocessor will run its course when
+ * theme_maintenance_page() is invoked. An alternate template file of
+ * maintenance-page--offline.html.twig can be used when the database is offline
+ * to hide errors and completely replace the content.
+ *
* @param array $variables
* An associative array containing:
* - content - An array of page content.
@@ -2223,29 +2217,117 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
* @see system_page_build()
*/
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';
- $classes[] = 'in-maintenance';
- if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
- $classes[] = 'db-offline';
+ $language_interface = \Drupal::languageManager()->getCurrentLanguage();
+
+ // Initializes attributes which are specific to the html element.
+ $variables['html_attributes'] = new Attribute;
+
+ // HTML element attributes.
+ $variables['html_attributes']['lang'] = $language_interface->id;
+ $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
+
+ // Add favicon
+ if (theme_get_setting('features.favicon')) {
+ $favicon = theme_get_setting('favicon.url');
+ $type = theme_get_setting('favicon.mimetype');
+ $build['#attached']['drupal_add_html_head_link'][][] = array(
+ 'rel' => 'shortcut icon',
+ 'href' => UrlHelper::stripDangerousProtocols($favicon),
+ 'type' => $type,
+ );
+ drupal_render($build);
}
- $attributes['class'] = $classes;
- // @see system_page_build()
- $attached = array(
- '#attached' => array(
- 'library' => array(
- 'core/normalize',
- 'system/maintenance',
- ),
- ),
- );
+ foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
+ if (!isset($variables[$region_key])) {
+ $variables[$region_key] = array();
+ }
+ // Append region content set with drupal_add_region_content() as markup.
+ if ($region_content = drupal_get_region_content($region_key)) {
+ $variables[$region_key][]['#markup'] = $region_content;
+ }
+ }
+
+ // Setup layout variable.
+ $variables['layout'] = 'none';
+ if (!empty($variables['sidebar_first'])) {
+ $variables['layout'] = 'first';
+ }
+ if (!empty($variables['sidebar_second'])) {
+ $variables['layout'] = ($variables['layout'] == 'first') ? 'both' : 'second';
+ }
+
+ $site_config = \Drupal::config('system.site');
+ $site_name = $site_config->get('name');
+ $site_slogan = $site_config->get('slogan');
+
+ // Construct the page title.
+ if (isset($variables['page']['#title'])) {
+ $head_title = array(
+ 'title' => strip_tags($variables['page']['#title']),
+ 'name' => String::checkPlain($site_config->get('name')),
+ );
+ }
+ else {
+ $head_title = array('name' => String::checkPlain($site_name));
+ if ($site_slogan) {
+ $head_title['slogan'] = strip_tags(filter_xss_admin($site_slogan));
+ }
+ }
+
+ // These are usually added from system_page_build() except maintenance.css.
+ // When the database is inactive it's not called so we add it here.
+ $default_css['library'][] = 'core/normalize';
+ $default_css['library'][] = 'system/maintenance';
+ $attached = array('#attached' => $default_css);
drupal_render($attached);
+ $variables['messages'] = array(
+ '#theme' => 'status_messages',
+ '#access' => $variables['show_messages'],
+ );
+
+ $variables['head_title_array'] = $head_title;
+ $variables['head_title'] = implode(' | ', $head_title);
+ $variables['front_page'] = url();
+ $variables['help'] = '';
+ $variables['language'] = $language_interface;
+ $variables['logo'] = theme_get_setting('logo.url');
+ $variables['site_name'] = (theme_get_setting('features.name') ? String::checkPlain($site_name) : '');
+ $variables['site_slogan'] = (theme_get_setting('features.slogan') ? filter_xss_admin($site_slogan) : '');
+
+ // Compile a list of classes that are going to be applied to the body element.
+ $variables['attributes']['class'][] = 'maintenance-page';
+ $variables['attributes']['class'][] = 'in-maintenance';
+ if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
+ $variables['attributes']['class'][] = 'db-offline';
+ }
+ if ($variables['layout'] == 'both') {
+ $variables['attributes']['class'][] = 'two-sidebars';
+ }
+ elseif ($variables['layout'] == 'none') {
+ $variables['attributes']['class'][] = 'no-sidebars';
+ }
+ else {
+ $variables['attributes']['class'][] = 'one-sidebar';
+ $variables['attributes']['class'][] = 'sidebar-' . $variables['layout'];
+ }
+
+ $variables['head'] = drupal_get_html_head();
+
+ // While this code is used in the installer, the language module may not be
+ // enabled yet (even maybe no database set up yet), but an RTL language
+ // selected should result in RTL stylesheets loaded properly already.
+ $css = _drupal_add_css();
+ include_once DRUPAL_ROOT . '/core/modules/language/language.module';
+ // Wrapping drupal_get_css() and drupal_get_js() in an object so they can
+ // be called when printed.
+ $variables['styles'] = new RenderWrapper('drupal_get_css', array($css));
+ $variables['scripts'] = new RenderWrapper('drupal_get_js');
+
+ // Allow the page to define a title.
+ if (isset($variables['page']['#title'])) {
+ $variables['title'] = $variables['page']['#title'];
+ }
}
/**
@@ -2253,21 +2335,20 @@ function template_preprocess_maintenance_page(&$variables) {
*
* Default template: install-page.html.twig.
*
+ * The variables array generated here is a mirror of
+ * template_preprocess_page(). This preprocessor will run its course when
+ * theme_install_page() is invoked.
+ *
* @param array $variables
* An associative array containing:
* - content - An array of page content.
*
* @see template_preprocess_maintenance_page()
+ *
*/
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;
-
+ $variables['attributes']['class'][] = 'install-page';
// 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());
@@ -2565,11 +2646,11 @@ function drupal_common_theme() {
),
// From theme.maintenance.inc.
'maintenance_page' => array(
- 'render element' => 'page',
+ 'variables' => array('content' => NULL, 'show_messages' => TRUE, 'page' => array()),
'template' => 'maintenance-page',
),
'install_page' => array(
- 'render element' => 'page',
+ 'variables' => array('content' => NULL, 'show_messages' => TRUE, 'page' => array()),
'template' => 'install-page',
),
'task_list' => array(
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index 1cd436c..57183d6 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -31,7 +31,6 @@ function _drupal_maintenance_theme() {
require_once __DIR__ . '/unicode.inc';
require_once __DIR__ . '/file.inc';
require_once __DIR__ . '/module.inc';
- require_once __DIR__ . '/database.inc';
Unicode::check();
// Install and update pages are treated differently to prevent theming overrides.
@@ -44,6 +43,13 @@ function _drupal_maintenance_theme() {
}
}
else {
+ // The bootstrap was not complete. So we are operating in a crippled
+ // environment, we need to bootstrap just enough to allow hook invocations
+ // to work. See _drupal_log_error().
+ if (!class_exists('Drupal\Core\Database\Database', FALSE)) {
+ require_once __DIR__ . '/database.inc';
+ }
+
// Use the maintenance theme if specified, otherwise attempt to use the
// default site theme.
try {
diff --git a/core/includes/update.inc b/core/includes/update.inc
index f7642cd..fd02de09 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -14,7 +14,6 @@ use Drupal\Component\Utility\String;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\ConfigException;
use Drupal\Core\DrupalKernel;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Utility\Error;
use Drupal\Component\Uuid\Uuid;
use Drupal\Component\Utility\NestedArray;
@@ -149,13 +148,19 @@ function update_check_requirements($skip_warnings = FALSE) {
// them if the caller has indicated they should be skipped.
if ($severity == REQUIREMENT_ERROR || ($severity == REQUIREMENT_WARNING && !$skip_warnings)) {
update_task_list('requirements');
- $status_report = array(
+ $status = array(
'#theme' => 'status_report',
'#requirements' => $requirements,
);
- $status_report['#suffix'] = 'Check the messages and <a href="' . check_url(drupal_requirements_url($severity)) . '">try again</a>.';
+ $status_report = drupal_render($status);
+ $status_report .= 'Check the messages and <a href="' . check_url(drupal_requirements_url($severity)) . '">try again</a>.';
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
- print DefaultHtmlPageRenderer::renderPage($status_report, 'Requirements problem');
+ $maintenance_page = array(
+ '#theme' => 'maintenance_page',
+ '#title' => 'Requirements problem',
+ '#content' => $status_report,
+ );
+ print drupal_render($maintenance_page);
exit();
}
}
diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php
index 9302ab9..d79567c 100644
--- a/core/lib/Drupal/Core/Controller/ExceptionController.php
+++ b/core/lib/Drupal/Core/Controller/ExceptionController.php
@@ -7,7 +7,6 @@
namespace Drupal\Core\Controller;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Page\HtmlPageRendererInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@@ -354,8 +353,15 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
drupal_set_message($message, $class, TRUE);
}
- $content = t('The website has encountered an error. Please try again later.');
- $output = DefaultHtmlPageRenderer::renderPage($content, t('Error'));
+ $page_content = array(
+ '#theme' => 'maintenance_page',
+ '#content' => t('The website has encountered an error. Please try again later.'),
+ '#page' => array(
+ '#title' => t('Error'),
+ ),
+ );
+
+ $output = drupal_render($page_content);
$response = new Response($output);
$response->setStatusCode(500, '500 Service unavailable (with message)');
diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
index 93501d0..93bfb42 100644
--- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
@@ -7,8 +7,6 @@
namespace Drupal\Core\EventSubscriber;
-use Drupal\Component\Utility\String;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelEvents;
@@ -46,10 +44,14 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
if ($request->attributes->get('_maintenance') != MENU_SITE_ONLINE && !($response instanceof RedirectResponse)) {
// Deliver the 503 page.
drupal_maintenance_theme();
- $content = filter_xss_admin(String::format(\Drupal::config('system.maintenance')->get('message'), array(
- '@site' => \Drupal::config('system.site')->get('name'),
- )));
- $content = DefaultHtmlPageRenderer::renderPage($content, t('Site under maintenance'));
+ $maintenance_page = array(
+ '#theme' => 'maintenance_page',
+ '#title' => t('Site under maintenance'),
+ '#content' => filter_xss_admin(
+ t(\Drupal::config('system.maintenance')->get('message'), array('@site' => \Drupal::config('system.site')->get('name')))
+ ),
+ );
+ $content = drupal_render($maintenance_page);
$response = new Response('Service unavailable', 503);
$response->setContent($content);
$event->setResponse($response);
diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
index 4358ead..821d42d 100644
--- a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
+++ b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php
@@ -23,87 +23,4 @@ class DefaultHtmlPageRenderer implements HtmlPageRendererInterface {
return drupal_render($render);
}
- /**
- * Renders a page using a custom page theme hook and optional region content.
- *
- * Temporary shim to facilitate modernization progress for special front
- * contollers (install.php, update.php, authorize.php), maintenance mode, and
- * the exception handler.
- *
- * Do NOT use this method in your code. This method will be removed as soon
- * as architecturally possible.
- *
- * This is functionally very similar to DefaultHtmlFragmentRenderer::render()
- * but with the following important differences:
- *
- * - drupal_prepare_page() and hook_page_build() cannot be invoked on the
- * maintenance and install pages, since possibly enabled page layout/block
- * modules would replace the main page content with configured region
- * content.
- * - This function composes a complete page render array including a page
- * template theme suggestion (as opposed to the main page content only).
- * - The render cache and cache tags is skipped.
- *
- * @param array|string $main
- * A render array or string containing the main page content.
- * @param string $title
- * (optional) The page title.
- * @param string $theme
- * (optional) The theme hook to use for rendering the page. Defaults to
- * 'maintenance'. The given value will be appended with '_page' to compose
- * the #theme property for #type 'page' currently; e.g., 'maintenance'
- * becomes 'maintenance_page'. Ultimately this parameter will be converted
- * into a page template theme suggestion; i.e., 'page__$theme'.
- * @param array $regions
- * (optional) Additional region content to add to the page. The given array
- * is added to the page render array, so this parameter may also be used to
- * pass e.g. the #show_messages property for #type 'page'.
- *
- * @return string
- * The rendered HTML page.
- *
- * @internal
- */
- public static function renderPage($main, $title = '', $theme = 'maintenance', array $regions = array()) {
- // Automatically convert the main page content into a render array.
- if (!is_array($main)) {
- $main = array('#markup' => $main);
- }
- $page = new HtmlPage('', array(), $title);
- $page_array = array(
- '#type' => 'page',
- // @todo Change into theme suggestions "page__$theme".
- '#theme' => $theme . '_page',
- '#title' => $title,
- 'content' => array(
- 'system_main' => $main,
- ),
- );
- // Append region content.
- $page_array += $regions;
- // Add default properties.
- $page_array += element_info('page');
-
- // hook_page_build() cannot be invoked on the maintenance and install pages,
- // because the application is in an unknown or special state.
- // In particular on the install page, invoking hook_page_build() directly
- // after e.g. Block module has been installed would *replace* the installer
- // output with the configured blocks of the installer theme (loaded from
- // default configuration of the installation profile).
-
- // Allow modules and themes to alter the page render array.
- // This allows e.g. themes to attach custom libraries.
- \Drupal::moduleHandler()->alter('page', $page_array);
-
- // @todo Move preparePage() before alter() above, so $page_array['#page'] is
- // available in hook_page_alter(), so that HTML attributes can be altered.
- $page = \Drupal::service('html_fragment_renderer')->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));
-
- return \Drupal::service('html_page_renderer')->render($page);
- }
-
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
index ef76a07..001b807 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
@@ -8,6 +8,10 @@
namespace Drupal\system\Tests\Common;
use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\UrlHelper;
+use Drupal\Component\Utility\Xss;
+use Drupal\Core\Language\Language;
+use Drupal\Core\Template\Attribute;
use Drupal\simpletest\DrupalUnitTestBase;
/**
@@ -40,72 +44,216 @@ class RenderElementTypesTest extends DrupalUnitTestBase {
* Asserts that an array of elements is rendered properly.
*
* @param array $elements
- * The render element array to test.
- * @param string $expected_html
- * The expected markup.
- * @param string $message
- * Assertion message.
+ * An array of associative arrays describing render elements and their
+ * expected markup. Each item in $elements must contain the following:
+ * - 'name': This human readable description will be displayed on the test
+ * results page.
+ * - 'value': This is the render element to test.
+ * - 'expected': This is the expected markup for the element in 'value'.
*/
- protected function assertElements(array $elements, $expected_html, $message) {
- $actual_html = drupal_render($elements);
+ function assertElements($elements) {
+ foreach($elements as $element) {
+ // More complicated "expected" strings may contain placeholders.
+ if (!empty($element['placeholders'])) {
+ $element['expected'] = String::format($element['expected'], $element['placeholders']);
+ }
- $out = '<table><tr>';
- $out .= '<td valign="top"><pre>' . String::checkPlain($expected_html) . '</pre></td>';
- $out .= '<td valign="top"><pre>' . String::checkPlain($actual_html) . '</pre></td>';
- $out .= '</tr></table>';
- $this->verbose($out);
+ // We don't care about whitespace for the sake of comparing markup.
+ $value = new \DOMDocument();
+ $value->preserveWhiteSpace = FALSE;
+ $value->loadXML(drupal_render($element['value']));
- $this->assertIdentical($actual_html, $expected_html, String::checkPlain($message));
+ $expected = new \DOMDocument();
+ $expected->preserveWhiteSpace = FALSE;
+ $expected->loadXML($element['expected']);
+
+ $message = isset($element['name']) ? '"' . $element['name'] . '" input rendered correctly by drupal_render().' : NULL;
+ $this->assertIdentical($value->saveXML(), $expected->saveXML(), $message);
+ }
}
/**
* Tests system #type 'container'.
*/
function testContainer() {
- // Basic container with no attributes.
- $this->assertElements(array(
- '#type' => 'container',
- '#markup' => 'foo',
- ), "<div>foo</div>\n", "#type 'container' with no HTML attributes");
-
- // Container with a class.
- $this->assertElements(array(
- '#type' => 'container',
- '#markup' => 'foo',
- '#attributes' => array(
- 'class' => 'bar',
+ $elements = array(
+ // Basic container with no attributes.
+ array(
+ 'name' => "#type 'container' with no HTML attributes",
+ 'value' => array(
+ '#type' => 'container',
+ '#markup' => 'foo',
+ ),
+ 'expected' => '<div>foo</div>' . "\n",
),
- ), '<div class="bar">foo</div>' . "\n", "#type 'container' with a class HTML attribute");
-
- // Container with children.
- $this->assertElements(array(
- '#type' => 'container',
- 'child' => array(
- '#markup' => 'foo',
+ // Container with a class.
+ array(
+ 'name' => "#type 'container' with a class HTML attribute",
+ 'value' => array(
+ '#type' => 'container',
+ '#markup' => 'foo',
+ '#attributes' => array(
+ 'class' => 'bar',
+ ),
+ ),
+ 'expected' => '<div class="bar">foo</div>' . "\n",
),
- ), "<div>foo</div>\n", "#type 'container' with child elements");
+ // Container with children.
+ array(
+ 'name' => "#type 'container' with child elements",
+ 'value' => array(
+ '#type' => 'container',
+ 'child' => array(
+ '#markup' => 'foo',
+ ),
+ ),
+ 'expected' => '<div>foo</div>' . "\n",
+ ),
+ );
+
+ $this->assertElements($elements);
}
/**
* Tests system #type 'html_tag'.
*/
function testHtmlTag() {
- // Test auto-closure meta tag generation.
- $this->assertElements(array(
- '#type' => 'html_tag',
- '#tag' => 'meta',
- '#attributes' => array(
- 'name' => 'description',
- 'content' => 'Drupal test',
+ $elements = array(
+ // Test auto-closure meta tag generation.
+ array(
+ 'name' => "#type 'html_tag' auto-closure meta tag generation",
+ 'value' => array(
+ '#type' => 'html_tag',
+ '#tag' => 'meta',
+ '#attributes' => array(
+ 'name' => 'description',
+ 'content' => 'Drupal test',
+ ),
+ ),
+ 'expected' => '<meta name="description" content="Drupal test" />' . "\n",
+ ),
+ // Test title tag generation.
+ array(
+ 'name' => "#type 'html_tag' title tag generation",
+ 'value' => array(
+ '#type' => 'html_tag',
+ '#tag' => 'title',
+ '#value' => 'title test',
+ ),
+ 'expected' => '<title>title test</title>' . "\n",
+ ),
+ );
+
+ $this->assertElements($elements);
+ }
+
+ /**
+ * Tests common #theme 'maintenance_page'.
+ */
+ function testMaintenancePage() {
+ // We need to simulate a lot of what would happen in the preprocess, or
+ // there's no way to make these tests portable.
+
+ // HTML element attributes.
+ $html_attributes = new Attribute;
+ $language_interface = \Drupal::service('language_manager')->getCurrentLanguage();
+ $html_attributes['lang'] = $language_interface->id;
+ $html_attributes['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
+
+ $site_config = \Drupal::config('system.site');
+
+ // Add favicon.
+ $favicon = theme_get_setting('favicon.url');
+ $type = theme_get_setting('favicon.mimetype');
+ drupal_add_html_head_link(array('rel' => 'shortcut icon', 'href' => UrlHelper::stripDangerousProtocols($favicon), 'type' => $type));
+
+ // Build CSS links.
+ drupal_static_reset('_drupal_add_css');
+ $default_css = array(
+ '#attached' => array(
+ 'library' => array(
+ 'core/normalize',
+ 'system/maintenance',
+ ),
),
- ), '<meta name="description" content="Drupal test" />' . "\n", "#type 'html_tag' auto-closure meta tag generation");
-
- // Test title tag generation.
- $this->assertElements(array(
- '#type' => 'html_tag',
- '#tag' => 'title',
- '#value' => 'title test',
- ), "<title>title test</title>\n", "#type 'html_tag' title tag generation");
+ );
+ drupal_render($default_css);
+ $css = _drupal_add_css();
+
+ // Simulate the expected output of a "vanilla" maintenance page.
+ $expected = <<<EOT
+<!DOCTYPE html>
+<html!html_attributes>
+ <head>
+ !head
+ <title>!head_title</title>
+ !styles
+ !scripts
+ </head>
+ <body class="!attributes.class">
+ <div class="l-container">
+ <header role="banner">
+ <a href="!front_page" title="Home" rel="home">
+ <img src="!logo" alt="Home"/>
+ </a>
+ <div class="name-and-slogan">
+ <h1 class="site-name">
+ <a href="!front_page" title="Home" rel="home">!site_name</a>
+ </h1>
+ </div>
+ </header>
+ <main role="main">
+ !title
+ !content
+ </main>
+ </div>
+ </body>
+</html>
+EOT;
+
+ $placeholders = array(
+ '!html_attributes' => $html_attributes->__toString(),
+ '!head' => drupal_get_html_head(),
+ '!head_title' => $site_config->get('name'),
+ '!styles' => drupal_get_css($css),
+ '!scripts' => drupal_get_js(),
+ '!attributes.class' => 'maintenance-page in-maintenance no-sidebars',
+ '!front_page' => url(),
+ '!logo' => theme_get_setting('logo.url'),
+ '!site_name' => $site_config->get('name'),
+ '!title' => '',
+ '!content' => '<span>foo</span>',
+ );
+
+ // We have to reset drupal_add_css between each test.
+ drupal_static_reset();
+
+ // Test basic string for maintenance page content.
+ // No page title is set, so it should default to the site name.
+ $elements = array(
+ array(
+ 'name' => "#theme 'maintenance_page' with content of <span>foo</span>",
+ 'value' => array(
+ '#theme' => 'maintenance_page',
+ '#content' => '<span>foo</span>',
+ '#show_messages' => FALSE,
+ ),
+ 'expected' => $expected,
+ 'placeholders' => $placeholders,
+ ),
+ );
+ $this->assertElements($elements);
+
+ // Test render array for maintenance page content.
+ drupal_static_reset();
+ $elements[0]['name'] = "#theme 'maintenance_page' with content as a render array";
+ $elements[0]['value']['#content'] = array('#markup' => '<span>foo</span>');
+ // Testing with a page title, which should be combined with the site name.
+ $title = t('A non-empty title');
+ $elements[0]['value']['#page']['#title'] = $title;
+ $elements[0]['placeholders']['!title'] = '<h1>' . $title . '</h1>';
+ $elements[0]['placeholders']['!head_title'] = strip_tags($title) . ' | ' . String::checkPlain($site_config->get('name'));
+ $this->assertElements($elements);
}
}
diff --git a/core/modules/system/templates/install-page.html.twig b/core/modules/system/templates/install-page.html.twig
index ad1c04c..031013e 100644
--- a/core/modules/system/templates/install-page.html.twig
+++ b/core/modules/system/templates/install-page.html.twig
@@ -3,14 +3,24 @@
* @file
* Default theme implementation to display a Drupal installation page.
*
- * All available variables are mirrored in page.html.twig.
- * Some may be blank but they are provided for consistency.
+ * All the available variables are mirrored in html.html.twig and
+ * page.html.twig. Some may be blank but they are provided for consistency.
*
* @see template_preprocess_install_page()
*
* @ingroup themeable
*/
#}
+<!DOCTYPE html>
+<html{{ html_attributes }}>
+<head>
+ {{ head }}
+ <title>{{ head_title }}</title>
+ {{ styles }}
+ {{ scripts }}
+</head>
+<body class="{{ attributes.class }}">
+
<div class="l-container">
<header role="banner">
@@ -31,25 +41,26 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
- {{ page.content }}
+ {{ content }}
</main>
- {% if page.sidebar_first %}
+ {% if sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
- {{ page.sidebar_first }}
+ {{ sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
- {% if page.sidebar_second %}
+ {% if sidebar_second %}
<aside class="l-sidebar-second" role="complementary">
- {{ page.sidebar_second }}
+ {{ sidebar_second }}
</aside>{# /.l-sidebar-second #}
{% endif %}
- {% if page.footer %}
+ {% if footer %}
<footer role="contentinfo">
- {{ page.footer }}
+ {{ footer }}
</footer>
{% endif %}
- </div>{# /.l-container #}
+</body>
+</html>
diff --git a/core/modules/system/templates/maintenance-page.html.twig b/core/modules/system/templates/maintenance-page.html.twig
index 3b5a59e..b5275c7 100644
--- a/core/modules/system/templates/maintenance-page.html.twig
+++ b/core/modules/system/templates/maintenance-page.html.twig
@@ -3,7 +3,7 @@
* @file
* Default theme implementation to display a single Drupal page while offline.
*
- * All available variables are mirrored in page.html.twig.
+ * All of the available variables are mirrored in html.html.twig.
* Some may be blank but they are provided for consistency.
*
* @see template_preprocess_maintenance_page()
@@ -11,6 +11,16 @@
* @ingroup themeable
*/
#}
+<!DOCTYPE html>
+<html{{ html_attributes }}>
+<head>
+ {{ head }}
+ <title>{{ head_title }}</title>
+ {{ styles }}
+ {{ scripts }}
+</head>
+<body class="{{ attributes.class }}">
+
<div class="l-container">
<header role="banner">
@@ -43,7 +53,7 @@
{{ messages }}
- {{ page.content }}
+ {{ content }}
</main>
{% if page.sidebar_first %}
@@ -65,3 +75,6 @@
{% endif %}
</div>{# /.l-container #}
+
+</body>
+</html>
diff --git a/core/themes/bartik/bartik.theme b/core/themes/bartik/bartik.theme
index 414f5af..6b99f45 100644
--- a/core/themes/bartik/bartik.theme
+++ b/core/themes/bartik/bartik.theme
@@ -5,6 +5,7 @@
* Functions to support theming in the Bartik theme.
*/
+use Drupal\Core\Template\RenderWrapper;
use Drupal\Core\Template\Attribute;
/**
@@ -94,6 +95,7 @@ function bartik_preprocess_maintenance_page(&$variables) {
if (!$variables['db_is_active']) {
$variables['site_name'] = '';
}
+ $variables['styles'] = new RenderWrapper('drupal_get_css');
// Normally we could attach libraries via hook_page_alter(), but when the
// database is inactive it's not called so we add them here.
$libraries = array(
@@ -103,7 +105,6 @@ function bartik_preprocess_maintenance_page(&$variables) {
),
),
);
- drupal_render($libraries);
// Set the options that apply to both page and maintenance page.
_bartik_process_page($variables);
diff --git a/core/themes/bartik/templates/maintenance-page.html.twig b/core/themes/bartik/templates/maintenance-page.html.twig
index 5de50cc..45cd12c 100644
--- a/core/themes/bartik/templates/maintenance-page.html.twig
+++ b/core/themes/bartik/templates/maintenance-page.html.twig
@@ -3,11 +3,25 @@
* @file
* Bartik's theme implementation to display a single Drupal page while offline.
*
- * All available variables are mirrored in page.html.twig.
+ * All of the available variables are mirrored in html.html.twig.
*
* @see template_preprocess_maintenance_page()
*/
#}
+<!DOCTYPE html>
+<html{{ html_attributes }}>
+<head>
+ {{ head }}
+ <title>{{ head_title }}</title>
+ {{ styles }}
+ {{ scripts }}
+</head>
+<body class="{{ attributes.class }}"{{ attributes }}>
+
+ <a href="#main-content" class="visually-hidden focusable skip-link">
+ {{ 'Skip to main content'|t }}
+ </a>
+
<div id="page-wrapper"><div id="page">
<header id="header" role="banner"><div class="section clearfix">
@@ -33,7 +47,7 @@
<main id="content" class="column" role="main"><section class="section">
<a id="main-content"></a>
{% if title %}<h1 class="title" id="page-title">{{ title }}</h1>{% endif %}
- {{ page.content }}
+ {{ content }}
{% if messages %}
<div id="messages"><div class="section clearfix">
{{ messages }}
@@ -43,3 +57,6 @@
</div></div> <!-- /#main, /#main-wrapper -->
</div></div> <!-- /#page, /#page-wrapper -->
+
+</body>
+</html>
diff --git a/core/themes/seven/seven.theme b/core/themes/seven/seven.theme
index 4aa6e5a..c0a5a08 100644
--- a/core/themes/seven/seven.theme
+++ b/core/themes/seven/seven.theme
@@ -5,6 +5,7 @@
* Functions to support theming in the Seven theme.
*/
+use Drupal\Core\Template\RenderWrapper;
use Drupal\Component\Utility\String;
/**
@@ -268,11 +269,8 @@ function seven_element_info_alter(&$type) {
* Implements hook_preprocess_install_page().
*/
function seven_preprocess_install_page(&$variables) {
- $page_object = $variables['page']['#page'];
- $attributes = $page_object->getHtmlAttributes();
- $classes = $attributes['class'];
- $classes[] = 'install-background';
- $attributes['class'] = $classes;
+ $variables['styles'] = new RenderWrapper('drupal_get_css');
+ $variables['scripts'] = new RenderWrapper('drupal_get_js');
// Normally we could attach libraries via hook_page_alter(), but when the
// database is inactive it's not called so we add them here.
@@ -291,12 +289,8 @@ function seven_preprocess_install_page(&$variables) {
* Implements hook_preprocess_maintenance_page().
*/
function seven_preprocess_maintenance_page(&$variables) {
- $page_object = $variables['page']['#page'];
- $attributes = $page_object->getHtmlAttributes();
- $classes = $attributes['class'];
- $classes[] = 'maintenance-background';
- $attributes['class'] = $classes;
-
+ $variables['styles'] = new RenderWrapper('drupal_get_css');
+ $variables['scripts'] = new RenderWrapper('drupal_get_js');
// // Normally we could attach libraries via hook_page_alter(), but when the
// // database is inactive it's not called so we add them here.
$libraries = array(
diff --git a/core/themes/seven/templates/install-page.html.twig b/core/themes/seven/templates/install-page.html.twig
index f86486e..40f9904 100644
--- a/core/themes/seven/templates/install-page.html.twig
+++ b/core/themes/seven/templates/install-page.html.twig
@@ -3,12 +3,23 @@
* @file
* Seven theme implementation to display a Drupal installation page.
*
- * All available variables are mirrored in page.html.twig.
+ * All the available variables are mirrored in html.html.twig and
+ * page.html.twig.
* Some may be blank but they are provided for consistency.
*
* @see template_preprocess_install_page()
*/
#}
+<!DOCTYPE html>
+<html{{ html_attributes }} class="install-background">
+<head>
+ {{ head }}
+ <title>{{ head_title }}</title>
+ {{ styles }}
+ {{ scripts }}
+</head>
+<body class="{{ attributes.class }}">
+
<div class="l-container">
<header role="banner">
@@ -24,9 +35,9 @@
{% endif %}
</header>
- {% if page.sidebar_first %}
+ {% if sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
- {{ page.sidebar_first }}
+ {{ sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
@@ -35,19 +46,22 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
- {{ page.content }}
+ {{ content }}
</main>
- {% if page.sidebar_second %}
+ {% if sidebar_second %}
<aside class="l-sidebar-second" role="complementary">
- {{ page.sidebar_second }}
+ {{ sidebar_second }}
</aside>{# /.l-sidebar-second #}
{% endif %}
- {% if page.page_bottom %}
+ {% if footer %}
<footer role="contentinfo">
- {{ page.page_bottom }}
+ {{ footer }}
</footer>
{% endif %}
</div>{# /.l-container #}
+
+</body>
+</html>
diff --git a/core/themes/seven/templates/maintenance-page.html.twig b/core/themes/seven/templates/maintenance-page.html.twig
index 9097297..cec60b5 100644
--- a/core/themes/seven/templates/maintenance-page.html.twig
+++ b/core/themes/seven/templates/maintenance-page.html.twig
@@ -3,14 +3,26 @@
* @file
* Seven's theme implementation to display a single Drupal page while offline.
*
- * All available variables are mirrored in page.html.twig.
- * Some may be blank but they are provided for consistency.
+ * All of the available variables are mirrored in html.html.twig.
*
* @see template_preprocess_maintenance_page()
+ * @see seven_preprocess_maintenance_page()
*/
#}
+<!DOCTYPE html>
+<html{{ html_attributes }} class="maintenance-background">
+<head>
+ {{ head }}
+ <title>{{ head_title }}</title>
+ {{ styles }}
+ {{ scripts }}
+</head>
+<body{{ attributes }}>
+
<div class="l-container">
+ {{ page_top }}
+
<header role="banner">
{% if site_name or site_slogan %}
<div class="name-and-slogan">
@@ -24,9 +36,9 @@
{% endif %}
</header>
- {% if page.sidebar_first %}
+ {% if sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
- {{ page.sidebar_first }}
+ {{ sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
@@ -35,13 +47,16 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
- {{ page.content }}
+ {{ content }}
</main>
- {% if page.page_bottom %}
+ {% if footer %}
<footer role="contentinfo">
- {{ page.page_bottom }}
+ {{ footer }}
</footer>
{% endif %}
</div>{# /.l-container #}
+
+</body>
+</html>
diff --git a/core/themes/seven/templates/page.html.twig b/core/themes/seven/templates/page.html.twig
index bbc804f..18b0bc1 100644
--- a/core/themes/seven/templates/page.html.twig
+++ b/core/themes/seven/templates/page.html.twig
@@ -50,13 +50,13 @@
* comment/reply/12345).
*
* Regions:
- * - page.page_top: Items for the header region.
+ * - page.header: Items for the header region.
* - page.highlighted: Items for the highlighted content region.
* - page.help: Dynamic help text, mostly for admin pages.
* - page.content: The main content of the current page.
* - page.sidebar_first: Items for the first sidebar.
* - page.sidebar_second: Items for the second sidebar.
- * - page.page_bottom: Items for the footer region.
+ * - page.footer: Items for the footer region.
*
* @see template_preprocess_page()
* @see seven_preprocess_page()
diff --git a/core/update.php b/core/update.php
index 2c81857..45904a2 100644
--- a/core/update.php
+++ b/core/update.php
@@ -16,7 +16,6 @@
use Drupal\Component\Utility\Settings;
use Drupal\Core\DrupalKernel;
-use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Update\Form\UpdateScriptSelectionForm;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -460,8 +459,18 @@ if (isset($output) && $output) {
}
else {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
- print DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'maintenance', array(
+ $maintenance_page = array(
+ '#theme' => 'maintenance_page',
+ // $output has to be rendered here, because the maintenance page template
+ // is not wrapped into the html template, which means that any #attached
+ // libraries in $output will not be loaded, because the wrapping HTML has
+ // been printed already.
+ '#content' => drupal_render($output),
'#show_messages' => !$progress_page,
- ));
+ );
+ if (isset($output['#title'])) {
+ $maintenance_page['#page']['#title'] = $output['#title'];
+ }
+ print drupal_render($maintenance_page);
}
}