]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/RssWriter.php
extra_empty_lines
[SourceForge/phpwiki.git] / lib / RssWriter.php
1 <?php // $Id$
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         echo('<'.'?xml version="1.0" encoding="'.RSS_ENCODING.'"?'.">\n");
121         //printf("<!-- generator=\"PhpWiki-%s\" -->\n", PHPWIKI_VERSION);
122         $this->printXML();
123     }
124
125     /**
126      * Create a new RDF <em>typedNode</em>.
127      */
128     function __node($type, $properties, $uri = false) {
129     if (! $uri)
130         $uri = $properties['link'];
131     $attr['rdf:about'] = $this->__uniquify_uri($uri);
132     return new XmlElement($type, $attr,
133                               $this->__elementize($properties));
134     }
135
136     /**
137      * Check object URI for uniqueness, create a unique URI if needed.
138      */
139     function __uniquify_uri ($uri) {
140     if (!$uri || isset($this->_uris_seen[$uri])) {
141         $n = count($this->_uris_seen);
142         $uri = $this->_channel->getAttr('rdf:about') . "#uri$n";
143         assert(!isset($this->_uris_seen[$uri]));
144     }
145     $this->_uris_seen[$uri] = true;
146     return $uri;
147     }
148
149     /**
150      * Convert hash of RDF properties to <em>propertyElt</em>s.
151      */
152     function __elementize ($elements) {
153     $out = array();
154         foreach ($elements as $prop => $val) {
155         $this->__check_predicate($prop);
156         if (is_array($val))
157             $out[] = new XmlElement($prop, $val);
158         elseif (is_object($val))
159             $out[] = $val;
160         else
161             $out[] = new XmlElement($prop, false, $val);
162     }
163     return $out;
164     }
165
166     /**
167      * Check property predicates for XMLNS sanity.
168      */
169     function __check_predicate ($name) {
170     if (preg_match('/^([^:]+):[^:]/', $name, $m)) {
171         $ns = $m[1];
172         if (! $this->getAttr("xmlns:$ns")) {
173         if (!isset($this->_modules[$ns]))
174             die("$name: unknown namespace ($ns)");
175         $this->setAttr("xmlns:$ns", $this->_modules[$ns]);
176         }
177     }
178     }
179
180     /**
181      * Create a <em>propertyElt</em> which references another node in the RSS.
182      */
183     function __ref($predicate, $reference) {
184         $attr['rdf:resource'] = $reference->getAttr('rdf:about');
185         return new XmlElement($predicate, $attr);
186     }
187 };
188
189 /* Taken from mediawiki.
190  * See http://www.atomenabled.org/developers/syndication/
191  */
192 class AtomFeed extends RssWriter {
193
194     // Args should include:
195     //  'title', 'link', 'description'
196     // and can include:
197     //  'URI'
198     function feed($properties, $uri = false) {
199         global $LANG;
200         $attr = array('xmlns' => 'http://www.w3.org/2005/Atom',
201                   'version' => '0.3', // or 1.0
202                   'lang' => $LANG);
203         $this->_channel = $this->__node('feed', $attr, $properties, $uri);
204     }
205
206     /**
207      * Write output to HTTP client.
208      */
209     function __spew() {
210         header("Content-Type: application/atom+xml; charset=" . RSS_ENCODING);
211         echo('<'.'?xml version="1.0" encoding="'.RSS_ENCODING.'"?'.">\n");
212         //printf("<!-- generator=\"PhpWiki-%s\" -->\n", PHPWIKI_VERSION);
213         $this->printXML();
214     }
215
216     /**
217      * Create a new entry
218      */
219     function __node($type, $attr, $properties, $uri = false) {
220     if (! $uri)
221         $uri = $properties['link'];
222     //$attr['rdf:about'] = $this->__uniquify_uri($uri);
223     return new XmlElement($type, $attr,
224                               $this->__elementize($properties));
225     }
226
227     // Args should include:
228     //  'title', 'link', author, modified, issued, created, summary,
229     // and can include:
230     //  comment
231     function addItem($properties, $attr=false, $uri = false) {
232         $this->_items[] = $this->__node('entry', $attr, $properties, $uri);
233     }
234
235     /**
236      * Print it.
237      */
238     function finish() {
239         if (isset($this->_finished))
240             return;
241
242         $channel = &$this->_channel;
243         $items = &$this->_items;
244     if ($items)
245         $channel->pushContent($items);
246     $this->pushContent($channel);
247
248         $this->__spew();
249         $this->_finished = true;
250     }
251 }
252
253 // Local Variables:
254 // mode: php
255 // tab-width: 8
256 // c-basic-offset: 4
257 // c-hanging-comment-ender-p: nil
258 // indent-tabs-mode: nil
259 // End:
260 ?>