mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-29 06:38:51 +03:00
feat: support itunes namespace in top channel feed (#3776)
Also preserves other properties.
This commit is contained in:
parent
ea58c8d2bc
commit
3ce94409ab
22 changed files with 298 additions and 203 deletions
|
@ -100,7 +100,7 @@ class DisplayAction implements ActionInterface
|
||||||
private function createResponse(array $request, BridgeAbstract $bridge, FormatAbstract $format)
|
private function createResponse(array $request, BridgeAbstract $bridge, FormatAbstract $format)
|
||||||
{
|
{
|
||||||
$items = [];
|
$items = [];
|
||||||
$infos = [];
|
$feed = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$bridge->loadConfiguration();
|
$bridge->loadConfiguration();
|
||||||
|
@ -116,12 +116,7 @@ class DisplayAction implements ActionInterface
|
||||||
}
|
}
|
||||||
$items = $feedItems;
|
$items = $feedItems;
|
||||||
}
|
}
|
||||||
$infos = [
|
$feed = $bridge->getFeed();
|
||||||
'name' => $bridge->getName(),
|
|
||||||
'uri' => $bridge->getURI(),
|
|
||||||
'donationUri' => $bridge->getDonationURI(),
|
|
||||||
'icon' => $bridge->getIcon()
|
|
||||||
];
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if ($e instanceof HttpException) {
|
if ($e instanceof HttpException) {
|
||||||
// Reproduce (and log) these responses regardless of error output and report limit
|
// Reproduce (and log) these responses regardless of error output and report limit
|
||||||
|
@ -155,7 +150,7 @@ class DisplayAction implements ActionInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
$format->setItems($items);
|
$format->setItems($items);
|
||||||
$format->setExtraInfos($infos);
|
$format->setFeed($feed);
|
||||||
$now = time();
|
$now = time();
|
||||||
$format->setLastModified($now);
|
$format->setLastModified($now);
|
||||||
$headers = [
|
$headers = [
|
||||||
|
|
|
@ -280,7 +280,7 @@ class ItakuBridge extends BridgeAbstract
|
||||||
$opt['range'] = '';
|
$opt['range'] = '';
|
||||||
$user_id = $this->getInput('user_id') ?? $this->getOwnerID($this->getInput('user'));
|
$user_id = $this->getInput('user_id') ?? $this->getOwnerID($this->getInput('user'));
|
||||||
|
|
||||||
$data = $this->getFeed(
|
$data = $this->getFeedData(
|
||||||
$opt,
|
$opt,
|
||||||
$user_id
|
$user_id
|
||||||
);
|
);
|
||||||
|
@ -289,7 +289,7 @@ class ItakuBridge extends BridgeAbstract
|
||||||
if ($this->queriedContext === 'Home feed') {
|
if ($this->queriedContext === 'Home feed') {
|
||||||
$opt['order'] = $this->getInput('order');
|
$opt['order'] = $this->getInput('order');
|
||||||
$opt['range'] = $this->getInput('range');
|
$opt['range'] = $this->getInput('range');
|
||||||
$data = $this->getFeed($opt);
|
$data = $this->getFeedData($opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data['results'] as $record) {
|
foreach ($data['results'] as $record) {
|
||||||
|
@ -409,7 +409,7 @@ class ItakuBridge extends BridgeAbstract
|
||||||
return $this->getData($url, false, true);
|
return $this->getData($url, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFeed(array $opt, $ownerID = null)
|
private function getFeedData(array $opt, $ownerID = null)
|
||||||
{
|
{
|
||||||
$url = self::URI . "/api/feed/?date_range={$opt['range']}&ordering={$opt['order']}&page=1&page_size=30&format=json";
|
$url = self::URI . "/api/feed/?date_range={$opt['range']}&ordering={$opt['order']}&page=1&page_size=30&format=json";
|
||||||
|
|
||||||
|
|
|
@ -17,44 +17,61 @@ class AtomFormat extends FormatAbstract
|
||||||
public function stringify()
|
public function stringify()
|
||||||
{
|
{
|
||||||
$document = new \DomDocument('1.0', $this->getCharset());
|
$document = new \DomDocument('1.0', $this->getCharset());
|
||||||
|
$document->formatOutput = true;
|
||||||
|
|
||||||
$feedUrl = get_current_url();
|
$feedUrl = get_current_url();
|
||||||
|
|
||||||
$extraInfos = $this->getExtraInfos();
|
|
||||||
if (empty($extraInfos['uri'])) {
|
|
||||||
$uri = REPOSITORY;
|
|
||||||
} else {
|
|
||||||
$uri = $extraInfos['uri'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$document->formatOutput = true;
|
|
||||||
$feed = $document->createElementNS(self::ATOM_NS, 'feed');
|
$feed = $document->createElementNS(self::ATOM_NS, 'feed');
|
||||||
$document->appendChild($feed);
|
$document->appendChild($feed);
|
||||||
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:media', self::MRSS_NS);
|
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:media', self::MRSS_NS);
|
||||||
|
|
||||||
|
$feedArray = $this->getFeed();
|
||||||
|
foreach ($feedArray as $feedKey => $feedValue) {
|
||||||
|
if (in_array($feedKey, ['donationUri'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($feedKey === 'name') {
|
||||||
$title = $document->createElement('title');
|
$title = $document->createElement('title');
|
||||||
$feed->appendChild($title);
|
$feed->appendChild($title);
|
||||||
$title->setAttribute('type', 'text');
|
$title->setAttribute('type', 'text');
|
||||||
$title->appendChild($document->createTextNode($extraInfos['name']));
|
$title->appendChild($document->createTextNode($feedValue));
|
||||||
|
} elseif ($feedKey === 'icon') {
|
||||||
|
if ($feedValue) {
|
||||||
|
$icon = $document->createElement('icon');
|
||||||
|
$feed->appendChild($icon);
|
||||||
|
$icon->appendChild($document->createTextNode($feedValue));
|
||||||
|
|
||||||
|
$logo = $document->createElement('logo');
|
||||||
|
$feed->appendChild($logo);
|
||||||
|
$logo->appendChild($document->createTextNode($feedValue));
|
||||||
|
}
|
||||||
|
} elseif ($feedKey === 'uri') {
|
||||||
|
if ($feedValue) {
|
||||||
|
$linkAlternate = $document->createElement('link');
|
||||||
|
$feed->appendChild($linkAlternate);
|
||||||
|
$linkAlternate->setAttribute('rel', 'alternate');
|
||||||
|
$linkAlternate->setAttribute('type', 'text/html');
|
||||||
|
$linkAlternate->setAttribute('href', $feedValue);
|
||||||
|
|
||||||
|
$linkSelf = $document->createElement('link');
|
||||||
|
$feed->appendChild($linkSelf);
|
||||||
|
$linkSelf->setAttribute('rel', 'self');
|
||||||
|
$linkSelf->setAttribute('type', 'application/atom+xml');
|
||||||
|
$linkSelf->setAttribute('href', $feedUrl);
|
||||||
|
}
|
||||||
|
} elseif ($feedKey === 'itunes') {
|
||||||
|
// todo: skip?
|
||||||
|
} else {
|
||||||
|
$element = $document->createElement($feedKey);
|
||||||
|
$feed->appendChild($element);
|
||||||
|
$element->appendChild($document->createTextNode($feedValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$id = $document->createElement('id');
|
$id = $document->createElement('id');
|
||||||
$feed->appendChild($id);
|
$feed->appendChild($id);
|
||||||
$id->appendChild($document->createTextNode($feedUrl));
|
$id->appendChild($document->createTextNode($feedUrl));
|
||||||
|
|
||||||
$uriparts = parse_url($uri);
|
|
||||||
if (empty($extraInfos['icon'])) {
|
|
||||||
$iconUrl = $uriparts['scheme'] . '://' . $uriparts['host'] . '/favicon.ico';
|
|
||||||
} else {
|
|
||||||
$iconUrl = $extraInfos['icon'];
|
|
||||||
}
|
|
||||||
$icon = $document->createElement('icon');
|
|
||||||
$feed->appendChild($icon);
|
|
||||||
$icon->appendChild($document->createTextNode($iconUrl));
|
|
||||||
|
|
||||||
$logo = $document->createElement('logo');
|
|
||||||
$feed->appendChild($logo);
|
|
||||||
$logo->appendChild($document->createTextNode($iconUrl));
|
|
||||||
|
|
||||||
$feedTimestamp = gmdate(DATE_ATOM, $this->lastModified);
|
$feedTimestamp = gmdate(DATE_ATOM, $this->lastModified);
|
||||||
$updated = $document->createElement('updated');
|
$updated = $document->createElement('updated');
|
||||||
$feed->appendChild($updated);
|
$feed->appendChild($updated);
|
||||||
|
@ -69,17 +86,7 @@ class AtomFormat extends FormatAbstract
|
||||||
$author->appendChild($authorName);
|
$author->appendChild($authorName);
|
||||||
$authorName->appendChild($document->createTextNode($feedAuthor));
|
$authorName->appendChild($document->createTextNode($feedAuthor));
|
||||||
|
|
||||||
$linkAlternate = $document->createElement('link');
|
|
||||||
$feed->appendChild($linkAlternate);
|
|
||||||
$linkAlternate->setAttribute('rel', 'alternate');
|
|
||||||
$linkAlternate->setAttribute('type', 'text/html');
|
|
||||||
$linkAlternate->setAttribute('href', $uri);
|
|
||||||
|
|
||||||
$linkSelf = $document->createElement('link');
|
|
||||||
$feed->appendChild($linkSelf);
|
|
||||||
$linkSelf->setAttribute('rel', 'self');
|
|
||||||
$linkSelf->setAttribute('type', 'application/atom+xml');
|
|
||||||
$linkSelf->setAttribute('href', $feedUrl);
|
|
||||||
|
|
||||||
foreach ($this->getItems() as $item) {
|
foreach ($this->getItems() as $item) {
|
||||||
$itemArray = $item->toArray();
|
$itemArray = $item->toArray();
|
||||||
|
|
|
@ -8,7 +8,7 @@ class HtmlFormat extends FormatAbstract
|
||||||
{
|
{
|
||||||
$queryString = $_SERVER['QUERY_STRING'];
|
$queryString = $_SERVER['QUERY_STRING'];
|
||||||
|
|
||||||
$extraInfos = $this->getExtraInfos();
|
$feedArray = $this->getFeed();
|
||||||
$formatFactory = new FormatFactory();
|
$formatFactory = new FormatFactory();
|
||||||
$buttons = [];
|
$buttons = [];
|
||||||
$linkTags = [];
|
$linkTags = [];
|
||||||
|
@ -29,9 +29,9 @@ class HtmlFormat extends FormatAbstract
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Configuration::getConfig('admin', 'donations') && $extraInfos['donationUri'] !== '') {
|
if (Configuration::getConfig('admin', 'donations') && $feedArray['donationUri']) {
|
||||||
$buttons[] = [
|
$buttons[] = [
|
||||||
'href' => e($extraInfos['donationUri']),
|
'href' => e($feedArray['donationUri']),
|
||||||
'value' => 'Donate to maintainer',
|
'value' => 'Donate to maintainer',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class HtmlFormat extends FormatAbstract
|
||||||
$items = [];
|
$items = [];
|
||||||
foreach ($this->getItems() as $item) {
|
foreach ($this->getItems() as $item) {
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'url' => $item->getURI() ?: $extraInfos['uri'],
|
'url' => $item->getURI() ?: $feedArray['uri'],
|
||||||
'title' => $item->getTitle() ?? '(no title)',
|
'title' => $item->getTitle() ?? '(no title)',
|
||||||
'timestamp' => $item->getTimestamp(),
|
'timestamp' => $item->getTimestamp(),
|
||||||
'author' => $item->getAuthor(),
|
'author' => $item->getAuthor(),
|
||||||
|
@ -51,9 +51,9 @@ class HtmlFormat extends FormatAbstract
|
||||||
|
|
||||||
$html = render_template(__DIR__ . '/../templates/html-format.html.php', [
|
$html = render_template(__DIR__ . '/../templates/html-format.html.php', [
|
||||||
'charset' => $this->getCharset(),
|
'charset' => $this->getCharset(),
|
||||||
'title' => $extraInfos['name'],
|
'title' => $feedArray['name'],
|
||||||
'linkTags' => $linkTags,
|
'linkTags' => $linkTags,
|
||||||
'uri' => $extraInfos['uri'],
|
'uri' => $feedArray['uri'],
|
||||||
'buttons' => $buttons,
|
'buttons' => $buttons,
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -25,18 +25,18 @@ class JsonFormat extends FormatAbstract
|
||||||
|
|
||||||
public function stringify()
|
public function stringify()
|
||||||
{
|
{
|
||||||
$host = $_SERVER['HTTP_HOST'] ?? '';
|
$feedArray = $this->getFeed();
|
||||||
$extraInfos = $this->getExtraInfos();
|
|
||||||
$data = [
|
$data = [
|
||||||
'version' => 'https://jsonfeed.org/version/1',
|
'version' => 'https://jsonfeed.org/version/1',
|
||||||
'title' => empty($extraInfos['name']) ? $host : $extraInfos['name'],
|
'title' => $feedArray['name'],
|
||||||
'home_page_url' => empty($extraInfos['uri']) ? REPOSITORY : $extraInfos['uri'],
|
'home_page_url' => $feedArray['uri'],
|
||||||
'feed_url' => get_current_url(),
|
'feed_url' => get_current_url(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!empty($extraInfos['icon'])) {
|
if ($feedArray['icon']) {
|
||||||
$data['icon'] = $extraInfos['icon'];
|
$data['icon'] = $feedArray['icon'];
|
||||||
$data['favicon'] = $extraInfos['icon'];
|
$data['favicon'] = $feedArray['icon'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$items = [];
|
$items = [];
|
||||||
|
|
|
@ -35,16 +35,8 @@ class MrssFormat extends FormatAbstract
|
||||||
public function stringify()
|
public function stringify()
|
||||||
{
|
{
|
||||||
$document = new \DomDocument('1.0', $this->getCharset());
|
$document = new \DomDocument('1.0', $this->getCharset());
|
||||||
|
|
||||||
$feedUrl = get_current_url();
|
|
||||||
$extraInfos = $this->getExtraInfos();
|
|
||||||
if (empty($extraInfos['uri'])) {
|
|
||||||
$uri = REPOSITORY;
|
|
||||||
} else {
|
|
||||||
$uri = $extraInfos['uri'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$document->formatOutput = true;
|
$document->formatOutput = true;
|
||||||
|
|
||||||
$feed = $document->createElement('rss');
|
$feed = $document->createElement('rss');
|
||||||
$document->appendChild($feed);
|
$document->appendChild($feed);
|
||||||
$feed->setAttribute('version', '2.0');
|
$feed->setAttribute('version', '2.0');
|
||||||
|
@ -54,26 +46,48 @@ class MrssFormat extends FormatAbstract
|
||||||
$channel = $document->createElement('channel');
|
$channel = $document->createElement('channel');
|
||||||
$feed->appendChild($channel);
|
$feed->appendChild($channel);
|
||||||
|
|
||||||
$title = $extraInfos['name'];
|
$feedArray = $this->getFeed();
|
||||||
|
$uri = $feedArray['uri'];
|
||||||
|
$title = $feedArray['name'];
|
||||||
|
|
||||||
|
foreach ($feedArray as $feedKey => $feedValue) {
|
||||||
|
if (in_array($feedKey, ['atom', 'donationUri'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($feedKey === 'name') {
|
||||||
$channelTitle = $document->createElement('title');
|
$channelTitle = $document->createElement('title');
|
||||||
$channel->appendChild($channelTitle);
|
$channel->appendChild($channelTitle);
|
||||||
$channelTitle->appendChild($document->createTextNode($title));
|
$channelTitle->appendChild($document->createTextNode($title));
|
||||||
|
|
||||||
|
$description = $document->createElement('description');
|
||||||
|
$channel->appendChild($description);
|
||||||
|
$description->appendChild($document->createTextNode($title));
|
||||||
|
} elseif ($feedKey === 'uri') {
|
||||||
$link = $document->createElement('link');
|
$link = $document->createElement('link');
|
||||||
$channel->appendChild($link);
|
$channel->appendChild($link);
|
||||||
$link->appendChild($document->createTextNode($uri));
|
$link->appendChild($document->createTextNode($uri));
|
||||||
|
|
||||||
$description = $document->createElement('description');
|
$linkAlternate = $document->createElementNS(self::ATOM_NS, 'link');
|
||||||
$channel->appendChild($description);
|
$channel->appendChild($linkAlternate);
|
||||||
$description->appendChild($document->createTextNode($extraInfos['name']));
|
$linkAlternate->setAttribute('rel', 'alternate');
|
||||||
|
$linkAlternate->setAttribute('type', 'text/html');
|
||||||
|
$linkAlternate->setAttribute('href', $uri);
|
||||||
|
|
||||||
|
$linkSelf = $document->createElementNS(self::ATOM_NS, 'link');
|
||||||
|
$channel->appendChild($linkSelf);
|
||||||
|
$linkSelf->setAttribute('rel', 'self');
|
||||||
|
$linkSelf->setAttribute('type', 'application/atom+xml');
|
||||||
|
$feedUrl = get_current_url();
|
||||||
|
$linkSelf->setAttribute('href', $feedUrl);
|
||||||
|
} elseif ($feedKey === 'icon') {
|
||||||
$allowedIconExtensions = [
|
$allowedIconExtensions = [
|
||||||
'.gif',
|
'.gif',
|
||||||
'.jpg',
|
'.jpg',
|
||||||
'.png',
|
'.png',
|
||||||
|
'.ico',
|
||||||
];
|
];
|
||||||
$icon = $extraInfos['icon'];
|
$icon = $feedValue;
|
||||||
if (!empty($icon) && in_array(substr($icon, -4), $allowedIconExtensions)) {
|
if ($icon && in_array(substr($icon, -4), $allowedIconExtensions)) {
|
||||||
$feedImage = $document->createElement('image');
|
$feedImage = $document->createElement('image');
|
||||||
$channel->appendChild($feedImage);
|
$channel->appendChild($feedImage);
|
||||||
$iconUrl = $document->createElement('url');
|
$iconUrl = $document->createElement('url');
|
||||||
|
@ -86,18 +100,19 @@ class MrssFormat extends FormatAbstract
|
||||||
$iconLink->appendChild($document->createTextNode($uri));
|
$iconLink->appendChild($document->createTextNode($uri));
|
||||||
$feedImage->appendChild($iconLink);
|
$feedImage->appendChild($iconLink);
|
||||||
}
|
}
|
||||||
|
} elseif ($feedKey === 'itunes') {
|
||||||
$linkAlternate = $document->createElementNS(self::ATOM_NS, 'link');
|
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:itunes', self::ITUNES_NS);
|
||||||
$channel->appendChild($linkAlternate);
|
foreach ($feedValue as $itunesKey => $itunesValue) {
|
||||||
$linkAlternate->setAttribute('rel', 'alternate');
|
$itunesProperty = $document->createElementNS(self::ITUNES_NS, $itunesKey);
|
||||||
$linkAlternate->setAttribute('type', 'text/html');
|
$channel->appendChild($itunesProperty);
|
||||||
$linkAlternate->setAttribute('href', $uri);
|
$itunesProperty->appendChild($document->createTextNode($itunesValue));
|
||||||
|
}
|
||||||
$linkSelf = $document->createElementNS(self::ATOM_NS, 'link');
|
} else {
|
||||||
$channel->appendChild($linkSelf);
|
$element = $document->createElement($feedKey);
|
||||||
$linkSelf->setAttribute('rel', 'self');
|
$channel->appendChild($element);
|
||||||
$linkSelf->setAttribute('type', 'application/atom+xml');
|
$element->appendChild($document->createTextNode($feedValue));
|
||||||
$linkSelf->setAttribute('href', $feedUrl);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->getItems() as $item) {
|
foreach ($this->getItems() as $item) {
|
||||||
$itemArray = $item->toArray();
|
$itemArray = $item->toArray();
|
||||||
|
@ -135,6 +150,7 @@ class MrssFormat extends FormatAbstract
|
||||||
$entry->appendChild($itunesProperty);
|
$entry->appendChild($itunesProperty);
|
||||||
$itunesProperty->appendChild($document->createTextNode($itunesValue));
|
$itunesProperty->appendChild($document->createTextNode($itunesValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($itemArray['enclosure'])) {
|
if (isset($itemArray['enclosure'])) {
|
||||||
$itunesEnclosure = $document->createElement('enclosure');
|
$itunesEnclosure = $document->createElement('enclosure');
|
||||||
$entry->appendChild($itunesEnclosure);
|
$entry->appendChild($itunesEnclosure);
|
||||||
|
@ -142,7 +158,9 @@ class MrssFormat extends FormatAbstract
|
||||||
$itunesEnclosure->setAttribute('length', $itemArray['enclosure']['length']);
|
$itunesEnclosure->setAttribute('length', $itemArray['enclosure']['length']);
|
||||||
$itunesEnclosure->setAttribute('type', $itemArray['enclosure']['type']);
|
$itunesEnclosure->setAttribute('type', $itemArray['enclosure']['type']);
|
||||||
}
|
}
|
||||||
} if (!empty($itemUri)) {
|
}
|
||||||
|
|
||||||
|
if (!empty($itemUri)) {
|
||||||
$entryLink = $document->createElement('link');
|
$entryLink = $document->createElement('link');
|
||||||
$entry->appendChild($entryLink);
|
$entry->appendChild($entryLink);
|
||||||
$entryLink->appendChild($document->createTextNode($itemUri));
|
$entryLink->appendChild($document->createTextNode($itemUri));
|
||||||
|
|
|
@ -6,11 +6,11 @@ class PlaintextFormat extends FormatAbstract
|
||||||
|
|
||||||
public function stringify()
|
public function stringify()
|
||||||
{
|
{
|
||||||
$data = [];
|
$feed = $this->getFeed();
|
||||||
foreach ($this->getItems() as $item) {
|
foreach ($this->getItems() as $item) {
|
||||||
$data[] = $item->toArray();
|
$feed['items'][] = $item->toArray();
|
||||||
}
|
}
|
||||||
$text = print_r($data, true);
|
$text = print_r($feed, true);
|
||||||
// Remove invalid non-UTF8 characters
|
// Remove invalid non-UTF8 characters
|
||||||
ini_set('mbstring.substitute_character', 'none');
|
ini_set('mbstring.substitute_character', 'none');
|
||||||
$text = mb_convert_encoding($text, $this->getCharset(), 'UTF-8');
|
$text = mb_convert_encoding($text, $this->getCharset(), 'UTF-8');
|
||||||
|
|
|
@ -40,9 +40,38 @@ abstract class BridgeAbstract
|
||||||
|
|
||||||
abstract public function collectData();
|
abstract public function collectData();
|
||||||
|
|
||||||
public function getItems()
|
public function getFeed(): array
|
||||||
{
|
{
|
||||||
return $this->items;
|
return [
|
||||||
|
'name' => $this->getName(),
|
||||||
|
'uri' => $this->getURI(),
|
||||||
|
'donationUri' => $this->getDonationURI(),
|
||||||
|
'icon' => $this->getIcon(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return static::NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getURI()
|
||||||
|
{
|
||||||
|
return static::URI ?? 'https://github.com/RSS-Bridge/rss-bridge/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDonationURI(): string
|
||||||
|
{
|
||||||
|
return static::DONATION_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIcon()
|
||||||
|
{
|
||||||
|
if (static::URI) {
|
||||||
|
// This favicon may or may not exist
|
||||||
|
return rtrim(static::URI, '/') . '/favicon.ico';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOption(string $name)
|
public function getOption(string $name)
|
||||||
|
@ -50,6 +79,9 @@ abstract class BridgeAbstract
|
||||||
return $this->configuration[$name] ?? null;
|
return $this->configuration[$name] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description is currently not used in feed production
|
||||||
|
*/
|
||||||
public function getDescription()
|
public function getDescription()
|
||||||
{
|
{
|
||||||
return static::DESCRIPTION;
|
return static::DESCRIPTION;
|
||||||
|
@ -60,29 +92,14 @@ abstract class BridgeAbstract
|
||||||
return static::MAINTAINER;
|
return static::MAINTAINER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return static::NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIcon()
|
|
||||||
{
|
|
||||||
return static::URI . '/favicon.ico';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getParameters(): array
|
public function getParameters(): array
|
||||||
{
|
{
|
||||||
return static::PARAMETERS;
|
return static::PARAMETERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getURI()
|
public function getItems()
|
||||||
{
|
{
|
||||||
return static::URI;
|
return $this->items;
|
||||||
}
|
|
||||||
|
|
||||||
public function getDonationURI(): string
|
|
||||||
{
|
|
||||||
return static::DONATION_URI;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCacheTimeout()
|
public function getCacheTimeout()
|
||||||
|
|
|
@ -9,10 +9,43 @@ abstract class FormatAbstract
|
||||||
protected string $charset = 'UTF-8';
|
protected string $charset = 'UTF-8';
|
||||||
protected array $items = [];
|
protected array $items = [];
|
||||||
protected int $lastModified;
|
protected int $lastModified;
|
||||||
protected array $extraInfos = [];
|
|
||||||
|
protected array $feed = [];
|
||||||
|
|
||||||
abstract public function stringify();
|
abstract public function stringify();
|
||||||
|
|
||||||
|
public function setFeed(array $feed)
|
||||||
|
{
|
||||||
|
$default = [
|
||||||
|
'name' => '',
|
||||||
|
'uri' => '',
|
||||||
|
'icon' => '',
|
||||||
|
'donationUri' => '',
|
||||||
|
];
|
||||||
|
$this->feed = array_merge($default, $feed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFeed(): array
|
||||||
|
{
|
||||||
|
return $this->feed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FeedItem[] $items
|
||||||
|
*/
|
||||||
|
public function setItems(array $items): void
|
||||||
|
{
|
||||||
|
$this->items = $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FeedItem[] The items
|
||||||
|
*/
|
||||||
|
public function getItems(): array
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
public function getMimeType(): string
|
public function getMimeType(): string
|
||||||
{
|
{
|
||||||
return static::MIME_TYPE;
|
return static::MIME_TYPE;
|
||||||
|
@ -32,44 +65,4 @@ abstract class FormatAbstract
|
||||||
{
|
{
|
||||||
$this->lastModified = $lastModified;
|
$this->lastModified = $lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FeedItem[] $items
|
|
||||||
*/
|
|
||||||
public function setItems(array $items): void
|
|
||||||
{
|
|
||||||
$this->items = $items;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return FeedItem[] The items
|
|
||||||
*/
|
|
||||||
public function getItems(): array
|
|
||||||
{
|
|
||||||
return $this->items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setExtraInfos(array $infos = [])
|
|
||||||
{
|
|
||||||
$extras = [
|
|
||||||
'name',
|
|
||||||
'uri',
|
|
||||||
'icon',
|
|
||||||
'donationUri',
|
|
||||||
];
|
|
||||||
foreach ($extras as $extra) {
|
|
||||||
if (!isset($infos[$extra])) {
|
|
||||||
$infos[$extra] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->extraInfos = $infos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExtraInfos(): array
|
|
||||||
{
|
|
||||||
if (!$this->extraInfos) {
|
|
||||||
$this->setExtraInfos();
|
|
||||||
}
|
|
||||||
return $this->extraInfos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,6 @@ const PATH_LIB_CACHES = __DIR__ . '/../caches/';
|
||||||
/** Path to the cache folder */
|
/** Path to the cache folder */
|
||||||
const PATH_CACHE = __DIR__ . '/../cache/';
|
const PATH_CACHE = __DIR__ . '/../cache/';
|
||||||
|
|
||||||
/** URL to the RSS-Bridge repository */
|
|
||||||
const REPOSITORY = 'https://github.com/RSS-Bridge/rss-bridge/';
|
|
||||||
|
|
||||||
// Allow larger files for simple_html_dom
|
// Allow larger files for simple_html_dom
|
||||||
// todo: extract to config (if possible)
|
// todo: extract to config (if possible)
|
||||||
const MAX_FILE_SIZE = 10000000;
|
const MAX_FILE_SIZE = 10000000;
|
||||||
|
|
72
tests/FormatTest.php
Normal file
72
tests/FormatTest.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace RssBridge\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class FormatTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testBridge()
|
||||||
|
{
|
||||||
|
$sut = new \MrssFormat();
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
'name' => '',
|
||||||
|
'uri' => '',
|
||||||
|
'icon' => '',
|
||||||
|
'donationUri' => '',
|
||||||
|
];
|
||||||
|
$this->assertEquals([], $sut->getFeed());
|
||||||
|
|
||||||
|
$sut->setFeed([
|
||||||
|
'name' => '0',
|
||||||
|
'uri' => '1',
|
||||||
|
'icon' => '2',
|
||||||
|
'donationUri' => '3',
|
||||||
|
]);
|
||||||
|
$expected = [
|
||||||
|
'name' => '0',
|
||||||
|
'uri' => '1',
|
||||||
|
'icon' => '2',
|
||||||
|
'donationUri' => '3',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $sut->getFeed());
|
||||||
|
|
||||||
|
$sut->setFeed([]);
|
||||||
|
$expected = [
|
||||||
|
'name' => '',
|
||||||
|
'uri' => '',
|
||||||
|
'icon' => '',
|
||||||
|
'donationUri' => '',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $sut->getFeed());
|
||||||
|
|
||||||
|
$sut->setFeed(['foo' => 'bar', 'foo2' => 'bar2']);
|
||||||
|
$expected = [
|
||||||
|
'name' => '',
|
||||||
|
'uri' => '',
|
||||||
|
'icon' => '',
|
||||||
|
'donationUri' => '',
|
||||||
|
'foo' => 'bar',
|
||||||
|
'foo2' => 'bar2',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $sut->getFeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestFormat extends \FormatAbstract
|
||||||
|
{
|
||||||
|
public function stringify()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestBridge extends \BridgeAbstract
|
||||||
|
{
|
||||||
|
public function collectData()
|
||||||
|
{
|
||||||
|
$this->items[] = ['title' => 'kek'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,7 +61,7 @@ abstract class BaseFormatTest extends TestCase
|
||||||
$formatFactory = new FormatFactory();
|
$formatFactory = new FormatFactory();
|
||||||
$format = $formatFactory->create($formatName);
|
$format = $formatFactory->create($formatName);
|
||||||
$format->setItems($sample->items);
|
$format->setItems($sample->items);
|
||||||
$format->setExtraInfos($sample->meta);
|
$format->setFeed($sample->meta);
|
||||||
$format->setLastModified(strtotime('2000-01-01 12:00:00 UTC'));
|
$format->setLastModified(strtotime('2000-01-01 12:00:00 UTC'));
|
||||||
|
|
||||||
return $format->stringify();
|
return $format->stringify();
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
|
|
||||||
<title type="text">Sample feed with common data</title>
|
<title type="text">Sample feed with common data</title>
|
||||||
<id>https://example.com/feed?type=common&items=4</id>
|
<link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
||||||
|
<link href="https://example.com/feed?type=common&items=4" rel="self" type="application/atom+xml"/>
|
||||||
<icon>https://example.com/logo.png</icon>
|
<icon>https://example.com/logo.png</icon>
|
||||||
<logo>https://example.com/logo.png</logo>
|
<logo>https://example.com/logo.png</logo>
|
||||||
|
<id>https://example.com/feed?type=common&items=4</id>
|
||||||
<updated>2000-01-01T12:00:00+00:00</updated>
|
<updated>2000-01-01T12:00:00+00:00</updated>
|
||||||
<author>
|
<author>
|
||||||
<name>RSS-Bridge</name>
|
<name>RSS-Bridge</name>
|
||||||
</author>
|
</author>
|
||||||
<link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
|
||||||
<link href="https://example.com/feed?type=common&items=4" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
<entry>
|
<entry>
|
||||||
<title type="html">Test Entry</title>
|
<title type="html">Test Entry</title>
|
||||||
|
|
|
@ -2,14 +2,12 @@
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
|
|
||||||
<title type="text">Sample feed with minimum data</title>
|
<title type="text">Sample feed with minimum data</title>
|
||||||
|
<link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
||||||
|
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
<id>https://example.com/feed</id>
|
<id>https://example.com/feed</id>
|
||||||
<icon>https://github.com/favicon.ico</icon>
|
|
||||||
<logo>https://github.com/favicon.ico</logo>
|
|
||||||
<updated>2000-01-01T12:00:00+00:00</updated>
|
<updated>2000-01-01T12:00:00+00:00</updated>
|
||||||
<author>
|
<author>
|
||||||
<name>RSS-Bridge</name>
|
<name>RSS-Bridge</name>
|
||||||
</author>
|
</author>
|
||||||
<link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
|
||||||
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
</feed>
|
</feed>
|
||||||
|
|
|
@ -2,15 +2,13 @@
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
|
|
||||||
<title type="text">Sample feed with minimum data</title>
|
<title type="text">Sample feed with minimum data</title>
|
||||||
|
<link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
||||||
|
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
<id>https://example.com/feed</id>
|
<id>https://example.com/feed</id>
|
||||||
<icon>https://github.com/favicon.ico</icon>
|
|
||||||
<logo>https://github.com/favicon.ico</logo>
|
|
||||||
<updated>2000-01-01T12:00:00+00:00</updated>
|
<updated>2000-01-01T12:00:00+00:00</updated>
|
||||||
<author>
|
<author>
|
||||||
<name>RSS-Bridge</name>
|
<name>RSS-Bridge</name>
|
||||||
</author>
|
</author>
|
||||||
<link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
|
||||||
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
<entry>
|
<entry>
|
||||||
<title type="html">Sample Item #1</title>
|
<title type="html">Sample Item #1</title>
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
|
|
||||||
<title type="text">Sample microblog feed</title>
|
<title type="text">Sample microblog feed</title>
|
||||||
<id>https://example.com/feed</id>
|
<link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
||||||
|
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
<icon>https://example.com/logo.png</icon>
|
<icon>https://example.com/logo.png</icon>
|
||||||
<logo>https://example.com/logo.png</logo>
|
<logo>https://example.com/logo.png</logo>
|
||||||
|
<id>https://example.com/feed</id>
|
||||||
<updated>2000-01-01T12:00:00+00:00</updated>
|
<updated>2000-01-01T12:00:00+00:00</updated>
|
||||||
<author>
|
<author>
|
||||||
<name>RSS-Bridge</name>
|
<name>RSS-Bridge</name>
|
||||||
</author>
|
</author>
|
||||||
<link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
|
||||||
<link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
<entry>
|
<entry>
|
||||||
<title type="html">Oh 😲 I found three monkeys 🙈🙉🙊</title>
|
<title type="html">Oh 😲 I found three monkeys 🙈🙉🙊</title>
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Sample feed with common data</title>
|
<title>Sample feed with common data</title>
|
||||||
<link>https://example.com/blog/</link>
|
|
||||||
<description>Sample feed with common data</description>
|
<description>Sample feed with common data</description>
|
||||||
|
<link>https://example.com/blog/</link>
|
||||||
|
<atom:link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
||||||
|
<atom:link href="https://example.com/feed?type=common&items=4" rel="self" type="application/atom+xml"/>
|
||||||
<image>
|
<image>
|
||||||
<url>https://example.com/logo.png</url>
|
<url>https://example.com/logo.png</url>
|
||||||
<title>Sample feed with common data</title>
|
<title>Sample feed with common data</title>
|
||||||
<link>https://example.com/blog/</link>
|
<link>https://example.com/blog/</link>
|
||||||
</image>
|
</image>
|
||||||
<atom:link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
|
||||||
<atom:link href="https://example.com/feed?type=common&items=4" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Test Entry</title>
|
<title>Test Entry</title>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Sample feed with minimum data</title>
|
<title>Sample feed with minimum data</title>
|
||||||
<link>https://github.com/RSS-Bridge/rss-bridge/</link>
|
|
||||||
<description>Sample feed with minimum data</description>
|
<description>Sample feed with minimum data</description>
|
||||||
|
<link>https://github.com/RSS-Bridge/rss-bridge/</link>
|
||||||
<atom:link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
<atom:link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
||||||
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
</channel>
|
</channel>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Sample feed with minimum data</title>
|
<title>Sample feed with minimum data</title>
|
||||||
<link>https://github.com/RSS-Bridge/rss-bridge/</link>
|
|
||||||
<description>Sample feed with minimum data</description>
|
<description>Sample feed with minimum data</description>
|
||||||
|
<link>https://github.com/RSS-Bridge/rss-bridge/</link>
|
||||||
<atom:link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
<atom:link href="https://github.com/RSS-Bridge/rss-bridge/" rel="alternate" type="text/html"/>
|
||||||
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Sample microblog feed</title>
|
<title>Sample microblog feed</title>
|
||||||
<link>https://example.com/blog/</link>
|
|
||||||
<description>Sample microblog feed</description>
|
<description>Sample microblog feed</description>
|
||||||
|
<link>https://example.com/blog/</link>
|
||||||
|
<atom:link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
||||||
|
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
||||||
<image>
|
<image>
|
||||||
<url>https://example.com/logo.png</url>
|
<url>https://example.com/logo.png</url>
|
||||||
<title>Sample microblog feed</title>
|
<title>Sample microblog feed</title>
|
||||||
<link>https://example.com/blog/</link>
|
<link>https://example.com/blog/</link>
|
||||||
</image>
|
</image>
|
||||||
<atom:link href="https://example.com/blog/" rel="alternate" type="text/html"/>
|
|
||||||
<atom:link href="https://example.com/feed" rel="self" type="application/atom+xml"/>
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<guid isPermaLink="false">1918f084648b82057c1dd3faa3d091da82a6fac2</guid>
|
<guid isPermaLink="false">1918f084648b82057c1dd3faa3d091da82a6fac2</guid>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "Sample feed with minimum data",
|
"name": "Sample feed with minimum data",
|
||||||
"uri": "",
|
"uri": "https://github.com/RSS-Bridge/rss-bridge/",
|
||||||
"icon": ""
|
"icon": ""
|
||||||
},
|
},
|
||||||
"items": []
|
"items": []
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "Sample feed with minimum data",
|
"name": "Sample feed with minimum data",
|
||||||
"uri": "",
|
"uri": "https://github.com/RSS-Bridge/rss-bridge/",
|
||||||
"icon": ""
|
"icon": ""
|
||||||
},
|
},
|
||||||
"items": [
|
"items": [
|
||||||
|
|
Loading…
Reference in a new issue