diff --git a/src/Controllers/FeedController.php b/src/Controllers/FeedController.php index b711aab..553816a 100644 --- a/src/Controllers/FeedController.php +++ b/src/Controllers/FeedController.php @@ -26,6 +26,22 @@ class FeedController return $this->view->render($response, 'index.twig.html', ['feeds' => $feeds]); } + public function get_feed(ServerRequestInterface $request, ResponseInterface $response) + { + $this->logger->info("FeedController::get_feed() called"); + $feed = $this->feedRepository->find($request->getAttribute('id')); + $filtered = $feed->get_filtered_feed(); + + $body = $response->getBody(); + $body->write($filtered->asXML()); + + $this->feedRepository->save($feed); + + return $response->withHeader('Content-Type', 'application/rss+xml') + ->withBody($body) + ->withStatus(200); + } + public function create(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { $this->logger->info("FeedController::create() called"); diff --git a/src/Models/Data/Feed.php b/src/Models/Data/Feed.php index 11c5e72..bdc1a3f 100644 --- a/src/Models/Data/Feed.php +++ b/src/Models/Data/Feed.php @@ -45,10 +45,15 @@ class Feed #[ORM\Column(type: XMLElement::NAME, nullable: true)] public SimpleXMLElement|null $filteredFeed; + #[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, nullable: true)] + public \DateTimeInterface|null $lastFetched; + public function fetch(): void { if (Robots::allowed($this->url)) { $this->remoteFeed = simplexml_load_file($this->url); + $this->filter(); + $this->lastFetched = new \DateTimeImmutable(); } else { throw new \Exception("Robots.txt disallows fetching this feed"); } @@ -65,10 +70,6 @@ class Feed public function filter() : void { - if ($this->remoteFeed === null) { - $this->fetch(); - } - $dom = dom_import_simplexml($this->remoteFeed); $doc = $dom->ownerDocument; @@ -78,11 +79,27 @@ class Feed $xpath_query = '//item[' . $filter_queries . ']'; $to_remove = $xpath->query($xpath_query); - echo "Removing " . $to_remove->length . " items\n"; + foreach ($to_remove as $item) { $item->parentNode->removeChild($item); } + $title = $xpath->query('//channel/title'); + $title->item(0)->nodeValue = $this->title; + $this->filteredFeed = simplexml_import_dom($dom); } + + public function get_filtered_feed(): SimpleXMLElement + { + if (!$this->lastFetched || $this->lastFetched < new \DateTimeImmutable('-1 hour')) { + $this->fetch(); + } + + if ($this->filteredFeed === null) { + $this->filter(); + } + + return $this->filteredFeed; + } } \ No newline at end of file diff --git a/src/Models/Repositories/FeedRepository.php b/src/Models/Repositories/FeedRepository.php index 77cb529..6fb0f14 100644 --- a/src/Models/Repositories/FeedRepository.php +++ b/src/Models/Repositories/FeedRepository.php @@ -15,4 +15,10 @@ class FeedRepository extends EntityRepository { parent::__construct($em, $em->getClassMetadata(Feed::class)); } + + public function save(Feed $feed): void + { + $this->_em->persist($feed); + $this->_em->flush(); + } } \ No newline at end of file diff --git a/src/Tools/Console/TestFeed.php b/src/Tools/Console/TestFeed.php index 717882f..fdb0c1f 100644 --- a/src/Tools/Console/TestFeed.php +++ b/src/Tools/Console/TestFeed.php @@ -44,36 +44,19 @@ class TestFeed extends Command $url = $input->getArgument("url"); $title = $input->getArgument("title"); -// $output->writeln("Setting up a new feed for: $url"); -// -// $feed = new Feed(); -// $feed->url = $url; -// $feed->title = $title; -// $feed->fetch(); -// $feed->feedFilters = new ArrayCollection(); -// $feed->feedFilters->add( new FeedFilter(FilterTarget::TITLE, FilterType::INCLUDE, "[No Ads]", $feed)); -// -// $this->em->persist($feed); -// $this->em->flush(); -// -// $cnt = $this->feedRepository->count([]); -// $output->writeln("Feed count: $cnt"); + $output->writeln("Setting up a new feed for: $url"); - $saved_feed = $this->feedRepository->findOneBy(['url' => $url, 'title' => $title]); - $output->writeln("Feed title: " . $saved_feed->title); + $feed = new Feed(); + $feed->url = $url; + $feed->title = $title; - $s2_filter = new FeedFilter(FilterTarget::TITLE, FilterType::EXCLUDE, "S2", $saved_feed); - $this->em->persist($s2_filter); + $feed->feedFilters = new ArrayCollection(); + $feed->feedFilters->add( new FeedFilter(FilterTarget::TITLE, FilterType::INCLUDE, "[No Ads]", $feed)); + $feed->feedFilters->add( new FeedFilter(FilterTarget::TITLE, FilterType::EXCLUDE, "S2", $feed)); + + $this->em->persist($feed); $this->em->flush(); - $saved_feed = $this->feedRepository->findOneBy(['url' => $url, 'title' => $title]); - $saved_feed->filter(); - - $this->em->persist($saved_feed); - $this->em->flush(); - - $output->writeln("Filtered feed: " . $saved_feed->filteredFeed->asXML('feed_filtered.xml')); - return Command::SUCCESS; } } \ No newline at end of file diff --git a/src/app.php b/src/app.php index e4efe59..15d8874 100644 --- a/src/app.php +++ b/src/app.php @@ -23,6 +23,8 @@ $app->get("/", [SampleController::class, 'get']); $app->get('/feed', [FeedController::class, 'get']); +$app->get('/feed/{id}', [FeedController::class, 'get_feed']); + $app->addErrorMiddleware(true, true, true); $app->run(); \ No newline at end of file