Fix duplicate ids from pinned comments
[aur.git] / web / lib / feedcreator.class.php
blob802eebbee4dfad0901ea27ebf5137abe08bfbcd2
1 <?php
2 /***************************************************************************
4 FeedCreator class v1.7.2
5 originally (c) Kai Blankenhorn
6 www.bitfolge.de
7 kaib@bitfolge.de
8 v1.3 work by Scott Reynen (scott@randomchaos.com) and Kai Blankenhorn
9 v1.5 OPML support by Dirk Clemens
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 ****************************************************************************
28 Changelog:
30 v1.7.2 10-11-04
31 license changed to LGPL
33 v1.7.1
34 fixed a syntax bug
35 fixed left over debug code
37 v1.7 07-18-04
38 added HTML and JavaScript feeds (configurable via CSS) (thanks to Pascal Van Hecke)
39 added HTML descriptions for all feed formats (thanks to Pascal Van Hecke)
40 added a switch to select an external stylesheet (thanks to Pascal Van Hecke)
41 changed default content-type to application/xml
42 added character encoding setting
43 fixed numerous smaller bugs (thanks to Sören Fuhrmann of golem.de)
44 improved changing ATOM versions handling (thanks to August Trometer)
45 improved the UniversalFeedCreator's useCached method (thanks to Sören Fuhrmann of golem.de)
46 added charset output in HTTP headers (thanks to Sören Fuhrmann of golem.de)
47 added Slashdot namespace to RSS 1.0 (thanks to Sören Fuhrmann of golem.de)
49 v1.6 05-10-04
50 added stylesheet to RSS 1.0 feeds
51 fixed generator comment (thanks Kevin L. Papendick and Tanguy Pruvot)
52 fixed RFC822 date bug (thanks Tanguy Pruvot)
53 added TimeZone customization for RFC8601 (thanks Tanguy Pruvot)
54 fixed Content-type could be empty (thanks Tanguy Pruvot)
55 fixed author/creator in RSS1.0 (thanks Tanguy Pruvot)
57 v1.6 beta 02-28-04
58 added Atom 0.3 support (not all features, though)
59 improved OPML 1.0 support (hopefully - added more elements)
60 added support for arbitrary additional elements (use with caution)
61 code beautification :-)
62 considered beta due to some internal changes
64 v1.5.1 01-27-04
65 fixed some RSS 1.0 glitches (thanks to Stéphane Vanpoperynghe)
66 fixed some inconsistencies between documentation and code (thanks to Timothy Martin)
68 v1.5 01-06-04
69 added support for OPML 1.0
70 added more documentation
72 v1.4 11-11-03
73 optional feed saving and caching
74 improved documentation
75 minor improvements
77 v1.3 10-02-03
78 renamed to FeedCreator, as it not only creates RSS anymore
79 added support for mbox
80 tentative support for echo/necho/atom/pie/???
82 v1.2 07-20-03
83 intelligent auto-truncating of RSS 0.91 attributes
84 don't create some attributes when they're not set
85 documentation improved
86 fixed a real and a possible bug with date conversions
87 code cleanup
89 v1.1 06-29-03
90 added images to feeds
91 now includes most RSS 0.91 attributes
92 added RSS 2.0 feeds
94 v1.0 06-24-03
95 initial release
99 ***************************************************************************/
101 /*** GENERAL USAGE *********************************************************
103 include("feedcreator.class.php");
105 $rss = new UniversalFeedCreator();
106 $rss->useCached(); // use cached version if age<1 hour
107 $rss->title = "PHP news";
108 $rss->description = "daily news from the PHP scripting world";
110 //optional
111 $rss->descriptionTruncSize = 500;
112 $rss->descriptionHtmlSyndicated = true;
114 $rss->link = "http://www.dailyphp.net/news";
115 $rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"];
117 $image = new FeedImage();
118 $image->title = "dailyphp.net logo";
119 $image->url = "http://www.dailyphp.net/images/logo.gif";
120 $image->link = "http://www.dailyphp.net";
121 $image->description = "Feed provided by dailyphp.net. Click to visit.";
123 //optional
124 $image->descriptionTruncSize = 500;
125 $image->descriptionHtmlSyndicated = true;
127 $rss->image = $image;
129 // get your news items from somewhere, e.g. your database:
130 mysql_select_db($dbHost, $dbUser, $dbPass);
131 $res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC");
132 while ($data = mysql_fetch_object($res)) {
133 $item = new FeedItem();
134 $item->title = $data->title;
135 $item->link = $data->url;
136 $item->description = $data->short;
138 //optional
139 item->descriptionTruncSize = 500;
140 item->descriptionHtmlSyndicated = true;
142 $item->date = $data->newsdate;
143 $item->source = "http://www.dailyphp.net";
144 $item->author = "John Doe";
146 $rss->addItem($item);
149 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated),
150 // MBOX, OPML, ATOM, ATOM0.3, HTML, JS
151 echo $rss->saveFeed("RSS1.0", "news/feed.xml");
154 ***************************************************************************
155 * A little setup *
156 **************************************************************************/
158 // your local timezone, set to "" to disable or for GMT
159 define("TIME_ZONE","+01:00");
165 * Version string.
167 define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2");
172 * A FeedItem is a part of a FeedCreator feed.
174 * @author Kai Blankenhorn <kaib@bitfolge.de>
175 * @since 1.3
177 class FeedItem extends HtmlDescribable {
179 * Mandatory attributes of an item.
181 var $title, $description, $link;
184 * Optional attributes of an item.
186 var $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator;
189 * Publishing date of an item. May be in one of the following formats:
191 * RFC 822:
192 * "Mon, 20 Jan 03 18:05:41 +0400"
193 * "20 Jan 03 18:05:41 +0000"
195 * ISO 8601:
196 * "2003-01-20T18:05:41+04:00"
198 * Unix:
199 * 1043082341
201 var $date;
204 * Any additional elements to include as an assiciated array. All $key => $value pairs
205 * will be included unencoded in the feed item in the form
206 * <$key>$value</$key>
207 * Again: No encoding will be used! This means you can invalidate or enhance the feed
208 * if $value contains markup. This may be abused to embed tags not implemented by
209 * the FeedCreator class used.
211 var $additionalElements = Array();
213 // on hold
214 // var $source;
220 * An FeedImage may be added to a FeedCreator feed.
221 * @author Kai Blankenhorn <kaib@bitfolge.de>
222 * @since 1.3
224 class FeedImage extends HtmlDescribable {
226 * Mandatory attributes of an image.
228 var $title, $url, $link;
231 * Optional attributes of an image.
233 var $width, $height, $description;
239 * An HtmlDescribable is an item within a feed that can have a description that may
240 * include HTML markup.
242 class HtmlDescribable {
244 * Indicates whether the description field should be rendered in HTML.
246 var $descriptionHtmlSyndicated;
249 * Indicates whether and to how many characters a description should be truncated.
251 var $descriptionTruncSize;
254 * Returns a formatted description field, depending on descriptionHtmlSyndicated and
255 * $descriptionTruncSize properties
256 * @return string the formatted description
258 function getDescription() {
259 $descriptionField = new FeedHtmlField($this->description);
260 $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;
261 $descriptionField->truncSize = $this->descriptionTruncSize;
262 return $descriptionField->output();
269 * An FeedHtmlField describes and generates
270 * a feed, item or image html field (probably a description). Output is
271 * generated based on $truncSize, $syndicateHtml properties.
272 * @author Pascal Van Hecke <feedcreator.class.php@vanhecke.info>
273 * @version 1.6
275 class FeedHtmlField {
277 * Mandatory attributes of a FeedHtmlField.
279 var $rawFieldContent;
282 * Optional attributes of a FeedHtmlField.
285 var $truncSize, $syndicateHtml;
288 * Creates a new instance of FeedHtmlField.
289 * @param $string: if given, sets the rawFieldContent property
291 function FeedHtmlField($parFieldContent) {
292 if ($parFieldContent) {
293 $this->rawFieldContent = $parFieldContent;
299 * Creates the right output, depending on $truncSize, $syndicateHtml properties.
300 * @return string the formatted field
302 function output() {
303 // when field available and syndicated in html we assume
304 // - valid html in $rawFieldContent and we enclose in CDATA tags
305 // - no truncation (truncating risks producing invalid html)
306 if (!$this->rawFieldContent) {
307 $result = "";
308 } elseif ($this->syndicateHtml) {
309 $result = "<![CDATA[".$this->rawFieldContent."]]>";
310 } else {
311 if ($this->truncSize and is_int($this->truncSize)) {
312 $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);
313 } else {
314 $result = htmlspecialchars($this->rawFieldContent);
317 return $result;
325 * UniversalFeedCreator lets you choose during runtime which
326 * format to build.
327 * For general usage of a feed class, see the FeedCreator class
328 * below or the example above.
330 * @since 1.3
331 * @author Kai Blankenhorn <kaib@bitfolge.de>
333 class UniversalFeedCreator extends FeedCreator {
334 var $_feed;
336 function _setFormat($format) {
337 switch (strtoupper($format)) {
339 case "2.0":
340 // fall through
341 case "RSS2.0":
342 $this->_feed = new RSSCreator20();
343 break;
345 case "1.0":
346 // fall through
347 case "RSS1.0":
348 $this->_feed = new RSSCreator10();
349 break;
351 case "0.91":
352 // fall through
353 case "RSS0.91":
354 $this->_feed = new RSSCreator091();
355 break;
357 case "PIE0.1":
358 $this->_feed = new PIECreator01();
359 break;
361 case "MBOX":
362 $this->_feed = new MBOXCreator();
363 break;
365 case "OPML":
366 $this->_feed = new OPMLCreator();
367 break;
369 case "ATOM":
370 // fall through: always the latest ATOM version
372 case "ATOM0.3":
373 $this->_feed = new AtomCreator03();
374 break;
376 case "HTML":
377 $this->_feed = new HTMLCreator();
378 break;
380 case "JS":
381 // fall through
382 case "JAVASCRIPT":
383 $this->_feed = new JSCreator();
384 break;
386 default:
387 $this->_feed = new RSSCreator091();
388 break;
391 $vars = get_object_vars($this);
392 foreach ($vars as $key => $value) {
393 // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
394 if (!in_array($key, array("_feed", "contentType", "encoding"))) {
395 $this->_feed->{$key} = $this->{$key};
401 * Creates a syndication feed based on the items previously added.
403 * @see FeedCreator::addItem()
404 * @param string format format the feed should comply to. Valid values are:
405 * "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"
406 * @return string the contents of the feed.
408 function createFeed($format = "RSS0.91") {
409 $this->_setFormat($format);
410 return $this->_feed->createFeed();
416 * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect
417 * header may be sent to redirect the use to the newly created file.
418 * @since 1.4
420 * @param string format format the feed should comply to. Valid values are:
421 * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"
422 * @param string filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
423 * @param boolean displayContents optional send the content of the file or not. If true, the file will be sent in the body of the response.
425 function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
426 $this->_setFormat($format);
427 $this->_feed->saveFeed($filename, $displayContents);
432 * Turns on caching and checks if there is a recent version of this feed in the cache.
433 * If there is, an HTTP redirect header is sent.
434 * To effectively use caching, you should create the FeedCreator object and call this method
435 * before anything else, especially before you do the time consuming task to build the feed
436 * (web fetching, for example).
438 * @param string format format the feed should comply to. Valid values are:
439 * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
440 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
441 * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
443 function useCached($format="RSS0.91", $filename="", $timeout=3600) {
444 $this->_setFormat($format);
445 $this->_feed->useCached($filename, $timeout);
452 * FeedCreator is the abstract base implementation for concrete
453 * implementations that implement a specific format of syndication.
455 * @abstract
456 * @author Kai Blankenhorn <kaib@bitfolge.de>
457 * @since 1.4
459 class FeedCreator extends HtmlDescribable {
462 * Mandatory attributes of a feed.
464 var $title, $description, $link;
468 * Optional attributes of a feed.
470 var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
473 * The url of the external xsl stylesheet used to format the naked rss feed.
474 * Ignored in the output when empty.
476 var $xslStyleSheet = "";
480 * @access private
482 var $items = Array();
486 * This feed's MIME content type.
487 * @since 1.4
488 * @access private
490 var $contentType = "application/xml";
494 * This feed's character encoding.
495 * @since 1.6.1
497 var $encoding = "ISO-8859-1";
501 * Any additional elements to include as an assiciated array. All $key => $value pairs
502 * will be included unencoded in the feed in the form
503 * <$key>$value</$key>
504 * Again: No encoding will be used! This means you can invalidate or enhance the feed
505 * if $value contains markup. This may be abused to embed tags not implemented by
506 * the FeedCreator class used.
508 var $additionalElements = Array();
512 * Adds an FeedItem to the feed.
514 * @param object FeedItem $item The FeedItem to add to the feed.
515 * @access public
517 function addItem($item) {
518 $this->items[] = $item;
523 * Truncates a string to a certain length at the most sensible point.
524 * First, if there's a '.' character near the end of the string, the string is truncated after this character.
525 * If there is no '.', the string is truncated after the last ' ' character.
526 * If the string is truncated, " ..." is appended.
527 * If the string is already shorter than $length, it is returned unchanged.
529 * @static
530 * @param string string A string to be truncated.
531 * @param int length the maximum length the string should be truncated to
532 * @return string the truncated string
534 function iTrunc($string, $length) {
535 if (strlen($string)<=$length) {
536 return $string;
539 $pos = strrpos($string,".");
540 if ($pos>=$length-4) {
541 $string = substr($string,0,$length-4);
542 $pos = strrpos($string,".");
544 if ($pos>=$length*0.4) {
545 return substr($string,0,$pos+1)." ...";
548 $pos = strrpos($string," ");
549 if ($pos>=$length-4) {
550 $string = substr($string,0,$length-4);
551 $pos = strrpos($string," ");
553 if ($pos>=$length*0.4) {
554 return substr($string,0,$pos)." ...";
557 return substr($string,0,$length-4)." ...";
563 * Creates a comment indicating the generator of this feed.
564 * The format of this comment seems to be recognized by
565 * Syndic8.com.
567 function _createGeneratorComment() {
568 return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n";
573 * Creates a string containing all additional elements specified in
574 * $additionalElements.
575 * @param elements array an associative array containing key => value pairs
576 * @param indentString string a string that will be inserted before every generated line
577 * @return string the XML tags corresponding to $additionalElements
579 function _createAdditionalElements($elements, $indentString="") {
580 $ae = "";
581 if (is_array($elements)) {
582 foreach($elements AS $key => $value) {
583 $ae.= $indentString."<$key>$value</$key>\n";
586 return $ae;
589 function _createStylesheetReferences() {
590 $xml = "";
591 if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";
592 if ($this->xslStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n";
593 return $xml;
598 * Builds the feed's text.
599 * @abstract
600 * @return string the feed's complete text
602 function createFeed() {
606 * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml.
607 * For example:
609 * echo $_SERVER["PHP_SELF"]."\n";
610 * echo FeedCreator::_generateFilename();
612 * would produce:
614 * /rss/latestnews.php
615 * latestnews.xml
617 * @return string the feed cache filename
618 * @since 1.4
619 * @access private
621 function _generateFilename() {
622 $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
623 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml";
628 * @since 1.4
629 * @access private
631 function _redirect($filename) {
632 // attention, heavily-commented-out-area
634 // maybe use this in addition to file time checking
635 //Header("Expires: ".date("r",time()+$this->_timeout));
637 /* no caching at all, doesn't seem to work as good:
638 Header("Cache-Control: no-cache");
639 Header("Pragma: no-cache");
642 // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
643 //Header("Location: ".$filename);
645 Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));
646 Header("Content-Disposition: inline; filename=".basename($filename));
647 readfile($filename, "r");
648 die();
652 * Turns on caching and checks if there is a recent version of this feed in the cache.
653 * If there is, an HTTP redirect header is sent.
654 * To effectively use caching, you should create the FeedCreator object and call this method
655 * before anything else, especially before you do the time consuming task to build the feed
656 * (web fetching, for example).
657 * @since 1.4
658 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
659 * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
661 function useCached($filename="", $timeout=3600) {
662 $this->_timeout = $timeout;
663 if ($filename=="") {
664 $filename = $this->_generateFilename();
666 if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {
667 $this->_redirect($filename);
673 * Saves this feed as a file on the local disk. After the file is saved, a redirect
674 * header may be sent to redirect the user to the newly created file.
675 * @since 1.4
677 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
678 * @param redirect boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
680 function saveFeed($filename="", $displayContents=true) {
681 if ($filename=="") {
682 $filename = $this->_generateFilename();
684 $feedFile = fopen($filename, "w+");
685 if ($feedFile) {
686 fputs($feedFile,$this->createFeed());
687 fclose($feedFile);
688 if ($displayContents) {
689 $this->_redirect($filename);
691 } else {
692 echo "<br /><strong>Error creating feed file, please check write permissions.</strong><br />";
700 * FeedDate is an internal class that stores a date for a feed or feed item.
701 * Usually, you won't need to use this.
703 class FeedDate {
704 var $unix;
707 * Creates a new instance of FeedDate representing a given date.
708 * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps.
709 * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used.
711 function FeedDate($dateString="") {
712 if ($dateString=="") $dateString = date("r");
714 if (is_integer($dateString)) {
715 $this->unix = $dateString;
716 return;
718 if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~",$dateString,$matches)) {
719 $months = Array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);
720 $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
721 if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
722 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
723 } else {
724 if (strlen($matches[7])==1) {
725 $oneHour = 3600;
726 $ord = ord($matches[7]);
727 if ($ord < ord("M")) {
728 $tzOffset = (ord("A") - $ord - 1) * $oneHour;
729 } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
730 $tzOffset = ($ord - ord("M")) * $oneHour;
731 } elseif ($matches[7]=="Z") {
732 $tzOffset = 0;
735 switch ($matches[7]) {
736 case "UT":
737 case "GMT": $tzOffset = 0;
740 $this->unix += $tzOffset;
741 return;
743 if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
744 $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
745 if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
746 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
747 } else {
748 if ($matches[7]=="Z") {
749 $tzOffset = 0;
752 $this->unix += $tzOffset;
753 return;
755 $this->unix = 0;
759 * Gets the date stored in this FeedDate as an RFC 822 date.
761 * @return a date in RFC 822 format
763 function rfc822() {
764 //return gmdate("r",$this->unix);
765 $date = gmdate("D, d M Y H:i:s", $this->unix);
766 if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);
767 return $date;
771 * Gets the date stored in this FeedDate as an ISO 8601 date.
773 * @return a date in ISO 8601 format
775 function iso8601() {
776 $date = gmdate("Y-m-d\TH:i:sO",$this->unix);
777 $date = substr($date,0,22) . ':' . substr($date,-2);
778 if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);
779 return $date;
783 * Gets the date stored in this FeedDate as unix time stamp.
785 * @return a date as a unix time stamp
787 function unix() {
788 return $this->unix;
794 * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0.
796 * @see http://www.purl.org/rss/1.0/
797 * @since 1.3
798 * @author Kai Blankenhorn <kaib@bitfolge.de>
800 class RSSCreator10 extends FeedCreator {
803 * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
804 * The feed will contain all items previously added in the same order.
805 * @return string the feed's complete text
807 function createFeed() {
808 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
809 $feed.= $this->_createGeneratorComment();
810 if ($this->cssStyleSheet=="") {
811 $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
813 $feed.= $this->_createStylesheetReferences();
814 $feed.= "<rdf:RDF\n";
815 $feed.= " xmlns=\"http://purl.org/rss/1.0/\"\n";
816 $feed.= " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
817 $feed.= " xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";
818 $feed.= " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
819 $feed.= " <channel rdf:about=\"".$this->syndicationURL."\">\n";
820 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
821 $feed.= " <description>".htmlspecialchars($this->description)."</description>\n";
822 $feed.= " <link>".$this->link."</link>\n";
823 if ($this->image!=null) {
824 $feed.= " <image rdf:resource=\"".$this->image->url."\" />\n";
826 $now = new FeedDate();
827 $feed.= " <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n";
828 $feed.= " <items>\n";
829 $feed.= " <rdf:Seq>\n";
830 for ($i=0;$i<count($this->items);$i++) {
831 $feed.= " <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
833 $feed.= " </rdf:Seq>\n";
834 $feed.= " </items>\n";
835 $feed.= " </channel>\n";
836 if ($this->image!=null) {
837 $feed.= " <image rdf:about=\"".$this->image->url."\">\n";
838 $feed.= " <title>".$this->image->title."</title>\n";
839 $feed.= " <link>".$this->image->link."</link>\n";
840 $feed.= " <url>".$this->image->url."</url>\n";
841 $feed.= " </image>\n";
843 $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
845 for ($i=0;$i<count($this->items);$i++) {
846 $feed.= " <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n";
847 //$feed.= " <dc:type>Posting</dc:type>\n";
848 $feed.= " <dc:format>text/html</dc:format>\n";
849 if ($this->items[$i]->date!=null) {
850 $itemDate = new FeedDate($this->items[$i]->date);
851 $feed.= " <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n";
853 if ($this->items[$i]->source!="") {
854 $feed.= " <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n";
856 if ($this->items[$i]->author!="") {
857 $feed.= " <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n";
859 $feed.= " <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")))."</title>\n";
860 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
861 $feed.= " <description>".htmlspecialchars($this->items[$i]->description)."</description>\n";
862 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
863 $feed.= " </item>\n";
865 $feed.= "</rdf:RDF>\n";
866 return $feed;
873 * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3.
875 * @see http://my.netscape.com/publish/formats/rss-spec-0.91.html
876 * @since 1.3
877 * @author Kai Blankenhorn <kaib@bitfolge.de>
879 class RSSCreator091 extends FeedCreator {
882 * Stores this RSS feed's version number.
883 * @access private
885 var $RSSVersion;
887 function RSSCreator091() {
888 $this->_setRSSVersion("0.91");
889 $this->contentType = "application/rss+xml";
893 * Sets this RSS feed's version number.
894 * @access private
896 function _setRSSVersion($version) {
897 $this->RSSVersion = $version;
901 * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
902 * The feed will contain all items previously added in the same order.
903 * @return string the feed's complete text
905 function createFeed() {
906 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
907 $feed.= $this->_createGeneratorComment();
908 $feed.= $this->_createStylesheetReferences();
909 $feed.= "<rss version=\"".$this->RSSVersion."\">\n";
910 $feed.= " <channel>\n";
911 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
912 $this->descriptionTruncSize = 500;
913 $feed.= " <description>".$this->getDescription()."</description>\n";
914 $feed.= " <link>".$this->link."</link>\n";
915 $now = new FeedDate();
916 $feed.= " <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n";
917 $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n";
919 if ($this->image!=null) {
920 $feed.= " <image>\n";
921 $feed.= " <url>".$this->image->url."</url>\n";
922 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n";
923 $feed.= " <link>".$this->image->link."</link>\n";
924 if ($this->image->width!="") {
925 $feed.= " <width>".$this->image->width."</width>\n";
927 if ($this->image->height!="") {
928 $feed.= " <height>".$this->image->height."</height>\n";
930 if ($this->image->description!="") {
931 $feed.= " <description>".$this->image->getDescription()."</description>\n";
933 $feed.= " </image>\n";
935 if ($this->language!="") {
936 $feed.= " <language>".$this->language."</language>\n";
938 if ($this->copyright!="") {
939 $feed.= " <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n";
941 if ($this->editor!="") {
942 $feed.= " <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n";
944 if ($this->webmaster!="") {
945 $feed.= " <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n";
947 if ($this->pubDate!="") {
948 $pubDate = new FeedDate($this->pubDate);
949 $feed.= " <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n";
951 if ($this->category!="") {
952 $feed.= " <category>".htmlspecialchars($this->category)."</category>\n";
954 if ($this->docs!="") {
955 $feed.= " <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n";
957 if ($this->ttl!="") {
958 $feed.= " <ttl>".htmlspecialchars($this->ttl)."</ttl>\n";
960 if ($this->rating!="") {
961 $feed.= " <rating>".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."</rating>\n";
963 if ($this->skipHours!="") {
964 $feed.= " <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n";
966 if ($this->skipDays!="") {
967 $feed.= " <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n";
969 $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
971 for ($i=0;$i<count($this->items);$i++) {
972 $feed.= " <item>\n";
973 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
974 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
975 $feed.= " <description>".$this->items[$i]->getDescription()."</description>\n";
977 if ($this->items[$i]->author!="") {
978 $feed.= " <author>".htmlspecialchars($this->items[$i]->author)."</author>\n";
981 // on hold
982 if ($this->items[$i]->source!="") {
983 $feed.= " <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";
986 if ($this->items[$i]->category!="") {
987 $feed.= " <category>".htmlspecialchars($this->items[$i]->category)."</category>\n";
989 if ($this->items[$i]->comments!="") {
990 $feed.= " <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n";
992 if ($this->items[$i]->date!="") {
993 $itemDate = new FeedDate($this->items[$i]->date);
994 $feed.= " <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n";
996 if ($this->items[$i]->guid!="") {
997 $feed.= " <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n";
999 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
1000 $feed.= " </item>\n";
1002 $feed.= " </channel>\n";
1003 $feed.= "</rss>\n";
1004 return $feed;
1011 * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.
1013 * @see http://backend.userland.com/rss
1014 * @since 1.3
1015 * @author Kai Blankenhorn <kaib@bitfolge.de>
1017 class RSSCreator20 extends RSSCreator091 {
1019 function RSSCreator20() {
1020 parent::_setRSSVersion("2.0");
1027 * PIECreator01 is a FeedCreator that implements the emerging PIE specification,
1028 * as in http://intertwingly.net/wiki/pie/Syntax.
1030 * @deprecated
1031 * @since 1.3
1032 * @author Scott Reynen <scott@randomchaos.com> and Kai Blankenhorn <kaib@bitfolge.de>
1034 class PIECreator01 extends FeedCreator {
1036 function PIECreator01() {
1037 $this->encoding = "utf-8";
1040 function createFeed() {
1041 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
1042 $feed.= $this->_createStylesheetReferences();
1043 $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n";
1044 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
1045 $this->truncSize = 500;
1046 $feed.= " <subtitle>".$this->getDescription()."</subtitle>\n";
1047 $feed.= " <link>".$this->link."</link>\n";
1048 for ($i=0;$i<count($this->items);$i++) {
1049 $feed.= " <entry>\n";
1050 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
1051 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
1052 $itemDate = new FeedDate($this->items[$i]->date);
1053 $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
1054 $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
1055 $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
1056 $feed.= " <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";
1057 if ($this->items[$i]->author!="") {
1058 $feed.= " <author>\n";
1059 $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
1060 if ($this->items[$i]->authorEmail!="") {
1061 $feed.= " <email>".$this->items[$i]->authorEmail."</email>\n";
1063 $feed.=" </author>\n";
1065 $feed.= " <content type=\"text/html\" xml:lang=\"en-us\">\n";
1066 $feed.= " <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";
1067 $feed.= " </content>\n";
1068 $feed.= " </entry>\n";
1070 $feed.= "</feed>\n";
1071 return $feed;
1077 * AtomCreator03 is a FeedCreator that implements the atom specification,
1078 * as in http://www.intertwingly.net/wiki/pie/FrontPage.
1079 * Please note that just by using AtomCreator03 you won't automatically
1080 * produce valid atom files. For example, you have to specify either an editor
1081 * for the feed or an author for every single feed item.
1083 * Some elements have not been implemented yet. These are (incomplete list):
1084 * author URL, item author's email and URL, item contents, alternate links,
1085 * other link content types than text/html. Some of them may be created with
1086 * AtomCreator03::additionalElements.
1088 * @see FeedCreator#additionalElements
1089 * @since 1.6
1090 * @author Kai Blankenhorn <kaib@bitfolge.de>, Scott Reynen <scott@randomchaos.com>
1092 class AtomCreator03 extends FeedCreator {
1094 function AtomCreator03() {
1095 $this->contentType = "application/atom+xml";
1096 $this->encoding = "utf-8";
1099 function createFeed() {
1100 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
1101 $feed.= $this->_createGeneratorComment();
1102 $feed.= $this->_createStylesheetReferences();
1103 $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\"";
1104 if ($this->language!="") {
1105 $feed.= " xml:lang=\"".$this->language."\"";
1107 $feed.= ">\n";
1108 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
1109 $feed.= " <tagline>".htmlspecialchars($this->description)."</tagline>\n";
1110 $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
1111 $feed.= " <id>".htmlspecialchars($this->link)."</id>\n";
1112 $now = new FeedDate();
1113 $feed.= " <modified>".htmlspecialchars($now->iso8601())."</modified>\n";
1114 if ($this->editor!="") {
1115 $feed.= " <author>\n";
1116 $feed.= " <name>".$this->editor."</name>\n";
1117 if ($this->editorEmail!="") {
1118 $feed.= " <email>".$this->editorEmail."</email>\n";
1120 $feed.= " </author>\n";
1122 $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n";
1123 $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
1124 for ($i=0;$i<count($this->items);$i++) {
1125 $feed.= " <entry>\n";
1126 $feed.= " <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
1127 $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
1128 if ($this->items[$i]->date=="") {
1129 $this->items[$i]->date = time();
1131 $itemDate = new FeedDate($this->items[$i]->date);
1132 $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
1133 $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
1134 $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
1135 $feed.= " <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
1136 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
1137 if ($this->items[$i]->author!="") {
1138 $feed.= " <author>\n";
1139 $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
1140 $feed.= " </author>\n";
1142 if ($this->items[$i]->description!="") {
1143 $feed.= " <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
1145 $feed.= " </entry>\n";
1147 $feed.= "</feed>\n";
1148 return $feed;
1154 * MBOXCreator is a FeedCreator that implements the mbox format
1155 * as described in http://www.qmail.org/man/man5/mbox.html
1157 * @since 1.3
1158 * @author Kai Blankenhorn <kaib@bitfolge.de>
1160 class MBOXCreator extends FeedCreator {
1162 function MBOXCreator() {
1163 $this->contentType = "text/plain";
1164 $this->encoding = "ISO-8859-15";
1167 function qp_enc($input = "", $line_max = 76) {
1168 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
1169 $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
1170 $eol = "\r\n";
1171 $escape = "=";
1172 $output = "";
1173 while( list(, $line) = each($lines) ) {
1174 //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
1175 $linlen = strlen($line);
1176 $newline = "";
1177 for($i = 0; $i < $linlen; $i++) {
1178 $c = substr($line, $i, 1);
1179 $dec = ord($c);
1180 if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
1181 $c = "=20";
1182 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1183 $h2 = floor($dec/16); $h1 = floor($dec%16);
1184 $c = $escape.$hex["$h2"].$hex["$h1"];
1186 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1187 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
1188 $newline = "";
1190 $newline .= $c;
1191 } // end of for
1192 $output .= $newline.$eol;
1194 return trim($output);
1199 * Builds the MBOX contents.
1200 * @return string the feed's complete text
1202 function createFeed() {
1203 for ($i=0;$i<count($this->items);$i++) {
1204 if ($this->items[$i]->author!="") {
1205 $from = $this->items[$i]->author;
1206 } else {
1207 $from = $this->title;
1209 $itemDate = new FeedDate($this->items[$i]->date);
1210 $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";
1211 $feed.= "Content-Type: text/plain;\n";
1212 $feed.= " charset=\"".$this->encoding."\"\n";
1213 $feed.= "Content-Transfer-Encoding: quoted-printable\n";
1214 $feed.= "Content-Type: text/plain\n";
1215 $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";
1216 $feed.= "Date: ".$itemDate->rfc822()."\n";
1217 $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";
1218 $feed.= "\n";
1219 $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));
1220 $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);
1221 $feed.= "\n";
1222 $feed.= "\n";
1224 return $feed;
1228 * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.
1229 * @return string the feed cache filename
1230 * @since 1.4
1231 * @access private
1233 function _generateFilename() {
1234 $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
1235 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";
1241 * OPMLCreator is a FeedCreator that implements OPML 1.0.
1243 * @see http://opml.scripting.com/spec
1244 * @author Dirk Clemens, Kai Blankenhorn
1245 * @since 1.5
1247 class OPMLCreator extends FeedCreator {
1249 function OPMLCreator() {
1250 $this->encoding = "utf-8";
1253 function createFeed() {
1254 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
1255 $feed.= $this->_createGeneratorComment();
1256 $feed.= $this->_createStylesheetReferences();
1257 $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
1258 $feed.= " <head>\n";
1259 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
1260 if ($this->pubDate!="") {
1261 $date = new FeedDate($this->pubDate);
1262 $feed.= " <dateCreated>".$date->rfc822()."</dateCreated>\n";
1264 if ($this->lastBuildDate!="") {
1265 $date = new FeedDate($this->lastBuildDate);
1266 $feed.= " <dateModified>".$date->rfc822()."</dateModified>\n";
1268 if ($this->editor!="") {
1269 $feed.= " <ownerName>".$this->editor."</ownerName>\n";
1271 if ($this->editorEmail!="") {
1272 $feed.= " <ownerEmail>".$this->editorEmail."</ownerEmail>\n";
1274 $feed.= " </head>\n";
1275 $feed.= " <body>\n";
1276 for ($i=0;$i<count($this->items);$i++) {
1277 $feed.= " <outline type=\"rss\" ";
1278 $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")));
1279 $feed.= " title=\"".$title."\"";
1280 $feed.= " text=\"".$title."\"";
1281 //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
1282 $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";
1283 $feed.= "/>\n";
1285 $feed.= " </body>\n";
1286 $feed.= "</opml>\n";
1287 return $feed;
1294 * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific
1295 * location, overriding the createFeed method of the parent FeedCreator.
1296 * The HTML produced can be included over http by scripting languages, or serve
1297 * as the source for an IFrame.
1298 * All output by this class is embedded in <div></div> tags to enable formatting
1299 * using CSS.
1301 * @author Pascal Van Hecke
1302 * @since 1.7
1304 class HTMLCreator extends FeedCreator {
1306 var $contentType = "text/html";
1309 * Contains HTML to be output at the start of the feed's html representation.
1311 var $header;
1314 * Contains HTML to be output at the end of the feed's html representation.
1316 var $footer ;
1319 * Contains HTML to be output between entries. A separator is only used in
1320 * case of multiple entries.
1322 var $separator;
1325 * Used to prefix the stylenames to make sure they are unique
1326 * and do not clash with stylenames on the users' page.
1328 var $stylePrefix;
1331 * Determines whether the links open in a new window or not.
1333 var $openInNewWindow = true;
1335 var $imageAlign ="right";
1338 * In case of very simple output you may want to get rid of the style tags,
1339 * hence this variable. There's no equivalent on item level, but of course you can
1340 * add strings to it while iterating over the items ($this->stylelessOutput .= ...)
1341 * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored
1342 * in the function createFeed().
1344 var $stylelessOutput ="";
1347 * Writes the HTML.
1348 * @return string the scripts's complete text
1350 function createFeed() {
1351 // if there is styleless output, use the content of this variable and ignore the rest
1352 if ($this->stylelessOutput!="") {
1353 return $this->stylelessOutput;
1356 //if no stylePrefix is set, generate it yourself depending on the script name
1357 if ($this->stylePrefix=="") {
1358 $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";
1361 //set an openInNewWindow_token_to be inserted or not
1362 if ($this->openInNewWindow) {
1363 $targetInsert = " target='_blank'";
1366 // use this array to put the lines in and implode later with "document.write" javascript
1367 $feedArray = array();
1368 if ($this->image!=null) {
1369 $imageStr = "<a href='".$this->image->link."'".$targetInsert.">".
1370 "<img src='".$this->image->url."' border='0' alt='".
1371 FeedCreator::iTrunc(htmlspecialchars($this->image->title),100).
1372 "' align='".$this->imageAlign."' ";
1373 if ($this->image->width) {
1374 $imageStr .=" width='".$this->image->width. "' ";
1376 if ($this->image->height) {
1377 $imageStr .=" height='".$this->image->height."' ";
1379 $imageStr .="/></a>";
1380 $feedArray[] = $imageStr;
1383 if ($this->title) {
1384 $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>".
1385 FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>";
1387 if ($this->getDescription()) {
1388 $feedArray[] = "<div class='".$this->stylePrefix."description'>".
1389 str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())).
1390 "</div>";
1393 if ($this->header) {
1394 $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>";
1397 for ($i=0;$i<count($this->items);$i++) {
1398 if ($this->separator and $i > 0) {
1399 $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>";
1402 if ($this->items[$i]->title) {
1403 if ($this->items[$i]->link) {
1404 $feedArray[] =
1405 "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix.
1406 "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
1407 "</a></div>";
1408 } else {
1409 $feedArray[] =
1410 "<div class='".$this->stylePrefix."item_title'>".
1411 FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
1412 "</div>";
1415 if ($this->items[$i]->getDescription()) {
1416 $feedArray[] =
1417 "<div class='".$this->stylePrefix."item_description'>".
1418 str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())).
1419 "</div>";
1422 if ($this->footer) {
1423 $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>";
1426 $feed= "".join($feedArray, "\r\n");
1427 return $feed;
1431 * Overrrides parent to produce .html extensions
1433 * @return string the feed cache filename
1434 * @since 1.4
1435 * @access private
1437 function _generateFilename() {
1438 $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
1439 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html";
1445 * JSCreator is a class that writes a js file to a specific
1446 * location, overriding the createFeed method of the parent HTMLCreator.
1448 * @author Pascal Van Hecke
1450 class JSCreator extends HTMLCreator {
1451 var $contentType = "text/javascript";
1454 * writes the javascript
1455 * @return string the scripts's complete text
1457 function createFeed()
1459 $feed = parent::createFeed();
1460 $feedArray = explode("\n",$feed);
1462 $jsFeed = "";
1463 foreach ($feedArray as $value) {
1464 $jsFeed .= "document.write('".trim(addslashes($value))."');\n";
1466 return $jsFeed;
1470 * Overrrides parent to produce .js extensions
1472 * @return string the feed cache filename
1473 * @since 1.4
1474 * @access private
1476 function _generateFilename() {
1477 $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
1478 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js";
1485 /*** TEST SCRIPT *********************************************************
1487 //include("feedcreator.class.php");
1489 $rss = new UniversalFeedCreator();
1490 $rss->useCached();
1491 $rss->title = "PHP news";
1492 $rss->description = "daily news from the PHP scripting world";
1494 //optional
1495 //$rss->descriptionTruncSize = 500;
1496 //$rss->descriptionHtmlSyndicated = true;
1497 //$rss->xslStyleSheet = "http://feedster.com/rss20.xsl";
1499 $rss->link = "http://www.dailyphp.net/news";
1500 $rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF;
1502 $image = new FeedImage();
1503 $image->title = "dailyphp.net logo";
1504 $image->url = "http://www.dailyphp.net/images/logo.gif";
1505 $image->link = "http://www.dailyphp.net";
1506 $image->description = "Feed provided by dailyphp.net. Click to visit.";
1508 //optional
1509 $image->descriptionTruncSize = 500;
1510 $image->descriptionHtmlSyndicated = true;
1512 $rss->image = $image;
1514 // get your news items from somewhere, e.g. your database:
1515 //mysql_select_db($dbHost, $dbUser, $dbPass);
1516 //$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC");
1517 //while ($data = mysql_fetch_object($res)) {
1518 $item = new FeedItem();
1519 $item->title = "This is an the test title of an item";
1520 $item->link = "http://localhost/item/";
1521 $item->description = "<b>description in </b><br/>HTML";
1523 //optional
1524 //item->descriptionTruncSize = 500;
1525 $item->descriptionHtmlSyndicated = true;
1527 $item->date = time();
1528 $item->source = "http://www.dailyphp.net";
1529 $item->author = "John Doe";
1531 $rss->addItem($item);
1532 //}
1534 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS
1535 echo $rss->saveFeed("RSS0.91", "feed.xml");
1539 ***************************************************************************/