Fixes #7009 -- Add no-op writer to RSS feed to register Podcast namespace for PSP-1 compliance.
This commit is contained in:
parent
b144860d63
commit
c33fd9f30c
|
@ -13,6 +13,7 @@ use App\Entity\PodcastEpisode;
|
||||||
use App\Exception\NotFoundException;
|
use App\Exception\NotFoundException;
|
||||||
use App\Http\Response;
|
use App\Http\Response;
|
||||||
use App\Http\ServerRequest;
|
use App\Http\ServerRequest;
|
||||||
|
use App\Rss\PodcastNamespaceWriter;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use MarcW\RssWriter\Extension\Atom\AtomLink;
|
use MarcW\RssWriter\Extension\Atom\AtomLink;
|
||||||
use MarcW\RssWriter\Extension\Atom\AtomWriter;
|
use MarcW\RssWriter\Extension\Atom\AtomWriter;
|
||||||
|
@ -54,14 +55,6 @@ final class PodcastFeedAction implements SingleActionInterface
|
||||||
|
|
||||||
$podcast = $request->getPodcast();
|
$podcast = $request->getPodcast();
|
||||||
|
|
||||||
// Create RSS Writer
|
|
||||||
$rssWriter = new RssWriter(null, [], true);
|
|
||||||
$rssWriter->registerWriter(new CoreWriter());
|
|
||||||
$rssWriter->registerWriter(new ItunesWriter());
|
|
||||||
$rssWriter->registerWriter(new SyWriter());
|
|
||||||
$rssWriter->registerWriter(new SlashWriter());
|
|
||||||
$rssWriter->registerWriter(new AtomWriter());
|
|
||||||
|
|
||||||
$channel = new RssChannel();
|
$channel = new RssChannel();
|
||||||
$channel->setTtl(5);
|
$channel->setTtl(5);
|
||||||
$channel->setLastBuildDate(new DateTime());
|
$channel->setLastBuildDate(new DateTime());
|
||||||
|
@ -98,8 +91,6 @@ final class PodcastFeedAction implements SingleActionInterface
|
||||||
$channel->setImage($rssImage);
|
$channel->setImage($rssImage);
|
||||||
|
|
||||||
// Iterate through episodes.
|
// Iterate through episodes.
|
||||||
$rssItems = [];
|
|
||||||
|
|
||||||
$hasPublishedEpisode = false;
|
$hasPublishedEpisode = false;
|
||||||
$hasExplicitEpisode = false;
|
$hasExplicitEpisode = false;
|
||||||
|
|
||||||
|
@ -114,42 +105,13 @@ final class PodcastFeedAction implements SingleActionInterface
|
||||||
$hasExplicitEpisode = true;
|
$hasExplicitEpisode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$episodeApi = $this->episodeApiGenerator->__invoke($episode, $request);
|
$channel->addItem($this->buildItemForEpisode($episode, $request));
|
||||||
|
|
||||||
$rssItem = new RssItem();
|
|
||||||
|
|
||||||
$rssItem->setGuid((new RssGuid())->setGuid($episodeApi->id));
|
|
||||||
$rssItem->setTitle($episodeApi->title);
|
|
||||||
$rssItem->setDescription($episodeApi->description);
|
|
||||||
$rssItem->setLink($episodeApi->link ?? $episodeApi->links['self']);
|
|
||||||
|
|
||||||
$rssItem->setPubDate((new DateTime())->setTimestamp($episode->getPublishAt()));
|
|
||||||
|
|
||||||
$rssEnclosure = new RssEnclosure();
|
|
||||||
$rssEnclosure->setUrl($episodeApi->links['download']);
|
|
||||||
|
|
||||||
$podcastMedia = $episode->getMedia();
|
|
||||||
if (null !== $podcastMedia) {
|
|
||||||
$rssEnclosure->setType($podcastMedia->getMimeType());
|
|
||||||
$rssEnclosure->setLength($podcastMedia->getLength());
|
|
||||||
}
|
|
||||||
$rssItem->setEnclosure($rssEnclosure);
|
|
||||||
|
|
||||||
$rssItem->addExtension(
|
|
||||||
(new ItunesItem())
|
|
||||||
->setExplicit($episode->getExplicit())
|
|
||||||
->setImage($episodeApi->art)
|
|
||||||
);
|
|
||||||
|
|
||||||
$rssItems[] = $rssItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$hasPublishedEpisode) {
|
if (!$hasPublishedEpisode) {
|
||||||
throw NotFoundException::podcast();
|
throw NotFoundException::podcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel->setItems($rssItems);
|
|
||||||
|
|
||||||
$itunesChannel = new ItunesChannel();
|
$itunesChannel = new ItunesChannel();
|
||||||
$itunesChannel->setExplicit($hasExplicitEpisode);
|
$itunesChannel->setExplicit($hasExplicitEpisode);
|
||||||
$itunesChannel->setImage($rssImage->getUrl());
|
$itunesChannel->setImage($rssImage->getUrl());
|
||||||
|
@ -179,6 +141,15 @@ final class PodcastFeedAction implements SingleActionInterface
|
||||||
->setType('application/rss+xml')
|
->setType('application/rss+xml')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$rssWriter = new RssWriter(null, [
|
||||||
|
new CoreWriter(),
|
||||||
|
new ItunesWriter(),
|
||||||
|
new SyWriter(),
|
||||||
|
new SlashWriter(),
|
||||||
|
new AtomWriter(),
|
||||||
|
new PodcastNamespaceWriter(),
|
||||||
|
], true);
|
||||||
|
|
||||||
$response->getBody()->write(
|
$response->getBody()->write(
|
||||||
$rssWriter->writeChannel($channel)
|
$rssWriter->writeChannel($channel)
|
||||||
);
|
);
|
||||||
|
@ -188,6 +159,38 @@ final class PodcastFeedAction implements SingleActionInterface
|
||||||
->withHeader('X-Robots-Tag', 'index, nofollow');
|
->withHeader('X-Robots-Tag', 'index, nofollow');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildItemForEpisode(PodcastEpisode $episode, ServerRequest $request): RssItem
|
||||||
|
{
|
||||||
|
$episodeApi = $this->episodeApiGenerator->__invoke($episode, $request);
|
||||||
|
|
||||||
|
$rssItem = new RssItem();
|
||||||
|
|
||||||
|
$rssItem->setGuid((new RssGuid())->setGuid($episodeApi->id));
|
||||||
|
$rssItem->setTitle($episodeApi->title);
|
||||||
|
$rssItem->setDescription($episodeApi->description);
|
||||||
|
$rssItem->setLink($episodeApi->link ?? $episodeApi->links['self']);
|
||||||
|
|
||||||
|
$rssItem->setPubDate((new DateTime())->setTimestamp($episode->getPublishAt()));
|
||||||
|
|
||||||
|
$rssEnclosure = new RssEnclosure();
|
||||||
|
$rssEnclosure->setUrl($episodeApi->links['download']);
|
||||||
|
|
||||||
|
$podcastMedia = $episode->getMedia();
|
||||||
|
if (null !== $podcastMedia) {
|
||||||
|
$rssEnclosure->setType($podcastMedia->getMimeType());
|
||||||
|
$rssEnclosure->setLength($podcastMedia->getLength());
|
||||||
|
}
|
||||||
|
$rssItem->setEnclosure($rssEnclosure);
|
||||||
|
|
||||||
|
$rssItem->addExtension(
|
||||||
|
(new ItunesItem())
|
||||||
|
->setExplicit($episode->getExplicit())
|
||||||
|
->setImage($episodeApi->art)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $rssItem;
|
||||||
|
}
|
||||||
|
|
||||||
private function buildItunesOwner(Podcast $podcast): ?ItunesOwner
|
private function buildItunesOwner(Podcast $podcast): ?ItunesOwner
|
||||||
{
|
{
|
||||||
if (empty($podcast->getAuthor()) && empty($podcast->getEmail())) {
|
if (empty($podcast->getAuthor()) && empty($podcast->getEmail())) {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Rss;
|
||||||
|
|
||||||
|
use MarcW\RssWriter\WriterRegistererInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placeholder class to write the Podcast namespace for PSP-1 compliance.
|
||||||
|
*/
|
||||||
|
class PodcastNamespaceWriter implements WriterRegistererInterface
|
||||||
|
{
|
||||||
|
public function getRegisteredWriters(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRegisteredNamespaces(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'podcast' => 'https://podcastindex.org/namespace/1.0',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue