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