repod/lib/Core/EpisodeAction/EpisodeActionReader.php
Michel Roux 48cc054db5
All checks were successful
repod / xml (push) Successful in 13m58s
repod / php (push) Successful in 14m11s
repod / nodejs (push) Successful in 7m7s
Update deps
2024-01-07 11:07:48 +01:00

144 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace OCA\RePod\Core\EpisodeAction;
use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
use OCA\GPodderSync\Db\EpisodeAction\EpisodeActionRepository;
use OCA\RePod\Service\UserService;
class EpisodeActionReader
{
public function __construct(
private EpisodeActionRepository $episodeActionRepository,
private UserService $userService
) {}
public function findByEpisodeUrl(string $episodeUrl): ?EpisodeAction {
return $this->episodeActionRepository->findByEpisodeUrl($episodeUrl, $this->userService->getUserUID());
}
/**
* https://github.com/pbek/nextcloud-nextpod/blob/main/lib/Core/EpisodeAction/EpisodeActionExtraData.php#L119.
*
* @return EpisodeActionExtraData[]
* @throws \Exception if the XML data could not be parsed
*/
public function parseRssXml(string $xmlString, ?int $fetchedAtUnix = null): array {
$episodes = [];
$xml = new \SimpleXMLElement($xmlString);
$channel = $xml->channel;
// Find episode by url and add data for it
/** @var \SimpleXMLElement $item */
foreach ($channel->item as $item) {
$episodeUrl = (string) $item->enclosure['url'];
// Get episode guid
$episodeGuid = (string) $item->guid;
// Get episode filesize
$episodeFilesize = (int) $item->enclosure['length'];
// Get episode action
$episodeAction = $this->episodeActionRepository->findByGuid($episodeGuid, $this->userService->getUserUID());
if ($episodeAction) {
$episodeUrl = $episodeAction->getEpisode();
} else {
$episodeAction = $this->episodeActionRepository->findByEpisodeUrl($episodeUrl, $this->userService->getUserUID());
}
// Get episode name
$episodeName = $this->stringOrNull($item->title);
// Get episode link
$episodeLink = $this->stringOrNull($item->link);
// Get episode image
$episodeImage = $this->stringOrNull($channel->image->url);
$episodeChildren = $item->children('http://www.itunes.com/dtds/podcast-1.0.dtd');
if ($episodeChildren) {
$episodeImageAttributes = (array) $episodeChildren->image->attributes();
$episodeImage = $this->stringOrNull(array_key_exists('href', $episodeImageAttributes) ? (string) $episodeImageAttributes['href'] : '');
$iTunesChildren = $item->children('itunes', true);
// Get episode duration
if ($iTunesChildren) {
$rawDuration = $this->stringOrNull((string) $iTunesChildren->duration);
$splitDuration = array_reverse(explode(':', $rawDuration ?? ''));
$episodeDuration = (int) $splitDuration[0];
$episodeDuration += !empty($splitDuration[1]) ? (int) $splitDuration[1] * 60 : 0;
$episodeDuration += !empty($splitDuration[2]) ? (int) $splitDuration[2] * 60 : 0;
}
if ($iTunesChildren && !$episodeImage) {
$episodeImage = $this->stringOrNull((string) $iTunesChildren->image['href']);
}
if ($iTunesChildren && !$episodeImage) {
$episodeImage = $this->stringOrNull((string) $iTunesChildren->image['href']);
}
if (!$episodeImage) {
$channelChildren = $channel->children('http://www.itunes.com/dtds/podcast-1.0.dtd');
if ($channelChildren) {
$episodeImageAttributes = (array) $channelChildren->image->attributes();
$episodeImage = $this->stringOrNull(array_key_exists('href', $episodeImageAttributes) ? (string) $episodeImageAttributes['href'] : '');
}
}
if (!$episodeImage) {
preg_match('/<itunes:image\s+href="([^"]+)"/', $xmlString, $matches);
$episodeImage = $this->stringOrNull($matches[1]);
}
}
// Get episode description
$episodeDescription = $this->stringOrNull($item->description);
$episodeContentChildren = $item->children('content', true);
if ($episodeContentChildren) {
$episodeDescription = $this->stringOrNull($episodeContentChildren->encoded);
}
// Remove tags
$episodeDescription = strip_tags($episodeDescription ?? '');
// Get episode pubDate
$rawPubDate = $this->stringOrNull($item->pubDate);
$episodePubDate = $rawPubDate ? new \DateTime($rawPubDate) : null;
$episodes[] = new EpisodeActionExtraData(
$episodeUrl,
$this->stringOrNull($channel->title),
$episodeName,
$episodeLink,
$episodeImage,
$episodeDescription,
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
$episodeGuid,
$episodePubDate,
$episodeFilesize,
$episodeDuration ?? null,
$episodeAction
);
}
return $episodes;
}
/**
* @param null|\SimpleXMLElement|string $value
*/
private function stringOrNull($value): ?string {
if ($value) {
return (string) $value;
}
return null;
}
}