Hi, attached to this message you will find a patch for savane (SVN towards-1.5) which adds (very) basic RSS feed support to savane.
This patch only adds news-feed support, nothing else. However, using the FeedItem and Feed classes it should be trivial to add feed support for something other than news items. The code in feed/news.php shows how this could be done. (Note: this patch might require you to create the feed directory in <savane_source>/frontend/php). Best regards, Stephan Peijnik
Index: include/Feed.class =================================================================== --- include/Feed.class (revision 0) +++ include/Feed.class (revision 0) @@ -0,0 +1,146 @@ +<?php +# This file is part of the Savane project +# <http://gna.org/projects/savane/> +# +# $Id$ +# +# Copyright 2006 (C) Stephan Peijnik <sp--at--fsfe.org> +# +# The Savane project is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# The Savane project is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the Savane project; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +require 'version.php'; + +class FeedItem +{ + # feed item's title + var $title; + # feed item's link + var $link; + # feed item's description + var $description; + # feed item's guid + var $guid; + # feed item's pubDate (unix timestamp!) + var $pubDate; + + function FeedItem($title, $link, $description, $guid, $pubDate) + { + $this->title = $title; + $this->link = $link; + $this->description = str_replace("\r\n", "", $description); + $this->guid = $guid; + $this->pubDate = date("r", $pubDate); + } + + # return the item's XML data + function getXMLData() + { + $res = ""; + + # indent <item> by 4 spaces and <item>'s members by 6 + # <rss> is at level 0 (-> 0 * 2 = 0) + # <channel> is at level 1 (-> 1 * 2 = 0) + # <item> is hence at level 2 (-> 2 * 2 = 4) + + # open up a new 'item' + $res .= " <item>\n"; + + $res .= " <title>" . $this->title ."</title>\n"; + $res .= " <link>". $this->link ."</link>\n"; + $res .= " <description>". $this->description + ."</description>\n"; + $res .= " <guid isPermaLink=\"true\">". $this->guid ."</guid>\n"; + $res .= " <pubDate>". $this->pubDate ."</pubDate>\n"; + + # close item again + $res .= " </item>\n"; + + return $res; + } +} + +class Feed +{ + # feed name + var $title; + # feed description + var $description; + # feed link + var $link; + # feed items + var $items; + # last build date + var $lastBuildDate; + + function Feed($title, $description, $link) + { + $this->title = $title; + $this->description = $description; + $this->link = $link; + $this->lastBuildDate = 0; + $this->items = array(); + } + + # add item to feed + function addItem($item) + { + if (!method_exists($item, "FeedItem")) + { + #uhoh, die! + die("Feed.class: object not of type FeedItem"); + } + $this->items[] = $item; + } + + # get feed's XML data + # this function generates the complete feed and returns it + function getXMLData() + { + $res = ""; + + # let's start with the mandatory things... + # this is an RSS feed of version 2.0 and RSS feeds are XML, right? ;) + $res .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; + $res .= "<rss version=\"2.0\">\n"; + $res .= " <channel>\n"; + + # before adding all the items go for the channel description + $res .= " <title>" . $this->title ."</title>\n"; + $res .= " <link>" . $this->link ."</link>\n"; + $res .= " <description>". $this->description ."</description>\n"; + $res .= " <lastBuildDate>". $this->lastBuildDate + ."</lastBuildDate>\n"; + $res .= " <generator>Savane ". $GLOBALS['savane_version'] . + "</generator>\n"; + $res .= " <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n"; + + # time to add every item's data + foreach($this->items as $item) + { + $res .= $item->getXMLData(); + } + + $res .= " </channel>\n"; + $res .= "</rss>\n"; + + return $res; + } + + function setLastBuildDate($lastBuildDate) + { + # use RFC822 datetime stamp + $this->lastBuildDate = date("r", $lastBuildDate); + } +} Index: feed/news.php =================================================================== --- feed/news.php (revision 0) +++ feed/news.php (revision 0) @@ -0,0 +1,146 @@ +<?php +# This file is part of the Savane project +# <http://gna.org/projects/savane/> +# +# $Id$ +# +# Copyright 2006 (C) Stephan Peijnik <sp--at--fsfe.org> +# +# The Savane project is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# The Savane project is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the Savane project; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +require '../include/pre.php'; +require '../include/Feed.class'; + +if ($_POST['group_id']) + { + $group_id = $_POST['group_id']; + } +elseif ($_GET['group_id']) + { + $group_id = $_GET['group_id']; + } + +if (!$group_id) +{ + $group_id = $GLOBALS['sys_group_id']; +} + +if ($_POST['group']) + { + $group = $_POST['group']; + } +elseif ($_GET['group']) + { + $group = $_GET['group']; + } + +$project=project_get_object($group_id); + +# TODO: this should generate some sort of 404 or a minimalistic +# 'error' feed +if (!$project->Uses("news") || !$project->isActive() || + !$project->isPublic()) +{ exit_error(_("This project has turned off the news tool.")); } + +$feed_title = $project->getPublicName() . " - news [". $sys_name ."]"; +$feed_link = "http://". $GLOBALS['sys_default_domain'] . + "/news/?group=" . $project->getUnixName(); + + +$feed = new Feed($feed_title, $feed_title, $feed_link); + +# this query is taken from include/news/general.php and should be okay +# however, we are using a fixed limit of 10 entries here +$sql = "SELECT user.user_name,news_bytes.forum_id,news_bytes.summary,news_bytes.date,news_bytes.details ". + "FROM user, news_bytes ". + "WHERE news_bytes.group_id='$group_id' AND ". + " news_bytes.is_approved <> 4 AND ". + " news_bytes.is_approved <> 5 AND ". + " user.user_id=news_bytes.submitted_by ". + "ORDER BY date DESC ". + "LIMIT 10"; + +$result = db_query($sql); + +if (!$result) +{ + print mysql_error(); +} + +$rows = db_numrows($result); + +if (!$result || $rows < 1) +{ + # TODO: error handling + exit; +} + +$summ_txt = ""; + +$lastBuildDate = 0; + +# again, taken from include/news/general.php +for($i = 0; $i < $rows; $i++) +{ + $story = rtrim(db_result($result, $i, 'details')); + if (strlen($story) > 500) + { + $summ_txt = substr($story, 0, 250); + $summ_txt = substr($summ_txt, 0, strrpos($summ_txt, ' ')); + $summ_txt .= "..."; + $summ_txt = "<br /><br />". + utils_make_links(nl2br($summ_txt), $group_id); + $summ_txt .= sprintf(_("%s[Read more]%s"), "<br />" . + "<a href=\"http://". $GLOBALS['sys_default_domain'] . + $GLOBALS['sys_home']. "forum/forum.php?" . + "forum_id=". db_result($result, $i, 'forum_id'). "\">", + "</a>"); + } + else + { + $summ_txt = "<br /><br />" . utils_make_links(nl2br($story), $group_id); + } + + $item_link = "http://" . $GLOBALS['sys_default_domain'] . + $GLOBALS['sys_home']. 'forum/forum.php?forum_id=' . + db_result($result, $i, 'forum_id'); + $item_date = db_result($result, $i, 'date'); + $summ_txt .= "<br /><br />". _("posted by")." <a href=\"http://". + $GLOBALS['sys_default_domain'] . + $GLOBALS['sys_home']."users/". + db_result($result, $i, 'user_name'). "\">". + db_result($result, $i, 'user_name'). "</a> on ". + format_date($sys_datefm, $item_date). "."; + + # having '<' and '>' in an XML node's content would break things + $summ_txt = htmlentities($summ_txt); + + $feeditem = new FeedItem(db_result($result, $i, 'summary'), $item_link, + $summ_txt, $item_link, $item_date); + $feed->addItem($feeditem); + + if ($item_date > $lastBuildDate) + { + $lastBuildDate = $item_date; + } +} + +# we really need to send another content-type here +header("Content-Type: application/xml"); +$feed->setLastBuildDate($lastBuildDate); +print $feed->getXMLData(); + +?>
signature.asc
Description: Digital signature
_______________________________________________ Savane-dev mailing list [email protected] https://mail.gna.org/listinfo/savane-dev
