Issue #2218039 by sun, dawehner: Render the maintenance/install page like any other HTML page.

8.0.x
Alex Pott 2014-04-03 14:59:23 +01:00
parent 719b36a492
commit 10b0389066
20 changed files with 254 additions and 513 deletions

View File

@ -21,6 +21,7 @@
*/
use Drupal\Component\Utility\Settings;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
// Change the directory to the Drupal root.
chdir('..');
@ -155,13 +156,7 @@ else {
if (!empty($output)) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
$maintenance_page = array(
'#page' => array(
'#title' => $page_title,
),
'#theme' => 'maintenance_page',
'#content' => $output,
print DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array(
'#show_messages' => $show_messages,
);
print drupal_render($maintenance_page);
));
}

View File

@ -16,6 +16,7 @@
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;
@ -121,18 +122,14 @@ 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 = drupal_render($fallback);
$fallback = DefaultHtmlPageRenderer::renderPage($fallback, $current_set['title'], 'maintenance', array(
'#show_messages' => FALSE,
));
list($fallback) = explode('<!--partial-->', $fallback);
print $fallback;

View File

@ -5,6 +5,7 @@
* Functions for error handling.
*/
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Utility\Error;
use Drupal\Component\Utility\String;
use Symfony\Component\HttpFoundation\Response;
@ -231,12 +232,7 @@ function _drupal_log_error($error, $fatal = FALSE) {
install_display_output($output, $GLOBALS['install_state']);
}
else {
$output = array(
'#theme' => 'maintenance_page',
'#title' => 'Error',
'#content' => $message,
);
$output = drupal_render($output);
$output = DefaultHtmlPageRenderer::renderPage($message, 'Error');
}
$response = new Response($output, 500);

View File

@ -14,6 +14,7 @@ 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;
@ -903,6 +904,7 @@ 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.
@ -912,20 +914,10 @@ function install_display_output($output, $install_state) {
'#items' => install_tasks_to_display($install_state),
'#active' => $active_task,
);
drupal_add_region_content('sidebar_first', drupal_render($task_list));
$regions['sidebar_first'] = $task_list;
}
$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);
print DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'install', $regions);
exit;
}

View File

