]> git.immae.eu Git - github/wallabag/wallabag.git/blame - inc/3rdparty/libraries/feedwriter/FeedWriter.php
[fix] rss feed content type set to text/xml #636
[github/wallabag/wallabag.git] / inc / 3rdparty / libraries / feedwriter / FeedWriter.php
CommitLineData
42c80841
NL
1<?php\r
2define('RSS2', 1, true);\r
3define('JSON', 2, true);\r
4define('JSONP', 3, true);\r
5\r
6 /**\r
7 * Univarsel Feed Writer class\r
8 *\r
9 * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed)\r
10 *\r
11 * Modified for FiveFilters.org's Full-Text RSS project\r
182faf26 12 * to allow for inclusion of hubs, JSON output.\r
42c80841 13 * Stripped RSS1 and ATOM support.\r
182faf26 14 *\r
42c80841
NL
15 * @package UnivarselFeedWriter\r
16 * @author Anis uddin Ahmad <anisniit@gmail.com>\r
17 * @link http://www.ajaxray.com/projects/rss\r
18 */\r
19 class FeedWriter\r
20 {\r
7a873ef1
NL
21 private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html\r
22 private $hubs = array(); // PubSubHubbub hubs\r
23 private $channels = array(); // Collection of channel elements\r
24 private $items = array(); // Collection of items as object of FeedItem class.\r
25 private $data = array(); // Store some other version wise data\r
26 private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA\r
27 private $xsl = null; // stylesheet to render RSS (used by Chrome)\r
28 private $json = null; // JSON object\r
29\r
30 private $version = null;\r
31\r
32 /**\r
33 * Constructor\r
34 *\r
35 * @param constant the version constant (RSS2 or JSON).\r
36 */\r
37 function __construct($version = RSS2)\r
38 {\r
39 $this->version = $version;\r
40\r
41 // Setting default value for assential channel elements\r
42 $this->channels['title'] = $version . ' Feed';\r
43 $this->channels['link'] = 'http://www.ajaxray.com/blog';\r
44\r
45 //Tag names to encode in CDATA\r
46 $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');\r
47 }\r
48\r
49 public function setFormat($format) {\r
50 $this->version = $format;\r
51 }\r
52\r
53 // Start # public functions ---------------------------------------------\r
54\r
55 /**\r
56 * Set a channel element\r
57 * @access public\r
58 * @param srting name of the channel tag\r
59 * @param string content of the channel tag\r
60 * @return void\r
61 */\r
62 public function setChannelElement($elementName, $content)\r
63 {\r
64 $this->channels[$elementName] = $content ;\r
65 }\r
66\r
67 /**\r
68 * Set multiple channel elements from an array. Array elements\r
69 * should be 'channelName' => 'channelContent' format.\r
70 *\r
71 * @access public\r
72 * @param array array of channels\r
73 * @return void\r
74 */\r
75 public function setChannelElementsFromArray($elementArray)\r
76 {\r
77 if(! is_array($elementArray)) return;\r
78 foreach ($elementArray as $elementName => $content)\r
79 {\r
80 $this->setChannelElement($elementName, $content);\r
81 }\r
82 }\r
83\r
84 /**\r
85 * Genarate the actual RSS/JSON file\r
86 *\r
87 * @access public\r
88 * @return void\r
89 */\r
90 public function genarateFeed()\r
91 {\r
6212acfc
NL
92 header('Content-type: text/xml; charset=UTF-8');\r
93 // this line prevents Chrome 20 from prompting download\r
94 // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss\r
95 header('X-content-type-options: nosniff');\r
96\r
7a873ef1
NL
97 $this->printHead();\r
98 $this->printChannels();\r
99 $this->printItems();\r
100 $this->printTale();\r
101 if ($this->version == JSON || $this->version == JSONP) {\r
102 echo json_encode($this->json);\r
103 }\r
104 }\r
105\r
106 /**\r
107 * Create a new FeedItem.\r
108 *\r
109 * @access public\r
110 * @return object instance of FeedItem class\r
111 */\r
112 public function createNewItem()\r
113 {\r
114 $Item = new FeedItem($this->version);\r
115 return $Item;\r
116 }\r
117\r
118 /**\r
119 * Add a FeedItem to the main class\r
120 *\r
121 * @access public\r
122 * @param object instance of FeedItem class\r
123 * @return void\r
124 */\r
125 public function addItem($feedItem)\r
126 {\r
127 $this->items[] = $feedItem;\r
128 }\r
129\r
130 // Wrapper functions -------------------------------------------------------------------\r
131\r
132 /**\r
133 * Set the 'title' channel element\r
134 *\r
135 * @access public\r
136 * @param srting value of 'title' channel tag\r
137 * @return void\r
138 */\r
139 public function setTitle($title)\r
140 {\r
141 $this->setChannelElement('title', $title);\r
142 }\r
143\r
144 /**\r
145 * Add a hub to the channel element\r
146 *\r
147 * @access public\r
148 * @param string URL\r
149 * @return void\r
150 */\r
151 public function addHub($hub)\r
152 {\r
153 $this->hubs[] = $hub;\r
154 }\r
155\r
156 /**\r
157 * Set XSL URL\r
158 *\r
159 * @access public\r
160 * @param string URL\r
161 * @return void\r
162 */\r
163 public function setXsl($xsl)\r
164 {\r
165 $this->xsl = $xsl;\r
166 }\r
167\r
168 /**\r
169 * Set self URL\r
170 *\r
171 * @access public\r
172 * @param string URL\r
173 * @return void\r
174 */\r
175 public function setSelf($self)\r
176 {\r
177 $this->self = $self;\r
178 }\r
179\r
180 /**\r
181 * Set the 'description' channel element\r
182 *\r
183 * @access public\r
184 * @param srting value of 'description' channel tag\r
185 * @return void\r
186 */\r
187 public function setDescription($description)\r
188 {\r
189 $this->setChannelElement('description', $description);\r
190 }\r
191\r
192 /**\r
193 * Set the 'link' channel element\r
194 *\r
195 * @access public\r
196 * @param srting value of 'link' channel tag\r
197 * @return void\r
198 */\r
199 public function setLink($link)\r
200 {\r
201 $this->setChannelElement('link', $link);\r
202 }\r
203\r
204 /**\r
205 * Set the 'image' channel element\r
206 *\r
207 * @access public\r
208 * @param srting title of image\r
209 * @param srting link url of the imahe\r
210 * @param srting path url of the image\r
211 * @return void\r
212 */\r
213 public function setImage($title, $link, $url)\r
214 {\r
215 $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));\r
216 }\r
217\r
218 // End # public functions ----------------------------------------------\r
219\r
220 // Start # private functions ----------------------------------------------\r
221\r
222 /**\r
223 * Prints the xml and rss namespace\r
224 *\r
225 * @access private\r
226 * @return void\r
227 */\r
228 private function printHead()\r
229 {\r
230 if ($this->version == RSS2)\r
231 {\r
232 $out = '<?xml version="1.0" encoding="utf-8"?>'."\n";\r
233 if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;\r
234 $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL;\r
235 echo $out;\r
236 }\r
237 elseif ($this->version == JSON || $this->version == JSONP)\r
238 {\r
239 $this->json->rss = array('@attributes' => array('version' => '2.0'));\r
240 }\r
241 }\r
242\r
243 /**\r
244 * Closes the open tags at the end of file\r
245 *\r
246 * @access private\r
247 * @return void\r
248 */\r
249 private function printTale()\r
250 {\r
251 if ($this->version == RSS2)\r
252 {\r
253 echo '</channel>',PHP_EOL,'</rss>';\r
254 }\r
255 // do nothing for JSON\r
256 }\r
257\r
258 /**\r
259 * Creates a single node as xml format\r
260 *\r
261 * @access private\r
262 * @param string name of the tag\r
263 * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format\r
264 * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
265 * @return string formatted xml tag\r
266 */\r
267 private function makeNode($tagName, $tagContent, $attributes = null)\r
268 {\r
269 if ($this->version == RSS2)\r
270 {\r
271 $nodeText = '';\r
272 $attrText = '';\r
273 if (is_array($attributes))\r
274 {\r
275 foreach ($attributes as $key => $value)\r
276 {\r
277 $attrText .= " $key=\"$value\" ";\r
278 }\r
279 }\r
280 $nodeText .= "<{$tagName}{$attrText}>";\r
281 if (is_array($tagContent))\r
282 {\r
283 foreach ($tagContent as $key => $value)\r
284 {\r
285 $nodeText .= $this->makeNode($key, $value);\r
286 }\r
287 }\r
288 else\r
289 {\r
290 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);\r
291 $nodeText .= htmlspecialchars($tagContent);\r
292 }\r
293 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";\r
294 $nodeText .= "</$tagName>";\r
295 return $nodeText . PHP_EOL;\r
296 }\r
297 elseif ($this->version == JSON || $this->version == JSONP)\r
298 {\r
299 $tagName = (string)$tagName;\r
300 $tagName = strtr($tagName, ':', '_');\r
301 $node = null;\r
302 if (!$tagContent && is_array($attributes) && count($attributes))\r
303 {\r
304 $node = array('@attributes' => $this->json_keys($attributes));\r
305 } else {\r
306 if (is_array($tagContent)) {\r
307 $node = $this->json_keys($tagContent);\r
308 } else {\r
309 $node = $tagContent;\r
310 }\r
311 }\r
312 return $node;\r
313 }\r
314 return ''; // should not get here\r
315 }\r
316\r
317 private function json_keys(array $array) {\r
318 $new = array();\r
319 foreach ($array as $key => $val) {\r
320 if (is_string($key)) $key = strtr($key, ':', '_');\r
321 if (is_array($val)) {\r
322 $new[$key] = $this->json_keys($val);\r
323 } else {\r
324 $new[$key] = $val;\r
325 }\r
326 }\r
327 return $new;\r
328 }\r
329\r
330 /**\r
331 * @desc Print channels\r
332 * @access private\r
333 * @return void\r
334 */\r
335 private function printChannels()\r
336 {\r
337 //Start channel tag\r
338 if ($this->version == RSS2) {\r
339 echo '<channel>' . PHP_EOL;\r
340 // add hubs\r
341 foreach ($this->hubs as $hub) {\r
342 //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
343 echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
344 }\r
345 // add self\r
346 if (isset($this->self)) {\r
347 //echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
348 echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
349 }\r
350 //Print Items of channel\r
351 foreach ($this->channels as $key => $value)\r
352 {\r
353 echo $this->makeNode($key, $value);\r
354 }\r
355 } elseif ($this->version == JSON || $this->version == JSONP) {\r
356 $this->json->rss['channel'] = (object)$this->json_keys($this->channels);\r
357 }\r
358 }\r
359\r
360 /**\r
361 * Prints formatted feed items\r
362 *\r
363 * @access private\r
364 * @return void\r
365 */\r
366 private function printItems()\r
367 {\r
368 foreach ($this->items as $item) {\r
369 $itemElements = $item->getElements();\r
370\r
371 echo $this->startItem();\r
372\r
373 if ($this->version == JSON || $this->version == JSONP) {\r
374 $json_item = array();\r
375 }\r
376\r
377 foreach ($itemElements as $thisElement) {\r
378 foreach ($thisElement as $instance) {\r
379 if ($this->version == RSS2) {\r
380 echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
381 } elseif ($this->version == JSON || $this->version == JSONP) {\r
382 $_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
383 if (count($thisElement) > 1) {\r
384 $json_item[strtr($instance['name'], ':', '_')][] = $_json_node;\r
385 } else {\r
386 $json_item[strtr($instance['name'], ':', '_')] = $_json_node;\r
387 }\r
388 }\r
389 }\r
390 }\r
391 echo $this->endItem();\r
392 if ($this->version == JSON || $this->version == JSONP) {\r
393 if (count($this->items) > 1) {\r
394 $this->json->rss['channel']->item[] = $json_item;\r
395 } else {\r
396 $this->json->rss['channel']->item = $json_item;\r
397 }\r
398 }\r
399 }\r
400 }\r
401\r
402 /**\r
403 * Make the starting tag of channels\r
404 *\r
405 * @access private\r
406 * @return void\r
407 */\r
408 private function startItem()\r
409 {\r
410 if ($this->version == RSS2)\r
411 {\r
412 echo '<item>' . PHP_EOL;\r
413 }\r
414 // nothing for JSON\r
415 }\r
416\r
417 /**\r
418 * Closes feed item tag\r
419 *\r
420 * @access private\r
421 * @return void\r
422 */\r
423 private function endItem()\r
424 {\r
425 if ($this->version == RSS2)\r
426 {\r
427 echo '</item>' . PHP_EOL;\r
428 }\r
429 // nothing for JSON\r
430 }\r
431\r
432 // End # private functions ----------------------------------------------\r
42c80841 433 }