PageRenderTime 69ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/class/org/xml/RSS.class.php

https://github.com/monkeycraps/swoole_framework
PHP | 1335 lines | 720 code | 156 blank | 459 comment | 107 complexity | eacefa4fef9c0e8412ec41a073103b65 MD5 | raw file
  1. <?php
  2. define("TIME_ZONE","+08:00");
  3. define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2");
  4. class FeedItem extends HtmlDescribable {
  5. public $title, $description, $link;
  6. public $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator;
  7. public $date;
  8. public $additionalElements = Array();
  9. }
  10. /**
  11. * An FeedImage may be added to a FeedCreator feed.
  12. * @author Kai Blankenhorn <kaib@bitfolge.de>
  13. * @since 1.3
  14. */
  15. class FeedImage extends HtmlDescribable {
  16. /**
  17. * Mandatory attributes of an image.
  18. */
  19. public $title, $url, $link;
  20. /**
  21. * Optional attributes of an image.
  22. */
  23. public $width, $height, $description;
  24. }
  25. /**
  26. * An HtmlDescribable is an item within a feed that can have a description that may
  27. * include HTML markup.
  28. */
  29. class HtmlDescribable {
  30. /**
  31. * Indicates whether the description field should be rendered in HTML.
  32. */
  33. public $descriptionHtmlSyndicated;
  34. /**
  35. * Indicates whether and to how many characters a description should be truncated.
  36. */
  37. public $descriptionTruncSize;
  38. /**
  39. * Returns a formatted description field, depending on descriptionHtmlSyndicated and
  40. * $descriptionTruncSize properties
  41. * @return string the formatted description
  42. */
  43. function getDescription() {
  44. $descriptionField = new FeedHtmlField($this->description);
  45. $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;
  46. $descriptionField->truncSize = $this->descriptionTruncSize;
  47. return $descriptionField->output();
  48. }
  49. }
  50. /**
  51. * An FeedHtmlField describes and generates
  52. * a feed, item or image html field (probably a description). Output is
  53. * generated based on $truncSize, $syndicateHtml properties.
  54. * @author Pascal Van Hecke <feedcreator.class.php@vanhecke.info>
  55. * @version 1.6
  56. */
  57. class FeedHtmlField {
  58. /**
  59. * Mandatory attributes of a FeedHtmlField.
  60. */
  61. public $rawFieldContent;
  62. /**
  63. * Optional attributes of a FeedHtmlField.
  64. *
  65. */
  66. public $truncSize, $syndicateHtml;
  67. /**
  68. * Creates a new instance of FeedHtmlField.
  69. * @param $string: if given, sets the rawFieldContent property
  70. */
  71. function FeedHtmlField($parFieldContent) {
  72. if ($parFieldContent) {
  73. $this->rawFieldContent = $parFieldContent;
  74. }
  75. }
  76. /**
  77. * Creates the right output, depending on $truncSize, $syndicateHtml properties.
  78. * @return string the formatted field
  79. */
  80. function output() {
  81. // when field available and syndicated in html we assume
  82. // - valid html in $rawFieldContent and we enclose in CDATA tags
  83. // - no truncation (truncating risks producing invalid html)
  84. if (!$this->rawFieldContent) {
  85. $result = "";
  86. } elseif ($this->syndicateHtml) {
  87. $result = "<![CDATA[".$this->rawFieldContent."]]>";
  88. } else {
  89. if ($this->truncSize and is_int($this->truncSize)) {
  90. $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);
  91. } else {
  92. $result = htmlspecialchars($this->rawFieldContent);
  93. }
  94. }
  95. return $result;
  96. }
  97. }
  98. /**
  99. * UniversalFeedCreator lets you choose during runtime which
  100. * format to build.
  101. * For general usage of a feed class, see the FeedCreator class
  102. * below or the example above.
  103. *
  104. * @since 1.3
  105. * @author Kai Blankenhorn <kaib@bitfolge.de>
  106. */
  107. class UniversalFeedCreator extends FeedCreator {
  108. public $_feed;
  109. function _setFormat($format) {
  110. switch (strtoupper($format)) {
  111. case "2.0":
  112. // fall through
  113. case "RSS2.0":
  114. $this->_feed = new RSSCreator20();
  115. break;
  116. case "1.0":
  117. // fall through
  118. case "RSS1.0":
  119. $this->_feed = new RSSCreator10();
  120. break;
  121. case "0.91":
  122. // fall through
  123. case "RSS0.91":
  124. $this->_feed = new RSSCreator091();
  125. break;
  126. case "PIE0.1":
  127. $this->_feed = new PIECreator01();
  128. break;
  129. case "MBOX":
  130. $this->_feed = new MBOXCreator();
  131. break;
  132. case "OPML":
  133. $this->_feed = new OPMLCreator();
  134. break;
  135. case "ATOM":
  136. // fall through: always the latest ATOM version
  137. case "ATOM0.3":
  138. $this->_feed = new AtomCreator03();
  139. break;
  140. case "HTML":
  141. $this->_feed = new HTMLCreator();
  142. break;
  143. case "JS":
  144. // fall through
  145. case "JAVASCRIPT":
  146. $this->_feed = new JSCreator();
  147. break;
  148. default:
  149. $this->_feed = new RSSCreator091();
  150. break;
  151. }
  152. $vars = get_object_vars($this);
  153. foreach ($vars as $key => $value) {
  154. // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
  155. if (!in_array($key, array("_feed", "contentType", "encoding"))) {
  156. $this->_feed->{$key} = $this->{$key};
  157. }
  158. }
  159. }
  160. /**
  161. * Creates a syndication feed based on the items previously added.
  162. *
  163. * @see FeedCreator::addItem()
  164. * @param string format format the feed should comply to. Valid values are:
  165. * "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"
  166. * @return string the contents of the feed.
  167. */
  168. function createFeed($format = "RSS0.91") {
  169. $this->_setFormat($format);
  170. return $this->_feed->createFeed();
  171. }
  172. /**
  173. * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect
  174. * header may be sent to redirect the use to the newly created file.
  175. * @since 1.4
  176. *
  177. * @param string format format the feed should comply to. Valid values are:
  178. * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"
  179. * @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()).
  180. * @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.
  181. */
  182. function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
  183. $this->_setFormat($format);
  184. $this->_feed->saveFeed($filename, $displayContents);
  185. }
  186. /**
  187. * Turns on caching and checks if there is a recent version of this feed in the cache.
  188. * If there is, an HTTP redirect header is sent.
  189. * To effectively use caching, you should create the FeedCreator object and call this method
  190. * before anything else, especially before you do the time consuming task to build the feed
  191. * (web fetching, for example).
  192. *
  193. * @param string format format the feed should comply to. Valid values are:
  194. * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
  195. * @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()).
  196. * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
  197. */
  198. function useCached($format="RSS0.91", $filename="", $timeout=3600) {
  199. $this->_setFormat($format);
  200. $this->_feed->useCached($filename, $timeout);
  201. }
  202. }
  203. /**
  204. * FeedCreator is the abstract base implementation for concrete
  205. * implementations that implement a specific format of syndication.
  206. *
  207. * @abstract
  208. * @author Kai Blankenhorn <kaib@bitfolge.de>
  209. * @since 1.4
  210. */
  211. class FeedCreator extends HtmlDescribable {
  212. /**
  213. * Mandatory attributes of a feed.
  214. */
  215. public $title, $description, $link;
  216. /**
  217. * Optional attributes of a feed.
  218. */
  219. public $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
  220. /**
  221. * The url of the external xsl stylesheet used to format the naked rss feed.
  222. * Ignored in the output when empty.
  223. */
  224. public $xslStyleSheet = "";
  225. /**
  226. * @access private
  227. */
  228. public $items = Array();
  229. /**
  230. * This feed's MIME content type.
  231. * @since 1.4
  232. * @access private
  233. */
  234. public $contentType = "application/xml";
  235. /**
  236. * This feed's character encoding.
  237. * @since 1.6.1
  238. **/
  239. public $encoding = "UTF-8";
  240. /**
  241. * Any additional elements to include as an assiciated array. All $key => $value pairs
  242. * will be included unencoded in the feed in the form
  243. * <$key>$value</$key>
  244. * Again: No encoding will be used! This means you can invalidate or enhance the feed
  245. * if $value contains markup. This may be abused to embed tags not implemented by
  246. * the FeedCreator class used.
  247. */
  248. public $additionalElements = Array();
  249. /**
  250. * Adds an FeedItem to the feed.
  251. *
  252. * @param object FeedItem $item The FeedItem to add to the feed.
  253. * @access public
  254. */
  255. function addItem($item) {
  256. $this->items[] = $item;
  257. }
  258. /**
  259. * Truncates a string to a certain length at the most sensible point.
  260. * First, if there's a '.' character near the end of the string, the string is truncated after this character.
  261. * If there is no '.', the string is truncated after the last ' ' character.
  262. * If the string is truncated, " ..." is appended.
  263. * If the string is already shorter than $length, it is returned unchanged.
  264. *
  265. * @static
  266. * @param string string A string to be truncated.
  267. * @param int length the maximum length the string should be truncated to
  268. * @return string the truncated string
  269. */
  270. function iTrunc($string, $length) {
  271. if (strlen($string)<=$length) {
  272. return $string;
  273. }
  274. $pos = strrpos($string,".");
  275. if ($pos>=$length-4) {
  276. $string = substr($string,0,$length-4);
  277. $pos = strrpos($string,".");
  278. }
  279. if ($pos>=$length*0.4) {
  280. return substr($string,0,$pos+1)." ...";
  281. }
  282. $pos = strrpos($string," ");
  283. if ($pos>=$length-4) {
  284. $string = substr($string,0,$length-4);
  285. $pos = strrpos($string," ");
  286. }
  287. if ($pos>=$length*0.4) {
  288. return substr($string,0,$pos)." ...";
  289. }
  290. return substr($string,0,$length-4)." ...";
  291. }
  292. /**
  293. * Creates a comment indicating the generator of this feed.
  294. * The format of this comment seems to be recognized by
  295. * Syndic8.com.
  296. */
  297. function _createGeneratorComment() {
  298. return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n";
  299. }
  300. /**
  301. * Creates a string containing all additional elements specified in
  302. * $additionalElements.
  303. * @param elements array an associative array containing key => value pairs
  304. * @param indentString string a string that will be inserted before every generated line
  305. * @return string the XML tags corresponding to $additionalElements
  306. */
  307. function _createAdditionalElements($elements, $indentString="") {
  308. $ae = "";
  309. if (is_array($elements)) {
  310. foreach($elements AS $key => $value) {
  311. $ae.= $indentString."<$key>$value</$key>\n";
  312. }
  313. }
  314. return $ae;
  315. }
  316. function _createStylesheetReferences() {
  317. $xml = "";
  318. if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";
  319. if ($this->xslStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n";
  320. return $xml;
  321. }
  322. /**
  323. * Builds the feed's text.
  324. * @abstract
  325. * @return string the feed's complete text
  326. */
  327. function createFeed() {
  328. }
  329. /**
  330. * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml.
  331. * For example:
  332. *
  333. * echo $_SERVER["PHP_SELF"]."\n";
  334. * echo FeedCreator::_generateFilename();
  335. *
  336. * would produce:
  337. *
  338. * /rss/latestnews.php
  339. * latestnews.xml
  340. *
  341. * @return string the feed cache filename
  342. * @since 1.4
  343. * @access private
  344. */
  345. function _generateFilename() {
  346. $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
  347. return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml";
  348. }
  349. /**
  350. * @since 1.4
  351. * @access private
  352. */
  353. function _redirect($filename) {
  354. // attention, heavily-commented-out-area
  355. // maybe use this in addition to file time checking
  356. //Header("Expires: ".date("r",time()+$this->_timeout));
  357. /* no caching at all, doesn't seem to work as good:
  358. Header("Cache-Control: no-cache");
  359. Header("Pragma: no-cache");
  360. */
  361. // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
  362. //Header("Location: ".$filename);
  363. Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));
  364. Header("Content-Disposition: inline; filename=".basename($filename));
  365. readfile($filename, "r");
  366. die();
  367. }
  368. /**
  369. * Turns on caching and checks if there is a recent version of this feed in the cache.
  370. * If there is, an HTTP redirect header is sent.
  371. * To effectively use caching, you should create the FeedCreator object and call this method
  372. * before anything else, especially before you do the time consuming task to build the feed
  373. * (web fetching, for example).
  374. * @since 1.4
  375. * @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()).
  376. * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
  377. */
  378. function useCached($filename="", $timeout=3600) {
  379. $this->_timeout = $timeout;
  380. if ($filename=="") {
  381. $filename = $this->_generateFilename();
  382. }
  383. if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {
  384. $this->_redirect($filename);
  385. }
  386. }
  387. /**
  388. * Saves this feed as a file on the local disk. After the file is saved, a redirect
  389. * header may be sent to redirect the user to the newly created file.
  390. * @since 1.4
  391. *
  392. * @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()).
  393. * @param redirect boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
  394. */
  395. function saveFeed($filename="", $displayContents=true) {
  396. if ($filename=="") {
  397. $filename = $this->_generateFilename();
  398. }
  399. $feedFile = fopen($filename, "w+");
  400. if ($feedFile) {
  401. fputs($feedFile,$this->createFeed());
  402. fclose($feedFile);
  403. if ($displayContents) {
  404. $this->_redirect($filename);
  405. }
  406. } else {
  407. echo "<br /><b>Error creating feed file, please check write permissions.</b><br />";
  408. }
  409. }
  410. }
  411. /**
  412. * FeedDate is an internal class that stores a date for a feed or feed item.
  413. * Usually, you won't need to use this.
  414. */
  415. class FeedDate {
  416. public $unix;
  417. /**
  418. * Creates a new instance of FeedDate representing a given date.
  419. * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps.
  420. * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used.
  421. */
  422. function FeedDate($dateString="") {
  423. if ($dateString=="") $dateString = date("r");
  424. if (is_integer($dateString)) {
  425. $this->unix = $dateString;
  426. return;
  427. }
  428. 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)) {
  429. $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);
  430. $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
  431. if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
  432. $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
  433. } else {
  434. if (strlen($matches[7])==1) {
  435. $oneHour = 3600;
  436. $ord = ord($matches[7]);
  437. if ($ord < ord("M")) {
  438. $tzOffset = (ord("A") - $ord - 1) * $oneHour;
  439. } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
  440. $tzOffset = ($ord - ord("M")) * $oneHour;
  441. } elseif ($matches[7]=="Z") {
  442. $tzOffset = 0;
  443. }
  444. }
  445. switch ($matches[7]) {
  446. case "UT":
  447. case "GMT": $tzOffset = 0;
  448. }
  449. }
  450. $this->unix += $tzOffset;
  451. return;
  452. }
  453. if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
  454. $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
  455. if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
  456. $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
  457. } else {
  458. if ($matches[7]=="Z") {
  459. $tzOffset = 0;
  460. }
  461. }
  462. $this->unix += $tzOffset;
  463. return;
  464. }
  465. $this->unix = 0;
  466. }
  467. /**
  468. * Gets the date stored in this FeedDate as an RFC 822 date.
  469. *
  470. * @return a date in RFC 822 format
  471. */
  472. function rfc822() {
  473. //return gmdate("r",$this->unix);
  474. $date = gmdate("D, d M Y H:i:s", $this->unix);
  475. if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);
  476. return $date;
  477. }
  478. /**
  479. * Gets the date stored in this FeedDate as an ISO 8601 date.
  480. *
  481. * @return a date in ISO 8601 format
  482. */
  483. function iso8601() {
  484. $date = gmdate("Y-m-d\TH:i:sO",$this->unix);
  485. $date = substr($date,0,22) . ':' . substr($date,-2);
  486. if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);
  487. return $date;
  488. }
  489. /**
  490. * Gets the date stored in this FeedDate as unix time stamp.
  491. *
  492. * @return a date as a unix time stamp
  493. */
  494. function unix() {
  495. return $this->unix;
  496. }
  497. }
  498. /**
  499. * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0.
  500. *
  501. * @see http://www.purl.org/rss/1.0/
  502. * @since 1.3
  503. * @author Kai Blankenhorn <kaib@bitfolge.de>
  504. */
  505. class RSSCreator10 extends FeedCreator {
  506. /**
  507. * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
  508. * The feed will contain all items previously added in the same order.
  509. * @return string the feed's complete text
  510. */
  511. function createFeed() {
  512. $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
  513. $feed.= $this->_createGeneratorComment();
  514. if ($this->cssStyleSheet=="") {
  515. $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
  516. }
  517. $feed.= $this->_createStylesheetReferences();
  518. $feed.= "<rdf:RDF\n";
  519. $feed.= " xmlns=\"http://purl.org/rss/1.0/\"\n";
  520. $feed.= " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
  521. $feed.= " xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";
  522. $feed.= " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
  523. $feed.= " <channel rdf:about=\"".$this->syndicationURL."\">\n";
  524. $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
  525. $feed.= " <description>".htmlspecialchars($this->description)."</description>\n";
  526. $feed.= " <link>".$this->link."</link>\n";
  527. if ($this->image!=null) {
  528. $feed.= " <image rdf:resource=\"".$this->image->url."\" />\n";
  529. }
  530. $now = new FeedDate();
  531. $feed.= " <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n";
  532. $feed.= " <items>\n";
  533. $feed.= " <rdf:Seq>\n";
  534. for ($i=0;$i<count($this->items);$i++) {
  535. $feed.= " <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
  536. }
  537. $feed.= " </rdf:Seq>\n";
  538. $feed.= " </items>\n";
  539. $feed.= " </channel>\n";
  540. if ($this->image!=null) {
  541. $feed.= " <image rdf:about=\"".$this->image->url."\">\n";
  542. $feed.= " <title>".$this->image->title."</title>\n";
  543. $feed.= " <link>".$this->image->link."</link>\n";
  544. $feed.= " <url>".$this->image->url."</url>\n";
  545. $feed.= " </image>\n";
  546. }
  547. $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
  548. for ($i=0;$i<count($this->items);$i++) {
  549. $feed.= " <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n";
  550. //$feed.= " <dc:type>Posting</dc:type>\n";
  551. $feed.= " <dc:format>text/html</dc:format>\n";
  552. if ($this->items[$i]->date!=null) {
  553. $itemDate = new FeedDate($this->items[$i]->date);
  554. $feed.= " <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n";
  555. }
  556. if ($this->items[$i]->source!="") {
  557. $feed.= " <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n";
  558. }
  559. if ($this->items[$i]->author!="") {
  560. $feed.= " <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n";
  561. }
  562. $feed.= " <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")))."</title>\n";
  563. $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
  564. $feed.= " <description>".htmlspecialchars($this->items[$i]->description)."</description>\n";
  565. $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
  566. $feed.= " </item>\n";
  567. }
  568. $feed.= "</rdf:RDF>\n";
  569. return $feed;
  570. }
  571. }
  572. /**
  573. * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3.
  574. *
  575. * @see http://my.netscape.com/publish/formats/rss-spec-0.91.html
  576. * @since 1.3
  577. * @author Kai Blankenhorn <kaib@bitfolge.de>
  578. */
  579. class RSSCreator091 extends FeedCreator {
  580. /**
  581. * Stores this RSS feed's version number.
  582. * @access private
  583. */
  584. public $RSSVersion;
  585. function RSSCreator091() {
  586. $this->_setRSSVersion("0.91");
  587. $this->contentType = "application/rss+xml";
  588. }
  589. /**
  590. * Sets this RSS feed's version number.
  591. * @access private
  592. */
  593. function _setRSSVersion($version) {
  594. $this->RSSVersion = $version;
  595. }
  596. /**
  597. * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
  598. * The feed will contain all items previously added in the same order.
  599. * @return string the feed's complete text
  600. */
  601. function createFeed() {
  602. $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
  603. $feed.= $this->_createGeneratorComment();
  604. $feed.= $this->_createStylesheetReferences();
  605. $feed.= "<rss version=\"".$this->RSSVersion."\">\n";
  606. $feed.= " <channel>\n";
  607. $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
  608. $this->descriptionTruncSize = 500;
  609. $feed.= " <description>".$this->getDescription()."</description>\n";
  610. $feed.= " <link>".$this->link."</link>\n";
  611. $now = new FeedDate();
  612. $feed.= " <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n";
  613. $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n";
  614. if ($this->image!=null) {
  615. $feed.= " <image>\n";
  616. $feed.= " <url>".$this->image->url."</url>\n";
  617. $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n";
  618. $feed.= " <link>".$this->image->link."</link>\n";
  619. if ($this->image->width!="") {
  620. $feed.= " <width>".$this->image->width."</width>\n";
  621. }
  622. if ($this->image->height!="") {
  623. $feed.= " <height>".$this->image->height."</height>\n";
  624. }
  625. if ($this->image->description!="") {
  626. $feed.= " <description>".$this->image->getDescription()."</description>\n";
  627. }
  628. $feed.= " </image>\n";
  629. }
  630. if ($this->language!="") {
  631. $feed.= " <language>".$this->language."</language>\n";
  632. }
  633. if ($this->copyright!="") {
  634. $feed.= " <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n";
  635. }
  636. if ($this->editor!="") {
  637. $feed.= " <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n";
  638. }
  639. if ($this->webmaster!="") {
  640. $feed.= " <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n";
  641. }
  642. if ($this->pubDate!="") {
  643. $pubDate = new FeedDate($this->pubDate);
  644. $feed.= " <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n";
  645. }
  646. if ($this->category!="") {
  647. $feed.= " <category>".htmlspecialchars($this->category)."</category>\n";
  648. }
  649. if ($this->docs!="") {
  650. $feed.= " <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n";
  651. }
  652. if ($this->ttl!="") {
  653. $feed.= " <ttl>".htmlspecialchars($this->ttl)."</ttl>\n";
  654. }
  655. if ($this->rating!="") {
  656. $feed.= " <rating>".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."</rating>\n";
  657. }
  658. if ($this->skipHours!="") {
  659. $feed.= " <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n";
  660. }
  661. if ($this->skipDays!="") {
  662. $feed.= " <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n";
  663. }
  664. $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
  665. for ($i=0;$i<count($this->items);$i++) {
  666. $feed.= " <item>\n";
  667. $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
  668. $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
  669. $feed.= " <description>".$this->items[$i]->getDescription()."</description>\n";
  670. if ($this->items[$i]->author!="") {
  671. $feed.= " <author>".htmlspecialchars($this->items[$i]->author)."</author>\n";
  672. }
  673. /*
  674. // on hold
  675. if ($this->items[$i]->source!="") {
  676. $feed.= " <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";
  677. }
  678. */
  679. if ($this->items[$i]->category!="") {
  680. $feed.= " <category>".htmlspecialchars($this->items[$i]->category)."</category>\n";
  681. }
  682. if ($this->items[$i]->comments!="") {
  683. $feed.= " <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n";
  684. }
  685. if ($this->items[$i]->date!="") {
  686. $itemDate = new FeedDate($this->items[$i]->date);
  687. $feed.= " <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n";
  688. }
  689. if ($this->items[$i]->guid!="") {
  690. $feed.= " <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n";
  691. }
  692. $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
  693. $feed.= " </item>\n";
  694. }
  695. $feed.= " </channel>\n";
  696. $feed.= "</rss>\n";
  697. return $feed;
  698. }
  699. }
  700. /**
  701. * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.
  702. *
  703. * @see http://backend.userland.com/rss
  704. * @since 1.3
  705. * @author Kai Blankenhorn <kaib@bitfolge.de>
  706. */
  707. class RSSCreator20 extends RSSCreator091 {
  708. function RSSCreator20() {
  709. parent::_setRSSVersion("2.0");
  710. }
  711. }
  712. /**
  713. * PIECreator01 is a FeedCreator that implements the emerging PIE specification,
  714. * as in http://intertwingly.net/wiki/pie/Syntax.
  715. *
  716. * @deprecated
  717. * @since 1.3
  718. * @author Scott Reynen <scott@randomchaos.com> and Kai Blankenhorn <kaib@bitfolge.de>
  719. */
  720. class PIECreator01 extends FeedCreator {
  721. function PIECreator01() {
  722. $this->encoding = "utf-8";
  723. }
  724. function createFeed() {
  725. $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
  726. $feed.= $this->_createStylesheetReferences();
  727. $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n";
  728. $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
  729. $this->truncSize = 500;
  730. $feed.= " <subtitle>".$this->getDescription()."</subtitle>\n";
  731. $feed.= " <link>".$this->link."</link>\n";
  732. for ($i=0;$i<count($this->items);$i++) {
  733. $feed.= " <entry>\n";
  734. $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
  735. $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
  736. $itemDate = new FeedDate($this->items[$i]->date);
  737. $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
  738. $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
  739. $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
  740. $feed.= " <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";
  741. if ($this->items[$i]->author!="") {
  742. $feed.= " <author>\n";
  743. $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
  744. if ($this->items[$i]->authorEmail!="") {
  745. $feed.= " <email>".$this->items[$i]->authorEmail."</email>\n";
  746. }
  747. $feed.=" </author>\n";
  748. }
  749. $feed.= " <content type=\"text/html\" xml:lang=\"en-us\">\n";
  750. $feed.= " <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";
  751. $feed.= " </content>\n";
  752. $feed.= " </entry>\n";
  753. }
  754. $feed.= "</feed>\n";
  755. return $feed;
  756. }
  757. }
  758. /**
  759. * AtomCreator03 is a FeedCreator that implements the atom specification,
  760. * as in http://www.intertwingly.net/wiki/pie/FrontPage.
  761. * Please note that just by using AtomCreator03 you won't automatically
  762. * produce valid atom files. For example, you have to specify either an editor
  763. * for the feed or an author for every single feed item.
  764. *
  765. * Some elements have not been implemented yet. These are (incomplete list):
  766. * author URL, item author's email and URL, item contents, alternate links,
  767. * other link content types than text/html. Some of them may be created with
  768. * AtomCreator03::additionalElements.
  769. *
  770. * @see FeedCreator#additionalElements
  771. * @since 1.6
  772. * @author Kai Blankenhorn <kaib@bitfolge.de>, Scott Reynen <scott@randomchaos.com>
  773. */
  774. class AtomCreator03 extends FeedCreator {
  775. function AtomCreator03() {
  776. $this->contentType = "application/atom+xml";
  777. $this->encoding = "utf-8";
  778. }
  779. function createFeed() {
  780. $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
  781. $feed.= $this->_createGeneratorComment();
  782. $feed.= $this->_createStylesheetReferences();
  783. $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\"";
  784. if ($this->language!="") {
  785. $feed.= " xml:lang=\"".$this->language."\"";
  786. }
  787. $feed.= ">\n";
  788. $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
  789. $feed.= " <tagline>".htmlspecialchars($this->description)."</tagline>\n";
  790. $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
  791. $feed.= " <id>".htmlspecialchars($this->link)."</id>\n";
  792. $now = new FeedDate();
  793. $feed.= " <modified>".htmlspecialchars($now->iso8601())."</modified>\n";
  794. if ($this->editor!="") {
  795. $feed.= " <author>\n";
  796. $feed.= " <name>".$this->editor."</name>\n";
  797. if ($this->editorEmail!="") {
  798. $feed.= " <email>".$this->editorEmail."</email>\n";
  799. }
  800. $feed.= " </author>\n";
  801. }
  802. $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n";
  803. $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
  804. for ($i=0;$i<count($this->items);$i++) {
  805. $feed.= " <entry>\n";
  806. $feed.= " <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
  807. $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
  808. if ($this->items[$i]->date=="") {
  809. $this->items[$i]->date = time();
  810. }
  811. $itemDate = new FeedDate($this->items[$i]->date);
  812. $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
  813. $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
  814. $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
  815. $feed.= " <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
  816. $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
  817. if ($this->items[$i]->author!="") {
  818. $feed.= " <author>\n";
  819. $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
  820. $feed.= " </author>\n";
  821. }
  822. if ($this->items[$i]->description!="") {
  823. $feed.= " <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
  824. }
  825. $feed.= " </entry>\n";
  826. }
  827. $feed.= "</feed>\n";
  828. return $feed;
  829. }
  830. }
  831. /**
  832. * MBOXCreator is a FeedCreator that implements the mbox format
  833. * as described in http://www.qmail.org/man/man5/mbox.html
  834. *
  835. * @since 1.3
  836. * @author Kai Blankenhorn <kaib@bitfolge.de>
  837. */
  838. class MBOXCreator extends FeedCreator {
  839. function MBOXCreator() {
  840. $this->contentType = "text/plain";
  841. $this->encoding = "ISO-8859-15";
  842. }
  843. function qp_enc($input = "", $line_max = 76) {
  844. $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
  845. $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
  846. $eol = "\r\n";
  847. $escape = "=";
  848. $output = "";
  849. while( list(, $line) = each($lines) ) {
  850. //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
  851. $linlen = strlen($line);
  852. $newline = "";
  853. for($i = 0; $i < $linlen; $i++) {
  854. $c = substr($line, $i, 1);
  855. $dec = ord($c);
  856. if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
  857. $c = "=20";
  858. } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
  859. $h2 = floor($dec/16); $h1 = floor($dec%16);
  860. $c = $escape.$hex["$h2"].$hex["$h1"];
  861. }
  862. if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
  863. $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
  864. $newline = "";
  865. }
  866. $newline .= $c;
  867. } // end of for
  868. $output .= $newline.$eol;
  869. }
  870. return trim($output);
  871. }
  872. /**
  873. * Builds the MBOX contents.
  874. * @return string the feed's complete text
  875. */
  876. function createFeed() {
  877. for ($i=0;$i<count($this->items);$i++) {
  878. if ($this->items[$i]->author!="") {
  879. $from = $this->items[$i]->author;
  880. } else {
  881. $from = $this->title;
  882. }
  883. $itemDate = new FeedDate($this->items[$i]->date);
  884. $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";
  885. $feed.= "Content-Type: text/plain;\n";
  886. $feed.= " charset=\"".$this->encoding."\"\n";
  887. $feed.= "Content-Transfer-Encoding: quoted-printable\n";
  888. $feed.= "Content-Type: text/plain\n";
  889. $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";
  890. $feed.= "Date: ".$itemDate->rfc822()."\n";
  891. $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";
  892. $feed.= "\n";
  893. $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));
  894. $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);
  895. $feed.= "\n";
  896. $feed.= "\n";
  897. }
  898. return $feed;
  899. }
  900. /**
  901. * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.
  902. * @return string the feed cache filename
  903. * @since 1.4
  904. * @access private
  905. */
  906. function _generateFilename() {
  907. $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
  908. return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";
  909. }
  910. }
  911. /**
  912. * OPMLCreator is a FeedCreator that implements OPML 1.0.
  913. *
  914. * @see http://opml.scripting.com/spec
  915. * @author Dirk Clemens, Kai Blankenhorn
  916. * @since 1.5
  917. */
  918. class OPMLCreator extends FeedCreator {
  919. function OPMLCreator() {
  920. $this->encoding = "utf-8";
  921. }
  922. function createFeed() {
  923. $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
  924. $feed.= $this->_createGeneratorComment();
  925. $feed.= $this->_createStylesheetReferences();
  926. $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
  927. $feed.= " <head>\n";
  928. $feed.= " <title>".htmlspecialchars($this->title)."</title>\n";
  929. if ($this->pubDate!="") {
  930. $date = new FeedDate($this->pubDate);
  931. $feed.= " <dateCreated>".$date->rfc822()."</dateCreated>\n";
  932. }
  933. if ($this->lastBuildDate!="") {
  934. $date = new FeedDate($this->lastBuildDate);
  935. $feed.= " <dateModified>".$date->rfc822()."</dateModified>\n";
  936. }
  937. if ($this->editor!="") {
  938. $feed.= " <ownerName>".$this->editor."</ownerName>\n";
  939. }
  940. if ($this->editorEmail!="") {
  941. $feed.= " <ownerEmail>".$this->editorEmail."</ownerEmail>\n";
  942. }
  943. $feed.= " </head>\n";
  944. $feed.= " <body>\n";
  945. for ($i=0;$i<count($this->items);$i++) {
  946. $feed.= " <outline type=\"rss\" ";
  947. $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")));
  948. $feed.= " title=\"".$title."\"";
  949. $feed.= " text=\"".$title."\"";
  950. //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
  951. $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";
  952. $feed.= "/>\n";
  953. }
  954. $feed.= " </body>\n";
  955. $feed.= "</opml>\n";
  956. return $feed;
  957. }
  958. }
  959. /**
  960. * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific
  961. * location, overriding the createFeed method of the parent FeedCreator.
  962. * The HTML produced can be included over http by scripting languages, or serve
  963. * as the source for an IFrame.
  964. * All output by this class is embedded in <div></div> tags to enable formatting
  965. * using CSS.
  966. *
  967. * @author Pascal Van Hecke
  968. * @since 1.7
  969. */
  970. class HTMLCreator extends FeedCreator {
  971. public $contentType = "text/html";
  972. /**
  973. * Contains HTML to be output at the start of the feed's html representation.
  974. */
  975. public $header;
  976. /**
  977. * Contains HTML to be output at the end of the feed's html representation.
  978. */
  979. public $footer ;
  980. /**
  981. * Contains HTML to be output between entries. A separator is only used in
  982. * case of multiple entries.
  983. */
  984. public $separator;
  985. /**
  986. * Used to prefix the stylenames to make sure they are unique
  987. * and do not clash with stylenames on the users' page.
  988. */
  989. public $stylePrefix;
  990. /**
  991. * Determines whether the links open in a new window or not.
  992. */
  993. public $openInNewWindow = true;
  994. public $imageAlign ="right";
  995. /**
  996. * In case of very simple output you may want to get rid of the style tags,
  997. * hence this variable. There's no equivalent on item level, but of course you can
  998. * add strings to it while iterating over the items ($this->stylelessOutput .= ...)
  999. * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored
  1000. * in the function createFeed().
  1001. */
  1002. public $stylelessOutput ="";
  1003. /**
  1004. * Writes the HTML.
  1005. * @return string the scripts's complete text
  1006. */
  1007. function createFeed() {
  1008. // if there is styleless output, use the content of this variable and ignore the rest
  1009. if ($this->stylelessOutput!="") {
  1010. return $this->stylelessOutput;
  1011. }
  1012. //if no stylePrefix is set, generate it yourself depending on the script name
  1013. if ($this->stylePrefix=="") {
  1014. $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";
  1015. }
  1016. //set an openInNewWindow_token_to be inserted or not
  1017. if ($this->openInNewWindow) {
  1018. $targetInsert = " target='_blank'";
  1019. }
  1020. // use this array to put the lines in and implode later with "document.write" javascript
  1021. $feedArray = array();
  1022. if ($this->image!=null) {
  1023. $imageStr = "<a href='".$this->image->link."'".$targetInsert.">".
  1024. "<img src='".$this->image->url."' border='0' alt='".
  1025. FeedCreator::iTrunc(htmlspecialchars($this->image->title),100).
  1026. "' align='".$this->imageAlign."' ";
  1027. if ($this->image->width) {
  1028. $imageStr .=" width='".$this->image->width. "' ";
  1029. }
  1030. if ($this->image->height) {
  1031. $imageStr .=" height='".$this->image->height."' ";
  1032. }
  1033. $imageStr .="/></a>";
  1034. $feedArray[] = $imageStr;
  1035. }
  1036. if ($this->title) {
  1037. $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>".
  1038. FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>";
  1039. }
  1040. if ($this->getDescription()) {
  1041. $feedArray[] = "<div class='".$this->stylePrefix."description'>".
  1042. str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())).
  1043. "</div>";
  1044. }
  1045. if ($this->header) {
  1046. $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>";
  1047. }
  1048. for ($i=0;$i<count($this->items);$i++) {
  1049. if ($this->separator and $i > 0) {
  1050. $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>";
  1051. }
  1052. if ($this->items[$i]->title) {
  1053. if ($this->items[$i]->link) {
  1054. $feedArray[] =
  1055. "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix.
  1056. "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
  1057. "</a></div>";
  1058. } else {
  1059. $feedArray[] =
  1060. "<div class='".$this->stylePrefix."item_title'>".
  1061. FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
  1062. "</div>";
  1063. }
  1064. }
  1065. if ($this->items[$i]->getDescription()) {
  1066. $feedArray[] =
  1067. "<div class='".$this->stylePrefix."item_description'>".
  1068. str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())).
  1069. "</div>";
  1070. }
  1071. }
  1072. if ($this->footer) {
  1073. $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>";
  1074. }
  1075. $feed= "".join($feedArray, "\r\n");
  1076. return $feed;
  1077. }
  1078. /**
  1079. * Overrrides parent to produce .html extensions
  1080. *
  1081. * @return string the feed cache filename
  1082. * @since 1.4
  1083. * @access private
  1084. */
  1085. function _generateFilename() {
  1086. $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
  1087. return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html";
  1088. }
  1089. }
  1090. /**
  1091. * JSCreator is a class that writes a js file to a specific
  1092. * location, overriding the createFeed method of the parent HTMLCreator.
  1093. *
  1094. * @author Pascal Van Hecke
  1095. */
  1096. class JSCreator extends HTMLCreator {
  1097. public $contentType = "text/javascript";
  1098. /**
  1099. * writes the javascript
  1100. * @return string the scripts's complete text
  1101. */
  1102. function createFeed()
  1103. {
  1104. $feed = parent::createFeed();
  1105. $feedArray = explode("\n",$feed);
  1106. $jsFeed = "";
  1107. foreach ($feedArray as $value) {
  1108. $jsFeed .= "document.write('".trim(addslashes($value))."');\n";
  1109. }
  1110. return $jsFeed;
  1111. }
  1112. /**
  1113. * Overrrides parent to produce .js extensions
  1114. *
  1115. * @return string the feed cache filename
  1116. * @since 1.4
  1117. * @access private
  1118. */
  1119. function _generateFilename() {
  1120. $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
  1121. return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js";
  1122. }
  1123. }
  1124. /*** TEST SCRIPT *********************************************************
  1125. //include("feedcreator.class.php");
  1126. $rss = new UniversalFeedCreator();
  1127. $rss->useCached();
  1128. $rss->title = "PHP news";
  1129. $rss->description = "daily news from the PHP scripting world";
  1130. //optional
  1131. //$rss->descriptionTruncSize = 500;
  1132. //$rss->descriptionHtmlSyndicated = true;
  1133. //$rss->xslStyleSheet = "http://feedster.com/rss20.xsl";
  1134. $rss->link = "http://www.dailyphp.net/news";
  1135. $rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF;
  1136. $image = new FeedImage();
  1137. $image->title = "dailyphp.net logo";
  1138. $image->url = "http://www.dailyphp.net/images/logo.gif";
  1139. $image->link = "http://www.dailyphp.net";
  1140. $image->description = "Feed provided by dailyphp.net. Click to visit.";
  1141. //optional
  1142. $image->descriptionTruncSize = 500;
  1143. $image->descriptionHtmlSyndicated = true;
  1144. $rss->image = $image;
  1145. // get your news items from somewhere, e.g. your database:
  1146. //mysql_select_db($dbHost, $dbUser, $dbPass);
  1147. //$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC");
  1148. //while ($data = mysql_fetch_object($res)) {
  1149. $item = new FeedItem();
  1150. $item->title = "This is an the test title of an item";
  1151. $item->link = "http://localhost/item/";
  1152. $item->description = "<b>description in </b><br/>HTML";
  1153. //optional
  1154. //item->descriptionTruncSize = 500;
  1155. $item->descriptionHtmlSyndicated = true;
  1156. $item->date = time();
  1157. $item->source = "http://www.dailyphp.net";
  1158. $item->author = "John Doe";
  1159. $rss->addItem($item);
  1160. //}
  1161. // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS
  1162. echo $rss->saveFeed("RSS0.91", "feed.xml");
  1163. ***************************************************************************/
  1164. ?>