1 <?php rcs_id('$Id: RssWriter.php,v 1.14 2007-07-01 09:17:45 rurban Exp $');
3 * Code for creating RSS 1.0.
6 // Encoding for RSS output.
7 if (!defined('RSS_ENCODING'))
8 define('RSS_ENCODING', $GLOBALS['charset']);
11 * A class for writing RSS 1.0.
13 * @see http://purl.org/rss/1.0/spec,
14 * http://www.usemod.com/cgi-bin/mb.pl?ModWiki
16 class RssWriter extends XmlElement
18 function RssWriter () {
19 $this->XmlElement('rdf:RDF',
20 array('xmlns' => "http://purl.org/rss/1.0/",
21 'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'));
23 $this->_modules = array(
25 'content' => "http://purl.org/rss/1.0/modules/content/",
26 'dc' => "http://purl.org/dc/elements/1.1/",
27 'sy' => "http://purl.org/rss/1.0/modules/syndication/",
29 'wiki' => "http://purl.org/rss/1.0/modules/wiki/",
30 'ag' => "http://purl.org/rss/1.0/modules/aggregation/",
31 'annotate' => "http://purl.org/rss/1.0/modules/annotate/",
32 'audio' => "http://media.tangent.org/rss/1.0/",
33 'cp' => "http://my.theinfo.org/changed/1.0/rss/",
34 'rss091' => "http://purl.org/rss/1.0/modules/rss091/",
35 'slash' => "http://purl.org/rss/1.0/modules/slash/",
36 'taxo' => "http://purl.org/rss/1.0/modules/taxonomy/",
37 'thr' => "http://purl.org/rss/1.0/modules/threading/"
40 $this->_uris_seen = array();
41 $this->_items = array();
44 function registerModule($alias, $uri) {
45 assert(!isset($this->_modules[$alias]));
46 $this->_modules[$alias] = $uri;
49 // Args should include:
50 // 'title', 'link', 'description'
53 function channel($properties, $uri = false) {
54 $this->_channel = $this->__node('channel', $properties, $uri);
57 // Args should include:
60 // 'description', 'URI'
61 function addItem($properties, $uri = false) {
62 $this->_items[] = $this->__node('item', $properties, $uri);
65 // Args should include:
66 // 'url', 'title', 'link'
69 function image($properties, $uri = false) {
70 $this->_image = $this->__node('image', $properties, $uri);
73 // Args should include:
74 // 'title', 'description', 'name', and 'link'
77 function textinput($properties, $uri = false) {
78 $this->_textinput = $this->__node('textinput', $properties, $uri);
82 * Finish construction of RSS.
85 if (isset($this->_finished))
88 $channel = &$this->_channel;
89 $items = &$this->_items;
91 $seq = new XmlElement('rdf:Seq');
93 foreach ($items as $item)
94 $seq->pushContent($this->__ref('rdf:li', $item));
96 $channel->pushContent(new XmlElement('items', false, $seq));
98 if (isset($this->_image)) {
99 $channel->pushContent($this->__ref('image', $this->_image));
100 $items[] = $this->_image;
102 if (isset($this->_textinput)) {
103 $channel->pushContent($this->__ref('textinput', $this->_textinput));
104 $items[] = $this->_textinput;
107 $this->pushContent($channel);
109 $this->pushContent($items);
112 $this->_finished = true;
116 * Write output to HTTP client.
119 header("Content-Type: application/xml; charset=" . RSS_ENCODING);
120 printf("<?xml version=\"1.0\" encoding=\"%s\"?>\n", RSS_ENCODING);
121 printf("<!-- generator=\"PhpWiki-%s\" -->\n", PHPWIKI_VERSION);
127 * Create a new RDF <em>typedNode</em>.
129 function __node($type, $properties, $uri = false) {
131 $uri = $properties['link'];
132 $attr['rdf:about'] = $this->__uniquify_uri($uri);
133 return new XmlElement($type, $attr,
134 $this->__elementize($properties));
138 * Check object URI for uniqueness, create a unique URI if needed.
140 function __uniquify_uri ($uri) {
141 if (!$uri || isset($this->_uris_seen[$uri])) {
142 $n = count($this->_uris_seen);
143 $uri = $this->_channel->getAttr('rdf:about') . "#uri$n";
144 assert(!isset($this->_uris_seen[$uri]));
146 $this->_uris_seen[$uri] = true;
151 * Convert hash of RDF properties to <em>propertyElt</em>s.
153 function __elementize ($elements) {
155 foreach ($elements as $prop => $val) {
156 $this->__check_predicate($prop);
158 $out[] = new XmlElement($prop, $val);
159 elseif (is_object($val))
162 $out[] = new XmlElement($prop, false, $val);
168 * Check property predicates for XMLNS sanity.
170 function __check_predicate ($name) {
171 if (preg_match('/^([^:]+):[^:]/', $name, $m)) {
173 if (! $this->getAttr("xmlns:$ns")) {
174 if (!isset($this->_modules[$ns]))
175 die("$name: unknown namespace ($ns)");
176 $this->setAttr("xmlns:$ns", $this->_modules[$ns]);
182 * Create a <em>propertyElt</em> which references another node in the RSS.
184 function __ref($predicate, $reference) {
185 $attr['rdf:resource'] = $reference->getAttr('rdf:about');
186 return new XmlElement($predicate, $attr);
190 /* taken from mediawiki */
191 class AtomFeed extends RssWriter {
193 // Args should include:
194 // 'title', 'link', 'description'
197 function feed($properties, $uri = false) {
199 $attr = array('xmlns' => 'http://www.w3.org/2005/Atom',
200 'version' => '0.3', // or 1.0
202 $this->_channel = $this->__node('feed', $attr, $properties, $uri);
206 * Write output to HTTP client.
209 header("Content-Type: application/atom+xml; charset=" . RSS_ENCODING);
210 printf("<?xml version=\"1.0\" encoding=\"%s\"?>\n", RSS_ENCODING);
211 printf("<!-- generator=\"PhpWiki-%s\" -->\n", PHPWIKI_VERSION);
213 <feed version="0.3" xmlns="http://www.w3.org/2005/Atom" xml:lang="$LANG">
214 <title><?php print $this->getTitle() ?></title>
215 <link rel="alternate" type="text/html" href="<?php print $this->getUrl() ?>"/>
216 <modified><?= gmdate( 'Y-m-d\TH:i:s', wfTimestamp( TS_UNIX, $ts ) ) ?>Z</modified>
217 <tagline><?php print $this->getDescription() ?></tagline>
225 function __node($type, $attr, $properties, $uri = false) {
227 $uri = $properties['link'];
228 //$attr['rdf:about'] = $this->__uniquify_uri($uri);
229 return new XmlElement($type, $attr,
230 $this->__elementize($properties));
233 // Args should include:
234 // 'title', 'link', author, modified, issued, created, summary,
237 function addItem($properties, $attr=false, $uri = false) {
238 $this->_items[] = $this->__node('entry', $attr, $properties, $uri);
241 <title><?php print $item->getTitle() ?></title>
242 <link rel="alternate" type="<?php print $wgMimeType ?>" href="<?php print $item->getUrl() ?>"/>
243 <?php if( $item->getDate() ) { ?>
244 <modified><?php print $this->formatTime( $item->getDate() ) ?>Z</modified>
245 <issued><?php print $this->formatTime( $item->getDate() ) ?></issued>
246 <created><?php print $this->formatTime( $item->getDate() ) ?>Z</created><?php } ?>
248 <summary type="text/plain"><?php print $item->getDescription() ?></summary>
249 <?php if( $item->getAuthor() ) { ?><author><name><?php print $item->getAuthor() ?></name><!-- <url></url><email></email> --></author><?php }?>
250 <comment>foobar</comment>
251 <?php if( $item->getComments() ) { ?><dc:comment><?php print $item->getComments() ?></dc:comment><?php }?>
257 * Finish construction of RSS.
260 if (isset($this->_finished))
263 $channel = &$this->_channel;
264 $items = &$this->_items;
266 $seq = new XmlElement('rdf:Seq');
268 foreach ($items as $item)
269 $seq->pushContent($this->__ref('rdf:li', $item));
271 $channel->pushContent(new XmlElement('items', false, $seq));
272 if (isset($this->_image)) {
273 $channel->pushContent($this->__ref('image', $this->_image));
274 $items[] = $this->_image;
276 if (isset($this->_textinput)) {
277 $channel->pushContent($this->__ref('textinput', $this->_textinput));
278 $items[] = $this->_textinput;
283 $channel->pushContent($items);
284 $this->pushContent($channel);
287 $this->_finished = true;
292 // (c-file-style: "gnu")
297 // c-hanging-comment-ender-p: nil
298 // indent-tabs-mode: nil