- Patch #351235 by dmitrig01, webchick, frando, moshe weitzman, et al: hook_page_alter. Oh, behave.

merge-requests/26/head
Dries Buytaert 2009-01-27 00:22:27 +00:00
parent ba5609c11a
commit 2e8ca690ff
17 changed files with 379 additions and 200 deletions

View File

@ -301,8 +301,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 instead of a return in your menu callback.
*
* @param $path
* A Drupal path or a full URL.
@ -379,19 +378,23 @@ function drupal_not_found() {
$path = drupal_get_normal_path(variable_get('site_404', ''));
if ($path && $path != $_GET['q']) {
// Set the active item in case there are tabs to display, or other
// dependencies on the path.
// Custom 404 handler. Set the active item in case there are tabs to
// display, or other dependencies on the path.
menu_set_active_item($path);
$return = menu_execute_active_handler($path);
}
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
// Standard 404 handler.
drupal_set_title(t('Page not found'));
$return = t('The requested page could not be found.');
}
$page = drupal_get_page($return);
// To conserve CPU and bandwidth, omit the blocks.
print theme('page', $return, FALSE);
$page['#show_blocks'] = FALSE;
print drupal_render_page($page);
}
/**
@ -408,17 +411,19 @@ function drupal_access_denied() {
$path = drupal_get_normal_path(variable_get('site_403', ''));
if ($path && $path != $_GET['q']) {
// Set the active item in case there are tabs to display or other
// dependencies on the path.
// Custom 403 handler. Set the active item in case there are tabs to
// display or other dependencies on the path.
menu_set_active_item($path);
$return = menu_execute_active_handler($path);
}
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
// Standard 403 handler.
drupal_set_title(t('Access denied'));
$return = t('You are not authorized to access this page.');
}
print theme('page', $return);
print drupal_render_page($return);
}
/**
@ -816,7 +821,10 @@ 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.
$page = drupal_get_page(t('The website encountered an unexpected error. Please try again later.'));
$page['#show_blocks'] = FALSE;
print drupal_render_page($page);
}
else {
print theme('maintenance_page', t('The website encountered an unexpected error. Please try again later.'), FALSE);
@ -3194,6 +3202,53 @@ function drupal_alter($type, &$data) {
}
}
/**
* Retrieve a $page element that is ready for decorating.
*
* Used by menu callbacks in order to populate the page with content
* and behavior (e.g. #show_blocks).
*
* @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().
*/
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;
}
/**
* Renders the page, including all theming.
*
* @param $page
* 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()
*/
function drupal_render_page($page) {
// Allow menu callbacks to return strings.
if (is_string($page)) {
$page = drupal_get_page($page);
}
// Modules alter the $page as needed. Blocks are populated into regions like
// 'left', 'footer', etc.
drupal_alter('page', $page);
return drupal_render($page);
}
/**
* Renders HTML given a structured array tree.
*
@ -3366,7 +3421,7 @@ function drupal_common_theme() {
'arguments' => array('text' => NULL)
),
'page' => array(
'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE),
'arguments' => array('page' => NULL),
'template' => 'page',
),
'maintenance_page' => array(
@ -3425,6 +3480,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),
),

View File

@ -1568,6 +1568,25 @@ function theme_item_list($items = array(), $title = NULL, $type = 'ul', $attribu
return $output;
}
/**
* 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').
* - #title: a title which prints above the list.
* - #list_type: the type of list to return. Defaults to "ul".
* - #attributes: an array of attributes as expected by theme('item_list').
* @return
* A string containing the list output.
*/
function theme_list($elements) {
// Populate any missing array elements with their defaults.
$elements += _element_info('list');
return theme('item_list', $elements['#items'], $elements['#title'], $elements['#list_type'], $elements['#attributes']);
}
/**
* Returns code that emits the 'more help'-link.
*/
@ -1630,30 +1649,6 @@ function theme_closure($main = 0) {
return implode("\n", $footer) . drupal_get_js('footer');
}
/**
* 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 == <i>module</i>_<i>delta</i>
$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.
*
@ -1816,32 +1811,26 @@ function template_preprocess(&$variables, $hook) {
* Any changes to variables in this preprocessor should also be changed inside
* template_preprocess_maintenance_page() to keep all of them consistent.
*
* The $variables array contains the following arguments:
* - $content
* - $show_blocks
* The $variables array contains two keys:
* - 'page': the fully decorated page.
* - 'content': the content of the page, already rendered.
*
* @see drupal_render_page
* @see page.tpl.php
*/
function template_preprocess_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" />');
// Move some variables to the top level for themer convenience and template cleanliness.
$variables['show_blocks'] = $variables['page']['#show_blocks'];
$variables['show_messages'] = $variables['page']['#show_messages'];
// Render each region into top level variables.
foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
$variables[$region_key] = empty($variables['page'][$region_key]) ? '' : drupal_render($variables['page'][$region_key]);
}
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;
// 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" />');
}
// Set up layout variable.
@ -1881,8 +1870,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', '') : '');
@ -1975,6 +1964,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);
@ -1982,17 +1973,17 @@ function template_preprocess_node(&$variables) {
$variables['node_url'] = url('node/' . $node->nid);
$variables['title'] = check_plain($node->title);
$variables['page'] = (bool)menu_get_object();
if ($node->build_mode == NODE_BUILD_PREVIEW) {
unset($node->content['links']);
}
// Render taxonomy links separately.
$variables['terms'] = !empty($node->content['links']['terms']) ? drupal_render($node->content['links']['terms']) : '';
// Render all remaining node links.
$variables['links'] = !empty($node->content['links']) ? drupal_render($node->content['links']) : '';
// Render any comments.
$variables['comments'] = !empty($node->content['comments']) ? drupal_render($node->content['comments']) : '';
@ -2035,6 +2026,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;

View File

@ -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.
print drupal_render_page($return);
}
drupal_page_footer();

