Index: drupal/includes/common.inc diff -u drupal/includes/common.inc:1.1.2.3 drupal/includes/common.inc:1.1.2.3.2.4 --- drupal/includes/common.inc:1.1.2.3 Mon Apr 5 13:09:44 2004 +++ drupal/includes/common.inc Sun Apr 11 20:02:23 2004 @@ -746,22 +746,125 @@ return $output; } -function format_rss_item($title, $link, $description, $args = array()) { - // arbitrary elements may be added using the $args associative array - - $output = "\n"; - $output .= " ". drupal_specialchars(strip_tags($title)) ."\n"; - $output .= " ". drupal_specialchars(strip_tags($link)) ."\n"; - $output .= " ". drupal_specialchars(check_output($description)) ."\n"; - foreach ($args as $key => $value) { - $output .= "<$key>". drupal_specialchars(strip_tags($value)) .""; +function format_rss_item(&$namespaces, $node, $version) { + $xml['item']->contents['title']->contents = drupal_specialchars(strip_tags($node->title)); + $xml['item']->contents['link']->contents = drupal_specialchars(strip_tags(url("node/view/$node->nid", NULL, NULL, 1))); + $xml['item']->contents['description']->contents = drupal_specialchars(check_output($node->teaser ? $node->teaser : $node->body)); + $xml['item']->contents['pubDate']->contents = date('r', $node->changed); + + foreach (module_list() as $name) { + $function = $name ."_rss_item"; + if (function_exists($function)) { + $function($xml['item']->contents, $namespaces, $node, $version); + } } - $output .= "\n"; + + return format_xml($xml); +} +/** + * Formats an associative array of XML tags as an xml document. Each array key + * is the name (including abbreviated namespace) of a top level tag. The array + * values are objects containing the attributes and contents of the xml tag. + * The object format is described in detail in the documentation for the + * format_xml_tag function. + * + * @param $xml An associative array of tag name => xml tag as object + * @return String of indented XML + */ +function format_xml($xml) { + foreach ($xml as $tag => $content) { + $output .= format_xml_tag($content, $tag); + } return $output; } /** + * An xml tag contains two important things, attributes and contents, these are + * the two variables in an xml tag object as processed by this function. Either + * or both may be omitted if applicable. + * + * $xml->attributes is an associative array of attribute names as keys with + * attribute values as values. + * $xml->contents can either be a string or array of tags. If the tag only + * contains a string then use a string. If it is an array of tags, then + * contents will be an associative array with tag names as keys. The values of + * the associative array are other objects constructed in the same way if there + * is only one tag with that name; if there are multiples then the value will + * be a simple array of objects. + * + * This function makes no attempt to assure valid xml output, if the input is + * not well formed, then the output won't be well formed either. Use proper + * entity coding where necessary, especially for angle brackets, ampersands, + * and double quotes. + * + * @param $xml An object structured to represent an XML tag as described above. + * @param $name The name of the represented XML tag. + * @param $indent The base indentation of the tag as a string of whitespace. + * @return A string containing the XML tag in XML format. + */ +function format_xml_tag($xml, $name, $indent = '') { + $result = $indent .'<'. $name; + if ($xml->attributes) { + foreach ($xml->attributes as $attribute => $value) { + $result .= ' '. $attribute .'="'. $value .'"'; + } + } + if (is_array($xml->contents)) { + $result .= ">\n"; + foreach ($xml->contents as $tag => $content) { + if (is_array($content)) { + foreach($content as $content_value) { + $result .= format_xml_tag($content_value, $tag, ' '. $indent); + } + } + else { + $result .= format_xml_tag($content, $tag, ' '. $indent); + } + } + $result .= $indent .''; + } + else if ($xml->contents) { + $result .= '>'. $xml->contents .''; + } + else { + $result .= ' />'; + } + return $result ."\n"; +} + +/** + * Formats a date accorfing to the W3C pecification at + * http://www.w3.org/TR/NOTE-datetime + * + * @param $timestamp The exact date to format. + * @param $precision either 'year', 'month', 'day', or 'time'. + * @param $timezone Timezone offset in seconds in case the user timezone + * should not be used. + * @return The W3C formatted date with the requested percision. + */ +function format_w3c_date($timestamp, $precision = 'time', $timzone = NULL) { + if ($timezone === NULL) { + global $user; + $timezone = $user->uid ? $user->timezone : variable_get('date_default_timezone', 0); + } + $timestamp += $timezone; + + switch ($precision) { + case 'time': + $result = 'T'. gmdate('H', $timestamp) .':'. gmdate('i', $timestamp) . sprintf('%s%02d:%02d', ($timezone < 0 ? '-' : '+'), abs($timezone / 3600), abs($timezone % 3600) / 60) . $result; + case 'day': + $result = '-'. gmdate('d', $timestamp) . $result; + case 'month': + $result = '-'. gmdate('m', $timestamp) . $result; + case 'year': + $result = gmdate('Y', $timestamp) . $result; + } + + return $result; +} + +/** * Formats a string with a count of items so that the string is pluralized * correctly. format_plural calls t() by itself, make sure not to pass already * localized strings to it. Index: drupal/modules/node.module diff -u drupal/modules/node.module:1.1.2.4 drupal/modules/node.module:1.1.2.4.2.4 --- drupal/modules/node.module:1.1.2.4 Wed Apr 7 09:25:26 2004 +++ drupal/modules/node.module Mon Apr 12 12:55:37 2004 @@ -1002,18 +1002,8 @@ $nodes = db_query_range('SELECT nid FROM {node} WHERE promote = 1 AND status = 1 ORDER BY created DESC', 0, 15); } - while ($node = db_fetch_object($nodes)) { - /* - ** Load the specified node: - */ - - $item = node_load(array('nid' => $node->nid)); - $link = url("node/view/$node->nid", NULL, NULL, 1); - $items .= format_rss_item($item->title, $link, ($item->teaser ? $item->teaser : $item->body), array('pubDate' => date('r', $item->changed))); - } - $channel_defaults = array( - 'version' => '0.92', + 'version' => '2.0', 'title' => variable_get('site_name', 'drupal') .' - '. variable_get('site_slogan', ''), 'link' => $base_url, 'description' => variable_get('site_mission', ''), @@ -1021,9 +1011,18 @@ ); $channel = array_merge($channel_defaults, $channel); + $namespaces = array(); + while ($node = db_fetch_object($nodes)) { + $items .= format_rss_item($namespaces, node_load(array('nid' => $node->nid)), $channel["version"]); + } + $output = "\n"; $output .= "]>\n"; - $output .= "\n"; + $output .= " $url) { + $output .= " xmlns:$ns=\"$url\""; + } + $output .= ">\n"; $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']); $output .= "\n";