From 43f7ac39da4f70b1379bc0d40b408aa353c544b0 Mon Sep 17 00:00:00 2001 From: Dag Date: Sat, 25 Jan 2025 18:26:13 +0100 Subject: [PATCH] feat(FeedParser): recursively parse rss modules Also stop excluding the media module fix #4415 --- lib/FeedParser.php | 12 ++++-- tests/FeedParserTest.php | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/lib/FeedParser.php b/lib/FeedParser.php index 0ad90965b0b..3b133b85307 100644 --- a/lib/FeedParser.php +++ b/lib/FeedParser.php @@ -174,7 +174,7 @@ public function parseRss2Item(\SimpleXMLElement $feedItem): array } foreach ($namespaces as $namespaceName => $namespaceUrl) { - if (in_array($namespaceName, ['', 'content', 'media'])) { + if (in_array($namespaceName, ['', 'content'])) { continue; } $item[$namespaceName] = $this->parseModule($feedItem, $namespaceName, $namespaceUrl); @@ -250,11 +250,17 @@ public function parseRss1Item(\SimpleXMLElement $feedItem): array private function parseModule(\SimpleXMLElement $element, string $namespaceName, string $namespaceUrl): array { + // Unfortunately this parses out only node values as string + // TODO: parse attributes too + $result = []; $module = $element->children($namespaceUrl); foreach ($module as $name => $value) { - // todo: add custom parsing if it's something other than a string - $result[$name] = (string) $value; + if (get_class($value) === 'SimpleXMLElement' && $value->count() !== 0) { + $result[$name] = $this->parseModule($value, $namespaceName, $namespaceUrl); + } else { + $result[$name] = (string) $value; + } } return $result; } diff --git a/tests/FeedParserTest.php b/tests/FeedParserTest.php index 45dc1234b29..458bdb53d65 100644 --- a/tests/FeedParserTest.php +++ b/tests/FeedParserTest.php @@ -183,4 +183,83 @@ public function testAppleItunesModule() ]; $this->assertEquals($expected, $feed); } + + public function testYoutubeMediaModule() + { + $xml = << + + + yt:channel:uCkxoKLYO_EQ2GeFtbM_bw + uCkxoKLYO_EQ2GeFtbM_bw + Half as Interesting + + + Half as Interesting + https://www.youtube.com/channel/UCuCkxoKLYO_EQ2GeFtbM_bw + + 2017-08-26T20:06:05+00:00 + + yt:video:Upjg7F28DJw + Upjg7F28DJw + UCuCkxoKLYO_EQ2GeFtbM_bw + The Nuke-Proof US Military Base in a Mountain + + + Half as Interesting + https://www.youtube.com/channel/UCuCkxoKLYO_EQ2GeFtbM_bw + + 2025-01-24T15:44:18+00:00 + 2025-01-25T06:55:19+00:00 + + The Nuke-Proof US Military Base in a Mountain + + + Receive 10% off anything on bellroy.com: https://bit.ly/3HdOWu9 + + + + + + + + XML; + + $feed = $this->sut->parseFeed($xml); + $expected = [ + 'title' => 'Half as Interesting', + 'uri' => 'https://www.youtube.com/channel/UCuCkxoKLYO_EQ2GeFtbM_bw', + 'icon' => null, + 'items' => [ + [ + 'uri' => 'https://www.youtube.com/watch?v=Upjg7F28DJw', + 'title' => 'The Nuke-Proof US Military Base in a Mountain', + 'content' => '', + 'timestamp' => 1737788119, + 'author' => 'Half as Interesting', + 'id' => 'yt:video:Upjg7F28DJw', + 'published' => '2025-01-24T15:44:18+00:00', + 'updated' => '2025-01-25T06:55:19+00:00', + 'link' => '', + 'yt' => [ + 'videoId' => 'Upjg7F28DJw', + 'channelId' => 'UCuCkxoKLYO_EQ2GeFtbM_bw', + ], + 'media' => [ + 'group' => [ + 'title' => 'The Nuke-Proof US Military Base in a Mountain', + 'content' => '', + 'thumbnail' => '', + 'description' => 'Receive 10% off anything on bellroy.com: https://bit.ly/3HdOWu9', + 'community' => [ + 'starRating' => '', + 'statistics' => '', + ], + ], + ], + ] + ], + ]; + $this->assertEquals($expected, $feed); + } }