diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php index 2a184598..a5703e5e 100644 --- a/actions/DisplayAction.php +++ b/actions/DisplayAction.php @@ -93,7 +93,6 @@ class DisplayAction implements ActionInterface private function createResponse(Request $request, BridgeAbstract $bridge, string $format) { $items = []; - $feed = []; try { $bridge->loadConfiguration(); @@ -113,14 +112,6 @@ class DisplayAction implements ActionInterface $bridge->setInput($input); $bridge->collectData(); $items = $bridge->getItems(); - if (isset($items[0]) && is_array($items[0])) { - $feedItems = []; - foreach ($items as $item) { - $feedItems[] = FeedItem::fromArray($item); - } - $items = $feedItems; - } - $feed = $bridge->getFeed(); } catch (\Throwable $e) { if ($e instanceof RateLimitException) { // These are internally generated by bridges @@ -162,7 +153,7 @@ class DisplayAction implements ActionInterface $format = $formatFactory->create($format); $format->setItems($items); - $format->setFeed($feed); + $format->setFeed($bridge->getFeed()); $now = time(); $format->setLastModified($now); $headers = [ @@ -172,19 +163,20 @@ class DisplayAction implements ActionInterface return new Response($format->stringify(), 200, $headers); } - private function createFeedItemFromException($e, BridgeAbstract $bridge): FeedItem + private function createFeedItemFromException($e, BridgeAbstract $bridge): array { - $item = new FeedItem(); + $item = []; // Create a unique identifier every 24 hours $uniqueIdentifier = urlencode((int)(time() / 86400)); $title = sprintf('Bridge returned error %s! (%s)', $e->getCode(), $uniqueIdentifier); - $item->setTitle($title); - $item->setURI(get_current_url()); - $item->setTimestamp(time()); + + $item['title'] = $title; + $item['uri'] = get_current_url(); + $item['timestamp'] = time(); // Create an item identifier for feed readers e.g. "staysafetv twitch videos_19389" - $item->setUid($bridge->getName() . '_' . $uniqueIdentifier); + $item['uid'] = $bridge->getName() . '_' . $uniqueIdentifier; $content = render_template(__DIR__ . '/../templates/bridge-error.html.php', [ 'error' => render_template(__DIR__ . '/../templates/exception.html.php', ['e' => $e]), @@ -192,7 +184,8 @@ class DisplayAction implements ActionInterface 'issueUrl' => self::createGithubIssueUrl($bridge, $e, create_sane_exception_message($e)), 'maintainer' => $bridge->getMaintainer(), ]); - $item->setContent($content); + $item['content'] = $content; + return $item; } diff --git a/bridges/GULPProjekteBridge.php b/bridges/GULPProjekteBridge.php index e0bb8cbe..05689bc9 100644 --- a/bridges/GULPProjekteBridge.php +++ b/bridges/GULPProjekteBridge.php @@ -129,24 +129,24 @@ class GULPProjekteBridge extends WebDriverAbstract while (true) { $items = $this->getDriver()->findElements(WebDriverBy::tagName('app-project-view')); foreach ($items as $item) { - $feedItem = new FeedItem(); + $feedItem = []; $heading = $item->findElement(WebDriverBy::xpath('.//app-heading-tag/h1/a')); - $feedItem->setTitle($heading->getText()); - $feedItem->setURI('https://www.gulp.de' . $heading->getAttribute('href')); + $feedItem['title'] = $heading->getText(); + $feedItem['uri'] = 'https://www.gulp.de' . $heading->getAttribute('href'); $info = $item->findElement(WebDriverBy::tagName('app-icon-info-list')); if ($logo = $this->getLogo($item)) { - $feedItem->setEnclosures([$logo]); + $feedItem['enclosures'] = [$logo]; } if (str_contains($info->getText(), 'Projektanbieter:')) { - $feedItem->setAuthor($info->findElement(WebDriverBy::xpath('.//li/span[2]/span'))->getText()); + $feedItem['author'] = $info->findElement(WebDriverBy::xpath('.//li/span[2]/span'))->getText(); } else { // mostly "Direkt vom Auftraggeber" or "GULP Agentur" - $feedItem->setAuthor($item->findElement(WebDriverBy::tagName('b'))->getText()); + $feedItem['author'] = $item->findElement(WebDriverBy::tagName('b'))->getText(); } - $feedItem->setContent($item->findElement(WebDriverBy::xpath('.//p[@class="description"]'))->getText()); + $feedItem['content'] = $item->findElement(WebDriverBy::xpath('.//p[@class="description"]'))->getText(); $timeAgo = $item->findElement(WebDriverBy::xpath('.//small[contains(@class, "time-ago")]'))->getText(); - $feedItem->setTimestamp($this->getTimestamp($timeAgo)); + $feedItem['timestamp'] = $this->getTimestamp($timeAgo); $this->items[] = $feedItem; } diff --git a/bridges/NintendoBridge.php b/bridges/NintendoBridge.php index 1c4ecf2b..2f6113b2 100644 --- a/bridges/NintendoBridge.php +++ b/bridges/NintendoBridge.php @@ -477,7 +477,7 @@ class NintendoBridge extends XPathAbstract return $date->getTimestamp(); } - protected function generateItemId(FeedItem $item) + protected function generateItemId(array $item) { return $this->getCurrentCategory() . '-' . $this->lastId; } diff --git a/bridges/RutubeBridge.php b/bridges/RutubeBridge.php index 39577575..f8e106c8 100644 --- a/bridges/RutubeBridge.php +++ b/bridges/RutubeBridge.php @@ -107,10 +107,10 @@ class RutubeBridge extends BridgeAbstract } foreach ($videos as $video) { - $item = new FeedItem(); - $item->setTitle($video->title); - $item->setURI($video->video_url); - $content = ''; + $item = []; + $item['title'] = $video->title; + $item['uri'] = $video->video_url; + $content = ''; $content .= ''; $content .= '
'; $content .= nl2br( @@ -122,9 +122,10 @@ class RutubeBridge extends BridgeAbstract $video->description . ' ' ) ); - $item->setTimestamp($video->created_ts); - $item->setAuthor($video->author->name); - $item->setContent($content); + $item['timestamp'] = $video->created_ts; + $item['author'] = $video->author->name; + $item['content'] = $content; + $this->items[] = $item; } } diff --git a/bridges/ScalableCapitalBlogBridge.php b/bridges/ScalableCapitalBlogBridge.php index 6f95efb3..d95431c6 100644 --- a/bridges/ScalableCapitalBlogBridge.php +++ b/bridges/ScalableCapitalBlogBridge.php @@ -41,16 +41,20 @@ class ScalableCapitalBlogBridge extends WebDriverAbstract $items = $this->getDriver()->findElements(WebDriverBy::xpath('//div[contains(@class, "articles")]//div[@class="items"]//div[contains(@class, "item")]')); foreach ($items as $item) { - $feedItem = new FeedItem(); + $feedItem = []; + + $feedItem['enclosures'] = ['https://de.scalable.capital' . $item->findElement(WebDriverBy::tagName('img'))->getAttribute('src')]; - $feedItem->setEnclosures(['https://de.scalable.capital' . $item->findElement(WebDriverBy::tagName('img'))->getAttribute('src')]); $heading = $item->findElement(WebDriverBy::tagName('a')); - $feedItem->setTitle($heading->getText()); - $feedItem->setURI('https://de.scalable.capital' . $heading->getAttribute('href')); - $feedItem->setContent($item->findElement(WebDriverBy::xpath('.//div[@class="summary"]'))->getText()); + $feedItem['title'] = $heading->getText(); + + $feedItem['uri'] = 'https://de.scalable.capital' . $heading->getAttribute('href'); + $feedItem['content'] = $item->findElement(WebDriverBy::xpath('.//div[@class="summary"]'))->getText(); + $date = $item->findElement(WebDriverBy::xpath('.//div[@class="published-date"]'))->getText(); - $feedItem->setTimestamp($this->formatItemTimestamp($date)); - $feedItem->setAuthor($item->findElement(WebDriverBy::xpath('.//div[@class="author"]'))->getText()); + $feedItem['timestamp'] = $this->formatItemTimestamp($date); + + $feedItem['author'] = $item->findElement(WebDriverBy::xpath('.//div[@class="author"]'))->getText(); $this->items[] = $feedItem; } diff --git a/bridges/Vk2Bridge.php b/bridges/Vk2Bridge.php index 62ba8e05..f52850ce 100644 --- a/bridges/Vk2Bridge.php +++ b/bridges/Vk2Bridge.php @@ -255,7 +255,7 @@ class Vk2Bridge extends BridgeAbstract if (!$ownerId) { $ownerId = $post['owner_id']; } - $item = new FeedItem(); + $item = []; $content = $this->generateContentFromPost($post); if (isset($post['copy_history'])) { if ($this->getInput('hide_reposts')) { @@ -277,11 +277,11 @@ class Vk2Bridge extends BridgeAbstract $content .= '):

'; $content .= $this->generateContentFromPost($originalPost); } - $item->setContent($content); - $item->setTimestamp($post['date']); - $item->setAuthor($this->ownerNames[$post['from_id']]); - $item->setTitle($this->getTitle(strip_tags($content))); - $item->setURI($this->getPostURI($post)); + $item['content'] = $content; + $item['timestamp'] = $post['date']; + $item['author'] = $this->ownerNames[$post['from_id']]; + $item['title'] = $this->getTitle(strip_tags($content)); + $item['uri'] = $this->getPostURI($post); $this->items[] = $item; } diff --git a/lib/FeedItem.php b/lib/FeedItem.php index 8a092a27..bca06c23 100644 --- a/lib/FeedItem.php +++ b/lib/FeedItem.php @@ -12,10 +12,6 @@ class FeedItem protected ?string $uid = null; protected array $misc = []; - public function __construct() - { - } - public static function fromArray(array $itemArray): self { $item = new self(); @@ -25,6 +21,10 @@ class FeedItem return $item; } + private function __construct() + { + } + public function __set($name, $value) { switch ($name) { @@ -89,18 +89,6 @@ class FeedItem return $this->uri; } - /** - * Set URI to the full article. - * - * Use {@see FeedItem::getURI()} to get the URI. - * - * _Note_: Removes whitespace from the beginning and end of the URI. - * - * _Remarks_: Uses the attribute "href" or "src" if the provided URI is an - * object of simple_html_dom_node. - * - * @param simple_html_dom_node|object|string $uri URI to the full article. - */ public function setURI($uri) { $this->uri = null; // Clear previous data diff --git a/lib/FormatAbstract.php b/lib/FormatAbstract.php index 28eb4bbf..9cba0d8c 100644 --- a/lib/FormatAbstract.php +++ b/lib/FormatAbstract.php @@ -6,11 +6,11 @@ abstract class FormatAbstract const MIME_TYPE = 'text/plain'; - protected string $charset = 'UTF-8'; - protected array $items = []; - protected int $lastModified; - protected array $feed = []; + protected array $items = []; + protected string $charset = 'UTF-8'; + + protected int $lastModified; abstract public function stringify(); @@ -30,12 +30,11 @@ abstract class FormatAbstract return $this->feed; } - /** - * @param FeedItem[] $items - */ public function setItems(array $items): void { - $this->items = $items; + foreach ($items as $item) { + $this->items[] = FeedItem::fromArray($item); + } } /** diff --git a/lib/XPathAbstract.php b/lib/XPathAbstract.php index 6163ca13..44cbab67 100644 --- a/lib/XPathAbstract.php +++ b/lib/XPathAbstract.php @@ -422,9 +422,18 @@ abstract class XPathAbstract extends BridgeAbstract } foreach ($entries as $entry) { - $item = new FeedItem(); - foreach (['title', 'content', 'uri', 'author', 'timestamp', 'enclosures', 'categories'] as $param) { - $expression = $this->getParam($param); + $item = []; + $parameters = [ + 'title', + 'content', + 'uri', + 'author', + 'timestamp', + 'enclosures', + 'categories', + ]; + foreach ($parameters as $parameter) { + $expression = $this->getParam($parameter); if ('' === $expression) { continue; } @@ -438,21 +447,21 @@ abstract class XPathAbstract extends BridgeAbstract continue; } - if ('categories' === $param && $typedResult instanceof \DOMNodeList) { + if ('categories' === $parameter && $typedResult instanceof \DOMNodeList) { $value = []; foreach ($typedResult as $domNode) { $value[] = $this->getItemValueOrNodeValue($domNode, false); } } else { - $value = $this->getItemValueOrNodeValue($typedResult, 'content' === $param); + $value = $this->getItemValueOrNodeValue($typedResult, 'content' === $parameter); } - $item->__set($param, $this->formatParamValue($param, $value)); + $item[$parameter] = $this->formatParamValue($parameter, $value); } $itemId = $this->generateItemId($item); if (null !== $itemId) { - $item->setUid($itemId); + $item['uid'] = $itemId; } $this->items[] = $item; @@ -646,10 +655,9 @@ abstract class XPathAbstract extends BridgeAbstract /** * Allows overriding default mechanism determining items Uid's * - * @param FeedItem $item * @return string|null */ - protected function generateItemId(FeedItem $item) + protected function generateItemId(array $item) { return null; } diff --git a/tests/FeedItemTest.php b/tests/FeedItemTest.php index 3390e7b3..fbc7a4ea 100644 --- a/tests/FeedItemTest.php +++ b/tests/FeedItemTest.php @@ -4,45 +4,16 @@ declare(strict_types=1); namespace RssBridge\Tests; -use FeedItem; use PHPUnit\Framework\TestCase; class FeedItemTest extends TestCase { public function test() { - $item = new FeedItem(); - $item->setTitle('hello'); - $this->assertSame('hello', $item->getTitle()); - - $item = FeedItem::fromArray(['title' => 'hello2']); - $this->assertSame('hello2', $item->getTitle()); - - $item = new FeedItem(); - $item->setAuthor('123'); - $this->assertSame('123', $item->getAuthor()); - - $item = new FeedItem(); - $item->title = 'aa'; - $this->assertSame('aa', $item->title); - $this->assertSame('aa', $item->getTitle()); - } - - public function testTimestamp() - { - $item = new FeedItem(); - $item->setTimestamp(5); - $this->assertSame(5, $item->getTimestamp()); - - $item->setTimestamp('5'); - $this->assertSame(5, $item->getTimestamp()); - - $item->setTimestamp('1970-01-01 18:00:00'); - $this->assertSame(64800, $item->getTimestamp()); - - $item->setTimestamp('1st jan last year'); - - // This will fail at 2025-01-01 hehe - $this->assertSame(1672531200, $item->getTimestamp()); + $item = [ + 'title' => 'kek', + ]; + $feedItem = \FeedItem::fromArray($item); + $this->assertSame('kek', $feedItem->getTitle()); } } diff --git a/tests/Formats/BaseFormatTest.php b/tests/Formats/BaseFormatTest.php index 8999e772..0907b72a 100644 --- a/tests/Formats/BaseFormatTest.php +++ b/tests/Formats/BaseFormatTest.php @@ -39,7 +39,7 @@ abstract class BaseFormatTest extends TestCase $items = []; foreach ($data['items'] as $item) { - $items[] = \FeedItem::fromArray($item); + $items[] = ($item); } return (object)[