diff --git includes/common.inc includes/common.inc
index 58b0845..e2545e5 100644
--- includes/common.inc
+++ includes/common.inc
@@ -42,6 +42,8 @@ define('JS_THEME', 100);
/**
* Set content for a specified region.
+ *
+ * @todo: Drop this in favor of drupal_decorate_page. It's already only used in maintance theme mode.
*
* @param $region
* Page region the content is assigned to.
@@ -60,6 +62,8 @@ function drupal_set_content($region = NULL, $data = NULL) {
/**
* Get assigned content.
*
+ * @todo: Drop this in favor of drupal_decorate_page. It's already only used in maintance theme mode.
+ *
* @param $region
* A specified region to fetch content for. If NULL, all regions will be
* returned.
@@ -301,8 +305,7 @@ function drupal_get_destination() {
* Drupal will ensure that messages set by drupal_set_message() and other
* session data are written to the database before the user is redirected.
*
- * This function ends the request; use it rather than a print theme('page')
- * statement in your menu callback.
+ * This function ends the request; use it rather than returning an array in your menu callback.
*
* @param $path
* A Drupal path or a full URL.
@@ -385,11 +388,12 @@ function drupal_not_found() {
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
drupal_set_title(t('Page not found'));
- $return = t('The requested page could not be found.');
+ $return = array('#markup' => t('The requested page could not be found.'));
}
// To conserve CPU and bandwidth, omit the blocks.
- print theme('page', $return, FALSE);
+ drupal_decorate_page(array('#show_blocks' => FALSE));
+ print drupal_render_page($return);
}
/**
@@ -414,9 +418,10 @@ function drupal_access_denied() {
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
drupal_set_title(t('Access denied'));
- $return = t('You are not authorized to access this page.');
+ $return = array('#markup' => t('You are not authorized to access this page.'));
}
- print theme('page', $return);
+
+ print drupal_render_page($return);
}
/**
@@ -821,7 +826,11 @@ function _drupal_log_error($error, $fatal = FALSE) {
drupal_set_header($_SERVER['SERVER_PROTOCOL'] . ' Service unavailable');
drupal_set_title(t('Error'));
if (!defined('MAINTENANCE_MODE') && drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) {
- print theme('page', t('The website encountered an unexpected error. Please try again later.'), FALSE);
+ // To conserve CPU and bandwidth, omit the blocks.
+ drupal_decorate_page(array('#show_blocks' => FALSE));
+ print drupal_render_page(array(
+ '#markup' => t('The website encountered an unexpected error. Please try again later.'),
+ ));
}
else {
print theme('maintenance_page', t('The website encountered an unexpected error. Please try again later.'), FALSE);
@@ -3176,6 +3185,56 @@ function drupal_alter($type, &$data) {
}
/**
+ * Renders the page and adds all theming.
+ *
+ * @param $content
+ * A string or array representing the content of the page.
+ */
+function drupal_render_page($content) {
+ // The theme system might not yet be initialized.
+ init_theme();
+ global $theme;
+ // Initialize page array with defaults.
+ $page = _element_info('page');
+ $page['#type'] = 'page';
+
+ // Set the main content.
+ $page['content'] = is_array($content) ? $content : array('#markup' => $content);
+
+ // Include decorations.
+ $page = array_merge($page, drupal_decorate_page());
+
+ // Allow final alteration.
+ drupal_alter('page', $page);
+
+ // Ensure that we don't have any empty regions.
+ foreach (system_region_list($theme) as $region_key => $region_name) {
+ if(empty($page[$region_key])) {
+ $page[$region_key] = array('#markup' => '');
+ }
+ }
+
+ print drupal_render($page);
+}
+
+/**
+ * Add elements to the page.
+ *
+ * The passed in array is usually keyed by valid regions, as otherwise content
+ * will probably not be themed automatically.
+ *
+ * @param $decorations
+ * A renderable array that will later on be merged into the main page array.
+ * @return
+ * The collected decorations.
+ */
+function drupal_decorate_page($decorations = array()) {
+ static $page = array();
+ $page += $decorations;
+ return $page;
+}
+
+/**
* Renders HTML given a structured array tree.
*
* Recursively iterates over each of the array elements, generating HTML code.
@@ -3246,7 +3305,17 @@ function drupal_render(&$elements) {
// Render each of the children using drupal_render and concatenate them.
if (!isset($content) || $content === '') {
foreach ($children as $key) {
- $content .= drupal_render($elements[$key]);
+ // If #concatenate_children is set to FALSE, the rendered children of the
+ // element are not concatenated into a single string, but instead kept as
+ // a keyed array of rendered string in the #children property of the parent
+ // element. The parent's element theming function is then responsible for
+ // printing out all elements in the #children array.
+ if (isset($elements['#concatenate_children']) && $elements['#concatenate_children'] == FALSE) {
+ $content[$key] = drupal_render($elements[$key]);
+ }
+ else {
+ $content .= drupal_render($elements[$key]);
+ }
}
}
}
@@ -3339,7 +3408,7 @@ function drupal_common_theme() {
'arguments' => array('text' => NULL)
),
'page' => array(
- 'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE),
+ 'arguments' => array('content' => NULL),
'template' => 'page',
),
'maintenance_page' => array(
@@ -3398,6 +3467,9 @@ function drupal_common_theme() {
'item_list' => array(
'arguments' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => NULL),
),
+ 'list' => array(
+ 'arguments' => array('elements' => NULL),
+ ),
'more_help_link' => array(
'arguments' => array('url' => NULL),
),
diff --git includes/theme.inc includes/theme.inc
index 37d8652..e297904 100644
--- includes/theme.inc
+++ includes/theme.inc
@@ -1571,6 +1571,28 @@ function theme_item_list($items = array(), $title = NULL, $type = 'ul', $attribu
}
/**
+ * Return a themed list of items from a drupal_render() style array.
+ *
+ * @param $elements
+ * An array consisting of the following keys:
+ * - #items. An array of items as expected by theme('item_list'). Mandatory.
+ * - #title. A title which prints above the list. Optional.
+ * - #list_type. The type of list to return. Defaults to "ul".
+ * - #attributes. An array of attributes as expected by theme('item_list'). Optional.
+ * @return
+ * A string containing the list output.
+ */
+function theme_list($elements) {
+ // Populate any missing array elements with their defaults.
+ $elements += array(
+ '#title' => '',
+ '#list_type' => 'ul',
+ '#attributes' => array(),
+ '#items' => array(),
+ );
+ return theme('item_list', $elements['#items'], $elements['#title'], $elements['#list_type'], $elements['#attributes']);
+}
+/**
* Returns code that emits the 'more help'-link.
*/
function theme_more_help_link($url) {
@@ -1633,30 +1655,6 @@ function theme_closure($main = 0) {
}
/**
- * Return a set of blocks available for the current user.
- *
- * @param $region
- * Which set of blocks to retrieve.
- * @return
- * A string containing the themed blocks for this region.
- */
-function theme_blocks($region) {
- $output = '';
-
- if ($list = block_list($region)) {
- foreach ($list as $key => $block) {
- // $key == module_delta
- $output .= theme('block', $block);
- }
- }
-
- // Add any content assigned to this region through drupal_set_content() calls.
- $output .= drupal_get_content($region);
-
- return $output;
-}
-
-/**
* Format a username.
*
* @param $object
@@ -1825,27 +1823,21 @@ function template_preprocess(&$variables, $hook) {
* @see page.tpl.php
*/
function template_preprocess_page(&$variables) {
+ // Move some variables to the top level for themer convenience and template cleanliness.
+ $variables['show_blocks'] = $variables['content']['#show_blocks'];
+ $variables['show_messages'] = $variables['content']['#show_messages'];
+
+ // Import children of the content array as variables.
+ // This contains the main 'content' and the regions (with rendered blocks).
+ $content = $variables['content']['#children'];
+ foreach ($content as $key => $child) {
+ $variables[$key] = $child;
+ }
// Add favicon
if (theme_get_setting('toggle_favicon')) {
drupal_set_html_head('');
}
- global $theme;
- // Populate all block regions.
- $regions = system_region_list($theme);
- // Load all region content assigned via blocks.
- foreach (array_keys($regions) as $region) {
- // Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE.
- if ($variables['show_blocks'] || ($region != 'left' && $region != 'right')) {
- $blocks = theme('blocks', $region);
- }
- else {
- $blocks = '';
- }
- // Assign region to a region variable.
- isset($variables[$region]) ? $variables[$region] .= $blocks : $variables[$region] = $blocks;
- }
-
// Set up layout variable.
$variables['layout'] = 'none';
if (!empty($variables['left'])) {
@@ -1883,8 +1875,8 @@ function template_preprocess_page(&$variables) {
$variables['logo'] = theme_get_setting('logo');
$variables['messages'] = $variables['show_messages'] ? theme('status_messages') : '';
$variables['mission'] = isset($mission) ? $mission : '';
- $variables['main_menu'] = theme_get_setting('toggle_main_menu') ? menu_main_menu() : array();
- $variables['secondary_menu'] = theme_get_setting('toggle_secondary_menu') ? menu_secondary_menu() : array();
+ $variables['main_menu'] = theme_get_setting('toggle_main_menu') ? menu_main_menu() : array();
+ $variables['secondary_menu'] = theme_get_setting('toggle_secondary_menu') ? menu_secondary_menu() : array();
$variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : '');
$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', '') : '');
@@ -1977,6 +1969,8 @@ function template_preprocess_page(&$variables) {
* @see node.tpl.php
*/
function template_preprocess_node(&$variables) {
+ $variables['teaser'] = &$variables['elements']['teaser'];
+ $variables['node'] = &$variables['elements']['node'];
$node = $variables['node'];
$variables['date'] = format_date($node->created);
@@ -2042,6 +2036,7 @@ function template_preprocess_node(&$variables) {
*/
function template_preprocess_block(&$variables) {
static $block_counter = array();
+ $variables['block'] = $variables['block']['#block'];
// All blocks get an independent counter for each region.
if (!isset($block_counter[$variables['block']->region])) {
$block_counter[$variables['block']->region] = 1;
diff --git index.php index.php
index e9cdef1..0eeb3aa 100644
--- index.php
+++ index.php
@@ -21,7 +21,7 @@ require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$return = menu_execute_active_handler();
-// Menu status constants are integers; page content is a string.
+// Menu status constants are integers; page content is a string or array.
if (is_int($return)) {
switch ($return) {
case MENU_NOT_FOUND:
@@ -36,8 +36,8 @@ if (is_int($return)) {
}
}
elseif (isset($return)) {
- // Print any value (including an empty string) except NULL or undefined:
- print theme('page', $return);
+ // Print anything besides a menu constant, assuming it's not NULL or undefined.
+ drupal_render_page($return);
}
drupal_page_footer();
diff --git modules/block/block.admin.inc modules/block/block.admin.inc
index 2feb425..358c98c 100644
--- modules/block/block.admin.inc
+++ modules/block/block.admin.inc
@@ -369,7 +369,8 @@ function template_preprocess_block_admin_display_form(&$variables) {
foreach ($block_regions as $key => $value) {
// Highlight regions on page to provide visual reference.
- drupal_set_content($key, '
' . t('For more information, please refer to the help section, or the online Drupal handbooks. You may also post at the Drupal forum, or view the wide range of other support options available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '
';
- $output = '
' . $default_message . '
';
+ $page = array('#markup' => '
' . $default_message . '
');
}
drupal_set_title('');
- return $output;
+ return $page;
}
/**
@@ -2930,7 +2954,7 @@ function node_unpublish_by_keyword_action_submit($form, $form_state) {
*/
function node_unpublish_by_keyword_action($node, $context) {
foreach ($context['keywords'] as $keyword) {
- if (strstr(node_view(clone $node), $keyword) || strstr($node->title, $keyword)) {
+ if (strstr(drupal_render(node_view(clone $node)), $keyword) || strstr($node->title, $keyword)) {
$node->status = 0;
watchdog('action', 'Set @type %title to unpublished.', array('@type' => node_get_types('name', $node), '%title' => $node->title));
break;
diff --git modules/node/node.pages.inc modules/node/node.pages.inc
index 76e28b1..511c042 100644
--- modules/node/node.pages.inc
+++ modules/node/node.pages.inc
@@ -415,12 +415,12 @@ function theme_node_preview($node) {
if ($preview_trimmed_version) {
drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication. You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.'));
$output .= '
',
+ '#markup' => t('There are currently no posts in this category.'),
+ '#suffix' => '
',
+ );
+ }
+ // Only display the description if we have a single term, to avoid clutter and confusion.
+ if (count($tids) == 1) {
+ $term = taxonomy_term_load($tids[0]);
+ $description = $term->description;
+
+ // Check that a description is set.
+ if (!empty($description)) {
+ $page['term_description'] = array(
+ '#markup' => filter_xss_admin($description),
+ '#weight' => -1,
+ '#prefix' => '
',
+ '#suffix' => '
',
+ );
+ }
+ }
+ return $page;
+ break;
case 'feed':
$channel['link'] = url('taxonomy/term/' . $str_tids . '/' . $depth, array('absolute' => TRUE));
$channel['title'] = variable_get('site_name', 'Drupal') . ' - ' . $title;
@@ -58,13 +90,9 @@ function taxonomy_term_page($terms, $depth = 0, $op = 'page') {
$channel['description'] = $term->description;
}
- $result = taxonomy_select_nodes($tids, $terms['operator'], $depth, FALSE);
- $items = array();
- while ($row = db_fetch_object($result)) {
- $items[] = $row->nid;
- }
+ $nids = taxonomy_select_nodes($tids, $terms['operator'], $depth, FALSE);
- node_feed($items, $channel);
+ node_feed($nids, $channel);
break;
default:
@@ -78,38 +106,6 @@ function taxonomy_term_page($terms, $depth = 0, $op = 'page') {
}
/**
- * Render a taxonomy term page HTML output.
- *
- * @param $tids
- * An array of term ids.
- * @param $result
- * A pager_query() result, such as that performed by taxonomy_select_nodes().
- *
- * @ingroup themeable
- */
-function theme_taxonomy_term_page($tids, $result) {
- drupal_add_css(drupal_get_path('module', 'taxonomy') . '/taxonomy.css');
- $output = '';
-
- // Only display the description if we have a single term, to avoid clutter and confusion.
- if (count($tids) == 1) {
- $term = taxonomy_term_load($tids[0]);
- $description = $term->description;
-
- // Check that a description is set.
- if (!empty($description)) {
- $output .= '
';
- }
- }
-
- $output .= taxonomy_render_nodes($result);
-
- return $output;
-}
-
-/**
* Page to edit a vocabulary term.
*/
function taxonomy_term_edit($term) {
diff --git modules/upload/upload.test modules/upload/upload.test
index 11c7e98..4cd4973 100644
--- modules/upload/upload.test
+++ modules/upload/upload.test
@@ -53,7 +53,7 @@ class UploadTestCase extends DrupalWebTestCase {
// Assure that the attachment link appears on teaser view and has correct count.
$node = node_load($node->nid);
- $teaser = node_view($node, TRUE);
+ $teaser = drupal_render(node_view($node, TRUE));
$this->assertTrue(strpos($teaser, format_plural(2, '1 attachment', '@count attachments')), 'Attachments link found on node teaser.');
// Fetch db record and use fid to rename and delete file.