Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.339 diff -u -r1.339 aggregator.module --- modules/aggregator/aggregator.module 14 May 2007 13:43:33 -0000 1.339 +++ modules/aggregator/aggregator.module 17 May 2007 15:38:01 -0000 @@ -1233,15 +1233,15 @@ } 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/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.111 diff -u -r1.111 system.install --- modules/system/system.install 17 May 2007 07:28:42 -0000 1.111 +++ modules/system/system.install 17 May 2007 15:38:06 -0000 @@ -4032,6 +4032,13 @@ return $ret; } +function system_update_6017() { + $old_keys = array('title' => NODE_BODY_HIDDEN, 'teaser' => NODE_BODY_TRIMMED, 'fulltext' => NODE_BODY_FULL); + $rss_item_length = variable_get('feed_item_length', 'teaser'); + variable_set('feed_item_length', $old_keys[$rss_item_length]); + return array(); +} + /** * @} End of "defgroup updates-5.x-to-6.x" * The next series of updates should start at 7000. Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.478 diff -u -r1.478 system.module --- modules/system/system.module 17 May 2007 07:28:42 -0000 1.478 +++ modules/system/system.module 17 May 2007 15:38:07 -0000 @@ -823,8 +823,8 @@ $form['feed_item_length'] = array( '#type' => 'select', '#title' => t('Display of XML feed items'), - '#default_value' => variable_get('feed_item_length', 'teaser'), - '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')), + '#default_value' => variable_get('feed_item_length', NODE_BODY_TRIMMED), + '#options' => array(NODE_BODY_HIDDEN => t('Titles only'), NODE_BODY_TRIMMED => t('Titles plus teaser'), NODE_BODY_FULL => t('Full text')), '#description' => t('Global setting for the length of XML feed items that are output by default.') ); Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.397 diff -u -r1.397 forum.module --- modules/forum/forum.module 14 May 2007 13:43:36 -0000 1.397 +++ modules/forum/forum.module 17 May 2007 15:38:02 -0000 @@ -166,7 +166,7 @@ /** * Implementation of hook_nodeapi(). */ -function forum_nodeapi(&$node, $op, $teaser, $page) { +function forum_nodeapi(&$node, $op, $style = 'full', $options = array()) { switch ($op) { case 'delete revision': db_query('DELETE FROM {forum} WHERE vid = %d', $node->vid); @@ -313,11 +313,22 @@ } } +function forum_node_styles() { + $styles['default']['options'] = array( + 'show_forum_navigation' => FALSE, + ); + + $styles['full']['options'] = array( + 'show_forum_navigation' => TRUE, + ); + return $styles; +} + /** * Implementation of hook_view(). */ -function forum_view(&$node, $teaser = FALSE, $page = FALSE) { - if ($page) { +function forum_view(&$node, $style = 'full', $options = array()) { + if ($options['page']) { $vocabulary = taxonomy_vocabulary_load(variable_get('forum_nav_vocabulary', '')); // Breadcrumb navigation $breadcrumb = array(); @@ -332,8 +343,8 @@ menu_set_location($breadcrumb); } - $node = node_prepare($node, $teaser); - if (!$teaser) { + $node = node_prepare($node, $style, $options); + if ($options['show_forum_navigation']) { $node->content['forum_navigation'] = array( '#value' => theme('forum_topic_navigation', $node), '#weight' => 100, @@ -1185,5 +1196,3 @@ $order = _forum_get_topic_order($sortby); return $order['field'] .' '. $order['sort']; } - - Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.814 diff -u -r1.814 node.module --- modules/node/node.module 16 May 2007 13:45:16 -0000 1.814 +++ modules/node/node.module 17 May 2007 15:38:03 -0000 @@ -8,6 +8,9 @@ */ define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60); +define('NODE_BODY_HIDDEN', 0); +define('NODE_BODY_TRIMMED', 1); +define('NODE_BODY_FULL', 2); /** * Implementation of hook_help(). @@ -735,54 +738,62 @@ * @return * An HTML representation of the themed node. */ -function node_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) { +function node_view($node, $style = 'full', $options = array()) { $node = (object)$node; - $node = node_build_content($node, $teaser, $page); + // Let's merge in the default display options for the current node + // style. + $defaults = node_get_style_options($style); + $options += $defaults; - if ($links) { - $node->links = module_invoke_all('link', 'node', $node, !$page); + $node = node_build_content($node, $style, $options); + + if (!empty($options['show_links'])) { + $node->links = module_invoke_all('link', 'node', $node, $style); drupal_alter('link', $node->links, $node); } - // Set the proper node part, then unset unused $node part so that a bad - // theme can not open a security hole. - $content = drupal_render($node->content); - if ($teaser) { - $node->teaser = $content; - unset($node->body); - } - else { - $node->body = $content; - unset($node->teaser); - } + $node->teaser = $node->body = drupal_render($node->content); // Allow modules to modify the fully-built node. - node_invoke_nodeapi($node, 'alter', $teaser, $page); + node_invoke_nodeapi($node, 'alter', $style, $options); + + if ($options['mark_read']) { + node_tag_new($node->nid); + } - return theme('node', $node, $teaser, $page); + 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; } @@ -801,21 +812,23 @@ * 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,18 +837,121 @@ * 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; } +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']; + } +} + + +function node_get_style_names() { + $styles = node_get_styles(); + foreach ($styles as $key => $style) { + $styles[$key] = $style['name']; + } + return $styles; +} + + +function node_get_style_options($style = 'full') { + $styles = node_get_styles(); + if (!empty($styles[$style])) { + return $styles[$style]['options']; + } +} + + +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(). */ @@ -978,7 +1094,7 @@ 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 @@ -1851,59 +1967,42 @@ 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)); + $node = node_load($result->nid); - if ($item_length != 'title') { - $teaser = ($item_length == 'teaser') ? TRUE : FALSE; - - // 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 = 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( @@ -2295,12 +2394,12 @@ 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 .= ''. t('The outline feature allows you to include posts in the book hierarchy.', array('@book' => url('book'))) .'
'; } } - - Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.160 diff -u -r1.160 upload.module --- modules/upload/upload.module 14 May 2007 13:43:38 -0000 1.160 +++ modules/upload/upload.module 17 May 2007 15:38:07 -0000 @@ -49,11 +49,11 @@ /** * Implementation of hook_link(). */ -function upload_link($type, $node = NULL, $teaser = FALSE) { +function upload_link($type, $node = NULL, $style = 'full') { $links = array(); // Display a link with the number of attachments - if ($teaser && $type == 'node' && isset($node->files) && user_access('view uploaded files')) { + if ($style == 'teaser' && $type == 'node' && isset($node->files) && user_access('view uploaded files')) { $num_files = 0; foreach ($node->files as $file) { if ($file->list) { @@ -484,7 +484,7 @@ /** * Implementation of hook_nodeapi(). */ -function upload_nodeapi(&$node, $op, $teaser) { +function upload_nodeapi(&$node, $op, $style = 'full', $options = array()) { switch ($op) { case 'load': @@ -508,7 +508,7 @@ // Add the attachments list to node body with a heavy // weight to ensure they're below other elements if (count($node->files)) { - if (!$teaser && user_access('view uploaded files')) { + if ($style != 'teaser' && user_access('view uploaded files')) { $node->content['files'] = array( '#value' => theme('upload_attachments', $node->files), '#weight' => 50, Index: themes/chameleon/chameleon.theme =================================================================== RCS file: /cvs/drupal/drupal/themes/chameleon/chameleon.theme,v retrieving revision 1.65 diff -u -r1.65 chameleon.theme --- themes/chameleon/chameleon.theme 6 May 2007 05:47:52 -0000 1.65 +++ themes/chameleon/chameleon.theme 17 May 2007 15:38:07 -0000 @@ -122,12 +122,12 @@ return $output; } -function chameleon_node($node, $teaser = 0, $page = 0) { +function chameleon_node($node, $style = 'full', $options = array()) { $output = "