249 lines
7.1 KiB
PHP
249 lines
7.1 KiB
PHP
<?php
|
|
/**
|
|
* Class: RSSFeed
|
|
* Generates an RSS feed piece by piece.
|
|
*
|
|
* See Also:
|
|
* http://www.rssboard.org/rss-2-0-11
|
|
*/
|
|
class RSSFeed implements FeedGenerator {
|
|
# Boolean: $open
|
|
# Has the feed been opened?
|
|
protected $open = false;
|
|
|
|
# Variable: $count
|
|
# The number of entries generated.
|
|
protected $count = 0;
|
|
|
|
# Array: $xml
|
|
# Holds the feed as an array.
|
|
protected $xml = array();
|
|
|
|
/**
|
|
* Function: type
|
|
* Returns the content type of the feed.
|
|
*/
|
|
public static function type(): string {
|
|
return "application/rss+xml";
|
|
}
|
|
|
|
/**
|
|
* Function: open
|
|
* Adds the opening channel element and top-level elements.
|
|
*
|
|
* Parameters:
|
|
* $title - Title for this channel.
|
|
* $subtitle - Subtitle (optional).
|
|
* $id - Feed ID (optional).
|
|
* $updated - Time of update (optional).
|
|
*/
|
|
public function open(
|
|
$title,
|
|
$subtitle = "",
|
|
$id = "",
|
|
$updated = null
|
|
): bool {
|
|
if ($this->open)
|
|
return false;
|
|
|
|
$language = lang_base(Config::current()->locale);
|
|
$link = url("/", MainController::current());
|
|
|
|
$feed = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
|
$feed.= '<rss version="2.0">'."\n";
|
|
$feed.= '<channel>'."\n";
|
|
$feed.= '<language>'.fix($language).'</language>'."\n";
|
|
$feed.= '<title>'.strip_tags($title).'</title>'."\n";
|
|
|
|
if (!empty($subtitle))
|
|
$feed.= '<description>'.
|
|
strip_tags($subtitle).
|
|
'</description>'.
|
|
"\n";
|
|
|
|
$feed.= '<lastBuildDate>'.
|
|
when(DATE_RSS, oneof($updated, time())).
|
|
'</lastBuildDate>'.
|
|
"\n";
|
|
|
|
$feed.= '<link>'.$link.'</link>'."\n";
|
|
$feed.= '<generator>'.CHYRP_IDENTITY.'</generator>'."\n";
|
|
|
|
$this->xml = array(
|
|
"feed" => $feed,
|
|
"items" => array()
|
|
);
|
|
|
|
return $this->open = true;
|
|
}
|
|
|
|
/**
|
|
* Function: entry
|
|
* Adds an individual feed item.
|
|
*
|
|
* Parameters:
|
|
* $title - Title for this item.
|
|
* $id - The unique ID.
|
|
* $content - Content for this item.
|
|
* $link - The URL to the resource.
|
|
* $published - Time of creation.
|
|
* $updated - Time of update (optional).
|
|
* $name - Name of the author (optional).
|
|
* $uri - URI of the author (optional).
|
|
* $email - Email address of the author (optional).
|
|
*
|
|
* Notes:
|
|
* The item remains open to allow triggered insertions.
|
|
*/
|
|
public function entry(
|
|
$title,
|
|
$id,
|
|
$content,
|
|
$link,
|
|
$published,
|
|
$updated = null,
|
|
$name = "",
|
|
$uri = "",
|
|
$email = ""
|
|
): bool {
|
|
if (!$this->open)
|
|
return false;
|
|
|
|
$this->count++;
|
|
|
|
$entry = '<title>'.strip_tags($title).'</title>'."\n";
|
|
$entry.= '<guid>'.fix($id).'</guid>'."\n";
|
|
|
|
$entry.= '<pubDate>'.
|
|
when(DATE_RSS, $published).
|
|
'</pubDate>'.
|
|
"\n";
|
|
|
|
$entry.= '<link>'.fix($link).'</link>'."\n";
|
|
|
|
$entry.= '<description>'.
|
|
fix($content, false, true).
|
|
'</description>'.
|
|
"\n";
|
|
|
|
if (!empty($email) and is_email($email))
|
|
$entry.= '<author>'.fix($email).'</author>'."\n";
|
|
|
|
$item = $this->count - 1;
|
|
$this->xml["items"][$item] = $entry;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function: category
|
|
* Adds a category element for an item.
|
|
*
|
|
* Parameters:
|
|
* $term - String that identifies the category.
|
|
* $scheme - URI for the categorization scheme (optional).
|
|
* $label - Human-readable label for the category (optional).
|
|
*/
|
|
public function category($term, $scheme = "", $label = ""): bool {
|
|
if (!$this->open)
|
|
return false;
|
|
|
|
if (!$this->count)
|
|
return false;
|
|
|
|
$category = '<category';
|
|
|
|
if (!empty($scheme))
|
|
$category.= ' domain="'.fix($scheme, true).'"';
|
|
|
|
$category.= '>'.fix($term, true).'</category>'."\n";
|
|
|
|
$item = $this->count - 1;
|
|
$this->xml["items"][$item].= $category;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function: rights
|
|
* Not implemented in RSS 2.0.11.
|
|
*/
|
|
public function rights($text): bool {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function: enclosure
|
|
* Adds an enclosure element for a resource that is potentially large in size.
|
|
*
|
|
* Parameters:
|
|
* $link - The URL to the resource.
|
|
* $length - Size in bytes of the resource (optional).
|
|
* $type - The media type of the resource (optional).
|
|
* $title - Title for the resource (optional).
|
|
*/
|
|
public function enclosure(
|
|
$link,
|
|
$length = 0,
|
|
$type = "",
|
|
$title = ""
|
|
): bool {
|
|
if (!$this->open)
|
|
return false;
|
|
|
|
$enclosure = '<enclosure url="'.fix($link, true).'"'.
|
|
' length="'.fix($length, true).'"'.
|
|
' type="'.
|
|
fix(oneof($type, "application/octet-stream"), true).
|
|
'" />'.
|
|
"\n";
|
|
|
|
if (!$this->count) {
|
|
$this->xml["feed"].= $enclosure;
|
|
} else {
|
|
$item = $this->count - 1;
|
|
$this->xml["items"][$item].= $enclosure;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function: related
|
|
* Not implemented in RSS 2.0.11.
|
|
*/
|
|
public function related($link): bool {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function: feed
|
|
* Returns the generated feed.
|
|
*/
|
|
public function feed(): string {
|
|
$feed = $this->xml["feed"];
|
|
$items = $this->xml["items"];
|
|
|
|
foreach ($items as $item) {
|
|
$feed.= '<item>'."\n".
|
|
$item.
|
|
'</item>'."\n";
|
|
}
|
|
|
|
$feed.= '</channel>'."\n";
|
|
$feed.= '</rss>'."\n";
|
|
return $feed;
|
|
}
|
|
|
|
/**
|
|
* Function: output
|
|
* Displays the generated feed.
|
|
*/
|
|
public function display(): bool {
|
|
if (headers_sent())
|
|
return false;
|
|
|
|
header("Content-Type: ".self::type()."; charset=UTF-8");
|
|
echo $this->feed();
|
|
return true;
|
|
}
|
|
}
|