diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index a8da6fcb24b087c0ae82e30a186694ffd6c5a77a..5345d59260a8edaa84820eb32f939632d38eddd9 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -369,7 +369,6 @@ function conf_init() { */ function drupal_get_filename($type, $name, $filename = NULL) { static $files = array(); - global $active_db; if (!isset($files[$type])) { $files[$type] = array(); @@ -385,7 +384,7 @@ function drupal_get_filename($type, $name, $filename = NULL) { // the database. This is required because this function is called both // before we have a database connection (i.e. during installation) and // when a database connection fails. - elseif ($active_db && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { + elseif (db_is_active() && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { $files[$type][$name] = $file; } else { @@ -971,35 +970,16 @@ function _drupal_bootstrap($phase) { } /** - * Enables use of the theme system without requiring database access. Since - * there is not database access no theme will be enabled and the default - * themeable functions will be called. Some themeable functions can not be used - * without the full Drupal API loaded. For example, theme_page() is - * unavailable and theme_maintenance_page() must be used in its place. + * Enables use of the theme system without requiring database access. + * + * Loads and initializes the theme system for site installs, updates and when + * the site is in off-line mode. This also applies when the database fails. + * + * @see _drupal_maintenance_theme() */ function drupal_maintenance_theme() { - global $theme; - require_once './includes/path.inc'; - require_once './includes/theme.inc'; - require_once './includes/common.inc'; - require_once './includes/unicode.inc'; - require_once './includes/file.inc'; - require_once './modules/filter/filter.module'; - unicode_check(); - drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module'); - drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module'); - drupal_add_css(drupal_get_path('module', 'system') .'/system-menus.css', 'module'); - $theme = ''; - - // Special case registry of theme functions used by the installer - $themes = drupal_common_themes(); - foreach ($themes as $hook => $info) { - if (!isset($info['file']) && !isset($info['function'])) { - $themes[$hook]['function'] = 'theme_'. $hook; - $themes[$hook]['theme path'] = 'misc'; - } - } - _theme_set_registry($themes); + require_once './includes/theme.maintenance.inc'; + _drupal_maintenance_theme(); } /** diff --git a/includes/common.inc b/includes/common.inc index 6455bdb71177be18d8ca215a553314d0538fba43..4af694080e756c12e7e79b5fc2c0c73bcd5a0a51 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2865,7 +2865,7 @@ function element_children($element) { /** * Provide theme registration for themes across .inc files. */ -function drupal_common_themes() { +function drupal_common_theme() { return array( // theme.inc 'placeholder' => array( @@ -2876,6 +2876,10 @@ function drupal_common_themes() { 'template' => 'page', ), 'maintenance_page' => array( + 'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), + 'template' => 'maintenance-page', + ), + 'update_page' => array( 'arguments' => array('content' => NULL, 'show_messages' => TRUE), ), 'install_page' => array( diff --git a/includes/database.inc b/includes/database.inc index 63536e036be7d9106cdf461fb6840f22fef6b68e..917fbb830a9aa9821cee86814d77f04e28c31101 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -163,6 +163,14 @@ function db_set_active($name = 'default') { return array_search($previous_db, $db_conns); } +/** + * Returns a boolean depending on the availability of the database. + */ +function db_is_active() { + global $active_db; + return !empty($active_db); +} + /** * Helper function for db_query(). */ diff --git a/includes/install.inc b/includes/install.inc index f034dda851024ef11cfc46292342d1dcf885f102..04f7939b0c56dc4c82462011ae904e357fc24cb1 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -615,7 +615,6 @@ function st($string, $args = array()) { } require_once './includes/theme.inc'; - $GLOBALS['theme'] = 'theme'; // Transform arguments before inserting them foreach ($args as $key => $value) { switch ($key[0]) { diff --git a/includes/theme.inc b/includes/theme.inc index 89825dba5093620cf3e6c812c1146510e6d8227a..e0e10cafaf924861fba0e1b149c4fa818753f587 100644 --- a/includes/theme.inc +++ b/includes/theme.inc @@ -29,7 +29,7 @@ * Initialize the theme system by loading the theme. */ function init_theme() { - global $theme, $user, $custom_theme, $theme_engine, $theme_key; + global $theme, $user, $custom_theme, $theme_key; // If $theme is already set, assume the others are set, too, and do nothing if (isset($theme)) { @@ -82,8 +82,10 @@ function init_theme() { * the same information as the $theme object. It should be in * 'oldest first' order, meaning the top level of the chain will * be first. + * @param $registry_callback + * The callback to invoke to set the theme registry. */ -function _init_theme($theme, $base_theme = array()) { +function _init_theme($theme, $base_theme = array(), $registry_callback = '_theme_load_registry') { global $theme_info, $base_theme_info, $theme_engine, $theme_path; $theme_info = $theme; $base_theme_info = $base_theme; @@ -174,7 +176,8 @@ function _init_theme($theme, $base_theme = array()) { include_once './'. $theme->owner; } } - _theme_load_registry($theme, $base_theme, $theme_engine); + + $registry_callback($theme, $base_theme, $theme_engine); } /** @@ -394,6 +397,9 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) { /** * Provides a list of currently available themes. * + * If the database is active then it will be retrieved from the database. + * Otherwise it will retrieve a new list. + * * @param $refresh * Whether to reload the list of themes from the database. * @return @@ -408,59 +414,42 @@ function list_themes($refresh = FALSE) { if (empty($list)) { $list = array(); - $result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme'); - while ($theme = db_fetch_object($result)) { - if (file_exists($theme->filename)) { - $theme->info = unserialize($theme->info); - foreach ($theme->info['stylesheets'] as $media => $stylesheets) { - foreach ($stylesheets as $stylesheet => $path) { - if (file_exists($path)) { - $theme->stylesheets[$media][$stylesheet] = $path; - } - } + $themes = array(); + // Extract from the database only when it is available. + if (db_is_active()) { + $result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme'); + while ($theme = db_fetch_object($result)) { + if (file_exists($theme->filename)) { + $theme->info = unserialize($theme->info); + $themes[] = $theme; } - foreach ($theme->info['scripts'] as $script => $path) { + } + } + else { + // When the database is unavailable, scan the installation. + $themes = _system_theme_data(); + } + + foreach ($themes as $theme) { + foreach ($theme->info['stylesheets'] as $media => $stylesheets) { + foreach ($stylesheets as $stylesheet => $path) { if (file_exists($path)) { - $theme->scripts[$script] = $path; + $theme->stylesheets[$media][$stylesheet] = $path; } } - if (isset($theme->info['engine'])) { - $theme->engine = $theme->info['engine']; - } - if (isset($theme->info['base theme'])) { - $theme->base_theme = $theme->info['base theme']; + } + foreach ($theme->info['scripts'] as $script => $path) { + if (file_exists($path)) { + $theme->scripts[$script] = $path; } - $list[$theme->name] = $theme; } - } - } - - return $list; -} - -/** - * Provides a list of currently available theme engines - * - * @param $refresh - * Whether to reload the list of themes from the database. - * @return - * An array of the currently available theme engines. - */ -function list_theme_engines($refresh = FALSE) { - static $list; - - if ($refresh) { - unset($list); - } - - if (!$list) { - $list = array(); - $result = db_query("SELECT * FROM {system} WHERE type = '%s' AND status = %d ORDER BY name", 'theme_engine', '1'); - while ($engine = db_fetch_object($result)) { - if (file_exists($engine->filename)) { - $engine->info = unserialize($engine->info); - $list[$engine->name] = $engine; + if (isset($theme->info['engine'])) { + $theme->engine = $theme->info['engine']; } + if (isset($theme->info['base theme'])) { + $theme->base_theme = $theme->info['base theme']; + } + $list[$theme->name] = $theme; } } @@ -1028,117 +1017,6 @@ function theme_placeholder($text) { return '<em>'. check_plain($text) .'</em>'; } -/** - * Generate a themed maintenance page. - * - * Note: this function is not themeable. - * - * @param $content - * The page content to show. - * @param $show_messages - * Whether to output status and error messages. - * FALSE can be useful to postpone the messages to a subsequent page. - */ -function theme_maintenance_page($content, $show_messages = TRUE) { - // Set required headers. - drupal_set_header('Content-Type: text/html; charset=utf-8'); - drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() .'misc/maintenance.css" />'); - drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() . drupal_get_path('module', 'system') .'/defaults.css" />'); - drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() . drupal_get_path('module', 'system') .'/system.css" />'); - drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />'); - - // Prepare variables. - $variables = array( - 'head_title' => strip_tags(drupal_get_title()), - 'head' => drupal_get_html_head(), - 'styles' => '', - 'scripts' => drupal_get_js(), - 'left' => drupal_get_content('left'), - 'right' => drupal_get_content('right'), - 'base_path' => base_path(), - 'path_to_theme' => base_path() .'themes/garland/minnelli', - 'logo' => base_path() .'themes/garland/minnelli/logo.png', - 'site_title' => t('Drupal'), - 'title' => drupal_get_title(), - 'messages' => $show_messages ? theme('status_messages') : '', - 'content' => $content, - ); - - $output = theme_render_template('misc/maintenance.tpl.php', $variables); - - return $output; -} - -/** - * Generate a themed installation page. - * - * Note: this function is not themeable. - * - * @param $content - * The page content to show. - */ -function theme_install_page($content) { - drupal_set_header('Content-Type: text/html; charset=utf-8'); - drupal_add_css('misc/maintenance.css', 'module', 'all', FALSE); - drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />'); - - $variables = array( - 'head_title' => strip_tags(drupal_get_title()), - 'head' => drupal_get_html_head(), - 'styles' => drupal_get_css(), - 'scripts' => drupal_get_js(), - 'left' => drupal_get_content('left'), - 'right' => drupal_get_content('right'), - 'base_path' => base_path(), - 'path_to_theme' => base_path() .'themes/garland/minnelli', - 'logo' => base_path() .'themes/garland/minnelli/logo.png', - 'site_title' => st('Drupal Installation'), - 'title' => drupal_get_title(), - 'messages' => '', - 'content' => $content, - ); - - // Special handling of error messages - $messages = drupal_set_message(); - if (isset($messages['error'])) { - $title = count($messages['error']) > 1 ? st('The following errors must be resolved before you can continue the installation process') : st('The following error must be resolved before you can continue the installation process'); - $variables['messages'] .= '<h3>'. $title .':</h3>'; - $variables['messages'] .= theme('status_messages', 'error'); - $variables['content'] .= '<p>'. st('Please check the error messages and <a href="!url">try again</a>.', array('!url' => request_uri())) .'</p>'; - } - - // Special handling of status messages - if (isset($messages['status'])) { - $warnings = count($messages['status']) > 1 ? st('The following installation warnings should be carefully reviewed, but in most cases may be safely ignored') : st('The following installation warning should be carefully reviewed, but in most cases may be safely ignored'); - $variables['messages'] .= '<h4>'. $title .':</h4>'; - $variables['messages'] .= theme('status_messages', 'status'); - } - - return theme_render_template('misc/maintenance.tpl.php', $variables); -} - -/** - * Return a themed list of maintenance tasks to perform. - * - * Note: this function is not themeable. - */ -function theme_task_list($items, $active = NULL) { - $done = isset($items[$active]) || $active == NULL; - $output = '<ol class="task-list">'; - foreach ($items as $k => $item) { - if ($active == $k) { - $class = 'active'; - $done = false; - } - else { - $class = $done ? 'done' : ''; - } - $output .= '<li class="'. $class .'">'. $item .'</li>'; - } - $output .= '</ol>'; - return $output; -} - /** * Return a themed set of status and/or error messages. The messages are grouped * by type. @@ -1733,11 +1611,21 @@ function template_preprocess(&$variables, $hook) { // Tell all templates where they are located. $variables['directory'] = path_to_theme(); - // Flag front page status. - $variables['is_front'] = drupal_is_front_page(); - // Tell all templates by which kind of user they're viewed. - $variables['logged_in'] = ($user->uid > 0); - $variables['is_admin'] = user_access('access administration pages'); + + // Set default variables that depend on the database. + $variables['is_admin'] = FALSE; + $variables['is_front'] = FALSE; + $variables['logged_in'] = FALSE; + if ($variables['db_is_active'] = db_is_active()) { + // Check for administrators. + if (user_access('access administration pages')) { + $variables['is_admin'] = TRUE; + } + // Flag front page status. + $variables['is_front'] = drupal_is_front_page(); + // Tell all templates by which kind of user they're viewed. + $variables['logged_in'] = ($user->uid > 0); + } } /** @@ -1750,6 +1638,9 @@ function template_preprocess(&$variables, $hook) { * Uses the arg() function to generate a series of page template suggestions * based on the current path. * + * Any changes to variables in this preprocessor should also be changed inside + * template_preprocess_maintenance_page() to keep all them consistent. + * * The $variables array contains the following arguments: * - $content * - $show_blocks @@ -1757,7 +1648,7 @@ function template_preprocess(&$variables, $hook) { * @see page.tpl.php */ function template_preprocess_page(&$variables) { - /* Add favicon */ + // Add favicon if (theme_get_setting('toggle_favicon')) { drupal_set_html_head('<link rel="shortcut icon" href="'. check_url(theme_get_setting('favicon')) .'" type="image/x-icon" />'); } diff --git a/includes/theme.maintenance.inc b/includes/theme.maintenance.inc new file mode 100644 index 0000000000000000000000000000000000000000..cfc34e09bced022448c1fe424154c36971437d65 --- /dev/null +++ b/includes/theme.maintenance.inc @@ -0,0 +1,258 @@ +<?php +// $Id$ + +/** + * @file + * Theming for maintenance pages. + */ + +/** + * Sets up the theming system for site installs, updates and when the site is + * in off-line mode. It also applies when the database is unavailable. + * + * Minnelli is always used for the initial install and update operations. In + * other cases, "settings.php" must have a "maintenance_theme" key set for the + * $conf variable in order to change the maintenance theme. + */ +function _drupal_maintenance_theme() { + global $theme, $theme_key; + + // If $theme is already set, assume the others are set too, and do nothing. + if (isset($theme)) { + return; + } + + require_once './includes/path.inc'; + require_once './includes/theme.inc'; + require_once './includes/common.inc'; + require_once './includes/unicode.inc'; + require_once './includes/file.inc'; + require_once './includes/module.inc'; + require_once './includes/database.inc'; + unicode_check(); + + // Load module basics (needed for hook invokes). + $module_list['system']['filename'] = 'modules/system/system.module'; + $module_list['filter']['filename'] = 'modules/filter/filter.module'; + module_list(TRUE, FALSE, FALSE, $module_list); + drupal_load('module', 'system'); + drupal_load('module', 'filter'); + + $themes = list_themes(); + + // Install and update pages are treated differently to prevent theming overrides. + if (defined('MAINTENANCE_MODE') && (MAINTENANCE_MODE == 'install' || MAINTENANCE_MODE == 'update')) { + $theme = 'minnelli'; + } + else { + $theme = variable_get('maintenance_theme', 'minnelli'); + } + + // Store the identifier for retrieving theme settings with. + $theme_key = $theme; + + // Find all our ancestor themes and put them in an array. + $base_theme = array(); + $ancestor = $theme; + while ($ancestor && isset($themes[$ancestor]->base_theme)) { + $base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme]; + $ancestor = $themes[$ancestor]->base_theme; + } + _init_theme($themes[$theme], array_reverse($base_theme), '_theme_load_offline_registry'); + + // These are usually added from system_init() -except maintenance.css. + // When the database is inactive it's not called so we add it here. + drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module'); + drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module'); + drupal_add_css(drupal_get_path('module', 'system') .'/system-menus.css', 'module'); + drupal_add_css(drupal_get_path('module', 'system') .'/maintenance.css', 'module'); +} + +/** + * This builds the registry when the site needs to bypass any database calls. + */ +function _theme_load_offline_registry($theme, $base_theme = NULL, $theme_engine = NULL) { + $registry = _theme_build_registry($theme, $base_theme, $theme_engine); + _theme_set_registry($registry); +} + +/** + * Return a themed list of maintenance tasks to perform. + */ +function theme_task_list($items, $active = NULL) { + $done = isset($items[$active]) || $active == NULL; + $output = '<ol class="task-list">'; + foreach ($items as $k => $item) { + if ($active == $k) { + $class = 'active'; + $done = false; + } + else { + $class = $done ? 'done' : ''; + } + $output .= '<li class="'. $class .'">'. $item .'</li>'; + } + $output .= '</ol>'; + return $output; +} + +/** + * Generate a themed installation page. + * + * Note: this function is not themeable. + * + * @param $content + * The page content to show. + */ +function theme_install_page($content) { + drupal_set_header('Content-Type: text/html; charset=utf-8'); + + // Assign content. + $variables['content'] = $content; + // Delay setting the message variable so it can be processed below. + $variables['show_messages'] = FALSE; + // The maintenance preprocess function is recycled here. + template_preprocess_maintenance_page($variables); + + // Special handling of error messages + $messages = drupal_set_message(); + if (isset($messages['error'])) { + $title = count($messages['error']) > 1 ? st('The following errors must be resolved before you can continue the installation process') : st('The following error must be resolved before you can continue the installation process'); + $variables['messages'] .= '<h3>'. $title .':</h3>'; + $variables['messages'] .= theme('status_messages', 'error'); + $variables['content'] .= '<p>'. st('Please check the error messages and <a href="!url">try again</a>.', array('!url' => request_uri())) .'</p>'; + } + + // Special handling of status messages + if (isset($messages['status'])) { + $warnings = count($messages['status']) > 1 ? st('The following installation warnings should be carefully reviewed, but in most cases may be safely ignored') : st('The following installation warning should be carefully reviewed, but in most cases may be safely ignored'); + $variables['messages'] .= '<h4>'. $title .':</h4>'; + $variables['messages'] .= theme('status_messages', 'status'); + } + + return theme_render_template('themes/garland/maintenance-page.tpl.php', $variables); +} + +/** + * Generate a themed update page. + * + * Note: this function is not themeable. + * + * @param $content + * The page content to show. + * @param $show_messages + * Whether to output status and error messages. + * FALSE can be useful to postpone the messages to a subsequent page. + */ +function theme_update_page($content, $show_messages = TRUE) { + // Set required headers. + drupal_set_header('Content-Type: text/html; charset=utf-8'); + + // Assign content and show message flag. + $variables['content'] = $content; + $variables['show_messages'] = $show_messages; + // The maintenance preprocess function is recycled here. + template_preprocess_maintenance_page($variables); + + return theme_render_template('themes/garland/maintenance-page.tpl.php', $variables); +} + +/** + * The variables generated here is a mirror of template_preprocess_page(). + * This preprocessor will run it's course when theme_maintenance_page() is + * invoked. It is also used in theme_install_page() and theme_update_page() to + * keep all the variables consistent. + * + * An alternate template file of "maintenance-page-offline.tpl.php" can be + * used when the database is offline to hide errors and completely replace the + * content. + * + * The $variables array contains the following arguments: + * - $content + * - $show_blocks + * + * @see maintenance-page.tpl.php + */ +function template_preprocess_maintenance_page(&$variables) { + // Add favicon + if (theme_get_setting('toggle_favicon')) { + drupal_set_html_head('<link rel="shortcut icon" href="'. check_url(theme_get_setting('favicon')) .'" type="image/x-icon" />'); + } + + global $theme; + // Retrieve the theme data to list all available regions. + $theme_data = _system_theme_data(); + $regions = $theme_data[$theme]->info['regions']; + + // Get all region content set with drupal_set_content(). + foreach (array_keys($regions) as $region) { + // Assign region to a region variable. + $region_content = drupal_get_content($region); + isset($variables[$region]) ? $variables[$region] .= $region_content : $variables[$region] = $region_content; + } + + // Setup layout variable. + $variables['layout'] = 'none'; + if (!empty($variables['left'])) { + $variables['layout'] = 'left'; + } + if (!empty($variables['right'])) { + $variables['layout'] = ($variables['layout'] == 'left') ? 'both' : 'right'; + } + + // Construct page title + if (drupal_get_title()) { + $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name', 'Drupal')); + } + else { + $head_title = array(variable_get('site_name', 'Drupal')); + if (variable_get('site_slogan', '')) { + $head_title[] = variable_get('site_slogan', ''); + } + } + $variables['head_title'] = implode(' | ', $head_title); + $variables['base_path'] = base_path(); + $variables['breadcrumb'] = ''; + $variables['feed_icons'] = ''; + $variables['footer_message'] = filter_xss_admin(variable_get('site_footer', FALSE)); + $variables['head'] = drupal_get_html_head(); + $variables['help'] = ''; + $variables['language'] = $GLOBALS['language']; + $variables['logo'] = theme_get_setting('logo'); + $variables['messages'] = $variables['show_messages'] ? theme('status_messages') : ''; + $variables['mission'] = ''; + $variables['primary_links'] = array(); + $variables['secondary_links'] = array(); + $variables['search_box'] = ''; + $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''); + $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''); + $variables['css'] = drupal_add_css(); + $variables['styles'] = drupal_get_css(); + $variables['scripts'] = drupal_get_js(); + $variables['tabs'] = ''; + $variables['title'] = drupal_get_title(); + $variables['closure'] = ''; + + // Compile a list of classes that are going to be applied to the body element. + $body_classes = array(); + $body_classes[] = 'in-maintenance'; + if (isset($variables['db_is_active']) && !$variables['db_is_active']) { + $body_classes[] = 'db-offline'; + } + if ($variables['layout'] == 'both') { + $body_classes[] = 'two-sidebars'; + } + elseif ($variables['layout'] == 'none') { + $body_classes[] = 'no-sidebars'; + } + else { + $body_classes[] = 'one-sidebar sidebar-'. $variables['layout']; + } + $variables['body_classes'] = implode(' ', $body_classes); + + // Dead databases will show error messages so supplying this template will + // allow themers to override the page and the content completely. + if (isset($variables['db_is_active']) && !$variables['db_is_active']) { + $variables['template_file'] = 'maintenance-page-offline'; + } +} diff --git a/install.php b/install.php index 1716ffed93bf1fc03eb5aa81ce6205181989f5d6..4125b29afc4c6f9c2d9527590feee99594c9ab05 100644 --- a/install.php +++ b/install.php @@ -3,6 +3,8 @@ require_once './includes/install.inc'; +define('MAINTENANCE_MODE', 'install'); + /** * The Drupal installation happens in a series of steps. We begin by verifying * that the current environment meets our minimum requirements. We then go diff --git a/misc/maintenance.tpl.php b/misc/maintenance.tpl.php deleted file mode 100644 index 24d554f4a634234b95a297171cab6513cfc5cc9a..0000000000000000000000000000000000000000 --- a/misc/maintenance.tpl.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -// $Id$ -?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title><?php print $head_title ?></title> - <?php print $head ?> - <?php print $styles ?> - <?php print $scripts ?> - <link type="text/css" rel="stylesheet" media="all" href="<?php print $path_to_theme ?>/style.css" /> - <!--[if lt IE 7]> - <link type="text/css" rel="stylesheet" media="all" href="<?php print $path_to_theme ?>/fix-ie.css" /> - <![endif]--> - </head> - <body class="<?php - $classes = array('', 'sidebar-left', 'sidebar-right', 'sidebar-both'); - print $classes[((bool)$left) + 2 * ((bool)$right)]; - ?>"> - -<!-- Layout --> - <div id="header-region" class="clear-block"></div> - - <div id="wrapper"> - <div id="container" class="clear-block"> - - <div id="header"> - <div id="logo-floater"> - <h1><a href="<?php print check_url($base_path) ?>"><img src="<?php print check_url($logo) ?>" alt="Drupal" id="logo" /><span><?php print $site_title ?></span></a></h1> - </div> - </div> <!-- /header --> - - <?php if ($left): ?> - <div id="sidebar-left" class="sidebar"> - <?php print $left ?> - </div> - <?php endif; ?> - - <div id="center"><div id="squeeze"><div class="right-corner"><div class="left-corner"> - <?php if ($title): print '<h2>'. $title .'</h2>'; endif; ?> - - <?php if ($messages): print $messages; endif; ?> - <div class="clear-block"> - <?php print $content ?> - </div> - - <!--partial--> - - </div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center --> - - <?php if ($right): ?> - <div id="sidebar-right" class="sidebar"> - <?php print $right ?> - </div> - <?php endif; ?> - - </div> <!-- /container --> - </div> -<!-- /layout --> - - </body> -</html> diff --git a/modules/system/maintenance-page.tpl.php b/modules/system/maintenance-page.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..12037ab93adc78e3e7eb9afa4280d0e3b6d9680f --- /dev/null +++ b/modules/system/maintenance-page.tpl.php @@ -0,0 +1,98 @@ +<?php +// $Id$ + +/** + * @file maintenance-page.tpl.php + * + * Theme implementation to display a single Drupal page while off-line. + * + * All the available variables are mirrored in page.tpl.php. Some may be left + * blank but they are provided for consistency. + * + * + * @see template_preprocess() + * @see template_preprocess_maintenance_page() + */ +?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language ?>" lang="<?php print $language->language ?>"> + +<head> + <title><?php print $head_title; ?></title> + <?php print $head; ?> + <?php print $styles; ?> + <?php print $scripts; ?> + <script type="text/javascript"><?php /* Needed to avoid Flash of Unstyled Content in IE */ ?> </script> +</head> +<body class="<?php print $body_classes; ?>"> + <div id="page"> + <div id="header"> + <div id="logo-title"> + + <?php if (!empty($logo)): ?> + <a href="<?php print $base_path; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> + <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" /> + </a> + <?php endif; ?> + + <div id="name-and-slogan"> + <?php if (!empty($site_name)): ?> + <h1 id="site-name"> + <a href="<?php print $base_path ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a> + </h1> + <?php endif; ?> + + <?php if (!empty($site_slogan)): ?> + <div id="site-slogan"><?php print $site_slogan; ?></div> + <?php endif; ?> + </div> <!-- /name-and-slogan --> + </div> <!-- /logo-title --> + + <?php if (!empty($header)): ?> + <div id="header-region"> + <?php print $header; ?> + </div> + <?php endif; ?> + + </div> <!-- /header --> + + <div id="container" class="clear-block"> + + <?php if (!empty($left)): ?> + <div id="sidebar-left" class="column sidebar"> + <?php print $left; ?> + </div> <!-- /sidebar-left --> + <?php endif; ?> + + <div id="main" class="column"><div id="main-squeeze"> + + <div id="content"> + <?php if (!empty($title)): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?> + <?php if (!empty($messages)): print $messages; endif; ?> + <div id="content-content" class="clear-block"> + <?php print $content; ?> + </div> <!-- /content-content --> + </div> <!-- /content --> + + </div></div> <!-- /main-squeeze /main --> + + <?php if (!empty($right)): ?> + <div id="sidebar-right" class="column sidebar"> + <?php print $right; ?> + </div> <!-- /sidebar-right --> + <?php endif; ?> + + </div> <!-- /container --> + + <div id="footer-wrapper"> + <div id="footer"> + <?php print $footer_message; ?> + <?php if (!empty($footer)): print $footer; endif; ?> + </div> <!-- /footer --> + </div> <!-- /footer-wrapper --> + + </div> <!-- /page --> + +</body> +</html> diff --git a/misc/maintenance.css b/modules/system/maintenance.css similarity index 100% rename from misc/maintenance.css rename to modules/system/maintenance.css diff --git a/modules/system/system.module b/modules/system/system.module index d6997c2f1fea98c8c82a3239d91ddce27ecfea6d..ca8e54703dc5965df30c7c7bb4d178870d1f66d8 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -77,7 +77,7 @@ function system_help($path, $arg) { } function system_theme() { - return array_merge(drupal_common_themes(), array( + return array_merge(drupal_common_theme(), array( 'system_theme_select_form' => array( 'arguments' => array('form' => NULL), 'file' => 'system.admin.inc', @@ -711,111 +711,119 @@ function system_theme_default() { } /** - * Collect data about all currently available themes + * Collect data about all currently available themes. + * + * @return + * Array of all available themes and their data. */ function system_theme_data() { - // Find themes - $themes = drupal_system_listing('\.info$', 'themes'); + // Scan the installation theme .info files and their engines. + $themes = _system_theme_data(); - // Find theme engines - $engines = drupal_system_listing('\.engine$', 'themes/engines'); - - // Remove all theme engines from the system table - db_query("DELETE FROM {system} WHERE type = '%s'", 'theme_engine'); + // Extract current files from database. + system_get_files_database($themes, 'theme'); - foreach ($engines as $engine) { - // Insert theme engine into system table - drupal_get_filename('theme_engine', $engine->name, $engine->filename); - drupal_load('theme_engine', $engine->name); - db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0); - } + db_query("DELETE FROM {system} WHERE type = 'theme'"); - $defaults = system_theme_default(); + foreach ($themes as $theme) { + if (!isset($theme->owner)) { + $theme->owner = ''; + } - $sub_themes = array(); - // Read info files for each theme - foreach ($themes as $key => $theme) { - $themes[$key]->info = drupal_parse_info_file($theme->filename) + $defaults; + db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0); + } - // Invoke hook_system_info_alter() to give installed modules a chance to - // modify the data in the .info files if necessary. - drupal_alter('system_info', $themes[$key]->info, $themes[$key]); + return $themes; +} - if (!empty($themes[$key]->info['base theme'])) { - $sub_themes[] = $key; - } - if (empty($themes[$key]->info['engine'])) { - $filename = dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.theme'; - if (file_exists($filename)) { - $themes[$key]->owner = $filename; - $themes[$key]->prefix = $key; +/** + * Helper function to scan and collect theme .info data and their engines. + */ +function _system_theme_data() { + static $themes_info = array(); + + if (empty($theme_info)) { + // Find themes + $themes = drupal_system_listing('\.info$', 'themes'); + // Find theme engines + $engines = drupal_system_listing('\.engine$', 'themes/engines'); + + $defaults = system_theme_default(); + + $sub_themes = array(); + // Read info files for each theme + foreach ($themes as $key => $theme) { + $themes[$key]->info = drupal_parse_info_file($theme->filename) + $defaults; + + // Invoke hook_system_info_alter() to give installed modules a chance to + // modify the data in the .info files if necessary. + drupal_alter('system_info', $themes[$key]->info, $themes[$key]); + + if (!empty($themes[$key]->info['base theme'])) { + $sub_themes[] = $key; } - } - else { - $engine = $themes[$key]->info['engine']; - if (isset($engines[$engine])) { - $themes[$key]->owner = $engines[$engine]->filename; - $themes[$key]->prefix = $engines[$engine]->name; - $themes[$key]->template = TRUE; + if (empty($themes[$key]->info['engine'])) { + $filename = dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.theme'; + if (file_exists($filename)) { + $themes[$key]->owner = $filename; + $themes[$key]->prefix = $key; + } } - } - - // Give the stylesheets proper path information. - $pathed_stylesheets = array(); - foreach ($themes[$key]->info['stylesheets'] as $media => $stylesheets) { - foreach ($stylesheets as $stylesheet) { - $pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->filename) .'/'. $stylesheet; + else { + $engine = $themes[$key]->info['engine']; + if (isset($engines[$engine])) { + $themes[$key]->owner = $engines[$engine]->filename; + $themes[$key]->prefix = $engines[$engine]->name; + $themes[$key]->template = TRUE; + } } - } - $themes[$key]->info['stylesheets'] = $pathed_stylesheets; - // Give the scripts proper path information. - $scripts = array(); - foreach ($themes[$key]->info['scripts'] as $script) { - $scripts[$script] = dirname($themes[$key]->filename) .'/'. $script; - } - $themes[$key]->info['scripts'] = $scripts; - // Give the screenshot proper path information. - if (!empty($themes[$key]->info['screenshot'])) { - $themes[$key]->info['screenshot'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['screenshot']; - } - } + // Give the stylesheets proper path information. + $pathed_stylesheets = array(); + foreach ($themes[$key]->info['stylesheets'] as $media => $stylesheets) { + foreach ($stylesheets as $stylesheet) { + $pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->filename) .'/'. $stylesheet; + } + } + $themes[$key]->info['stylesheets'] = $pathed_stylesheets; - // Now that we've established all our master themes, go back and fill in - // data for subthemes. - foreach ($sub_themes as $key) { - $base_key = system_find_base_theme($themes, $key); - if (!$base_key) { - continue; - } - // Copy the 'owner' and 'engine' over if the top level theme uses a - // theme engine. - if (isset($themes[$base_key]->owner)) { - if (isset($themes[$base_key]->info['engine'])) { - $themes[$key]->info['engine'] = $themes[$base_key]->info['engine']; - $themes[$key]->owner = $themes[$base_key]->owner; - $themes[$key]->prefix = $themes[$base_key]->prefix; + // Give the scripts proper path information. + $scripts = array(); + foreach ($themes[$key]->info['scripts'] as $script) { + $scripts[$script] = dirname($themes[$key]->filename) .'/'. $script; } - else { - $themes[$key]->prefix = $key; + $themes[$key]->info['scripts'] = $scripts; + // Give the screenshot proper path information. + if (!empty($themes[$key]->info['screenshot'])) { + $themes[$key]->info['screenshot'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['screenshot']; } } - } - - // Extract current files from database. - system_get_files_database($themes, 'theme'); - db_query("DELETE FROM {system} WHERE type = 'theme'"); - - foreach ($themes as $theme) { - if (!isset($theme->owner)) { - $theme->owner = ''; + // Now that we've established all our master themes, go back and fill in + // data for subthemes. + foreach ($sub_themes as $key) { + $base_key = system_find_base_theme($themes, $key); + if (!$base_key) { + continue; + } + // Copy the 'owner' and 'engine' over if the top level theme uses a + // theme engine. + if (isset($themes[$base_key]->owner)) { + if (isset($themes[$base_key]->info['engine'])) { + $themes[$key]->info['engine'] = $themes[$base_key]->info['engine']; + $themes[$key]->owner = $themes[$base_key]->owner; + $themes[$key]->prefix = $themes[$base_key]->prefix; + } + else { + $themes[$key]->prefix = $key; + } + } } - - db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0); + + $themes_info = $themes; } - return $themes; + return $themes_info; } /** diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 4fc53c3659a456ff4dad5b209af9a2b41e9c2875..69205fb301d67a3a7cc6de82c899756dbaf16ac0 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -172,6 +172,15 @@ # 'site_name' => 'My Drupal site', # 'theme_default' => 'minnelli', # 'anonymous' => 'Visitor', +/** + * A custom theme can be set for the off-line page. This applies when the site + * is explicitly set to off-line mode through the administration page or when + * the database is inactive due to an error. It can be set through the + * 'maintenance_theme' key. The template file should also be copied into the + * theme. It is located inside 'modules/system/maintenance-page.tpl.php'. + * Note: This setting does not apply to installation and update pages. + */ +# 'maintenance_theme' => 'minnelli', /** * reverse_proxy accepts a boolean value. * diff --git a/themes/garland/maintenance-page.tpl.php b/themes/garland/maintenance-page.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..6087b354c8b7c2ed9a940c48412b0c53d2fd005e --- /dev/null +++ b/themes/garland/maintenance-page.tpl.php @@ -0,0 +1,91 @@ +<?php +// $Id$ + +/** + * @file maintenance-page.tpl.php + * + * This is an override of the default maintenance page. Used for Garland and + * Minnelli, this file should not be moved or modified since the installation + * and update pages depend on this file. + * + * This mirrors closely page.tpl.php for Garland in order to share the same + * styles. + */ +?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language ?>" lang="<?php print $language->language ?>"> + <head> + <title><?php print $head_title ?></title> + <?php print $head ?> + <?php print $styles ?> + <?php print $scripts ?> + <!--[if lt IE 7]> + <?php print phptemplate_get_ie_styles(); ?> + <![endif]--> + </head> + <body<?php print phptemplate_body_class($left, $right); ?>> + +<!-- Layout --> + <div id="header-region" class="clear-block"><?php print $header; ?></div> + + <div id="wrapper"> + <div id="container" class="clear-block"> + + <div id="header"> + <div id="logo-floater"> + <?php + // Prepare header + $site_fields = array(); + if ($site_name) { + $site_fields[] = check_plain($site_name); + } + if ($site_slogan) { + $site_fields[] = check_plain($site_slogan); + } + $site_title = implode(' ', $site_fields); + if ($site_fields) { + $site_fields[0] = '<span>'. $site_fields[0] .'</span>'; + } + $site_html = implode(' ', $site_fields); + + if ($logo || $site_title) { + print '<h1><a href="'. check_url($base_path) .'" title="'. $site_title .'">'; + if ($logo) { + print '<img src="'. check_url($logo) .'" alt="'. $site_title .'" id="logo" />'; + } + print $site_html .'</a></h1>'; + } + ?> + </div> + + </div> <!-- /header --> + + <?php if ($left): ?> + <div id="sidebar-left" class="sidebar"> + <?php if ($search_box): ?><div class="block block-theme"><?php print $search_box ?></div><?php endif; ?> + <?php print $left ?> + </div> + <?php endif; ?> + + <div id="center"><div id="squeeze"><div class="right-corner"><div class="left-corner"> + <?php if ($title): print '<h2'. ($tabs ? ' class="with-tabs"' : '') .'>'. $title .'</h2>'; endif; ?> + <?php print $help; ?> + <?php print $messages; ?> + <div class="clear-block"> + <?php print $content ?> + </div> + <div id="footer"><?php print $footer_message . $footer ?></div> + </div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center --> + + <?php if ($right): ?> + <div id="sidebar-right" class="sidebar"> + <?php print $right ?> + </div> + <?php endif; ?> + + </div> <!-- /container --> + </div> +<!-- /layout --> + + </body> +</html> diff --git a/update.php b/update.php index 890d4c0ad040facce5a9b6e459dbf7c19ad4631f..38738dee96e7eab3ae9c0a0fc0be9e9584bd2a95 100644 --- a/update.php +++ b/update.php @@ -13,6 +13,8 @@ * be sure to open settings.php again, and change it back to its original state! */ +define('MAINTENANCE_MODE', 'update'); + /** * Add a column to a database using syntax appropriate for PostgreSQL. * Save result of SQL commands in $ret array. @@ -803,7 +805,7 @@ function update_task_list($active = NULL) { 'finished' => 'Review log', ); - drupal_set_content('left', theme_task_list($tasks, $active)); + drupal_set_content('left', theme('task_list', $tasks, $active)); } // Some unavoidable errors happen because the database is not yet up-to-date. @@ -875,5 +877,5 @@ function update_task_list($active = NULL) { $output = update_access_denied_page(); } if (isset($output) && $output) { - print theme('maintenance_page', $output); + print theme('update_page', $output); }