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();
+
+?>

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Savane-dev mailing list
[email protected]
https://mail.gna.org/listinfo/savane-dev

Reply via email to