repod/lib/Core/EpisodeAction/EpisodeActionReader.php

145 lines
4.0 KiB
PHP
Raw Normal View History

2023-08-24 10:48:10 +00:00
<?php
declare(strict_types=1);
namespace OCA\RePod\Core\EpisodeAction;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeActionReader as CoreEpisodeActionReader;
2023-08-29 10:04:14 +00:00
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\RePod\Service\UserService;
class EpisodeActionReader extends CoreEpisodeActionReader
2023-08-24 10:48:10 +00:00
{
2023-08-29 10:04:14 +00:00
public function __construct(
private EpisodeActionRepository $episodeActionRepository,
private UserService $userService
2023-12-23 16:25:20 +00:00
) {}
2023-08-29 10:04:14 +00:00
2023-08-24 10:48:10 +00:00
/**
* Base: https://github.com/pbek/nextcloud-nextpod/blob/main/lib/Core/EpisodeAction/EpisodeActionExtraData.php#L119.
* Specs : https://github.com/Podcast-Standards-Project/PSP-1-Podcast-RSS-Specification/blob/main/README.md.
2023-08-24 10:48:10 +00:00
*
2023-12-24 16:05:35 +00:00
* @return EpisodeActionExtraData[]
2024-01-07 10:07:48 +00:00
* @throws \Exception if the XML data could not be parsed
2023-08-24 10:48:10 +00:00
*/
2023-12-23 16:25:20 +00:00
public function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null): array {
2023-08-24 10:48:10 +00:00
$episodes = [];
$xml = new \SimpleXMLElement($xmlString);
$channel = $xml->channel;
$title = (string) $channel->title;
2023-08-24 10:48:10 +00:00
// Find episode by url and add data for it
/** @var \SimpleXMLElement $item */
foreach ($channel->item as $item) {
$url = (string) $item->enclosure['url'];
$type = (string) $item->enclosure['type'];
$size = (int) $item->enclosure['length'];
$guid = (string) $item->guid;
$iTunesItemChildren = $item->children('itunes', true);
$iTunesChannelChildren = $channel->children('itunes', true);
2023-08-24 17:03:11 +00:00
2023-08-29 10:04:14 +00:00
// Get episode action
$action = $this->episodeActionRepository->findByGuid($guid, $this->userService->getUserUID());
2023-12-23 20:51:48 +00:00
if ($action) {
$url = $action->getEpisode();
2023-12-23 20:51:48 +00:00
} else {
$action = $this->episodeActionRepository->findByEpisodeUrl($url, $this->userService->getUserUID());
2023-12-23 20:51:48 +00:00
}
2023-08-29 10:04:14 +00:00
2023-08-24 10:48:10 +00:00
// Get episode name
$name = (string) $item->title;
2023-08-24 10:48:10 +00:00
// Get episode link
$link = $this->stringOrNull($item->link);
2023-08-24 10:48:10 +00:00
// Get episode image
$image = $this->stringOrNull($item->image->url);
2023-08-29 10:04:14 +00:00
2024-01-18 16:42:20 +00:00
if (!isset($image) && isset($iTunesItemChildren)) {
2024-01-11 22:54:21 +00:00
$imageAttributes = $iTunesItemChildren->image->attributes();
2024-01-18 16:42:20 +00:00
$image = $this->stringOrNull(isset($imageAttributes) ? (string) $imageAttributes->href : '');
}
2023-08-24 17:03:11 +00:00
2024-01-18 16:42:20 +00:00
if (!isset($image)) {
$image = $this->stringOrNull($channel->image->url);
}
2023-08-24 10:48:10 +00:00
2024-01-18 16:42:20 +00:00
if (!isset($image) && isset($iTunesChannelChildren)) {
2024-01-11 22:54:21 +00:00
$imageAttributes = $iTunesChannelChildren->image->attributes();
2024-01-18 16:42:20 +00:00
$image = $this->stringOrNull(isset($imageAttributes) ? (string) $imageAttributes->href : '');
}
2023-08-24 10:48:10 +00:00
2024-01-18 16:42:20 +00:00
if (!isset($image)) {
preg_match('/<itunes:image\s+href="([^"]+)"/', $xmlString, $matches);
if (count($matches) > 1) {
$image = $this->stringOrNull($matches[1]);
}
2023-08-24 10:48:10 +00:00
}
// Get episode description
$itemContent = $item->children('content', true);
2024-01-18 16:42:20 +00:00
if (isset($itemContent)) {
$description = $this->stringOrNull($itemContent->encoded);
} else {
$description = $this->stringOrNull($item->description);
2023-08-24 10:48:10 +00:00
}
2024-01-18 16:42:20 +00:00
if (!isset($description) && isset($iTunesItemChildren)) {
$description = $this->stringOrNull($iTunesItemChildren->summary);
}
2023-08-24 10:48:10 +00:00
// Remove tags
$description = strip_tags(str_replace(['<br>', '<br/>', '<br />'], "\n", $description ?? ''));
// Get episode duration
2024-01-18 16:42:20 +00:00
if (isset($iTunesItemChildren)) {
2024-01-16 18:46:02 +00:00
$duration = $this->stringOrNull($iTunesItemChildren->duration);
} else {
2024-01-16 18:46:02 +00:00
$duration = $this->stringOrNull($item->duration);
}
// Get episode pubDate
$pubDate = $this->stringOrNull($item->pubDate);
if (isset($pubDate)) {
try {
$pubDate = new \DateTime($pubDate);
} catch (\Exception $e) {
$pubDate = null;
}
}
2023-08-24 10:48:10 +00:00
$episodes[] = new EpisodeActionExtraData(
$title,
$url,
$name,
$link,
$image,
$description,
2023-08-24 10:48:10 +00:00
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
$guid,
$type,
$size,
$pubDate,
$duration,
$action
2023-08-24 10:48:10 +00:00
);
}
return $episodes;
}
/**
* @param null|\SimpleXMLElement|string $value
*/
private function stringOrNull($value): ?string {
2024-01-18 16:42:20 +00:00
/** @psalm-suppress RiskyTruthyFalsyComparison */
if (!empty($value)) {
return (string) $value;
}
return null;
}
2023-08-24 10:48:10 +00:00
}