aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/3rdparty/feedwriter/FeedWriter.php
diff options
context:
space:
mode:
authorNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-12-03 01:42:21 -0800
committerNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-12-03 01:42:21 -0800
commitb8bb2b4ab647747806492b439698ccd834ac18da (patch)
tree78b133d6c397cf44d711f15a8f1785cd76c9d6ea /inc/3rdparty/feedwriter/FeedWriter.php
parent678f2cb6eef428e4a5aa522985d30704df3acc78 (diff)
parent72c20a52978f31b84ffc817894f9f85f4a8506ee (diff)
downloadwallabag-b8bb2b4ab647747806492b439698ccd834ac18da.tar.gz
wallabag-b8bb2b4ab647747806492b439698ccd834ac18da.tar.zst
wallabag-b8bb2b4ab647747806492b439698ccd834ac18da.zip
Merge pull request #350 from inthepoche/rss
add atom feeds for unread / favs
Diffstat (limited to 'inc/3rdparty/feedwriter/FeedWriter.php')
-rw-r--r--inc/3rdparty/feedwriter/FeedWriter.php339
1 files changed, 170 insertions, 169 deletions
diff --git a/inc/3rdparty/feedwriter/FeedWriter.php b/inc/3rdparty/feedwriter/FeedWriter.php
index d5d6648a..46ecc3d5 100644
--- a/inc/3rdparty/feedwriter/FeedWriter.php
+++ b/inc/3rdparty/feedwriter/FeedWriter.php
@@ -1,16 +1,16 @@
1<?php 1<?php
2define('RSS2', 1, true); 2// RSS 0.90 Officially obsoleted by 1.0
3define('JSON', 2, true); 3// RSS 0.91, 0.92, 0.93 and 0.94 Officially obsoleted by 2.0
4define('ATOM', 3, true); 4// So, define constants for RSS 1.0, RSS 2.0 and ATOM
5
6 define('RSS1', 'RSS 1.0', true);
7 define('RSS2', 'RSS 2.0', true);
8 define('ATOM', 'ATOM', true);
5 9
6 /** 10 /**
7 * Univarsel Feed Writer class 11 * Univarsel Feed Writer class
8 * 12 *
9 * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed) 13 * Genarate RSS 1.0, RSS2.0 and ATOM Feed
10 *
11 * Modified for FiveFilters.org's Full-Text RSS project
12 * to allow for inclusion of hubs, JSON output.
13 * Stripped RSS1 and ATOM support.
14 * 14 *
15 * @package UnivarselFeedWriter 15 * @package UnivarselFeedWriter
16 * @author Anis uddin Ahmad <anisniit@gmail.com> 16 * @author Anis uddin Ahmad <anisniit@gmail.com>
@@ -18,21 +18,17 @@ define('ATOM', 3, true);
18 */ 18 */
19 class FeedWriter 19 class FeedWriter
20 { 20 {
21 private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html
22 private $hubs = array(); // PubSubHubbub hubs
23 private $channels = array(); // Collection of channel elements 21 private $channels = array(); // Collection of channel elements
24 private $items = array(); // Collection of items as object of FeedItem class. 22 private $items = array(); // Collection of items as object of FeedItem class.
25 private $data = array(); // Store some other version wise data 23 private $data = array(); // Store some other version wise data
26 private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA 24 private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
27 private $xsl = null; // stylesheet to render RSS (used by Chrome)
28 private $json = null; // JSON object
29 25
30 private $version = null; 26 private $version = null;
31 27
32 /** 28 /**
33 * Constructor 29 * Constructor
34 * 30 *
35 * @param constant the version constant (RSS2 or JSON). 31 * @param constant the version constant (RSS1/RSS2/ATOM).
36 */ 32 */
37 function __construct($version = RSS2) 33 function __construct($version = RSS2)
38 { 34 {
@@ -43,11 +39,7 @@ define('ATOM', 3, true);
43 $this->channels['link'] = 'http://www.ajaxray.com/blog'; 39 $this->channels['link'] = 'http://www.ajaxray.com/blog';
44 40
45 //Tag names to encode in CDATA 41 //Tag names to encode in CDATA
46 $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary'); 42 $this->CDATAEncoding = array('description', 'content:encoded', 'summary');
47 }
48
49 public function setFormat($format) {
50 $this->version = $format;
51 } 43 }
52 44
53 // Start # public functions --------------------------------------------- 45 // Start # public functions ---------------------------------------------
@@ -82,26 +74,19 @@ define('ATOM', 3, true);
82 } 74 }
83 75
84 /** 76 /**
85 * Genarate the actual RSS/JSON file 77 * Genarate the actual RSS/ATOM file
86 * 78 *
87 * @access public 79 * @access public
88 * @return void 80 * @return void
89 */ 81 */
90 public function genarateFeed() 82 public function genarateFeed()
91 { 83 {
92 if ($this->version == RSS2) { 84 header("Content-type: text/xml");
93 header('Content-type: text/xml; charset=UTF-8'); 85
94 } elseif ($this->version == JSON) {
95 header('Content-type: application/json; charset=UTF-8');
96 $this->json = new stdClass();
97 }
98 $this->printHead(); 86 $this->printHead();
99 $this->printChannels(); 87 $this->printChannels();
100 $this->printItems(); 88 $this->printItems();
101 $this->printTale(); 89 $this->printTale();
102 if ($this->version == JSON) {
103 echo json_encode($this->json);
104 }
105 } 90 }
106 91
107 /** 92 /**
@@ -128,6 +113,7 @@ define('ATOM', 3, true);
128 $this->items[] = $feedItem; 113 $this->items[] = $feedItem;
129 } 114 }
130 115
116
131 // Wrapper functions ------------------------------------------------------------------- 117 // Wrapper functions -------------------------------------------------------------------
132 118
133 /** 119 /**
@@ -143,42 +129,6 @@ define('ATOM', 3, true);
143 } 129 }
144 130
145 /** 131 /**
146 * Add a hub to the channel element
147 *
148 * @access public
149 * @param string URL
150 * @return void
151 */
152 public function addHub($hub)
153 {
154 $this->hubs[] = $hub;
155 }
156
157 /**
158 * Set XSL URL
159 *
160 * @access public
161 * @param string URL
162 * @return void
163 */
164 public function setXsl($xsl)
165 {
166 $this->xsl = $xsl;
167 }
168
169 /**
170 * Set self URL
171 *
172 * @access public
173 * @param string URL
174 * @return void
175 */
176 public function setSelf($self)
177 {
178 $this->self = $self;
179 }
180
181 /**
182 * Set the 'description' channel element 132 * Set the 'description' channel element
183 * 133 *
184 * @access public 134 * @access public
@@ -187,8 +137,7 @@ define('ATOM', 3, true);
187 */ 137 */
188 public function setDescription($desciption) 138 public function setDescription($desciption)
189 { 139 {
190 $tag = ($this->version == ATOM)? 'subtitle' : 'description'; 140 $this->setChannelElement('description', $desciption);
191 $this->setChannelElement($tag, $desciption);
192 } 141 }
193 142
194 /** 143 /**
@@ -217,6 +166,36 @@ define('ATOM', 3, true);
217 $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url)); 166 $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
218 } 167 }
219 168
169 /**
170 * Set the 'about' channel element. Only for RSS 1.0
171 *
172 * @access public
173 * @param srting value of 'about' channel tag
174 * @return void
175 */
176 public function setChannelAbout($url)
177 {
178 $this->data['ChannelAbout'] = $url;
179 }
180
181 /**
182 * Genarates an UUID
183 * @author Anis uddin Ahmad <admin@ajaxray.com>
184 * @param string an optional prefix
185 * @return string the formated uuid
186 */
187 public static function uuid($key = null, $prefix = '')
188 {
189 $key = ($key == null)? uniqid(rand()) : $key;
190 $chars = md5($key);
191 $uuid = substr($chars,0,8) . '-';
192 $uuid .= substr($chars,8,4) . '-';
193 $uuid .= substr($chars,12,4) . '-';
194 $uuid .= substr($chars,16,4) . '-';
195 $uuid .= substr($chars,20,12);
196
197 return $prefix . $uuid;
198 }
220 // End # public functions ---------------------------------------------- 199 // End # public functions ----------------------------------------------
221 200
222 // Start # private functions ---------------------------------------------- 201 // Start # private functions ----------------------------------------------
@@ -229,17 +208,28 @@ define('ATOM', 3, true);
229 */ 208 */
230 private function printHead() 209 private function printHead()
231 { 210 {
232 if ($this->version == RSS2) 211 $out = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
212
213 if($this->version == RSS2)
214 {
215 $out .= '<rss version="2.0"
216 xmlns:content="http://purl.org/rss/1.0/modules/content/"
217 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
218 >' . PHP_EOL;
219 }
220 elseif($this->version == RSS1)
233 { 221 {
234 $out = '<?xml version="1.0" encoding="utf-8"?>'."\n"; 222 $out .= '<rdf:RDF
235 if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL; 223 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
236 $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL; 224 xmlns="http://purl.org/rss/1.0/"
237 echo $out; 225 xmlns:dc="http://purl.org/dc/elements/1.1/"
226 >' . PHP_EOL;;
238 } 227 }
239 elseif ($this->version == JSON) 228 else if($this->version == ATOM)
240 { 229 {
241 $this->json->rss = array('@attributes' => array('version' => '2.0')); 230 $out .= '<feed xmlns="http://www.w3.org/2005/Atom">' . PHP_EOL;;
242 } 231 }
232 echo $out;
243 } 233 }
244 234
245 /** 235 /**
@@ -250,83 +240,67 @@ define('ATOM', 3, true);
250 */ 240 */
251 private function printTale() 241 private function printTale()
252 { 242 {
253 if ($this->version == RSS2) 243 if($this->version == RSS2)
254 { 244 {
255 echo '</channel>',PHP_EOL,'</rss>'; 245 echo '</channel>' . PHP_EOL . '</rss>';
256 } 246 }
257 // do nothing for JSON 247 elseif($this->version == RSS1)
248 {
249 echo '</rdf:RDF>';
250 }
251 else if($this->version == ATOM)
252 {
253 echo '</feed>';
254 }
255
258 } 256 }
259 257
260 /** 258 /**
261 * Creates a single node as xml format 259 * Creates a single node as xml format
262 * 260 *
263 * @access private 261 * @access private
264 * @param string name of the tag 262 * @param srting name of the tag
265 * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format 263 * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
266 * @param array Attributes(if any) in 'attrName' => 'attrValue' format 264 * @param array Attributes(if any) in 'attrName' => 'attrValue' format
267 * @return string formatted xml tag 265 * @return string formatted xml tag
268 */ 266 */
269 private function makeNode($tagName, $tagContent, $attributes = null) 267 private function makeNode($tagName, $tagContent, $attributes = null)
270 { 268 {
271 if ($this->version == RSS2) 269 $nodeText = '';
270 $attrText = '';
271
272 if(is_array($attributes))
272 { 273 {
273 $nodeText = ''; 274 foreach ($attributes as $key => $value)
274 $attrText = '';
275 if (is_array($attributes))
276 { 275 {
277 foreach ($attributes as $key => $value) 276 $attrText .= " $key=\"$value\" ";
278 {
279 $attrText .= " $key=\"$value\" ";
280 }
281 } 277 }
282 $nodeText .= "<{$tagName}{$attrText}>";
283 if (is_array($tagContent))
284 {
285 foreach ($tagContent as $key => $value)
286 {
287 $nodeText .= $this->makeNode($key, $value);
288 }
289 }
290 else
291 {
292 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
293 $nodeText .= htmlspecialchars($tagContent);
294 }
295 //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
296 $nodeText .= "</$tagName>";
297 return $nodeText . PHP_EOL;
298 } 278 }
299 elseif ($this->version == JSON) 279
280 if(is_array($tagContent) && $this->version == RSS1)
300 { 281 {
301 $tagName = (string)$tagName; 282 $attrText = ' rdf:parseType="Resource"';
302 $tagName = strtr($tagName, ':', '_');
303 $node = null;
304 if (!$tagContent && is_array($attributes) && count($attributes))
305 {
306 $node = array('@attributes' => $this->json_keys($attributes));
307 } else {
308 if (is_array($tagContent)) {
309 $node = $this->json_keys($tagContent);
310 } else {
311 $node = $tagContent;
312 }
313 }
314 return $node;
315 } 283 }
316 return ''; // should not get here 284
317 } 285
318 286 $attrText .= (in_array($tagName, $this->CDATAEncoding) && $this->version == ATOM)? ' type="html" ' : '';
319 private function json_keys(array $array) { 287 $nodeText .= (in_array($tagName, $this->CDATAEncoding))? "<{$tagName}{$attrText}><![CDATA[" : "<{$tagName}{$attrText}>";
320 $new = array(); 288
321 foreach ($array as $key => $val) { 289 if(is_array($tagContent))
322 if (is_string($key)) $key = strtr($key, ':', '_'); 290 {
323 if (is_array($val)) { 291 foreach ($tagContent as $key => $value)
324 $new[$key] = $this->json_keys($val); 292 {
325 } else { 293 $nodeText .= $this->makeNode($key, $value);
326 $new[$key] = $val;
327 } 294 }
328 } 295 }
329 return $new; 296 else
297 {
298 $nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
299 }
300
301 $nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
302
303 return $nodeText . PHP_EOL;
330 } 304 }
331 305
332 /** 306 /**
@@ -340,27 +314,41 @@ define('ATOM', 3, true);
340 switch ($this->version) 314 switch ($this->version)
341 { 315 {
342 case RSS2: 316 case RSS2:
343 echo '<channel>' . PHP_EOL; 317 echo '<channel>' . PHP_EOL;
344 // add hubs
345 foreach ($this->hubs as $hub) {
346 //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));
347 echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
348 }
349 // add self
350 if (isset($this->self)) {
351 //echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));
352 echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
353 }
354 //Print Items of channel
355 foreach ($this->channels as $key => $value)
356 {
357 echo $this->makeNode($key, $value);
358 }
359 break; 318 break;
360 case JSON: 319 case RSS1:
361 $this->json->rss['channel'] = (object)$this->json_keys($this->channels); 320 echo (isset($this->data['ChannelAbout']))? "<channel rdf:about=\"{$this->data['ChannelAbout']}\">" : "<channel rdf:about=\"{$this->channels['link']}\">";
362 break; 321 break;
363 } 322 }
323
324 //Print Items of channel
325 foreach ($this->channels as $key => $value)
326 {
327 if($this->version == ATOM && $key == 'link')
328 {
329 // ATOM prints link element as href attribute
330 echo $this->makeNode($key,'',array('href'=>$value));
331 //Add the id for ATOM
332 echo $this->makeNode('id',self::uuid($value,'urn:uuid:'));
333 }
334 else
335 {
336 echo $this->makeNode($key, $value);
337 }
338
339 }
340
341 //RSS 1.0 have special tag <rdf:Seq> with channel
342 if($this->version == RSS1)
343 {
344 echo "<items>" . PHP_EOL . "<rdf:Seq>" . PHP_EOL;
345 foreach ($this->items as $item)
346 {
347 $thisItems = $item->getElements();
348 echo "<rdf:li resource=\"{$thisItems['link']['content']}\"/>" . PHP_EOL;
349 }
350 echo "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
351 }
364 } 352 }
365 353
366 /** 354 /**
@@ -375,28 +363,14 @@ define('ATOM', 3, true);
375 { 363 {
376 $thisItems = $item->getElements(); 364 $thisItems = $item->getElements();
377 365
378 echo $this->startItem(); 366 //the argument is printed as rdf:about attribute of item in rss 1.0
379 367 echo $this->startItem($thisItems['link']['content']);
380 if ($this->version == JSON) {
381 $json_item = array();
382 }
383 368
384 foreach ($thisItems as $feedItem ) 369 foreach ($thisItems as $feedItem )
385 { 370 {
386 if ($this->version == RSS2) { 371 echo $this->makeNode($feedItem['name'], $feedItem['content'], $feedItem['attributes']);
387 echo $this->makeNode($feedItem['name'], $feedItem['content'], $feedItem['attributes']);
388 } elseif ($this->version == JSON) {
389 $json_item[strtr($feedItem['name'], ':', '_')] = $this->makeNode($feedItem['name'], $feedItem['content'], $feedItem['attributes']);
390 }
391 } 372 }
392 echo $this->endItem(); 373 echo $this->endItem();
393 if ($this->version == JSON) {
394 if (count($this->items) > 1) {
395 $this->json->rss['channel']->item[] = $json_item;
396 } else {
397 $this->json->rss['channel']->item = $json_item;
398 }
399 }
400 } 374 }
401 } 375 }
402 376
@@ -404,15 +378,30 @@ define('ATOM', 3, true);
404 * Make the starting tag of channels 378 * Make the starting tag of channels
405 * 379 *
406 * @access private 380 * @access private
381 * @param srting The vale of about tag which is used for only RSS 1.0
407 * @return void 382 * @return void
408 */ 383 */
409 private function startItem() 384 private function startItem($about = false)
410 { 385 {
411 if ($this->version == RSS2) 386 if($this->version == RSS2)
412 { 387 {
413 echo '<item>' . PHP_EOL; 388 echo '<item>' . PHP_EOL;
414 } 389 }
415 // nothing for JSON 390 elseif($this->version == RSS1)
391 {
392 if($about)
393 {
394 echo "<item rdf:about=\"$about\">" . PHP_EOL;
395 }
396 else
397 {
398 die('link element is not set .\n It\'s required for RSS 1.0 to be used as about attribute of item');
399 }
400 }
401 else if($this->version == ATOM)
402 {
403 echo "<entry>" . PHP_EOL;
404 }
416 } 405 }
417 406
418 /** 407 /**
@@ -423,12 +412,24 @@ define('ATOM', 3, true);
423 */ 412 */
424 private function endItem() 413 private function endItem()
425 { 414 {
426 if ($this->version == RSS2) 415 if($this->version == RSS2 || $this->version == RSS1)
427 { 416 {
428 echo '</item>' . PHP_EOL; 417 echo '</item>' . PHP_EOL;
429 } 418 }
430 // nothing for JSON 419 else if($this->version == ATOM)
420 {
421 echo "</entry>" . PHP_EOL;
422 }
431 } 423 }
432 424
425
426
433 // End # private functions ---------------------------------------------- 427 // End # private functions ----------------------------------------------
434 } \ No newline at end of file 428
429 } // end of class FeedWriter
430
431// autoload classes
432function __autoload($class_name)
433{
434 require_once $class_name . '.php';
435} \ No newline at end of file