@ -2070,16 +2070,26 @@ 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')) : '');
$variables['tabs'] = menu_local_tabs();
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'] = '';
}
// Pass the main menu and secondary menu to the template as render arrays.
if (!empty($variables['main_menu'])) {
@ -2120,10 +2130,12 @@ 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()
$variables['breadcrumb'] = array(
'#theme' => 'breadcrumb',
'#breadcrumb' => \Drupal::service('breadcrumb')->build(\Drupal::request()->attributes->all()),
);
if (!defined('MAINTENANCE_MODE')) {
$variables['breadcrumb'] = array(
'#theme' => 'breadcrumb',
'#breadcrumb' => \Drupal::service('breadcrumb')->build(\Drupal::request()->attributes->all()),
);
}
}
/**
@ -2201,12 +2213,6 @@ 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.
@ -2214,117 +2220,29 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
* @see system_page_build()
*/
function template_preprocess_maintenance_page(&$variables) {
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
// @todo Rename the templates to page--maintenance + page--install.
template_preprocess_page($variables);
// 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);
}
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';
$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']) {
$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'];
$classes[] = 'db-offline';
}
$attributes['class'] = $classes;
$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'];
}
// @see system_page_build()
$attached = array(
'#attached' => array(
'library' => array(
'core/normalize',
'system/maintenance',
),
),
);
drupal_render($attached);
}
/**
@ -2332,20 +2250,21 @@ 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);
$variables['attributes']['class'][] = 'install-page';
$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());
@ -2643,11 +2562,11 @@ function drupal_common_theme() {
),
// From theme.maintenance.inc.
'maintenance_page' => array(
'variables' => array('content' => NULL, 'show_messages' => TRUE, 'page' => array()),
'render element' => 'page',
'template' => 'maintenance-page',
),
'install_page' => array(
'variables' => array('content' => NULL, 'show_messages' => TRUE, 'page' => array()),
'render element' => 'page',
'template' => 'install-page',
),
'task_list' => array(

View File

@ -31,6 +31,7 @@ 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.
@ -43,13 +44,6 @@ 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 {

View File

@ -14,6 +14,7 @@ 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;
@ -148,19 +149,13 @@ 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 = array(
$status_report = array(
'#theme' => 'status_report',
'#requirements' => $requirements,
);
$status_report = drupal_render($status);
$status_report .= 'Check the messages and <a href="' . check_url(drupal_requirements_url($severity)) . '">try again</a>.';
$status_report['#suffix'] = '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');
$maintenance_page = array(
'#theme' => 'maintenance_page',
'#title' => 'Requirements problem',
'#content' => $status_report,
);
print drupal_render($maintenance_page);
print DefaultHtmlPageRenderer::renderPage($status_report, 'Requirements problem');
exit();
}
}

View File

@ -7,6 +7,7 @@
namespace Drupal\Core\Controller;
use Drupal\Core\Page\DefaultHtmlPageRenderer;
use Drupal\Core\Page\HtmlPageRendererInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@ -353,15 +354,8 @@ class ExceptionController extends HtmlControllerBase implements ContainerAwareIn
drupal_set_message($message, $class, TRUE);
}
$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);
$content = t('The website has encountered an error. Please try again later.');
$output = DefaultHtmlPageRenderer::renderPage($content, t('Error'));
$response = new Response($output);
$response->setStatusCode(500, '500 Service unavailable (with message)');

View File

@ -7,6 +7,8 @@
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;
@ -44,14 +46,10 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
if ($request->attributes->get('_maintenance') != MENU_SITE_ONLINE && !($response instanceof RedirectResponse)) {
// Deliver the 503 page.
drupal_maintenance_theme();
$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);
$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'));
$response = new Response('Service unavailable', 503);
$response->setContent($content);
$event->setResponse($response);

View File

@ -23,4 +23,87 @@ 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);
}
}

View File

@ -8,10 +8,6 @@
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;
/**
@ -44,216 +40,72 @@ class RenderElementTypesTest extends DrupalUnitTestBase {
* Asserts that an array of elements is rendered properly.
*
* @param array $elements
* 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'.
* The render element array to test.
* @param string $expected_html
* The expected markup.
* @param string $message
* Assertion message.
*/
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']);
}
protected function assertElements(array $elements, $expected_html, $message) {
$actual_html = drupal_render($elements);
// We don't care about whitespace for the sake of comparing markup.
$value = new \DOMDocument();
$value->preserveWhiteSpace = FALSE;
$value->loadXML(drupal_render($element['value']));
$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);
$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);
}
$this->assertIdentical($actual_html, $expected_html, String::checkPlain($message));
}
/**
* Tests system #type 'container'.
*/
function testContainer() {
$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",
),
// 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",
),
// Container with children.
array(
'name' => "#type 'container' with child elements",
'value' => array(
'#type' => 'container',
'child' => array(
'#markup' => 'foo',
),
),
'expected' => '<div>foo</div>' . "\n",
),
);
// Basic container with no attributes.
$this->assertElements(array(
'#type' => 'container',
'#markup' => 'foo',
), "<div>foo</div>\n", "#type 'container' with no HTML attributes");
$this->assertElements($elements);
// Container with a class.
$this->assertElements(array(
'#type' => 'container',
'#markup' => 'foo',
'#attributes' => array(
'class' => 'bar',
),
), '<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',
),
), "<div>foo</div>\n", "#type 'container' with child elements");
}
/**
* Tests system #type 'html_tag'.
*/
function testHtmlTag() {
$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 auto-closure meta tag generation.
$this->assertElements(array(
'#type' => 'html_tag',
'#tag' => 'meta',
'#attributes' => array(
'name' => 'description',
'content' => 'Drupal test',
),
// 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",
),
);
), '<meta name="description" content="Drupal test" />' . "\n", "#type 'html_tag' auto-closure meta tag generation");
$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',
),
),
);
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);
// 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");
}
}

View File

