Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

feedcreator.class.php

Go to the documentation of this file.
00001 <?php
00010 /***************************************************************************
00011 
00012 FeedCreator class v1.7.2
00013 originally (c) Kai Blankenhorn
00014 www.bitfolge.de
00015 kaib@bitfolge.de
00016 v1.3 work by Scott Reynen (scott@randomchaos.com) and Kai Blankenhorn
00017 v1.5 OPML support by Dirk Clemens
00018 
00019 This library is free software; you can redistribute it and/or
00020 modify it under the terms of the GNU Lesser General Public
00021 License as published by the Free Software Foundation; either
00022 version 2.1 of the License, or (at your option) any later version.
00023 
00024 This library is distributed in the hope that it will be useful,
00025 but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027 Lesser General Public License for more details.
00028 
00029 You should have received a copy of the GNU Lesser General Public
00030 License along with this library; if not, write to the Free Software
00031 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00032 
00033 ****************************************************************************
00034 
00035 
00036 Changelog:
00037 
00038 v1.7.2  10-11-04
00039     license changed to LGPL
00040 
00041 v1.7.1
00042     fixed a syntax bug
00043     fixed left over debug code
00044 
00045 v1.7    07-18-04
00046     added HTML and JavaScript feeds (configurable via CSS) (thanks to Pascal Van Hecke)
00047     added HTML descriptions for all feed formats (thanks to Pascal Van Hecke)
00048     added a switch to select an external stylesheet (thanks to Pascal Van Hecke)
00049     changed default content-type to application/xml
00050     added character encoding setting
00051     fixed numerous smaller bugs (thanks to Sören Fuhrmann of golem.de)
00052     improved changing ATOM versions handling (thanks to August Trometer)
00053     improved the UniversalFeedCreator's useCached method (thanks to Sören Fuhrmann of golem.de)
00054     added charset output in HTTP headers (thanks to Sören Fuhrmann of golem.de)
00055     added Slashdot namespace to RSS 1.0 (thanks to Sören Fuhrmann of golem.de)
00056 
00057 v1.6    05-10-04
00058     added stylesheet to RSS 1.0 feeds
00059     fixed generator comment (thanks Kevin L. Papendick and Tanguy Pruvot)
00060     fixed RFC822 date bug (thanks Tanguy Pruvot)
00061     added TimeZone customization for RFC8601 (thanks Tanguy Pruvot)
00062     fixed Content-type could be empty (thanks Tanguy Pruvot)
00063     fixed author/creator in RSS1.0 (thanks Tanguy Pruvot)
00064 
00065 v1.6 beta   02-28-04
00066     added Atom 0.3 support (not all features, though)
00067     improved OPML 1.0 support (hopefully - added more elements)
00068     added support for arbitrary additional elements (use with caution)
00069     code beautification :-)
00070     considered beta due to some internal changes
00071 
00072 v1.5.1  01-27-04
00073     fixed some RSS 1.0 glitches (thanks to Stéphane Vanpoperynghe)
00074     fixed some inconsistencies between documentation and code (thanks to Timothy Martin)
00075 
00076 v1.5    01-06-04
00077     added support for OPML 1.0
00078     added more documentation
00079 
00080 v1.4    11-11-03
00081     optional feed saving and caching
00082     improved documentation
00083     minor improvements
00084 
00085 v1.3    10-02-03
00086     renamed to FeedCreator, as it not only creates RSS anymore
00087     added support for mbox
00088     tentative support for echo/necho/atom/pie/???
00089         
00090 v1.2    07-20-03
00091     intelligent auto-truncating of RSS 0.91 attributes
00092     don't create some attributes when they're not set
00093     documentation improved
00094     fixed a real and a possible bug with date conversions
00095     code cleanup
00096 
00097 v1.1    06-29-03
00098     added images to feeds
00099     now includes most RSS 0.91 attributes
00100     added RSS 2.0 feeds
00101 
00102 v1.0    06-24-03
00103     initial release
00104 
00105 
00106 
00107 ***************************************************************************/
00108 
00109 /*** GENERAL USAGE *********************************************************
00110 
00111 include("feedcreator.class.php"); 
00112 
00113 $rss = new UniversalFeedCreator(); 
00114 $rss->useCached(); // use cached version if age<1 hour
00115 $rss->title = "PHP news"; 
00116 $rss->description = "daily news from the PHP scripting world"; 
00117 
00118 //optional
00119 $rss->descriptionTruncSize = 500;
00120 $rss->descriptionHtmlSyndicated = true;
00121 
00122 $rss->link = "http://www.dailyphp.net/news"; 
00123 $rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"]; 
00124 
00125 $image = new FeedImage(); 
00126 $image->title = "dailyphp.net logo"; 
00127 $image->url = "http://www.dailyphp.net/images/logo.gif"; 
00128 $image->link = "http://www.dailyphp.net"; 
00129 $image->description = "Feed provided by dailyphp.net. Click to visit."; 
00130 
00131 //optional
00132 $image->descriptionTruncSize = 500;
00133 $image->descriptionHtmlSyndicated = true;
00134 
00135 $rss->image = $image; 
00136 
00137 // get your news items from somewhere, e.g. your database: 
00138 mysql_select_db($dbHost, $dbUser, $dbPass); 
00139 $res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); 
00140 while ($data = mysql_fetch_object($res)) { 
00141     $item = new FeedItem(); 
00142     $item->title = $data->title; 
00143     $item->link = $data->url; 
00144     $item->description = $data->short; 
00145     
00146     //optional
00147     item->descriptionTruncSize = 500;
00148     item->descriptionHtmlSyndicated = true;
00149 
00150     $item->date = $data->newsdate; 
00151     $item->source = "http://www.dailyphp.net"; 
00152     $item->author = "John Doe"; 
00153      
00154     $rss->addItem($item); 
00155 } 
00156 
00157 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated),
00158 // MBOX, OPML, ATOM, ATOM0.3, HTML, JS
00159 echo $rss->saveFeed("RSS1.0", "news/feed.xml");
00160 
00161 
00162 ***************************************************************************
00163 *          A little setup                                                 *
00164 **************************************************************************/
00165 
00166 // your local timezone, set to "" to disable or for GMT
00167 define("TIME_ZONE","+01:00");
00168 
00169 
00170 
00171 
00175 define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2");
00176 
00177 
00178 
00185 class FeedItem extends HtmlDescribable {
00189     var $title, $description, $link;
00190     
00194     var $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator;
00195     
00209     var $date;
00210     
00219     var $additionalElements = Array();
00220 
00221     // on hold
00222     // var $source;
00223 }
00224 
00225 
00226 
00232 class FeedImage extends HtmlDescribable {
00236     var $title, $url, $link;
00237     
00241     var $width, $height, $description;
00242 }
00243 
00244 
00245 
00250 class HtmlDescribable {
00254     var $descriptionHtmlSyndicated;
00255     
00259     var $descriptionTruncSize;
00260     
00266     function getDescription() {
00267         $descriptionField = new FeedHtmlField($this->description);
00268         $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;
00269         $descriptionField->truncSize = $this->descriptionTruncSize;
00270         return $descriptionField->output();
00271     }
00272 
00273 }
00274 
00275 
00283 class FeedHtmlField {
00287     var $rawFieldContent;
00288     
00293     var $truncSize, $syndicateHtml;
00294     
00299     function FeedHtmlField($parFieldContent) {
00300         if ($parFieldContent) {
00301             $this->rawFieldContent = $parFieldContent;
00302         }
00303     }
00304         
00305         
00310     function output() {
00311         // when field available and syndicated in html we assume 
00312         // - valid html in $rawFieldContent and we enclose in CDATA tags
00313         // - no truncation (truncating risks producing invalid html)
00314         if (!$this->rawFieldContent) {
00315             $result = "";
00316         }   elseif ($this->syndicateHtml) {
00317             $result = "<![CDATA[".$this->rawFieldContent."]]>";
00318         } else {
00319             if ($this->truncSize and is_int($this->truncSize)) {
00320                 $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);
00321             } else {
00322                 $result = htmlspecialchars($this->rawFieldContent);
00323             }
00324         }
00325         return $result;
00326     }
00327 
00328 }
00329 
00330 
00331 
00341 class UniversalFeedCreator extends FeedCreator {
00342     var $_feed;
00343     
00344     function _setFormat($format) {
00345         switch (strtoupper($format)) {
00346             
00347             case "2.0":
00348                 // fall through
00349             case "RSS2.0":
00350                 $this->_feed = new RSSCreator20();
00351                 break;
00352             
00353             case "1.0":
00354                 // fall through
00355             case "RSS1.0":
00356                 $this->_feed = new RSSCreator10();
00357                 break;
00358             
00359             case "0.91":
00360                 // fall through
00361             case "RSS0.91":
00362                 $this->_feed = new RSSCreator091();
00363                 break;
00364             
00365             case "PIE0.1":
00366                 $this->_feed = new PIECreator01();
00367                 break;
00368             
00369             case "MBOX":
00370                 $this->_feed = new MBOXCreator();
00371                 break;
00372             
00373             case "OPML":
00374                 $this->_feed = new OPMLCreator();
00375                 break;
00376                 
00377             case "ATOM":
00378                 // fall through: always the latest ATOM version
00379                 
00380             case "ATOM0.3":
00381                 $this->_feed = new AtomCreator03();
00382                 break;
00383                 
00384             case "HTML":
00385                 $this->_feed = new HTMLCreator();
00386                 break;
00387             
00388             case "JS":
00389                 // fall through
00390             case "JAVASCRIPT":
00391                 $this->_feed = new JSCreator();
00392                 break;
00393             
00394             default:
00395                 $this->_feed = new RSSCreator091();
00396                 break;
00397         }
00398         
00399         $vars = get_object_vars($this);
00400         foreach ($vars as $key => $value) {
00401             // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
00402             if (!in_array($key, array("_feed", "contentType", "encoding"))) {
00403                 $this->_feed->{$key} = $this->{$key};
00404             }
00405         }
00406     }
00407     
00416     function createFeed($format = "RSS0.91") {
00417         $this->_setFormat($format);
00418         return $this->_feed->createFeed();
00419     }
00420     
00421     
00422     
00433     function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
00434         $this->_setFormat($format);
00435         $this->_feed->saveFeed($filename, $displayContents);
00436     }
00437 
00438 
00451    function useCached($format="RSS0.91", $filename="", $timeout=3600) {
00452       $this->_setFormat($format);
00453       $this->_feed->useCached($filename, $timeout);
00454    }
00455 
00456 }
00457 
00458 
00467 class FeedCreator extends HtmlDescribable {
00468 
00472     var $title, $description, $link;
00473     
00474     
00478     var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
00479 
00484     var $xslStyleSheet = "";
00485     
00486     
00490     var $items = Array();
00491     
00492     
00498     var $contentType = "application/xml";
00499     
00500     
00505     var $encoding = "ISO-8859-1";
00506     
00507     
00516     var $additionalElements = Array();
00517    
00518     
00525     function addItem($item) {
00526         $this->items[] = $item;
00527     }
00528     
00529     
00542     function iTrunc($string, $length) {
00543         if (strlen($string)<=$length) {
00544             return $string;
00545         }
00546         
00547         $pos = strrpos($string,".");
00548         if ($pos>=$length-4) {
00549             $string = substr($string,0,$length-4);
00550             $pos = strrpos($string,".");
00551         }
00552         if ($pos>=$length*0.4) {
00553             return substr($string,0,$pos+1)." ...";
00554         }
00555         
00556         $pos = strrpos($string," ");
00557         if ($pos>=$length-4) {
00558             $string = substr($string,0,$length-4);
00559             $pos = strrpos($string," ");
00560         }
00561         if ($pos>=$length*0.4) {
00562             return substr($string,0,$pos)." ...";
00563         }
00564         
00565         return substr($string,0,$length-4)." ...";
00566             
00567     }
00568     
00569     
00575     function _createGeneratorComment() {
00576         return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n";
00577     }
00578     
00579     
00587     function _createAdditionalElements($elements, $indentString="") {
00588         $ae = "";
00589         if (is_array($elements)) {
00590             foreach($elements AS $key => $value) {
00591                 $ae.= $indentString."<$key>$value</$key>\n";
00592             }
00593         }
00594         return $ae;
00595     }
00596     
00597     function _createStylesheetReferences() {
00598         $xml = "";
00599         if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";
00600         if ($this->xslStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n";
00601         return $xml;
00602     }
00603     
00604     
00610     function createFeed() {
00611     }
00612     
00629     function _generateFilename() {
00630         if (defined('FEEDCREATOR_TMP_DIR'))
00631             $tmpDir = FEEDCREATOR_TMP_DIR;
00632         else
00633             $tmpDir = '/tmp';
00634         
00635         return "$tmpDir/FEEDCREATOR_" . md5($_SERVER['REQUEST_URI']) . ".xml";
00636     }
00637     
00638     
00643     function _redirect($filename) {
00644         // attention, heavily-commented-out-area
00645         
00646         // maybe use this in addition to file time checking
00647         //Header("Expires: ".date("r",time()+$this->_timeout));
00648         
00649         /* no caching at all, doesn't seem to work as good:
00650         Header("Cache-Control: no-cache");
00651         Header("Pragma: no-cache");
00652         */
00653         
00654         // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
00655         //Header("Location: ".$filename);
00656 
00657         
00658         // proper header as per tip from: http://www.petefreitag.com/item/381.cfm
00659         if (strpos($_SERVER["HTTP_USER_AGENT"], 'Mozilla') !== null)
00660             header("Content-Type: text/xml");
00661         else
00662             header("Content-Type: application/rss+xml");
00663         
00664         //Header("Content-Disposition: inline; filename=".basename($filename));
00665         echo file_get_contents($filename, "r");
00666         die();
00667     }
00668     
00679     function useCached($filename="", $timeout=3600) {
00680         $this->_timeout = $timeout;
00681         if ($filename=="") {
00682             $filename = $this->_generateFilename();
00683         }
00684         if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {
00685             $this->_redirect($filename);
00686         }
00687     }
00688     
00689     
00698     function saveFeed($filename="", $displayContents=true) {
00699         if ($filename=="") {
00700             $filename = $this->_generateFilename();
00701         }
00702         $feedFile = fopen($filename, "w+");
00703         if ($feedFile) {
00704             fputs($feedFile,$this->createFeed());
00705             fclose($feedFile);
00706             if ($displayContents) {
00707                 $this->_redirect($filename);
00708             }
00709         } else {
00710             echo "<br /><b>Error creating feed file, please check write permissions.</b><br />";
00711         }
00712     }
00713     
00714 }
00715 
00716 
00721 class FeedDate {
00722     var $unix;
00723     
00729     function FeedDate($dateString="") {
00730         if ($dateString=="") $dateString = date("r");
00731         
00732         if (is_integer($dateString)) {
00733             $this->unix = $dateString;
00734             return;
00735         }
00736         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)) {
00737             $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);
00738             $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
00739             if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
00740                 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
00741             } else {
00742                 if (strlen($matches[7])==1) {
00743                     $oneHour = 3600;
00744                     $ord = ord($matches[7]);
00745                     if ($ord < ord("M")) {
00746                         $tzOffset = (ord("A") - $ord - 1) * $oneHour;
00747                     } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
00748                         $tzOffset = ($ord - ord("M")) * $oneHour;
00749                     } elseif ($matches[7]=="Z") {
00750                         $tzOffset = 0;
00751                     }
00752                 }
00753                 switch ($matches[7]) {
00754                     case "UT":
00755                     case "GMT": $tzOffset = 0;
00756                 }
00757             }
00758             $this->unix += $tzOffset;
00759             return;
00760         }
00761         if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
00762             $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
00763             if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
00764                 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
00765             } else {
00766                 if ($matches[7]=="Z") {
00767                     $tzOffset = 0;
00768                 }
00769             }
00770             $this->unix += $tzOffset;
00771             return;
00772         }
00773         $this->unix = 0;
00774     }
00775 
00781     function rfc822() {
00782         //return gmdate("r",$this->unix);
00783         $date = gmdate("D, d M Y H:i:s", $this->unix);
00784         if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);
00785         return $date;
00786     }
00787     
00793     function iso8601() {
00794         $date = gmdate("Y-m-d\TH:i:sO",$this->unix);
00795         $date = substr($date,0,22) . ':' . substr($date,-2);
00796         if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);
00797         return $date;
00798     }
00799     
00805     function unix() {
00806         return $this->unix;
00807     }
00808 }
00809 
00810 
00818 class RSSCreator10 extends FeedCreator {
00819 
00825     function createFeed() {     
00826         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
00827         $feed.= $this->_createGeneratorComment();
00828         if ($this->cssStyleSheet=="") {
00829             $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
00830         }
00831         $feed.= $this->_createStylesheetReferences();
00832         $feed.= "<rdf:RDF\n";
00833         $feed.= "    xmlns=\"http://purl.org/rss/1.0/\"\n";
00834         $feed.= "    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"; 
00835         $feed.= "    xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";
00836         $feed.= "    xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
00837         $feed.= "    <channel rdf:about=\"".$this->syndicationURL."\">\n";
00838         $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";
00839         $feed.= "        <description>".htmlspecialchars($this->description)."</description>\n";
00840         $feed.= "        <link>".$this->link."</link>\n";
00841         if ($this->image!=null) {
00842             $feed.= "        <image rdf:resource=\"".$this->image->url."\" />\n";
00843         }
00844         $now = new FeedDate();
00845         $feed.= "       <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n";
00846         $feed.= "        <items>\n";
00847         $feed.= "            <rdf:Seq>\n";
00848         for ($i=0;$i<count($this->items);$i++) {
00849             $feed.= "                <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
00850         }
00851         $feed.= "            </rdf:Seq>\n";
00852         $feed.= "        </items>\n";
00853         $feed.= "    </channel>\n";
00854         if ($this->image!=null) {
00855             $feed.= "    <image rdf:about=\"".$this->image->url."\">\n";
00856             $feed.= "        <title>".$this->image->title."</title>\n";
00857             $feed.= "        <link>".$this->image->link."</link>\n";
00858             $feed.= "        <url>".$this->image->url."</url>\n";
00859             $feed.= "    </image>\n";
00860         }
00861         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
00862         
00863         for ($i=0;$i<count($this->items);$i++) {
00864             $feed.= "    <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n";
00865             //$feed.= "        <dc:type>Posting</dc:type>\n";
00866             $feed.= "        <dc:format>text/html</dc:format>\n";
00867             if ($this->items[$i]->date!=null) {
00868                 $itemDate = new FeedDate($this->items[$i]->date);
00869                 $feed.= "        <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n";
00870             }
00871             if ($this->items[$i]->source!="") {
00872                 $feed.= "        <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n";
00873             }
00874             if ($this->items[$i]->author!="") {
00875                 $feed.= "        <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n";
00876             }
00877             $feed.= "        <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")))."</title>\n";
00878             $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
00879             $feed.= "        <description>".htmlspecialchars($this->items[$i]->description)."</description>\n";
00880             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
00881             $feed.= "    </item>\n";
00882         }
00883         $feed.= "</rdf:RDF>\n";
00884         return $feed;
00885     }
00886 }
00887 
00888 
00889 
00897 class RSSCreator091 extends FeedCreator {
00898 
00903     var $RSSVersion;
00904 
00905     function RSSCreator091() {
00906         $this->_setRSSVersion("0.91");
00907         $this->contentType = "application/rss+xml";
00908     }
00909     
00914     function _setRSSVersion($version) {
00915         $this->RSSVersion = $version;
00916     }
00917 
00923     function createFeed() {
00924         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
00925         $feed.= $this->_createGeneratorComment();
00926         $feed.= $this->_createStylesheetReferences();
00927         $feed.= "<rss version=\"".$this->RSSVersion."\">\n"; 
00928         $feed.= "    <channel>\n";
00929         $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
00930         $this->descriptionTruncSize = 500;
00931         $feed.= "        <description>".$this->getDescription()."</description>\n";
00932         $feed.= "        <link>".htmlspecialchars($this->link)."</link>\n";
00933         $now = new FeedDate();
00934         $feed.= "        <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n";
00935         $feed.= "        <generator>".FEEDCREATOR_VERSION."</generator>\n";
00936 
00937         if ($this->image!=null) {
00938             $feed.= "        <image>\n";
00939             $feed.= "            <url>".$this->image->url."</url>\n"; 
00940             $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n"; 
00941             $feed.= "            <link>".$this->image->link."</link>\n";
00942             if ($this->image->width!="") {
00943                 $feed.= "            <width>".$this->image->width."</width>\n";
00944             }
00945             if ($this->image->height!="") {
00946                 $feed.= "            <height>".$this->image->height."</height>\n";
00947             }
00948             if ($this->image->description!="") {
00949                 $feed.= "            <description>".$this->image->getDescription()."</description>\n";
00950             }
00951             $feed.= "        </image>\n";
00952         }
00953         if ($this->language!="") {
00954             $feed.= "        <language>".$this->language."</language>\n";
00955         }
00956         if ($this->copyright!="") {
00957             $feed.= "        <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n";
00958         }
00959         if ($this->editor!="") {
00960             $feed.= "        <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n";
00961         }
00962         if ($this->webmaster!="") {
00963             $feed.= "        <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n";
00964         }
00965         if ($this->pubDate!="") {
00966             $pubDate = new FeedDate($this->pubDate);
00967             $feed.= "        <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n";
00968         }
00969         if ($this->category!="") {
00970             $feed.= "        <category>".htmlspecialchars($this->category)."</category>\n";
00971         }
00972         if ($this->docs!="") {
00973             $feed.= "        <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n";
00974         }
00975         if ($this->ttl!="") {
00976             $feed.= "        <ttl>".htmlspecialchars($this->ttl)."</ttl>\n";
00977         }
00978         if ($this->rating!="") {
00979             $feed.= "        <rating>".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."</rating>\n";
00980         }
00981         if ($this->skipHours!="") {
00982             $feed.= "        <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n";
00983         }
00984         if ($this->skipDays!="") {
00985             $feed.= "        <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n";
00986         }
00987         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
00988 
00989         for ($i=0;$i<count($this->items);$i++) {
00990             $feed.= "        <item>\n";
00991             $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
00992             $feed.= "            <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
00993             $feed.= "            <description>".$this->items[$i]->getDescription()."</description>\n";
00994             
00995             if ($this->items[$i]->author!="") {
00996                 $feed.= "            <author>".htmlspecialchars($this->items[$i]->author)."</author>\n";
00997             }
00998             /*
00999             // on hold
01000             if ($this->items[$i]->source!="") {
01001                     $feed.= "            <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";
01002             }
01003             */
01004             if ($this->items[$i]->category!="") {
01005                 $feed.= "            <category>".htmlspecialchars($this->items[$i]->category)."</category>\n";
01006             }
01007             if ($this->items[$i]->comments!="") {
01008                 $feed.= "            <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n";
01009             }
01010             if ($this->items[$i]->date!="") {
01011             $itemDate = new FeedDate($this->items[$i]->date);
01012                 $feed.= "            <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n";
01013             }
01014             if ($this->items[$i]->guid!="") {
01015                 $feed.= "            <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n";
01016             }
01017             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
01018             $feed.= "        </item>\n";
01019         }
01020         $feed.= "    </channel>\n";
01021         $feed.= "</rss>\n";
01022         return $feed;
01023     }
01024 }
01025 
01026 
01027 
01035 class RSSCreator20 extends RSSCreator091 {
01036 
01037     function RSSCreator20() {
01038         parent::_setRSSVersion("2.0");
01039     }
01040     
01041 }
01042 
01043 
01052 class PIECreator01 extends FeedCreator {
01053     
01054     function PIECreator01() {
01055         $this->encoding = "utf-8";
01056     }
01057     
01058     function createFeed() {
01059         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01060         $feed.= $this->_createStylesheetReferences();
01061         $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n"; 
01062         $feed.= "    <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
01063         $this->truncSize = 500;
01064         $feed.= "    <subtitle>".$this->getDescription()."</subtitle>\n";
01065         $feed.= "    <link>".$this->link."</link>\n";
01066         for ($i=0;$i<count($this->items);$i++) {
01067             $feed.= "    <entry>\n";
01068             $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
01069             $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
01070             $itemDate = new FeedDate($this->items[$i]->date);
01071             $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
01072             $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
01073             $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
01074             $feed.= "        <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";
01075             if ($this->items[$i]->author!="") {
01076                 $feed.= "        <author>\n";
01077                 $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
01078                 if ($this->items[$i]->authorEmail!="") {
01079                     $feed.= "            <email>".$this->items[$i]->authorEmail."</email>\n";
01080                 }
01081                 $feed.="        </author>\n";
01082             }
01083             $feed.= "        <content type=\"text/html\" xml:lang=\"en-us\">\n";
01084             $feed.= "            <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";
01085             $feed.= "        </content>\n";
01086             $feed.= "    </entry>\n";
01087         }
01088         $feed.= "</feed>\n";
01089         return $feed;
01090     }
01091 }
01092 
01093 
01110 class AtomCreator03 extends FeedCreator {
01111 
01112     function AtomCreator03() {
01113         $this->contentType = "application/atom+xml";
01114         $this->encoding = "utf-8";
01115     }
01116     
01117     function createFeed() {
01118         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01119         $feed.= $this->_createGeneratorComment();
01120         $feed.= $this->_createStylesheetReferences();
01121         $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\"";
01122         if ($this->language!="") {
01123             $feed.= " xml:lang=\"".$this->language."\"";
01124         }
01125         $feed.= ">\n"; 
01126         $feed.= "    <title>".htmlspecialchars($this->title)."</title>\n";
01127         $feed.= "    <tagline>".htmlspecialchars($this->description)."</tagline>\n";
01128         $feed.= "    <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
01129         $feed.= "    <id>".htmlspecialchars($this->link)."</id>\n";
01130         $now = new FeedDate();
01131         $feed.= "    <modified>".htmlspecialchars($now->iso8601())."</modified>\n";
01132         if ($this->editor!="") {
01133             $feed.= "    <author>\n";
01134             $feed.= "        <name>".$this->editor."</name>\n";
01135             if ($this->editorEmail!="") {
01136                 $feed.= "        <email>".$this->editorEmail."</email>\n";
01137             }
01138             $feed.= "    </author>\n";
01139         }
01140         $feed.= "    <generator>".FEEDCREATOR_VERSION."</generator>\n";
01141         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
01142         for ($i=0;$i<count($this->items);$i++) {
01143             $feed.= "    <entry>\n";
01144             $feed.= "        <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
01145             $feed.= "        <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
01146             if ($this->items[$i]->date=="") {
01147                 $this->items[$i]->date = time();
01148             }
01149             $itemDate = new FeedDate($this->items[$i]->date);
01150             $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
01151             $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
01152             $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
01153             $feed.= "        <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
01154             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
01155             if ($this->items[$i]->author!="") {
01156                 $feed.= "        <author>\n";
01157                 $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
01158                 $feed.= "        </author>\n";
01159             }
01160             if ($this->items[$i]->description!="") {
01161                 $feed.= "        <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
01162             }
01163             $feed.= "    </entry>\n";
01164         }
01165         $feed.= "</feed>\n";
01166         return $feed;
01167     }
01168 }
01169 
01170 
01178 class MBOXCreator extends FeedCreator {
01179 
01180     function MBOXCreator() {
01181         $this->contentType = "text/plain";
01182         $this->encoding = "ISO-8859-15";
01183     }
01184     
01185     function qp_enc($input = "", $line_max = 76) { 
01186         $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 
01187         $lines = preg_split("/(?:\r\n|\r|\n)/", $input); 
01188         $eol = "\r\n"; 
01189         $escape = "="; 
01190         $output = ""; 
01191         while( list(, $line) = each($lines) ) { 
01192             //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary 
01193             $linlen = strlen($line); 
01194             $newline = ""; 
01195             for($i = 0; $i < $linlen; $i++) { 
01196                 $c = substr($line, $i, 1); 
01197                 $dec = ord($c); 
01198                 if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only 
01199                     $c = "=20"; 
01200                 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required 
01201                     $h2 = floor($dec/16); $h1 = floor($dec%16); 
01202                     $c = $escape.$hex["$h2"].$hex["$h1"]; 
01203                 } 
01204                 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted 
01205                     $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 
01206                     $newline = ""; 
01207                 } 
01208                 $newline .= $c; 
01209             } // end of for 
01210             $output .= $newline.$eol; 
01211         } 
01212         return trim($output); 
01213     }
01214     
01215 
01220     function createFeed() {
01221         for ($i=0;$i<count($this->items);$i++) {
01222             if ($this->items[$i]->author!="") {
01223                 $from = $this->items[$i]->author;
01224             } else {
01225                 $from = $this->title;
01226             }
01227             $itemDate = new FeedDate($this->items[$i]->date);
01228             $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";
01229             $feed.= "Content-Type: text/plain;\n";
01230             $feed.= "   charset=\"".$this->encoding."\"\n";
01231             $feed.= "Content-Transfer-Encoding: quoted-printable\n";
01232             $feed.= "Content-Type: text/plain\n";
01233             $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";
01234             $feed.= "Date: ".$itemDate->rfc822()."\n";
01235             $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";
01236             $feed.= "\n";
01237             $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));
01238             $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);
01239             $feed.= "\n";
01240             $feed.= "\n";
01241         }
01242         return $feed;
01243     }
01244     
01251     function _generateFilename() {
01252         $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
01253         return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";
01254     }
01255 }
01256 
01257 
01265 class OPMLCreator extends FeedCreator {
01266 
01267     function OPMLCreator() {
01268         $this->encoding = "utf-8";
01269     }
01270     
01271     function createFeed() {     
01272         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01273         $feed.= $this->_createGeneratorComment();
01274         $feed.= $this->_createStylesheetReferences();
01275         $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
01276         $feed.= "    <head>\n";
01277         $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";
01278         if ($this->pubDate!="") {
01279             $date = new FeedDate($this->pubDate);
01280             $feed.= "         <dateCreated>".$date->rfc822()."</dateCreated>\n";
01281         }
01282         if ($this->lastBuildDate!="") {
01283             $date = new FeedDate($this->lastBuildDate);
01284             $feed.= "         <dateModified>".$date->rfc822()."</dateModified>\n";
01285         }
01286         if ($this->editor!="") {
01287             $feed.= "         <ownerName>".$this->editor."</ownerName>\n";
01288         }
01289         if ($this->editorEmail!="") {
01290             $feed.= "         <ownerEmail>".$this->editorEmail."</ownerEmail>\n";
01291         }
01292         $feed.= "    </head>\n";
01293         $feed.= "    <body>\n";
01294         for ($i=0;$i<count($this->items);$i++) {
01295             $feed.= "    <outline type=\"rss\" ";
01296             $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")));
01297             $feed.= " title=\"".$title."\"";
01298             $feed.= " text=\"".$title."\"";
01299             //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
01300             $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";
01301             $feed.= "/>\n";
01302         }
01303         $feed.= "    </body>\n";
01304         $feed.= "</opml>\n";
01305         return $feed;
01306     }
01307 }
01308 
01309 
01310 
01322 class HTMLCreator extends FeedCreator {
01323 
01324     var $contentType = "text/html";
01325     
01329     var $header;
01330     
01334     var $footer ;
01335     
01340     var $separator;
01341     
01346     var $stylePrefix;
01347     
01351     var $openInNewWindow = true;
01352     
01353     var $imageAlign ="right";
01354     
01362     var $stylelessOutput ="";
01363 
01368     function createFeed() {
01369         // if there is styleless output, use the content of this variable and ignore the rest
01370         if ($this->stylelessOutput!="") {
01371             return $this->stylelessOutput;
01372         }
01373         
01374         //if no stylePrefix is set, generate it yourself depending on the script name
01375         if ($this->stylePrefix=="") {
01376             $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";
01377         }
01378 
01379         //set an openInNewWindow_token_to be inserted or not
01380         if ($this->openInNewWindow) {
01381             $targetInsert = " target='_blank'";
01382         }
01383         
01384         // use this array to put the lines in and implode later with "document.write" javascript
01385         $feedArray = array();
01386         if ($this->image!=null) {
01387             $imageStr = "<a href='".$this->image->link."'".$targetInsert.">".
01388                             "<img src='".$this->image->url."' border='0' alt='".
01389                             FeedCreator::iTrunc(htmlspecialchars($this->image->title),100).
01390                             "' align='".$this->imageAlign."' ";
01391             if ($this->image->width) {
01392                 $imageStr .=" width='".$this->image->width. "' ";
01393             }
01394             if ($this->image->height) {
01395                 $imageStr .=" height='".$this->image->height."' ";
01396             }
01397             $imageStr .="/></a>";
01398             $feedArray[] = $imageStr;
01399         }
01400         
01401         if ($this->title) {
01402             $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>".
01403                 FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>";
01404         }
01405         if ($this->getDescription()) {
01406             $feedArray[] = "<div class='".$this->stylePrefix."description'>".
01407                 str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())).
01408                 "</div>";
01409         }
01410         
01411         if ($this->header) {
01412             $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>";
01413         }
01414         
01415         for ($i=0;$i<count($this->items);$i++) {
01416             if ($this->separator and $i > 0) {
01417                 $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>";
01418             }
01419             
01420             if ($this->items[$i]->title) {
01421                 if ($this->items[$i]->link) {
01422                     $feedArray[] = 
01423                         "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix.
01424                         "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
01425                         "</a></div>";
01426                 } else {
01427                     $feedArray[] = 
01428                         "<div class='".$this->stylePrefix."item_title'>".
01429                         FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
01430                         "</div>";
01431                 }
01432             }
01433             if ($this->items[$i]->getDescription()) {
01434                 $feedArray[] = 
01435                 "<div class='".$this->stylePrefix."item_description'>".
01436                     str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())).
01437                     "</div>";
01438             }
01439         }
01440         if ($this->footer) {
01441             $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>";
01442         }
01443         
01444         $feed= "".join($feedArray, "\r\n");
01445         return $feed;
01446     }
01447     
01455     function _generateFilename() {
01456         $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
01457         return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html";
01458     }
01459 }   
01460 
01461 
01468 class JSCreator extends HTMLCreator {
01469     var $contentType = "text/javascript";
01470     
01475     function createFeed() 
01476     {
01477         $feed = parent::createFeed();
01478         $feedArray = explode("\n",$feed);
01479         
01480         $jsFeed = "";
01481         foreach ($feedArray as $value) {
01482             $jsFeed .= "document.write('".trim(addslashes($value))."');\n";
01483         }
01484         return $jsFeed;
01485     }
01486     
01494     function _generateFilename() {
01495         $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
01496         return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js";
01497     }
01498     
01499 }   
01500 
01501 
01502 
01503 /*** TEST SCRIPT *********************************************************
01504 
01505 //include("feedcreator.class.php"); 
01506 
01507 $rss = new UniversalFeedCreator(); 
01508 $rss->useCached(); 
01509 $rss->title = "PHP news"; 
01510 $rss->description = "daily news from the PHP scripting world"; 
01511 
01512 //optional
01513 //$rss->descriptionTruncSize = 500;
01514 //$rss->descriptionHtmlSyndicated = true;
01515 //$rss->xslStyleSheet = "http://feedster.com/rss20.xsl";
01516 
01517 $rss->link = "http://www.dailyphp.net/news"; 
01518 $rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF; 
01519 
01520 $image = new FeedImage(); 
01521 $image->title = "dailyphp.net logo"; 
01522 $image->url = "http://www.dailyphp.net/images/logo.gif"; 
01523 $image->link = "http://www.dailyphp.net"; 
01524 $image->description = "Feed provided by dailyphp.net. Click to visit."; 
01525 
01526 //optional
01527 $image->descriptionTruncSize = 500;
01528 $image->descriptionHtmlSyndicated = true;
01529 
01530 $rss->image = $image; 
01531 
01532 // get your news items from somewhere, e.g. your database: 
01533 //mysql_select_db($dbHost, $dbUser, $dbPass); 
01534 //$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); 
01535 //while ($data = mysql_fetch_object($res)) { 
01536     $item = new FeedItem(); 
01537     $item->title = "This is an the test title of an item"; 
01538     $item->link = "http://localhost/item/"; 
01539     $item->description = "<b>description in </b><br/>HTML"; 
01540     
01541     //optional
01542     //item->descriptionTruncSize = 500;
01543     $item->descriptionHtmlSyndicated = true;
01544     
01545     $item->date = time(); 
01546     $item->source = "http://www.dailyphp.net"; 
01547     $item->author = "John Doe"; 
01548      
01549     $rss->addItem($item); 
01550 //} 
01551 
01552 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS
01553 echo $rss->saveFeed("RSS0.91", "feed.xml"); 
01554 
01555 
01556 
01557 ***************************************************************************/
01558 
01560 ?>

Generated on Fri Oct 27 12:26:39 2006 for BaseJumper by doxygen 1.3.9.1