View File

@ -368,8 +368,6 @@ function template_preprocess_block_admin_display_form(&$variables) {
$variables['block_regions'] = $block_regions + array(BLOCK_REGION_NONE => t('Disabled'));
foreach ($block_regions as $key => $value) {
// Highlight regions on page to provide visual reference.
drupal_set_content($key, '<div class="block-region">' . $value . '</div>');
// Initialize an empty array for the region.
$variables['block_listing'][$key] = array();
}

View File

@ -225,6 +225,61 @@ function block_block_view($delta = 0, $edit = array()) {
return $data;
}
/**
* Implementation of hook_page_alter().
*
* Render blocks into their regions.
*/
function block_page_alter($page) {
global $theme;
// The theme system might not yet be initialized. We need $theme.
init_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 ($page['#show_blocks'] || ($region != 'left' && $region != 'right')) {
// Assign blocks to region.
if ($blocks = block_get_blocks_by_region($region)) {
$page[$region]['blocks'] = $blocks;
}
// Append region description if we are rendering the block admin page.
$item = menu_get_item();
if ($item['path'] == 'admin/build/block') {
$description = '<div class="block-region">' . $regions[$region] . '</div>';
$page[$region]['blocks']['block_description'] = array('#markup' => $description);
}
}
}
}
/**
* Get a renderable array of a region containing all enabled blocks.
*
* @param $region
* The requested region.
*/
function block_get_blocks_by_region($region) {
$weight = 0;
$build = array();
if ($list = block_list($region)) {
foreach ($list as $key => $block) {
$build[$key] = array(
'#theme' => 'block',
'#block' => $block,
'#weight' => ++$weight,
);
}
$build['#sorted'] = TRUE;
}
return $build;
}
/**
* Update the 'block' DB table with the blocks currently exported by modules.
*

View File

@ -23,18 +23,20 @@ function blog_page_user($account) {
$items[] = t('You are not allowed to post a new blog entry.');
}
$output = theme('item_list', $items);
$build['blog_actions'] = array(
'#items' => $items,
'#theme' => 'list',
'#weight' => -1,
);
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid);
$has_posts = FALSE;
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load($node->nid), 1);
$has_posts = TRUE;
}
if ($has_posts) {
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
$nids = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid)->fetchCol();
if (!empty($nids)) {
$nodes = node_load_multiple($nids);
$build += node_build_multiple($nodes);
$build['pager'] = array(
'#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10)),
'#weight' => 5,
);
}
else {
if ($account->uid == $user->uid) {
@ -46,7 +48,7 @@ function blog_page_user($account) {
}
drupal_add_feed(url('blog/' . $account->uid . '/feed'), t('RSS - !title', array('!title' => $title)));
return $output;
return drupal_get_page($build);
}
/**
@ -54,33 +56,33 @@ function blog_page_user($account) {
*/
function blog_page_last() {
global $user;
$output = '';
$items = array();
$build = array();
if (user_access('edit own blog')) {
$items[] = l(t('Create new blog entry.'), "node/add/blog");
$build['blog_actions'] = array(
'#items' => $items,
'#theme' => 'list',
'#weight' => -1,
);
}
$output = theme('item_list', $items);
$nids = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10))->fetchCol();
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10));
$has_posts = FALSE;
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load($node->nid), 1);
$has_posts = TRUE;
}
if ($has_posts) {
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
if (!empty($nids)) {
$nodes = node_load_multiple($nids);
$build += node_build_multiple($nodes);
$build['pager'] = array(
'#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10)),
'#weight' => 5,
);
}
else {
drupal_set_message(t('No blog entries have been created.'));
}
drupal_add_feed(url('blog/feed'), t('RSS - blogs'));
return $output;
return drupal_get_page($build);
}
/**

View File

@ -1649,7 +1649,7 @@ function comment_form_add_preview($form, &$form_state) {
}
else {
$suffix = empty($form['#suffix']) ? '' : $form['#suffix'];
$form['#suffix'] = $suffix . node_view($node);
$form['#suffix'] = $suffix . drupal_render(node_build($node));
$edit['pid'] = 0;
}

View File

@ -92,7 +92,7 @@ function comment_reply($node, $pid = NULL) {
}
// This is the case where the comment is in response to a node. Display the node.
elseif (user_access('access content')) {
$output .= node_view($node);
$output .= drupal_render(node_build($node));
}
// Should we show the reply box?

View File

@ -81,7 +81,7 @@ function hook_node_access_records($node) {
return;
}
// We only care about the node if it's been marked private. If not, it is
// We only care about the node if it has been marked private. If not, it is
// treated just like any other node and we completely ignore it.
if ($node->private) {
$grants = array();
@ -169,7 +169,7 @@ function hook_node_operations() {
* @return
* None.
*/
function hook_nodeapi_alter($node, $teaser, $page) {
function hook_nodeapi_alter($node, $teaser) {
}
/**

View File

@ -96,7 +96,7 @@ function node_help($path, $arg) {
function node_theme() {
return array(
'node' => array(
'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE),
'arguments' => array('elements' => NULL),
'template' => 'node',
),
'node_list' => array(
@ -1126,24 +1126,28 @@ function node_delete($nid) {
}
/**
* Generate a display of the given node.
* Generate an array for rendering the given node.
*
* @param $node
* A node array or node object.
* @param $teaser
* Whether to display the teaser only or the full form.
* @param $links
* Whether or not to display node links. Links are omitted for node previews.
*
* @return
* An HTML representation of the themed node.
* An array as expected by drupal_render().
*/
function node_view($node, $teaser = FALSE) {
function node_build($node, $teaser = FALSE) {
$node = (object)$node;
$node = node_build_content($node, $teaser);
return theme('node', $node, $teaser);
$build = $node->content;
$build += array(
'#theme' => 'node',
'#node' => $node,
'#teaser' => $teaser,
);
return $build;
}
/**
@ -1205,25 +1209,31 @@ function node_build_content($node, $teaser = FALSE) {
node_invoke_nodeapi($node, 'view', $teaser);
// Allow modules to modify the structured node.
drupal_alter('node_view', $node, $teaser);
drupal_alter('node_build', $node, $teaser);
return $node;
}
/**
* Generate a page displaying a single node.
* Generate an array which displays a node detail page.
*
* @param $node
* A node object.
* @param $message
* A flag which sets a page title relevant to the revision being viewed.
* @return
* A $page element suitable for use by drupal_page_render().
*/
function node_show($node, $message = FALSE) {
if ($message) {
drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))), PASS_THROUGH);
}
$output = node_view($node, FALSE, TRUE);
// Update the history table, stating that this user viewed this node.
node_tag_new($node->nid);
return $output;
// For markup consistency with other pages, use node_build_multiple() rather than node_build().
return drupal_get_page(node_build_multiple(array($node), FALSE));
}
/**
@ -1904,21 +1914,44 @@ function node_feed($nids = FALSE, $channel = array()) {
print $output;
}
/**
* Construct a drupal_render() style array from an array of loaded nodes.
*
* @param $nodes
* An array of nodes as returned by node_load_multiple().
* @param $teaser
* Display nodes into teaser view or full view.
* @param $weight
* An integer representing the weight of the first node in the list.
* @return
* An array in the format expected by drupal_render().
*/
function node_build_multiple($nodes, $teaser = TRUE, $weight = 0) {
$build = array();
foreach ($nodes as $node) {
$build['nodes'][$node->nid] = node_build($node, $teaser);
$build['nodes'][$node->nid]['#weight'] = $weight;
$weight++;
}
$build['nodes']['#sorted'] = TRUE;
return $build;
}
/**
* Menu callback; Generate a listing of promoted nodes.
*/
function node_page_default() {
$nids = pager_query(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10))->fetchCol();
$nids = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10))->fetchCol();
if (!empty($nids)) {
$nodes = node_load_multiple($nids);
$output = '';
foreach ($nodes as $node) {
$output .= node_view($node, TRUE);
}
$build = node_build_multiple($nodes);
$feed_url = url('rss.xml', array('absolute' => TRUE));
drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') . ' ' . t('RSS'));
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
$build['pager'] = array(
'#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10)),
'#weight' => 5,
);
}
else {
$default_message = '<h1 class="title">' . t('Welcome to your new Drupal website!') . '</h1>';
@ -1930,12 +1963,14 @@ function node_page_default() {
$default_message .= '<li>' . t('<strong>Start posting content</strong> Finally, you can <a href="@content">create content</a> for your website. This message will disappear once you have promoted a post to the front page.', array('@content' => url('node/add'))) . '</li>';
$default_message .= '</ol>';
$default_message .= '<p>' . t('For more information, please refer to the <a href="@help">help section</a>, or the <a href="@handbook">online Drupal handbooks</a>. You may also post at the <a href="@forum">Drupal forum</a>, or view the wide range of <a href="@support">other support options</a> available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '</p>';
$output = '<div id="first-time">' . $default_message . '</div>';
$build['default_message'] = array(
'#markup' => $default_message,
'#prefix' => '<div id="first-time">',
'#suffix' => '</div>',
);
}
drupal_set_title('');
return $output;
return drupal_get_page($build);
}
/**
@ -2969,7 +3004,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_build(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;

View File

@ -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.<span class="no-js"> You can insert the delimiter "&lt;!--break--&gt;" (without the quotes) to fine-tune where your post gets split.</span>'));
$output .= '<h3>' . t('Preview trimmed version') . '</h3>';
$output .= node_view(clone $node, 1, FALSE);
$output .= drupal_render(node_build(clone $node, TRUE));
$output .= '<h3>' . t('Preview full version') . '</h3>';
$output .= node_view($node, 0, FALSE);
$output .= drupal_render(node_build($node, FALSE));
}
else {
$output .= node_view($node, 0, FALSE);
$output .= drupal_render(node_build($node, FALSE));
}
$output .= "</div>\n";

View File

@ -1888,7 +1888,10 @@ function system_batch_page() {
elseif (isset($output)) {
// Force a page without blocks or messages to
// display a list of collected messages later.
print theme('page', $output, FALSE, FALSE);
$page = drupal_get_page($output);
$page['#show_blocks'] = FALSE;
$page['#show_messages'] = FALSE;
return $page;
}
}

View File

@ -179,6 +179,63 @@ function hook_js_alter(&$javascript) {
$javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
}
/**
* Perform alterations before a page is rendered.
*
* Use this hook when you want to add, remove, or alter elements at the page
* level. If you are making changes to entities such as forms, menus, or user
* profiles, use those objects' native alter hooks instead (hook_form_alter(),
* for example).
*
* The $page array contains top level elements for each block region:
* @code
* $page['header']
* $page['left']
* $page['content']
* $page['right']
* $page['footer']
* @endcode
*
* The 'content' element contains the main content of the current page, and its
* structure will vary depending on what module is responsible for building the
* page. Some legacy modules may not return structured content at all: their
* pre-rendered markup will be located in $page['content']['main']['#markup'].
*
* Pages built by Drupal's core Node and Blog modules use a standard structure:
*
* @code
* // Node body.
* $page['content']['nodes'][$nid]['body']
* // Array of links attached to the node (add comments, read more).
* $page['content']['nodes'][$nid]['links']
* // The node object itself.
* $page['content']['nodes'][$nid]['#node']
* // The results pager.
* $page['content']['pager']
* @code
*
* Blocks may be referenced by their module/delta pair within a region:
* @code
* // The login block in the left sidebar region.
* $page['left']['user-login']['#block'];
* @endcode
*
* @param $page
* Nested array of renderable elements that make up the page.
*
* @see drupal_render_page()
*/
function hook_page_alter($page) {
if (menu_get_object('node', 1)) {
// We are on a node detail page. Append a standard disclaimer to the
// content region.
$page['content']['disclaimer'] = array(
'#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
'#weight' => 25,
);
}
}
/**
* Perform alterations before a form is rendered.
*

View File

@ -237,6 +237,19 @@ function system_elements() {
'#action' => request_uri(),
);
$type['page'] = array(
'#show_messages' => TRUE,
'#show_blocks' => TRUE,
'#theme' => 'page',
);
$type['list'] = array(
'#title' => '',
'#list_type' => 'ul',
'#attributes' => array(),
'#items' => array(),
);
/**
* Input elements.
*/

View File

@ -26,9 +26,6 @@ function taxonomy_theme() {
'taxonomy_term_select' => array(
'arguments' => array('element' => NULL),
),
'taxonomy_term_page' => array(
'arguments' => array('tids' => array(), 'result' => NULL),
),
'taxonomy_overview_vocabularies' => array(
'arguments' => array('form' => array()),
),
@ -73,7 +70,7 @@ function taxonomy_nodeapi_view($node) {
}
}
}
$node->content['links']['terms'] = array(
'#type' => 'node_links',
'#value' => $links,
@ -323,7 +320,7 @@ function taxonomy_term_save($term) {
$status = drupal_write_record('taxonomy_term_data', $term);
module_invoke_all('taxonomy_term_update', $term);
}
$or = db_or()->condition('tid1', $term->tid)->condition('tid2', $term->tid);
db_delete('taxonomy_term_relation')->condition($or)->execute();
@ -1224,7 +1221,7 @@ function theme_taxonomy_term_select($element) {
* @param $order
* The order clause for the query that retrieve the nodes.
* @return
* A resource identifier pointing to the query results.
* An array of node IDs.
*/
function taxonomy_select_nodes($tids = array(), $operator = 'or', $depth = 0, $pager = TRUE, $order = 'n.sticky DESC, n.created DESC') {
if (count($tids) > 0) {
@ -1254,44 +1251,20 @@ function taxonomy_select_nodes($tids = array(), $operator = 'or', $depth = 0, $p
$wheres .= ' AND tn' . $index . '.tid IN (' . db_placeholders($tids, 'int') . ')';
$args = array_merge($args, $tids);
}
$sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created FROM {node} n ' . $joins . ' WHERE n.status = 1 ' . $wheres . ' ORDER BY ' . $order;
$sql = 'SELECT DISTINCT(n.nid) AS nid, n.sticky, n.created FROM {node} n ' . $joins . ' WHERE n.status = 1 ' . $wheres . ' ORDER BY ' . $order;
$sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n ' . $joins . ' WHERE n.status = 1 ' . $wheres;
}
$sql = db_rewrite_sql($sql);
$sql_count = db_rewrite_sql($sql_count);
if ($pager) {
$result = pager_query($sql, variable_get('default_nodes_main', 10), 0, $sql_count, $args);
$nids = pager_query($sql, variable_get('default_nodes_main', 10), 0, $sql_count, $args)->fetchCol();
}
else {
$result = db_query_range($sql, $args, 0, variable_get('feed_default_items', 10));
$nids = db_query_range($sql, $args, 0, variable_get('feed_default_items', 10))->fetchCol();
}
}
return $result;
}
/**
* Accepts the result of a pager_query() call, such as that performed by
* taxonomy_select_nodes(), and formats each node along with a pager.
*/
function taxonomy_render_nodes($result) {
$output = '';
$nids = array();
foreach ($result as $record) {
$nids[] = $record->nid;
}
if (!empty($nids)) {
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
$output .= node_view($node, 1);
}
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
}
else {
$output .= '<p>' . t('There are currently no posts in this category.') . '</p>';
}
return $output;
return $nids;
}
/**

View File

@ -42,11 +42,40 @@ function taxonomy_term_page($terms, $depth = 0, $op = 'page') {
$breadcrumb[] = l(t('Home'), NULL);
$breadcrumb = array_reverse($breadcrumb);
drupal_set_breadcrumb($breadcrumb);
$output = theme('taxonomy_term_page', $tids, taxonomy_select_nodes($tids, $terms['operator'], $depth, TRUE));
drupal_add_feed(url('taxonomy/term/' . $str_tids . '/' . $depth . '/feed'), 'RSS - ' . $title);
return $output;
break;
drupal_add_css(drupal_get_path('module', 'taxonomy') . '/taxonomy.css');
$build = array();
// 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]);
if (!empty($term->description)) {
$build['term_description'] = array(
'#markup' => filter_xss_admin($term->description),
'#weight' => -1,
'#prefix' => '<div class="taxonomy-term-description">',
'#suffix' => '</div>',
);
}
}
if ($nids = taxonomy_select_nodes($tids, $terms['operator'], $depth, TRUE)) {
$nodes = node_load_multiple($nids);
$build += node_build_multiple($nodes);
$build['pager'] = array(
'#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10)),
'#weight' => 5,
);
}
else {
$build['no_content'] = array(
'#prefix' => '<p>',
'#markup' => t('There are currently no posts in this category.'),
'#suffix' => '</p>',
);
}
return drupal_get_page($build);
case 'feed':
$channel['link'] = url('taxonomy/term/' . $str_tids . '/' . $depth, array('absolute' => TRUE));
@ -58,13 +87,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:
@ -77,38 +102,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 .= '<div class="taxonomy-term-description">';
$output .= filter_xss_admin($description);
$output .= '</div>';
}
}
$output .= taxonomy_render_nodes($result);
return $output;
}
/**
* Page to edit a vocabulary term.
*/

View File

@ -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_build($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.