Fix RSS syntax according W3C recommendations

1. Add atom schema
2. Sanitize international characters in URL acording RFC3987
3. Ignore locale in date
This commit is contained in:
Max Kostikov 2019-09-15 14:27:30 +02:00 committed by GitHub
parent 9a7668587a
commit c742cb1ab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,142 +1,143 @@
<?php <<?php
class pluginRSS extends Plugin { class pluginRSS extends Plugin {
public function init() public function init()
{ {
// Fields and default values for the database of this plugin // Fields and default values for the database of this plugin
$this->dbFields = array( $this->dbFields = array(
'numberOfItems'=>5 'numberOfItems'=>5
); );
} }
// Method called on the settings of the plugin on the admin area // Method called on the settings of the plugin on the admin area
public function form() public function form()
{ {
global $L; global $L;
$html = '<div class="alert alert-primary" role="alert">'; $html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description(); $html .= $this->description();
$html .= '</div>'; $html .= '</div>';
$html .= '<div>'; $html .= '<div>';
$html .= '<label>'.$L->get('RSS URL').'</label>'; $html .= '<label>'.$L->get('RSS URL').'</label>';
$html .= '<a href="'.Theme::rssUrl().'">'.Theme::rssUrl().'</a>'; $html .= '<a href="'.Theme::rssUrl().'">'.Theme::rssUrl().'</a>';
$html .= '</div>'; $html .= '</div>';
$html .= '<div>'; $html .= '<div>';
$html .= '<label>'.$L->get('Amount of items').'</label>'; $html .= '<label>'.$L->get('Amount of items').'</label>';
$html .= '<input id="jsnumberOfItems" name="numberOfItems" type="text" value="'.$this->getValue('numberOfItems').'">'; $html .= '<input id="jsnumberOfItems" name="numberOfItems" type="text" value="'.$this->getValue('numberOfItems').'">';
$html .= '<span class="tip">'.$L->get('Amount of items to show on the feed').'</span>'; $html .= '<span class="tip">'.$L->get('Amount of items to show on the feed').'</span>';
$html .= '</div>'; $html .= '</div>';
return $html; return $html;
} }
private function createXML() private function createXML()
{ {
global $site; global $site;
global $pages; global $pages;
global $url; global $url;
// Amount of pages to show // Amount of pages to show
$numberOfItems = $this->getValue('numberOfItems'); $numberOfItems = $this->getValue('numberOfItems');
// Get the list of public pages (sticky and static included) // Get the list of public pages (sticky and static included)
$list = $pages->getList( $list = $pages->getList(
$pageNumber=1, $pageNumber=1,
$numberOfItems, $numberOfItems,
$published=true, $published=true,
$static=true, $static=true,
$sticky=true, $sticky=true,
$draft=false, $draft=false,
$scheduled=false $scheduled=false
); );
$xml = '<?xml version="1.0" encoding="UTF-8" ?>'; $xml = '<?xml version="1.0" encoding="UTF-8" ?>';
$xml .= '<rss version="2.0">'; $xml .= '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">';
$xml .= '<channel>'; $xml .= '<channel>';
$xml .= '<title>'.$site->title().'</title>'; $xml .= '<atom:link href="'.DOMAIN_BASE.'rss.xml" rel="self" type="application/rss+xml" />';
$xml .= '<link>'.$site->url().'</link>'; $xml .= '<title>'.$site->title().'</title>';
$xml .= '<description>'.$site->description().'</description>'; $xml .= '<link>'.preg_replace_callback("/[^\x20-\x7f]/", function($match) { return urlencode($match[0]); },$site->url()).'</link>';
$xml .= '<lastBuildDate>'.date(DATE_RSS).'</lastBuildDate>'; $xml .= '<description>'.$site->description().'</description>';
$xml .= '<lastBuildDate>'.date(DATE_RSS).'</lastBuildDate>';
// Get keys of pages // Get keys of pages
foreach ($list as $pageKey) { foreach ($list as $pageKey) {
try { try {
// Create the page object from the page key // Create the page object from the page key
$page = new Page($pageKey); $page = new Page($pageKey);
$xml .= '<item>'; $xml .= '<item>';
$xml .= '<title>'.$page->title().'</title>'; $xml .= '<title>'.$page->title().'</title>';
$xml .= '<link>'.$page->permalink().'</link>'; $xml .= "<link>".preg_replace_callback('/[^\x20-\x7f]/',function($match){return urlencode($match[0]);},$page->permalink())."</link>";
$xml .= '<description>'.Sanitize::html($page->contentBreak()).'</description>'; $xml .= '<description>'.Sanitize::html($page->contentBreak()).'</description>';
$xml .= '<pubDate>'.date('r',strtotime($page->getValue('dateRaw'))).'</pubDate>'; $xml .= '<pubDate>'.date('r',strtotime($page->getValue('dateRaw'))).'</pubDate>';
$xml .= '<guid isPermaLink="false">'.$page->uuid().'</guid>'; $xml .= '<guid isPermaLink="false">'.$page->uuid().'</guid>';
$xml .= '</item>'; $xml .= '</item>';
} catch (Exception $e) { } catch (Exception $e) {
// Continue // Continue
} }
} }
$xml .= '</channel></rss>'; $xml .= '</channel></rss>';
// New DOM document // New DOM document
$doc = new DOMDocument(); $doc = new DOMDocument();
$doc->formatOutput = true; $doc->formatOutput = true;
$doc->loadXML($xml); $doc->loadXML($xml);
return $doc->save($this->workspace().'rss.xml'); return $doc->save($this->workspace().'rss.xml');
} }
public function install($position=0) public function install($position=0)
{ {
parent::install($position); parent::install($position);
return $this->createXML(); return $this->createXML();
} }
public function post() public function post()
{ {
parent::post(); parent::post();
return $this->createXML(); return $this->createXML();
} }
public function afterPageCreate() public function afterPageCreate()
{ {
$this->createXML(); $this->createXML();
} }
public function afterPageModify() public function afterPageModify()
{ {
$this->createXML(); $this->createXML();
} }
public function afterPageDelete() public function afterPageDelete()
{ {
$this->createXML(); $this->createXML();
} }
public function siteHead() public function siteHead()
{ {
return '<link rel="alternate" type="application/rss+xml" href="'.DOMAIN_BASE.'rss.xml" title="RSS Feed">'.PHP_EOL; return '<link rel="alternate" type="application/rss+xml" href="'.DOMAIN_BASE.'rss.xml" title="RSS Feed">'.PHP_EOL;
} }
public function beforeAll() public function beforeAll()
{ {
$webhook = 'rss.xml'; $webhook = 'rss.xml';
if ($this->webhook($webhook)) { if ($this->webhook($webhook)) {
// Send XML header // Send XML header
header('Content-type: text/xml'); header('Content-type: text/xml');
$doc = new DOMDocument(); $doc = new DOMDocument();
// Load XML // Load XML
libxml_disable_entity_loader(false); libxml_disable_entity_loader(false);
$doc->load($this->workspace().'rss.xml'); $doc->load($this->workspace().'rss.xml');
libxml_disable_entity_loader(true); libxml_disable_entity_loader(true);
// Print the XML // Print the XML
echo $doc->saveXML(); echo $doc->saveXML();
// Stop Bludit execution // Stop Bludit execution
exit(0); exit(0);
} }
} }
} }