Skip to content

Commit

Permalink
feat: add RSS feed
Browse files Browse the repository at this point in the history
  • Loading branch information
tonai committed Feb 6, 2025
1 parent 89ee278 commit 665db4c
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/Controller/RSSFeedController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Controller;

use App\Services\RSSFeed\RSSFeed;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\Cache;
use Symfony\Component\Routing\Attribute\Route;

#[Route(
'/rss',
name: 'cartesgouvfr_rss_feed_',
options: ['expose' => true],
)]
class RSSFeedController extends AbstractController
{
#[Route('/alerts', name: 'alerts')]
#[Cache(public: true, maxage: 3600, mustRevalidate: true)]
public function alerts(RSSFeed $rssFeed): Response
{
try {
$xml = $rssFeed->renderRssAlerts();

return new Response($xml, Response::HTTP_OK, [
'Content-Type' => 'application/xml',
]);
} catch (\Throwable $th) {
return new Response($th->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}
72 changes: 72 additions & 0 deletions src/Services/RSSFeed/RSSFeed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace App\Services\RSSFeed;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Twig\Environment as TwigEnvironment;

class RSSFeed
{
private const ALERTS_JSON_URL = 'https://data.geopf.fr/annexes/cartes.gouv.fr-config/public/alerts.json';

private HttpClientInterface $httpClient;

public function __construct(
private RouterInterface $router,
private TwigEnvironment $twig,
private CacheInterface $cache,
ParameterBagInterface $parameters,
HttpClientInterface $httpClient,
) {
$this->httpClient = $httpClient->withOptions([
'proxy' => $parameters->get('http_proxy'),
'verify_peer' => false,
'verify_host' => false,
]);
}

public function renderRssAlerts(): string
{
$alerts = $this->getAlerts();

$alerts = array_map(function (array $alert) {
// ajout de la racine dans l'URL si non absolue
$url = $alert['link']['url'];
if ('/' === mb_substr($url, 0, 1)) {
$alert['link']['url'] = substr($this->router->generate('cartesgouvfr_app', [], RouterInterface::ABSOLUTE_URL), 0, -1).$url;
}

// formattage de date
$date = new \DateTime($alert['date']);
$alert['date'] = $date->format(\DateTime::RSS);

return $alert;
}, $alerts);

$link = $this->router->generate('cartesgouvfr_rss_feed_alerts', [], RouterInterface::ABSOLUTE_URL);

return $this->twig->render('rss/alerts.xml.twig', [
'alerts' => $alerts,
'link' => $link,
]);
}

private function getAlerts(): array
{
return $this->cache->get('alerts', function (ItemInterface $item) {
$item->expiresAfter(3600);

$response = $this->httpClient->request('GET', self::ALERTS_JSON_URL);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new \Exception('Une erreur est survenue, veuillez réessayer ultérieurement');
}

return $response->toArray();
});
}
}
24 changes: 24 additions & 0 deletions templates/rss/alerts.xml.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>cartes.gouv.fr - Alertes</title>
<description>Suivez les alertes, incidents ou maintenances programmées de cartes.gouv.fr et la géoplateforme</description>
<link>{{ link }}</link>
<language>fr-fr</language>
{# <copyright>2020 Example.com All rights reserved</copyright> #}
{# <lastBuildDate>Mon, 6 Sep 2010 00:01:00 +0000</lastBuildDate>
<pubDate>Sun, 6 Sep 2009 16:20:00 +0000</pubDate> #}
<ttl>3600</ttl>

{% for alert in alerts %}
<item>
<title>{{ alert.title }}</title>
<description>{{ alert.description }}</description>
<link>{{ alert.link.url }}</link>
<guid>{{ alert.id }}</guid>
<pubDate>{{ alert.date }}</pubDate>
</item>
{% endfor %}

</channel>
</rss>

0 comments on commit 665db4c

Please sign in to comment.