Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.656 diff -u -F^f -r1.656 common.inc --- includes/common.inc 18 Jun 2007 06:59:11 -0000 1.656 +++ includes/common.inc 20 Jun 2007 12:11:47 -0000 @@ -2694,7 +2694,7 @@ function drupal_common_themes() { 'arguments' => array(), ), 'node' => array( - 'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE), + 'arguments' => array('node' => NULL, 'style' => 'full', 'options' => array()), 'file' => 'node', ), 'submenu' => array( Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.358 diff -u -F^f -r1.358 theme.inc --- includes/theme.inc 8 Jun 2007 12:51:58 -0000 1.358 +++ includes/theme.inc 20 Jun 2007 12:11:48 -0000 @@ -1579,6 +1579,10 @@ function template_preprocess_page(&$vari */ function template_preprocess_node(&$variables) { $node = $variables['node']; + foreach($variables['options'] as $option => $value) { + $variables[$option] = $value; + } + if (module_exists('taxonomy')) { $variables['taxonomy'] = taxonomy_link('taxonomy terms', $node); } @@ -1586,7 +1590,7 @@ function template_preprocess_node(&$vari $variables['taxonomy'] = array(); } - if ($variables['teaser'] && $node->teaser) { + if ($variables['style'] == 'teaser' && $node->teaser) { $variables['content'] = $node->teaser; } elseif (isset($node->body)) { @@ -1616,6 +1620,8 @@ function template_preprocess_node(&$vari $variables['picture'] = ''; } + $variables['template_files'][] = 'node-'. $variables['style'] .'-'. $node->type; + $variables['template_files'][] = 'node-'. $variables['style']; $variables['template_files'][] = 'node-'. $node->type; } Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.345 diff -u -F^f -r1.345 aggregator.module --- modules/aggregator/aggregator.module 5 Jun 2007 12:13:21 -0000 1.345 +++ modules/aggregator/aggregator.module 20 Jun 2007 12:11:49 -0000 @@ -1232,15 +1232,15 @@ function aggregator_page_rss() { } while ($item = db_fetch_object($result)) { - switch (variable_get('feed_item_length', 'teaser')) { - case 'teaser': + switch (variable_get('feed_item_length', NODE_BODY_TRIMMED)) { + case NODE_BODY_TRIMMED: $teaser = node_teaser($item->description); if ($teaser != $item->description) { $teaser .= '
\n"; } $item->description = $teaser; break; - case 'title': + case NODE_BODY_HIDDEN: $item->description = ''; break; } Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.280 diff -u -F^f -r1.280 blog.module --- modules/blog/blog.module 30 Apr 2007 17:03:23 -0000 1.280 +++ modules/blog/blog.module 20 Jun 2007 12:11:49 -0000 @@ -152,7 +152,7 @@ function blog_page_user($uid) { $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); while ($node = db_fetch_object($result)) { - $output .= node_view(node_load($node->nid), 1); + $output .= node_view(node_load($node->nid), 'teaser'); } $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); drupal_add_feed(url('blog/'. $account->uid .'/feed'), t('RSS - !title', array('!title' => $title))); @@ -175,7 +175,7 @@ function blog_page_last() { $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)); while ($node = db_fetch_object($result)) { - $output .= node_view(node_load($node->nid), 1); + $output .= node_view(node_load($node->nid), 'teaser'); } $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); drupal_add_feed(url('blog/feed'), t('RSS - blogs')); @@ -218,21 +218,21 @@ function blog_form(&$node) { /** * Implementation of hook_view(). */ -function blog_view($node, $teaser = FALSE, $page = FALSE) { - if ($page) { +function blog_view($node, $style = 'full', $options = array()) { + if ($options['page']) { // Breadcrumb navigation $breadcrumb[] = array('path' => 'blog', 'title' => t('Blogs')); $breadcrumb[] = array('path' => 'blog/'. $node->uid, 'title' => t("@name's blog", array('@name' => $node->name))); $breadcrumb[] = array('path' => 'node/'. $node->nid); menu_set_location($breadcrumb); } - return node_prepare($node, $teaser); + return node_prepare($node, $style, $options); } /** * Implementation of hook_link(). */ -function blog_link($type, $node = NULL, $teaser = FALSE) { +function blog_link($type, $node = NULL, $style = 'full') { $links = array(); if ($type == 'node' && $node->type == 'blog') { Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.423 diff -u -F^f -r1.423 book.module --- modules/book/book.module 10 Jun 2007 08:55:55 -0000 1.423 +++ modules/book/book.module 20 Jun 2007 12:11:49 -0000 @@ -74,12 +74,12 @@ function book_access($op, $node) { /** * Implementation of hook_link(). */ -function book_link($type, $node = NULL, $teaser = FALSE) { +function book_link($type, $node = NULL, $style = 'full') { $links = array(); if ($type == 'node' && isset($node->parent)) { - if (!$teaser) { + if ($style != 'teaser') { if (book_access('create', $node) && $node->status == 1) { $links['book_add_child'] = array( 'title' => t('Add child page'), @@ -413,14 +413,28 @@ function book_next($node) { } /** - * Returns the content of a given node. If $teaser if TRUE, returns + * Returns the content of a given node. If $style == 'teaser', returns * the teaser rather than full content. Displays the most recently * approved revision of a node (if any) unless we have to display this * page in the context of the moderation queue. */ -function book_content($node, $teaser = FALSE) { +function book_content($node, $style = 'full', $options = array()) { // Return the page body. - return node_prepare($node, $teaser); + return node_prepare($node, $style, $options); +} + +/** + * Implementation of hook_node_styles(). + */ +function book_node_styles() { + $styles['default']['options'] = array( + 'show_book_navigation' => FALSE, + ); + + $styles['full']['options'] = array( + 'show_book_navigation' => TRUE, + ); + return $styles; } /** @@ -428,13 +442,13 @@ function book_content($node, $teaser = F * * Appends book navigation to all nodes in the book. */ -function book_nodeapi(&$node, $op, $teaser, $page) { +function book_nodeapi(&$node, $op, $style = 'full', $options = array()) { switch ($op) { case 'load': return db_fetch_array(db_query('SELECT parent, weight FROM {book} WHERE vid = %d', $node->vid)); break; case 'view': - if (!$teaser) { + if ($options['show_book_navigation']) { if (isset($node->parent)) { $path = book_location($node); // Construct the breadcrumb: @@ -449,7 +463,7 @@ function book_nodeapi(&$node, $op, $teas '#weight' => 100, ); - if ($page) { + if ($options['page']) { menu_set_location($node->breadcrumb); } } @@ -787,20 +801,8 @@ function book_recurse($nid = 0, $depth = * - the HTML generated for the given node. */ function book_node_visitor_html_pre($node, $depth, $nid) { - // Remove the delimiter (if any) that separates the teaser from the body. - $node->body = str_replace('', '', $node->body); - - // The 'view' hook can be implemented to overwrite the default function - // to display nodes. - if (node_hook($node, 'view')) { - $node = node_invoke($node, 'view', FALSE, FALSE); - } - else { - $node = node_prepare($node, FALSE); - } - - // Allow modules to make their own additions to the node. - node_invoke_nodeapi($node, 'print'); + $options = node_get_style_options('print'); + $node = node_build_content($node, 'print', $options); $output .= "");print_r($options);print("");
+ return theme('node', $node, $style, $options);
}
/**
* Apply filters and build the node's standard elements.
*/
-function node_prepare($node, $teaser = FALSE) {
+function node_prepare($node, $style = 'full', $options = array()) {
// First we'll overwrite the existing node teaser and body with
// the filtered copies! Then, we'll stick those into the content
// array and set the read more flag if appropriate.
$node->readmore = (strlen($node->teaser) < strlen($node->body));
- if ($teaser == FALSE) {
- $node->body = check_markup($node->body, $node->format, FALSE);
- }
- else {
- $node->teaser = check_markup($node->teaser, $node->format, FALSE);
+ switch ($options['body_field']) {
+ case NODE_BODY_HIDDEN:
+ $content = '';
+ break;
+
+ case NODE_BODY_TRIMMED:
+ $content = check_markup($node->teaser, $node->format, FALSE);
+ break;
+
+ case NODE_BODY_FULL:
+ $content = check_markup($node->body, $node->format, FALSE);
+ break;
}
- $node->content['body'] = array(
- '#value' => $teaser ? $node->teaser : $node->body,
- '#weight' => 0,
- );
+ if (!empty($content)) {
+ $node->content['body'] = array(
+ '#value' => $content,
+ '#weight' => 0,
+ );
+ }
return $node;
}
@@ -792,30 +802,32 @@ function node_prepare($node, $teaser = F
*
* @param $node
* A node object.
- * @param $teaser
- * Whether to display the teaser only, as on the main page.
- * @param $page
- * Whether the node is being displayed by itself as a page.
+ * @param $style
+ * The node display style to use for rendering. Defaults to 'full'.
+ * @param $options
+ * A keyed array of rendering options for the node.
*
* @return
* An structured array containing the individual elements
* of the node's body.
*/
-function node_build_content($node, $teaser = FALSE, $page = FALSE) {
+function node_build_content($node, $style = 'full', $options = array()) {
// Remove the delimiter (if any) that separates the teaser from the body.
$node->body = isset($node->body) ? str_replace('', '', $node->body) : '';
// The 'view' hook can be implemented to overwrite the default function
// to display nodes.
if (node_hook($node, 'view')) {
- $node = node_invoke($node, 'view', $teaser, $page);
+ $node = node_invoke($node, 'view', $style, $options);
}
else {
- $node = node_prepare($node, $teaser);
+ $node = node_prepare($node, $style, $options);
}
- // Allow modules to make their own additions to the node.
- node_invoke_nodeapi($node, 'view', $teaser, $page);
+ if (empty($options['skip_alter'])) {
+ // Allow modules to make their own additions to the node.
+ node_invoke_nodeapi($node, 'view', $style, $options);
+ }
return $node;
}
@@ -824,19 +836,143 @@ function node_build_content($node, $teas
* Generate a page displaying a single node, along with its comments.
*/
function node_show($node, $cid) {
- $output = node_view($node, FALSE, TRUE);
+ $options = array(
+ 'page' => TRUE,
+ 'mark_read' => TRUE,
+ );
+ $output = node_view($node, 'full', $options);
if (function_exists('comment_render') && $node->comment) {
$output .= comment_render($node, $cid);
}
- // Update the history table, stating that this user viewed this node.
- node_tag_new($node->nid);
-
return $output;
}
/**
+ * Return information about a node display style.
+ *
+ * @param $requested_style
+ * The machine-readable name of a node display style. System
+ * defaults are full, teaser, print, and feed. If no style is
+ * passed in, an array of all available styles will be returned.
+ *
+ * @return
+ * A keyed array containing the name, description, and default
+ * rendering options for the requested style or styles.
+ */
+function node_get_styles($requested_style = NULL) {
+ static $cache;
+
+ if (empty($cache)) {
+ $cache = _node_style_defaults();
+
+ foreach ($cache as $style => $data) {
+ $cache[$style] += array('name' => NULL, 'description' => NULL, 'options' => array());
+ }
+
+ foreach (module_implements('node_styles') as $module) {
+ $styles = module_invoke($module, 'node_styles');
+ if (!empty($styles)) {
+ foreach($styles as $style => $data) {
+ $data += array('name' => NULL, 'description' => NULL, 'options' => array());
+
+ if (empty($cache[$style])) {
+ $cache[$style] = $data;
+ }
+ else {
+ $cache[$style]['options'] = $data['options'] += $cache[$style]['options'];
+ }
+ }
+ }
+ }
+
+ $default = $cache['default'];
+ unset($cache['default']);
+
+ foreach ($cache as $style => $data) {
+ $cache[$style]['options'] += $default['options'];
+ }
+ }
+
+ if (empty($requested_style)) {
+ return $cache;
+ }
+ elseif (array_key_exists($requested_style, $cache)) {
+ return $cache[$requested_style];
+ }
+ else {
+ return $cache['default'];
+ }
+}
+
+
+/**
+ * Return a keyed array of node display style names.
+ */
+function node_get_style_names() {
+ $styles = node_get_styles();
+ foreach ($styles as $key => $style) {
+ $styles[$key] = $style['name'];
+ }
+ return $styles;
+}
+
+/**
+ * Return a keyed array of the default rendering options
+ * for a given node display style.
+ */
+function node_get_style_options($style = 'full') {
+ $styles = node_get_styles();
+ if (!empty($styles[$style])) {
+ return $styles[$style]['options'];
+ }
+}
+
+/**
+ * Return the default rendering options for Drupal's standard
+ * node display styles.
+ */
+function _node_style_defaults() {
+ $styles['default']['options'] = array(
+ 'show_links' => TRUE,
+ 'page' => FALSE,
+ 'mark_read' => FALSE,
+ 'skip_alter' => FALSE,
+ 'body_field' => NODE_BODY_FULL,
+ );
+
+ $styles['full'] = array(
+ 'name' => t('Full'),
+ 'description' => t("The standard view of a node's full content."),
+ );
+
+ $styles['teaser'] = array(
+ 'name' => t('Teaser'),
+ 'description' => t("The trimmed version of a node for use in listings and summaries. The exact length can be configured on the %settings_url page.", array('%settings_url', l('admin/content/settings', 'Content settings'))),
+ 'options' => array(
+ 'body_field' => NODE_BODY_TRIMMED,
+ ),
+ );
+
+ $styles['feed'] = array(
+ 'name' => t('News Feed'),
+ 'description' => t("A streamlined version of a node meant for use in a content syndication feed, like RSS."),
+ 'options' => array(
+ 'show_links' => FALSE,
+ 'body_field' => variable_get('feed_item_length', NODE_BODY_TRIMMED),
+ ),
+ );
+
+ $styles['print'] = array(
+ 'name' => t('Print'),
+ 'description' => t('A printer-friendly version of a node.'),
+ );
+
+ return $styles;
+}
+
+/**
* Implementation of hook_perm().
*/
function node_perm() {
@@ -978,7 +1114,7 @@ function node_search($op = 'search', $ke
foreach ($find as $item) {
// Build the node body.
$node = node_load($item->sid);
- $node = node_build_content($node, FALSE, FALSE);
+ $node = node_build_content($node, 'full', array('show_links' => FALSE));
$node->body = drupal_render($node->content);
// Fetch comments for snippet
@@ -1864,59 +2000,43 @@ function node_feed($nodes = 0, $channel
global $base_url, $language;
if (!$nodes) {
- $nodes = db_query_range(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));
+ $nodes = db_query_range(db_rewrite_sql('SELECT n.nid, n.title, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));
}
- $item_length = variable_get('feed_item_length', 'teaser');
$namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');
+ $options = node_get_style_options('feed');
$items = '';
- while ($node = db_fetch_object($nodes)) {
+ while ($result = db_fetch_object($nodes)) {
// Load the specified node:
- $item = node_load($node->nid);
- $link = url("node/$node->nid", array('absolute' => TRUE));
-
- if ($item_length != 'title') {
- $teaser = ($item_length == 'teaser') ? TRUE : FALSE;
+ $node = node_load($result->nid);
- // Filter and prepare node teaser
- if (node_hook($item, 'view')) {
- $item = node_invoke($item, 'view', $teaser, FALSE);
- }
- else {
- $item = node_prepare($item, $teaser);
- }
+ $link = url("node/$node->nid", array('absolute' => TRUE));
- // Allow modules to change $node->teaser before viewing.
- node_invoke_nodeapi($item, 'view', $teaser, FALSE);
+ if ($options['body_field'] == NODE_BODY_HIDDEN) {
+ $item_text = '';
+ }
+ else {
+ $node = node_build_content($node, 'feed', $options);
+ $item_text = drupal_render($node->content);
}
// Allow modules to add additional item fields and/or modify $item
- $extra = node_invoke_nodeapi($item, 'rss item');
- $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' => date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid .' at '. $base_url, 'attributes' => array('isPermaLink' => 'false'))));
+ $defaults = array(
+ array('key' => 'pubDate', 'value' => date('r', $node->created)),
+ array('key' => 'dc:creator', 'value' => $node->name),
+ array('key' => 'guid', 'value' => $node->nid .' at '. $base_url, 'attributes' => array('isPermaLink' => 'false'))
+ );
+
+ $extra = node_invoke_nodeapi($node, 'rss item');
+ $extra = array_merge($extra, $defaults);
foreach ($extra as $element) {
if (isset($element['namespace'])) {
$namespaces = array_merge($namespaces, $element['namespace']);
}
}
- // Prepare the item description
- switch ($item_length) {
- case 'fulltext':
- $item_text = $item->body;
- break;
- case 'teaser':
- $item_text = $item->teaser;
- if ($item->readmore) {
- $item_text .= ''. l(t('read more'), 'node/'. $item->nid, array('absolute' => TRUE)) .'
'; - } - break; - case 'title': - $item_text = ''; - break; - } - - $items .= format_rss_item($item->title, $link, $item_text, $extra); + $items .= format_rss_item($node->title, $link, $item_text, $extra); } $channel_defaults = array( @@ -2314,12 +2434,12 @@ function theme_node_preview($node) { if (!empty($node->teaser) && !empty($node->body) && $node->teaser != $node->body) { 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 .= '