]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/RssWriter.php
add ATOM support, a very questionable format
[SourceForge/phpwiki.git] / lib / RssWriter.php
1 <?php rcs_id('$Id: RssWriter.php,v 1.14 2007-07-01 09:17:45 rurban Exp $');
2 /*
3  * Code for creating RSS 1.0.
4  */
5
6 // Encoding for RSS output.
7 if (!defined('RSS_ENCODING'))
8   define('RSS_ENCODING', $GLOBALS['charset']);
9
10 /**
11  * A class for writing RSS 1.0.
12  *
13  * @see http://purl.org/rss/1.0/spec,
14  *      http://www.usemod.com/cgi-bin/mb.pl?ModWiki
15  */
16 class RssWriter extends XmlElement
17 {
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#'));
22
23         $this->_modules = array(
24             //Standards
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/",
28             //Proposed
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/"
38             );
39
40         $this->_uris_seen = array();
41         $this->_items = array();
42     }
43
44     function registerModule($alias, $uri) {
45         assert(!isset($this->_modules[$alias]));
46         $this->_modules[$alias] = $uri;
47     }
48
49     // Args should include:
50     //  'title', 'link', 'description'
51     // and can include:
52     //  'URI'
53     function channel($properties, $uri = false) {
54         $this->_channel = $this->__node('channel', $properties, $uri);
55     }
56     
57     // Args should include:
58     //  'title', 'link'
59     // and can include:
60     //  'description', 'URI'
61     function addItem($properties, $uri = false) {
62         $this->_items[] = $this->__node('item', $properties, $uri);
63     }
64
65     // Args should include:
66     //  'url', 'title', 'link'
67     // and can include:
68     //  'URI'
69     function image($properties, $uri = false) {
70         $this->_image = $this->__node('image', $properties, $uri);
71     }
72
73     // Args should include:
74     //  'title', 'description', 'name', and 'link'
75     // and can include:
76     //  'URI'
77     function textinput($properties, $uri = false) {
78         $this->_textinput = $this->__node('textinput', $properties, $uri);
79     }
80
81     /**
82      * Finish construction of RSS.
83      */
84     function finish() {
85         if (isset($this->_finished))
86             return;
87
88         $channel = &$this->_channel;
89         $items = &$this->_items;
90
91         $seq = new XmlElement('rdf:Seq');
92         if ($items) {
93             foreach ($items as $item)
94                 $seq->pushContent($this->__ref('rdf:li', $item));
95         }
96         $channel->pushContent(new XmlElement('items', false, $seq));
97      
98         if (isset($this->_image)) {
99             $channel->pushContent($this->__ref('image', $this->_image));
100             $items[] = $this->_image;
101         }
102         if (isset($this->_textinput)) {
103             $channel->pushContent($this->__ref('textinput', $this->_textinput));
104             $items[] = $this->_textinput;
105         }
106
107         $this->pushContent($channel);
108         if ($items)
109             $this->pushContent($items);
110
111         $this->__spew();
112         $this->_finished = true;
113     }
114             
115     /**
116      * Write output to HTTP client.
117      */
118     function __spew() {
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);
122         $this->printXML();
123     }
124         
125     
126     /**
127      * Create a new RDF <em>typedNode</em>.
128      */
129     function __node($type, $properties, $uri = false) {
130         if (! $uri)
131             $uri = $properties['link'];
132         $attr['rdf:about'] = $this->__uniquify_uri($uri);
133         return new XmlElement($type, $attr,
134                               $this->__elementize($properties));
135     }
136
137     /**
138      * Check object URI for uniqueness, create a unique URI if needed.
139      */
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]));
145         }
146         $this->_uris_seen[$uri] = true;
147         return $uri;
148     }
149
150     /**
151      * Convert hash of RDF properties to <em>propertyElt</em>s.
152      */
153     function __elementize ($elements) {
154         $out = array();
155         foreach ($elements as $prop => $val) {
156             $this->__check_predicate($prop);
157             if (is_array($val))
158                 $out[] = new XmlElement($prop, $val);
159             elseif (is_object($val))    
160                     $out[] = $val; 
161             else
162                 $out[] = new XmlElement($prop, false, $val);
163         }
164         return $out;
165     }
166
167     /**
168      * Check property predicates for XMLNS sanity.
169      */
170     function __check_predicate ($name) {
171         if (preg_match('/^([^:]+):[^:]/', $name, $m)) {
172             $ns = $m[1];
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]);
177             }
178         }
179     }
180
181     /**
182      * Create a <em>propertyElt</em> which references another node in the RSS.
183      */
184     function __ref($predicate, $reference) {
185         $attr['rdf:resource'] = $reference->getAttr('rdf:about');
186         return new XmlElement($predicate, $attr);
187     }
188 };
189
190 /* taken from mediawiki */
191 class AtomFeed extends RssWriter {
192   
193     // Args should include:
194     //  'title', 'link', 'description'
195     // and can include:
196     //  'URI'
197     function feed($properties, $uri = false) {
198         global $LANG;
199         $attr = array('xmlns' => 'http://www.w3.org/2005/Atom',
200                       'version' => '0.3', // or 1.0
201                       'lang' => $LANG);
202         $this->_channel = $this->__node('feed', $attr, $properties, $uri);
203     }
204
205     /**
206      * Write output to HTTP client.
207      */
208     function __spew() {
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);
212         /*
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>
218         */
219         $this->printXML();
220     }
221
222     /**
223      * Create a new entry
224      */
225     function __node($type, $attr, $properties, $uri = false) {
226         if (! $uri)
227             $uri = $properties['link'];
228         //$attr['rdf:about'] = $this->__uniquify_uri($uri);
229         return new XmlElement($type, $attr,
230                               $this->__elementize($properties));
231     }
232
233     // Args should include:
234     //  'title', 'link', author, modified, issued, created, summary,
235     // and can include:
236     //  comment
237     function addItem($properties, $attr=false, $uri = false) {
238         $this->_items[] = $this->__node('entry', $attr, $properties, $uri);
239     /*
240         <entry>
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 } ?>
247         
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 }?> 
252         </entry> 
253     */
254     }
255
256     /**
257      * Finish construction of RSS.
258      */
259     function finish() {
260         if (isset($this->_finished))
261             return;
262
263         $channel = &$this->_channel;
264         $items = &$this->_items;
265         /*
266         $seq = new XmlElement('rdf:Seq');
267         if ($items) {
268             foreach ($items as $item)
269                 $seq->pushContent($this->__ref('rdf:li', $item));
270         }
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;
275         }
276         if (isset($this->_textinput)) {
277             $channel->pushContent($this->__ref('textinput', $this->_textinput));
278             $items[] = $this->_textinput;
279         }
280         */
281
282         if ($items)
283             $channel->pushContent($items);
284         $this->pushContent($channel);
285
286         $this->__spew();
287         $this->_finished = true;
288     }
289 }
290
291
292 // (c-file-style: "gnu")
293 // Local Variables:
294 // mode: php
295 // tab-width: 8
296 // c-basic-offset: 4
297 // c-hanging-comment-ender-p: nil
298 // indent-tabs-mode: nil
299 // End:   
300 ?>