@ -3,24 +3,14 @@
* @file
* Default theme implementation to display a Drupal installation page.
*
* All the available variables are mirrored in html.html.twig and
* page.html.twig. Some may be blank but they are provided for consistency.
* All available variables are mirrored in 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">
@ -41,26 +31,25 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
{{ content }}
{{ page.content }}
</main>
{% if sidebar_first %}
{% if page.sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
{{ sidebar_first }}
{{ page.sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
{% if sidebar_second %}
{% if page.sidebar_second %}
<aside class="l-sidebar-second" role="complementary">
{{ sidebar_second }}
{{ page.sidebar_second }}
</aside>{# /.l-sidebar-second #}
{% endif %}
{% if footer %}
{% if page.footer %}
<footer role="contentinfo">
{{ footer }}
{{ page.footer }}
</footer>
{% endif %}
</body>
</html>
</div>{# /.l-container #}

View File

@ -3,7 +3,7 @@
* @file
* Default theme implementation to display a single Drupal page while offline.
*
* All of the available variables are mirrored in html.html.twig.
* All available variables are mirrored in page.html.twig.
* Some may be blank but they are provided for consistency.
*
* @see template_preprocess_maintenance_page()
@ -11,16 +11,6 @@
* @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">
@ -53,7 +43,7 @@
{{ messages }}
{{ content }}
{{ page.content }}
</main>
{% if page.sidebar_first %}
@ -75,6 +65,3 @@
{% endif %}
</div>{# /.l-container #}
</body>
</html>

View File

@ -5,7 +5,6 @@
* Functions to support theming in the Bartik theme.
*/
use Drupal\Core\Template\RenderWrapper;
use Drupal\Core\Template\Attribute;
/**
@ -95,7 +94,6 @@ 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(
@ -105,6 +103,7 @@ function bartik_preprocess_maintenance_page(&$variables) {
),
),
);
drupal_render($libraries);
// Set the options that apply to both page and maintenance page.
_bartik_process_page($variables);

View File

@ -3,25 +3,11 @@
* @file
* Bartik's theme implementation to display a single Drupal page while offline.
*
* All of the available variables are mirrored in html.html.twig.
* All available variables are mirrored in page.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">
@ -47,7 +33,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 %}
{{ content }}
{{ page.content }}
{% if messages %}
<div id="messages"><div class="section clearfix">
{{ messages }}
@ -57,6 +43,3 @@
</div></div> <!-- /#main, /#main-wrapper -->
</div></div> <!-- /#page, /#page-wrapper -->
</body>
</html>

View File

@ -5,7 +5,6 @@
* Functions to support theming in the Seven theme.
*/
use Drupal\Core\Template\RenderWrapper;
use Drupal\Component\Utility\String;
/**
@ -269,8 +268,11 @@ function seven_element_info_alter(&$type) {
* Implements hook_preprocess_install_page().
*/
function seven_preprocess_install_page(&$variables) {
$variables['styles'] = new RenderWrapper('drupal_get_css');
$variables['scripts'] = new RenderWrapper('drupal_get_js');
$page_object = $variables['page']['#page'];
$attributes = $page_object->getHtmlAttributes();
$classes = $attributes['class'];
$classes[] = 'install-background';
$attributes['class'] = $classes;
// Normally we could attach libraries via hook_page_alter(), but when the
// database is inactive it's not called so we add them here.
@ -289,8 +291,12 @@ function seven_preprocess_install_page(&$variables) {
* Implements hook_preprocess_maintenance_page().
*/
function seven_preprocess_maintenance_page(&$variables) {
$variables['styles'] = new RenderWrapper('drupal_get_css');
$variables['scripts'] = new RenderWrapper('drupal_get_js');
$page_object = $variables['page']['#page'];
$attributes = $page_object->getHtmlAttributes();
$classes = $attributes['class'];
$classes[] = 'maintenance-background';
$attributes['class'] = $classes;
// // 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(

View File

@ -3,23 +3,12 @@
* @file
* Seven theme implementation to display a Drupal installation page.
*
* All the available variables are mirrored in html.html.twig and
* page.html.twig.
* All available variables are mirrored in 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">
@ -35,9 +24,9 @@
{% endif %}
</header>
{% if sidebar_first %}
{% if page.sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
{{ sidebar_first }}
{{ page.sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
@ -46,22 +35,19 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
{{ content }}
{{ page.content }}
</main>
{% if sidebar_second %}
{% if page.sidebar_second %}
<aside class="l-sidebar-second" role="complementary">
{{ sidebar_second }}
{{ page.sidebar_second }}
</aside>{# /.l-sidebar-second #}
{% endif %}
{% if footer %}
{% if page.page_bottom %}
<footer role="contentinfo">
{{ footer }}
{{ page.page_bottom }}
</footer>
{% endif %}
</div>{# /.l-container #}
</body>
</html>

View File

@ -3,26 +3,14 @@
* @file
* Seven's theme implementation to display a single Drupal page while offline.
*
* All of the available variables are mirrored in html.html.twig.
* All available variables are mirrored in page.html.twig.
* Some may be blank but they are provided for consistency.
*
* @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">
@ -36,9 +24,9 @@
{% endif %}
</header>
{% if sidebar_first %}
{% if page.sidebar_first %}
<aside class="l-sidebar-first" role="complementary">
{{ sidebar_first }}
{{ page.sidebar_first }}
</aside>{# /.l-sidebar-first #}
{% endif %}
@ -47,16 +35,13 @@
<h1>{{ title }}</h1>
{% endif %}
{{ messages }}
{{ content }}
{{ page.content }}
</main>
{% if footer %}
{% if page.page_bottom %}
<footer role="contentinfo">
{{ footer }}
{{ page.page_bottom }}
</footer>
{% endif %}
</div>{# /.l-container #}
</body>
</html>

View File

@ -50,13 +50,13 @@
* comment/reply/12345).
*
* Regions:
* - page.header: Items for the header region.
* - page.page_top: 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.footer: Items for the footer region.
* - page.page_bottom: Items for the footer region.
*
* @see template_preprocess_page()
* @see seven_preprocess_page()

View File

@ -16,6 +16,7 @@
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;
@ -459,18 +460,8 @@ if (isset($output) && $output) {
}
else {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
$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),
print DefaultHtmlPageRenderer::renderPage($output, $output['#title'], 'maintenance', array(
'#show_messages' => !$progress_page,
);
if (isset($output['#title'])) {
$maintenance_page['#page']['#title'] = $output['#title'];
}
print drupal_render($maintenance_page);
));
}
}