leilukin-tumbleblog/includes/lib/RSSFeed.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;
}
}