* @since 1.4
*/
abstract class FeedCreator extends HtmlDescribable
{
/**
* Mandatory attributes of a feed.
*/
public $title, $description, $link;
public $format = 'BASE';
/**
* Optional attributes of a feed.
*/
public $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
/**
* The url of the external xsl stylesheet used to format the naked rss feed.
* Ignored in the output when empty.
*/
public $xslStyleSheet = "";
public $cssStyleSheet = "";
/** @var FeedItem[] */
public $items = Array();
/**
* Generator string
*/
public $generator = "info@mypapit.net";
/**
* This feed's MIME content type.
*
* @since 1.4
* @access private
*/
protected $contentType = "application/xml";
/**
* This feed's character encoding.
*
* @since 1.6.1
*/
protected $encoding = "UTF-8"; //"ISO-8859-1";
protected $_timeout; # lib/Creator/FeedCreator.php line 238
/**
* Any additional elements to include as an associated array. All $key => $value pairs
* will be included unencoded in the feed in the form
* <$key>$value$key>
* Again: No encoding will be used! This means you can invalidate or enhance the feed
* if $value contains markup. This may be abused to embed tags not implemented by
* the FeedCreator class used.
*/
public $additionalElements = Array();
/**
* Adds a FeedItem to the feed.
*
* @param FeedItem $item The FeedItem to add to the feed.
*/
public function addItem($item)
{
$this->items[] = $item;
}
/**
* Get the version string for the generator
*
* @return string
*/
public function version()
{
return FEEDCREATOR_VERSION." (".$this->generator.")";
}
/**
* Truncates a string to a certain length at the most sensible point.
* First, if there's a '.' character near the end of the string, the string is truncated after this character.
* If there is no '.', the string is truncated after the last ' ' character.
* If the string is truncated, " ..." is appended.
* If the string is already shorter than $length, it is returned unchanged.
*
* @param string $string A string to be truncated.
* @param int $length the maximum length the string should be truncated to
* @return string the truncated string
*/
public static function iTrunc($string, $length)
{
if (strlen($string) <= $length) {
return $string;
}
$pos = strrpos($string, ".");
if ($pos >= $length - 4) {
$string = substr($string, 0, $length - 4);
$pos = strrpos($string, ".");
}
if ($pos >= $length * 0.4) {
return substr($string, 0, $pos + 1)." ...";
}
$pos = strrpos($string, " ");
if ($pos >= $length - 4) {
$string = substr($string, 0, $length - 4);
$pos = strrpos($string, " ");
}
if ($pos >= $length * 0.4) {
return substr($string, 0, $pos)." ...";
}
return substr($string, 0, $length - 4)." ...";
}
/**
* Creates a comment indicating the generator of this feed.
* The format of this comment seems to be recognized by
* Syndic8.com.
*/
protected function _createGeneratorComment()
{
return "\n";
}
/**
* Creates a string containing all additional elements specified in
* $additionalElements.
*
* @param array $elements an associative array containing key => value pairs
* @param string $indentString a string that will be inserted before every generated line
* @return string the XML tags corresponding to $additionalElements
*/
protected function _createAdditionalElements($elements, $indentString = "")
{
$ae = "";
if (is_array($elements)) {
foreach ($elements AS $key => $value) {
$ae .= $indentString."<$key>$value$key>\n";
}
}
return $ae;
}
protected function _createStylesheetReferences()
{
$xml = "";
if (!empty($this->cssStyleSheet)) {
$xml .= "cssStyleSheet."\" type=\"text/css\"?>\n";
}
if (!empty($this->xslStyleSheet)) {
$xml .= "xslStyleSheet."\" type=\"text/xsl\"?>\n";
}
return $xml;
}
/**
* Builds the feed's text.
*
* @return string the feed's complete text
*/
abstract public function createFeed();
/**
* Generate a filename for the feed cache file. The result will be $_SERVER["SCRIPT_NAME"] with the extension changed
* to .xml. For example: echo $_SERVER["SCRIPT_NAME"]."\n"; echo FeedCreator::_generateFilename(); would produce:
* /rss/latestnews.php
* latestnews.xml
*
* @return string the feed cache filename
* @since 1.4
* @access private
*/
protected function _generateFilename()
{
$fileInfo = pathinfo($_SERVER["SCRIPT_NAME"]);
return substr($fileInfo["basename"], 0, -(strlen($fileInfo["extension"]) + 1)).".xml";
}
/**
* Send given file to Browser
*
* @since 1.4
* @param string $filename
*/
protected function _redirect($filename)
{
// attention, heavily-commented-out-area
// maybe use this in addition to file time checking
//header("Expires: ".date("r",time()+$this->_timeout));
/* no caching at all, doesn't seem to work as good:
header("Cache-Control: no-cache");
header("Pragma: no-cache");
*/
// HTTP redirect, some feed readers' simple HTTP implementations don't follow it
//header("Location: ".$filename);
header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));
if (preg_match('/\.(kml|gpx)$/', $filename)) {
header("Content-Disposition: attachment; filename=".basename($filename));
} else {
header("Content-Disposition: inline; filename=".basename($filename));
}
readfile($filename);
exit();
}
/**
* Turns on caching and checks if there is a recent version of this feed in the cache.
* If there is, an HTTP redirect header is sent.
* To effectively use caching, you should create the FeedCreator object and call this method
* before anything else, especially before you do the time consuming task to build the feed
* (web fetching, for example).
*
* @since 1.4
* @param string $filename optional the filename where a recent version of the feed is saved. If not specified,
* the filename is $_SERVER["SCRIPT_NAME"] with the extension changed to .xml (see
* _generateFilename()).
* @param int $timeout optional the timeout in seconds before a cached version is refreshed (defaults to
* 3600 = 1 hour)
*/
public function useCached($filename = "", $timeout = 3600)
{
$this->_timeout = $timeout;
if ($filename == "") {
$filename = $this->_generateFilename();
}
if (file_exists($filename) AND (time() - filemtime($filename) < $timeout)) {
$this->_redirect($filename);
}
}
/**
* Saves this feed as a file on the local disk. After the file is saved, a redirect
* header may be sent to redirect the user to the newly created file.
*
* @since 1.4
* @param string $filename optional the filename where a recent version of the feed is saved. If not
* specified, the filename is $_SERVER["SCRIPT_NAME"] with the extension changed to .xml
* (see _generateFilename()).
* @param bool $displayContents optional send an HTTP redirect header or not. If true, the user will be
* automatically redirected to the created file.
*/
public function saveFeed($filename = "", $displayContents = true)
{
if ($filename == "") {
$filename = $this->_generateFilename();
}
$feedFile = fopen($filename, "w+");
if ($feedFile) {
fputs($feedFile, $this->createFeed());
fclose($feedFile);
if ($displayContents) {
$this->_redirect($filename);
}
} else {
echo "
Error creating feed file, please check write permissions.
";
}
}
}