From 02c8592759c5b33d3d94fe6a515f10af4317dd5c Mon Sep 17 00:00:00 2001 From: Dries Buytaert <dries@buytaert.net> Date: Thu, 21 May 2009 21:12:25 +0000 Subject: [PATCH] - Patch #428744 by Gabor: make the main page content a real block and clean up some of the content API. --- CHANGELOG.txt | 4 +++ includes/common.inc | 54 +++++++++++++++------------- includes/theme.maintenance.inc | 4 +-- install.php | 2 +- modules/block/block.admin.inc | 2 ++ modules/block/block.install | 23 ++++++++++++ modules/block/block.js | 16 ++++++--- modules/block/block.module | 7 +++- modules/blog/blog.pages.inc | 4 +-- modules/node/node.module | 4 +-- modules/simpletest/tests/common.test | 18 +++++----- modules/system/system.admin.inc | 7 ++-- modules/system/system.install | 4 ++- modules/system/system.module | 9 +++++ modules/taxonomy/taxonomy.pages.inc | 2 +- modules/user/user.pages.inc | 2 +- profiles/default/default.profile | 12 ++++++- profiles/expert/expert.profile | 13 ++++++- update.php | 2 +- 19 files changed, 135 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4a2f5a718111..90876ed8f0a2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -115,6 +115,10 @@ Drupal 7.0, xxxx-xx-xx (development version) * Site mission is replaced with the highlighted content block region and separate RSS feed description settings. * The footer message setting was removed in favor of custom blocks. + * Made the main page content a block which can be moved and ordered + with other blocks in the same region. + * Blocks can now return structured arrays for later rendering just + like page callbacks. - Upgraded the core JavaScript library to jQuery version 1.3.2. - Upgraded the jQuery Forms library to 2.21. diff --git a/includes/common.inc b/includes/common.inc index 78f2fc4ae1a5..a6e5c3b7a4aa 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -56,14 +56,14 @@ define('JS_THEME', 100); /** - * Set content for a specified region. + * Add content to a specified region. * * @param $region - * Page region the content is assigned to. + * Page region the content is added to. * @param $data - * Content to be set. + * Content to be added. */ -function drupal_set_content($region = NULL, $data = NULL) { +function drupal_add_region_content($region = NULL, $data = NULL) { static $content = array(); if (!is_null($region) && !is_null($data)) { @@ -73,7 +73,7 @@ function drupal_set_content($region = NULL, $data = NULL) { } /** - * Get assigned content. + * Get assigned content for a given region. * * @param $region * A specified region to fetch content for. If NULL, all regions will be @@ -81,8 +81,8 @@ function drupal_set_content($region = NULL, $data = NULL) { * @param $delimiter * Content to be inserted between exploded array elements. */ -function drupal_get_content($region = NULL, $delimiter = ' ') { - $content = drupal_set_content(); +function drupal_get_region_content($region = NULL, $delimiter = ' ') { + $content = drupal_add_region_content(); if (isset($region)) { if (isset($content[$region]) && is_array($content[$region])) { return implode($delimiter, $content[$region]); @@ -372,7 +372,8 @@ function drupal_not_found() { $return = t('The requested page could not be found.'); } - $page = drupal_get_page($return); + drupal_set_page_content($return); + $page = element_info('page'); // To conserve CPU and bandwidth, omit the blocks. $page['#show_blocks'] = FALSE; @@ -3205,24 +3206,25 @@ function drupal_alter($type, &$data) { } /** - * Retrieve a $page element that is ready for decorating. + * Set the main page content value for later use. * - * Used by menu callbacks in order to populate the page with content - * and behavior (e.g. #show_blocks). + * Given the nature of the Drupal page handling, this will be called once with + * a string or array. We store that and return it later as the block is being + * displayed. * * @param $content * A string or renderable array representing the body of the page. * @return - * A $page element that should be decorated and then passed to drupal_render_page(). - * - * @see drupal_render_page(). + * A renderable array representing the body of the page. */ -function drupal_get_page($content = NULL) { - // Initialize page array with defaults. @see hook_elements() - 'page' element. - $page = element_info('page'); - $page['content'] = is_array($content) ? $content : array('main' => array('#markup' => $content)); - - return $page; +function drupal_set_page_content($content = NULL) { + $content_block = &drupal_static(__FUNCTION__, NULL); + if (!empty($content)) { + $content_block = (is_array($content) ? $content : array('main' => array('#markup' => $content))); + } + else { + return $content_block; + } } /** @@ -3232,17 +3234,19 @@ function drupal_get_page($content = NULL) { * A string or array representing the content of a page. The array consists of * the following keys: * - #type: Value is always 'page'. This pushes the theming through page.tpl.php (required). - * - content: A renderable array as built by the menu callback (required). * - #show_blocks: A marker which suppresses left/right regions if FALSE (optional). * - #show_messages: Suppress drupal_get_message() items. Used by Batch API (optional). * * @see hook_page_alter() - * @see drupal_get_page() + * @see element_info('page') */ function drupal_render_page($page) { - // Allow menu callbacks to return strings, or bare content arrays. - if (is_string($page) || empty($page['content'])) { - $page = drupal_get_page($page); + // Allow menu callbacks to return strings or arbitrary arrays to render. + // If the array returned is not of #type page directly, we need to fill + // in the page with defaults. + if (is_string($page) || (is_array($page) && (!isset($page['#type']) || ($page['#type'] != 'page')))) { + drupal_set_page_content($page); + $page = element_info('page'); } // Modules alter the $page as needed. Blocks are populated into regions like // 'left', 'footer', etc. diff --git a/includes/theme.maintenance.inc b/includes/theme.maintenance.inc index d36ad3950d74..0dba734b5c1a 100644 --- a/includes/theme.maintenance.inc +++ b/includes/theme.maintenance.inc @@ -220,10 +220,10 @@ function template_preprocess_maintenance_page(&$variables) { $theme_data = _system_theme_data(); $regions = $theme_data[$theme]->info['regions']; - // Get all region content set with drupal_set_content(). + // Get all region content set with drupal_add_region_content(). foreach (array_keys($regions) as $region) { // Assign region to a region variable. - $region_content = drupal_get_content($region); + $region_content = drupal_get_region_content($region); isset($variables[$region]) ? $variables[$region] .= $region_content : $variables[$region] = $region_content; } diff --git a/install.php b/install.php index 194c5abb33d4..61aced16b5d2 100644 --- a/install.php +++ b/install.php @@ -1001,7 +1001,7 @@ function install_task_list($active = NULL) { if (in_array($active, array('finished', 'done'))) { $active = NULL; } - drupal_set_content('left', theme_task_list($tasks, $active)); + drupal_add_region_content('left', theme_task_list($tasks, $active)); } /** diff --git a/modules/block/block.admin.inc b/modules/block/block.admin.inc index 80d1321ba42e..358211f3c5d2 100644 --- a/modules/block/block.admin.inc +++ b/modules/block/block.admin.inc @@ -85,6 +85,8 @@ function block_admin_display_form(&$form_state, $blocks, $theme = NULL) { ); } } + // Do not allow disabling the main system content block. + unset($form['system_main']['region']['#options'][BLOCK_REGION_NONE]); $form['submit'] = array( '#type' => 'submit', diff --git a/modules/block/block.install b/modules/block/block.install index cc2dd690d66a..0b4544ed08cd 100644 --- a/modules/block/block.install +++ b/modules/block/block.install @@ -178,6 +178,16 @@ function block_schema() { */ function block_install() { drupal_install_schema('block'); + + // Block should go first so that other modules can alter its output + // during hook_page_alter(). Almost everything on the page is a block, + // so before block module runs, there will not be much to alter. + db_update('system') + ->fields(array( + 'weight' => -5, + )) + ->condition('name', 'block') + ->execute(); } /** @@ -186,3 +196,16 @@ function block_install() { function block_uninstall() { drupal_uninstall_schema('block'); } + +/** + * Set system.weight to a low value for block module. + * + * Block should go first so that other modules can alter its output + * during hook_page_alter(). Almost everything on the page is a block, + * so before block module runs, there will not be much to alter. + */ +function block_update_7000() { + $ret = array(); + $ret[] = update_sql("UPDATE {system} SET weight = -5 WHERE name = 'block'"); + return $ret; +} diff --git a/modules/block/block.js b/modules/block/block.js index 3fd6a5aba960..b722d30df01c 100644 --- a/modules/block/block.js +++ b/modules/block/block.js @@ -25,10 +25,18 @@ Drupal.behaviors.blockDrag = { // Add a handler so when a row is dropped, update fields dropped into new regions. tableDrag.onDrop = function () { dragObject = this; - if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) { - var regionRow = $(dragObject.rowObject.element).prev('tr').get(0); - var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2'); - var regionField = $('select.block-region-select', dragObject.rowObject.element); + var regionRow = $(dragObject.rowObject.element).prev('tr').get(0); + var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2'); + var regionField = $('select.block-region-select', dragObject.rowObject.element); + // Check whether the newly picked region is available for this block. + if ($('option[value=' + regionName + ']', regionField).length == 0) { + // If not, alert the user and keep the block in its old region setting. + alert(Drupal.t('The block cannot be placed in this region.')); + // Simulate that there was a selected element change, so the row is put + // back to from where the user tried to drag it. + regionField.change(); + } + else if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) { var weightField = $('select.block-weight', dragObject.rowObject.element); var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2'); diff --git a/modules/block/block.module b/modules/block/block.module index aeb4bddc1d41..83146e9ab8da 100644 --- a/modules/block/block.module +++ b/modules/block/block.module @@ -241,7 +241,7 @@ function block_page_alter($page) { // 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 ($page['#show_blocks'] || ($region != 'left' && $region != 'right')) { + if (!empty($page['#show_blocks']) || ($region != 'left' && $region != 'right')) { // Assign blocks to region. if ($blocks = block_get_blocks_by_region($region)) { $page[$region]['blocks'] = $blocks; @@ -760,6 +760,11 @@ function template_preprocess_block(&$variables) { $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even'; $variables['block_id'] = $block_counter[$variables['block']->region]++; + if (is_array($variables['block']->content)) { + // Render the block contents if it is not already rendered. + $variables['block']->content = drupal_render($variables['block']->content); + } + $variables['template_files'][] = 'block-' . $variables['block']->region; $variables['template_files'][] = 'block-' . $variables['block']->module; $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta; diff --git a/modules/blog/blog.pages.inc b/modules/blog/blog.pages.inc index b6b0346f5fe0..ace4f8ece94b 100644 --- a/modules/blog/blog.pages.inc +++ b/modules/blog/blog.pages.inc @@ -60,7 +60,7 @@ function blog_page_user($account) { } drupal_add_feed(url('blog/' . $account->uid . '/feed'), t('RSS - !title', array('!title' => $title))); - return drupal_get_page($build); + return $build; } /** @@ -104,7 +104,7 @@ function blog_page_last() { } drupal_add_feed(url('blog/feed'), t('RSS - blogs')); - return drupal_get_page($build); + return $build; } /** diff --git a/modules/node/node.module b/modules/node/node.module index 1b61ed2fb017..0eb5c3f31bee 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -1325,7 +1325,7 @@ function node_show($node, $message = FALSE) { node_tag_new($node->nid); // For markup consistency with other pages, use node_build_multiple() rather than node_build(). - return drupal_get_page(node_build_multiple(array($node), FALSE)); + return node_build_multiple(array($node), FALSE); } /** @@ -2088,7 +2088,7 @@ function node_page_default() { ); } drupal_set_title(''); - return drupal_get_page($build); + return $build; } /** diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test index 3fcaa454d922..20e75ed6fc78 100644 --- a/modules/simpletest/tests/common.test +++ b/modules/simpletest/tests/common.test @@ -362,12 +362,12 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase { } /** - * Testing drupal_set_content and drupal_get_content. + * Testing drupal_add_region_content and drupal_get_region_content. */ class DrupalSetContentTestCase extends DrupalWebTestCase { public static function getInfo() { return array( - 'name' => t('Drupal set/get content'), + 'name' => t('Drupal set/get regions'), 'description' => t('Performs tests on setting and retrieiving content from theme regions.'), 'group' => t('System') ); @@ -386,22 +386,22 @@ class DrupalSetContentTestCase extends DrupalWebTestCase { // Set some random content for each region available. foreach ($block_regions as $region) { $first_chunk = $this->randomName(32); - drupal_set_content($region, $first_chunk); + drupal_add_region_content($region, $first_chunk); $second_chunk = $this->randomName(32); - drupal_set_content($region, $second_chunk); - // Store the expected result for a drupal_get_content call for this region. + drupal_add_region_content($region, $second_chunk); + // Store the expected result for a drupal_get_region_content call for this region. $values[$region] = $first_chunk . $delimiter . $second_chunk; } - // Ensure drupal_get_content returns expected results when fetching all regions. - $content = drupal_get_content(NULL, $delimiter); + // Ensure drupal_get_region_content returns expected results when fetching all regions. + $content = drupal_get_region_content(NULL, $delimiter); foreach ($content as $region => $region_content) { $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching all regions', array('@region' => $region))); } - // Ensure drupal_get_content returns expected results when fetching a single region. + // Ensure drupal_get_region_content returns expected results when fetching a single region. foreach ($block_regions as $region) { - $region_content = drupal_get_content($region, $delimiter); + $region_content = drupal_get_region_content($region, $delimiter); $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching single region.', array('@region' => $region))); } } diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index e352a60dc39a..a9f040f9632c 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -179,7 +179,9 @@ function system_themes_form() { } else { // Ensure this theme is compatible with this version of core. - if (!isset($theme->info['core']) || $theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) { + // Require the 'content' region to make sure the main page + // content has a common place in all themes. + if (!isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']))) { $incompatible_core[] = $theme->name; } if (version_compare(phpversion(), $theme->info['php']) < 0) { @@ -1882,7 +1884,8 @@ function system_batch_page() { elseif (isset($output)) { // Force a page without blocks or messages to // display a list of collected messages later. - $page = drupal_get_page($output); + drupal_set_page_content($output); + $page = element_info('page'); $page['#show_blocks'] = FALSE; $page['#show_messages'] = FALSE; return $page; diff --git a/modules/system/system.install b/modules/system/system.install index 9b8ab44d385f..d0246fbc883d 100644 --- a/modules/system/system.install +++ b/modules/system/system.install @@ -3347,7 +3347,7 @@ function system_update_7020() { } /** - * Add help block to the help region, migrate custom variables to blocks. + * Add new blocks to new regions, migrate custom variables to blocks. */ function system_update_7021() { $ret = array(); @@ -3359,6 +3359,8 @@ function system_update_7021() { $themes_with_blocks[] = $theme->name; // Add new system generated help block. $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('system', 'help', '" . $theme->name . "', 1, 0, 'help', '', 1)"); + // Add new system generated main page content block. + $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('system', 'main', '" . $theme->name . "', 1, 0, 'content', '', -1)"); } // Migrate contact form information. diff --git a/modules/system/system.module b/modules/system/system.module index 3f7c8521ba64..017c43473e69 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -878,6 +878,11 @@ function system_user_timezone(&$edit, &$form) { * Implementation of hook_block_list(). */ function system_block_list() { + $blocks['main'] = array( + 'info' => t('Main page content'), + // Cached elsewhere. + 'cache' => BLOCK_NO_CACHE, + ); $blocks['powered-by'] = array( 'info' => t('Powered by Drupal'), 'weight' => '10', @@ -946,6 +951,10 @@ function system_block_save($delta = '', $edit = NULL) { function system_block_view($delta = '') { $block = array(); switch ($delta) { + case 'main': + $block['subject'] = NULL; + $block['content'] = drupal_set_page_content(); + return $block; case 'powered-by': $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png'; $block['subject'] = NULL; diff --git a/modules/taxonomy/taxonomy.pages.inc b/modules/taxonomy/taxonomy.pages.inc index 65c81cbb128e..2454c51958dd 100644 --- a/modules/taxonomy/taxonomy.pages.inc +++ b/modules/taxonomy/taxonomy.pages.inc @@ -79,7 +79,7 @@ function taxonomy_term_page($terms, $depth = 0, $op = 'page') { ); } - return drupal_get_page($build); + return $build; case 'feed': $channel['link'] = url('taxonomy/term/' . $str_tids . '/' . $depth, array('absolute' => TRUE)); diff --git a/modules/user/user.pages.inc b/modules/user/user.pages.inc index 36a40bee1add..804f152e6992 100644 --- a/modules/user/user.pages.inc +++ b/modules/user/user.pages.inc @@ -176,7 +176,7 @@ function user_view($account) { '#account' => $account, ); - return drupal_get_page($build); + return $build; } /** diff --git a/profiles/default/default.profile b/profiles/default/default.profile index 0e7465c9d702..c6d6ec469a55 100644 --- a/profiles/default/default.profile +++ b/profiles/default/default.profile @@ -91,8 +91,18 @@ function default_profile_task_list() { */ function default_profile_tasks(&$task, $url) { - // Enable 5 standard blocks. + // Enable some standard blocks. $values = array( + array( + 'module' => 'system', + 'delta' => 'main', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'content', + 'pages' => '', + 'cache' => -1, + ), array( 'module' => 'user', 'delta' => 'login', diff --git a/profiles/expert/expert.profile b/profiles/expert/expert.profile index fdf22f47b35b..a9f09b596748 100644 --- a/profiles/expert/expert.profile +++ b/profiles/expert/expert.profile @@ -42,8 +42,19 @@ function expert_profile_task_list() { * Perform any final installation tasks for this profile. */ function expert_profile_tasks(&$task, $url) { - // Enable 4 standard blocks. + + // Enable some standard blocks. $values = array( + array( + 'module' => 'system', + 'delta' => 'main', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'content', + 'pages' => '', + 'cache' => -1, + ), array( 'module' => 'user', 'delta' => 'login', diff --git a/update.php b/update.php index 15c89bcc688c..7333f178ce1b 100644 --- a/update.php +++ b/update.php @@ -694,7 +694,7 @@ function update_task_list($active = NULL) { 'finished' => 'Review log', ); - drupal_set_content('left', theme('task_list', $tasks, $active)); + drupal_add_region_content('left', theme('task_list', $tasks, $active)); } /** -- GitLab