604 lines
25 KiB
PHP
604 lines
25 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Entity\Stats;
|
|
use App\Entity\Place;
|
|
use App\Service\Motocultrice;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
use GuzzleHttp\Client;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\Mime\Email;
|
|
use Symfony\Component\Mailer\MailerInterface;
|
|
use App\Service\ActionLogger;
|
|
|
|
class PublicController extends AbstractController
|
|
{
|
|
|
|
private $hide_filled_inputs = true;
|
|
|
|
public function __construct(
|
|
private EntityManagerInterface $entityManager,
|
|
private Motocultrice $motocultrice,
|
|
private MailerInterface $mailer,
|
|
private ActionLogger $actionLogger
|
|
) {}
|
|
|
|
#[Route('/propose-email/{email}/{type}/{id}', name: 'app_public_propose_email')]
|
|
public function proposeEmail(string $email, string $type, int $id): Response
|
|
{
|
|
|
|
|
|
$data = $this->motocultrice->get_osm_object_data($type, $id);
|
|
// Récupérer le code postal depuis les tags, sinon mettre -1
|
|
$zipCode = isset($data['tags_converted']['addr:postcode']) ? (int)$data['tags_converted']['addr:postcode'] : -1;
|
|
$place_name = $data['tags_converted']['name'];
|
|
|
|
// Vérifier si une Place existe déjà avec le même osm_kind et osmId
|
|
$existingPlace = $this->entityManager->getRepository(Place::class)->findOneBy([
|
|
'osm_kind' => $type,
|
|
'osmId' => $id
|
|
]);
|
|
|
|
if ($existingPlace) {
|
|
// Mettre à jour l'email de la Place existante
|
|
$existingPlace->setEmail($email)->setLastContactAttemptDate(new \DateTime());
|
|
if ($zipCode != -1) {
|
|
$existingPlace->setZipCode($zipCode);
|
|
}
|
|
$this->entityManager->persist($existingPlace);
|
|
$this->entityManager->flush();
|
|
|
|
$debug = '';
|
|
if ($this->getParameter('kernel.environment') !== 'prod') {
|
|
$debug = 'Bonjour, nous sommes des bénévoles d\'OpenStreetMap France et nous vous proposons de modifier les informations de votre commerce. Voici votre lien unique de modification: ' . $this->generateUrl('app_public_edit', [
|
|
'zipcode' => $zipCode,
|
|
'name' => $place_name,
|
|
'uuid' => $existingPlace->getUuidForUrl()
|
|
], true);
|
|
}
|
|
|
|
$this->addFlash('success', 'L\'email a été mis à jour. Un email vous sera envoyé avec le lien de modification. ' . $debug);
|
|
} else {
|
|
|
|
|
|
// Créer une nouvelle entité Place
|
|
$place = new Place();
|
|
$place->setEmail($email)
|
|
->setOsmId($id)
|
|
->setOsmKind($type)
|
|
->setAskedHumainsSupport(false)
|
|
->setOptedOut(false)
|
|
->setDead(false)
|
|
->setNote('')
|
|
->setModifiedDate(new \DateTime())
|
|
->setZipCode($zipCode)
|
|
->setPlaceCount(0)
|
|
->setMainTag($this->motocultrice->find_main_tag($data['tags_converted']) ?? '')
|
|
->setStreet($this->motocultrice->find_street($data['tags_converted']) ?? '')
|
|
->setHousenumber($this->motocultrice->find_housenumber($data['tags_converted']) ?? '')
|
|
->setLastContactAttemptDate(new \DateTime())
|
|
->setUuidForUrl(uniqid());
|
|
|
|
$this->entityManager->persist($place);
|
|
$this->entityManager->flush();
|
|
|
|
$debug = '';
|
|
if ($this->getParameter('kernel.environment') !== 'prod') {
|
|
$debug = 'Bonjour, nous sommes des bénévoles d\'OpenStreetMap France et nous vous proposons de modifier les informations de votre commerce. Voici votre lien unique de modification: ' . $this->generateUrl('app_public_edit', [
|
|
'zipcode' => $zipCode,
|
|
'name' => $place_name,
|
|
'uuid' => $place->getUuidForUrl()
|
|
], true);
|
|
}
|
|
$this->addFlash('success', 'Un email vous sera envoyé avec le lien de modification. ' . $debug);
|
|
}
|
|
|
|
// Envoyer l'email
|
|
$destinataire = $this->getParameter('kernel.environment') === 'prod' ? $email : 'contact+essai_osm_commerce@cipherbliss.com';
|
|
|
|
$message = (new Email())
|
|
->from('contact@osm-commerce.fr')
|
|
->to($destinataire)
|
|
->subject('Votre lien de modification OpenStreetMap')
|
|
->text('Bonjour, nous sommes des bénévoles d\'OpenStreetMap France et nous vous proposons de modifier les informations de votre commerce. Voici votre lien unique de modification: ' . $this->generateUrl('app_public_edit', [
|
|
'zipcode' => $zipCode,
|
|
'name' => $place_name,
|
|
'uuid' => $existingPlace ? $existingPlace->getUuidForUrl() : $place->getUuidForUrl()
|
|
], true));
|
|
|
|
$this->mailer->send($message);
|
|
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
#[Route('/', name: 'app_public_index')]
|
|
public function index(): Response
|
|
{
|
|
$stats = $this->entityManager->getRepository(Stats::class)->findAll();
|
|
|
|
// Préparer les données pour la carte
|
|
$citiesForMap = [];
|
|
foreach ($stats as $stat) {
|
|
if ($stat->getZone() && $stat->getZone() !== 'undefined' && preg_match('/^\d+$/', $stat->getZone())) {
|
|
// Récupérer les coordonnées de la ville via l'API Nominatim
|
|
$cityName = $stat->getName() ?: $stat->getZone();
|
|
$coordinates = $this->getCityCoordinates($cityName, $stat->getZone());
|
|
|
|
if ($coordinates) {
|
|
$citiesForMap[] = [
|
|
'name' => $cityName,
|
|
'zone' => $stat->getZone(),
|
|
'coordinates' => $coordinates,
|
|
'placesCount' => $stat->getPlacesCount(),
|
|
'completionPercent' => $stat->getCompletionPercent(),
|
|
'population' => $stat->getPopulation(),
|
|
'url' => $this->generateUrl('app_admin_stats', ['insee_code' => $stat->getZone()])
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->render('public/home.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'stats' => $stats,
|
|
'citiesForMap' => $citiesForMap,
|
|
'maptiler_token' => $_ENV['MAPTILER_TOKEN'] ?? null
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Récupère les coordonnées d'une ville via l'API Nominatim
|
|
*/
|
|
private function getCityCoordinates(string $cityName, string $inseeCode): ?array
|
|
{
|
|
// Cache simple pour éviter trop d'appels API
|
|
$cacheKey = 'city_coords_' . $inseeCode;
|
|
|
|
// Vérifier le cache (ici on utilise une approche simple)
|
|
// En production, vous pourriez utiliser le cache Symfony
|
|
|
|
$query = urlencode($cityName . ', France');
|
|
$url = "https://nominatim.openstreetmap.org/search?q={$query}&format=json&limit=1&countrycodes=fr";
|
|
|
|
try {
|
|
$response = file_get_contents($url);
|
|
$data = json_decode($response, true);
|
|
|
|
if (!empty($data) && isset($data[0]['lat']) && isset($data[0]['lon'])) {
|
|
return [
|
|
'lat' => (float) $data[0]['lat'],
|
|
'lon' => (float) $data[0]['lon']
|
|
];
|
|
}
|
|
} catch (\Exception $e) {
|
|
// En cas d'erreur, on retourne null
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#[Route('/edit/{zipcode}/{name}/{uuid}', name: 'app_public_edit')]
|
|
public function edit_with_uuid($zipcode, $name, $uuid): Response
|
|
{
|
|
$this->actionLogger->log('edit_place', [
|
|
'zipcode' => $zipcode,
|
|
'name' => $name,
|
|
'uuid' => $uuid,
|
|
|
|
]);
|
|
|
|
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['uuid_for_url' => $uuid]);
|
|
if (!$place) {
|
|
$this->addFlash('warning', 'Ce lien de modification n\'existe pas.' . $uuid);
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
if ($place->getOsmKind() === 'relation') {
|
|
$this->addFlash('warning', 'Les objets OSM de type "relation" ne sont pas gérés dans cet outil.');
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
// récupérer les tags de base
|
|
$base_tags = $this->motocultrice->base_tags;
|
|
$base_tags = array_fill_keys($base_tags, '');
|
|
|
|
$commerce_overpass = $this->motocultrice->get_osm_object_data($place->getOsmKind(), $place->getOsmId());
|
|
// Fusionner les tags de base avec les tags existants
|
|
|
|
$commerce_overpass['tags_converted'] = array_merge($base_tags, $commerce_overpass['tags_converted']);
|
|
|
|
// Trier les tags par ordre alphabétique des clés
|
|
ksort($commerce_overpass['tags_converted']);
|
|
|
|
$place->setDisplayedDate(new \DateTime());
|
|
$this->entityManager->persist($place);
|
|
$this->entityManager->flush();
|
|
|
|
return $this->render('public/edit.html.twig', [
|
|
'commerce_overpass' => $commerce_overpass,
|
|
'name' => $name,
|
|
'commerce' => $place,
|
|
'zone' => $zipcode,
|
|
'completion_percentage' => $place->getCompletionPercentage(),
|
|
'hide_filled_inputs' => $this->hide_filled_inputs,
|
|
'excluded_tags_to_render' => $this->motocultrice->excluded_tags_to_render,
|
|
'osm_kind' => $place->getOsmKind(),
|
|
"mapbox_token" => $_ENV['MAPBOX_TOKEN'],
|
|
"maptiler_token" => $_ENV['MAPTILER_TOKEN'],
|
|
]);
|
|
}
|
|
|
|
#[Route('/dashboard', name: 'app_public_dashboard')]
|
|
public function dashboard(): Response
|
|
{
|
|
|
|
$this->actionLogger->log('dashboard', []);
|
|
|
|
$stats_repo = $this->entityManager->getRepository(Stats::class)->findAll();
|
|
|
|
$stats_for_chart = [];
|
|
foreach ($stats_repo as $stat) {
|
|
if ($stat->getPlacesCount() > 0 && $stat->getName() !== null && $stat->getPopulation() > 0) {
|
|
$stats_for_chart[] = [
|
|
'name' => $stat->getName(),
|
|
'placesCount' => $stat->getPlacesCount(),
|
|
'completionPercent' => $stat->getCompletionPercent(),
|
|
'population' => $stat->getPopulation(),
|
|
'zone' => $stat->getZone(),
|
|
'osmDataDateAvg' => $stat->getOsmDataDateAvg() ? $stat->getOsmDataDateAvg()->format('Y-m-d') : null,
|
|
];
|
|
}
|
|
}
|
|
|
|
// Compter le nombre total de lieux
|
|
$placesCount = $this->entityManager->getRepository(Place::class)->count([]);
|
|
return $this->render('public/dashboard.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'mapbox_token' => $_ENV['MAPBOX_TOKEN'] ?? null,
|
|
'maptiler_token' => $_ENV['MAPTILER_TOKEN'] ?? null,
|
|
'stats' => json_encode($stats_for_chart),
|
|
'stats_list' => $stats_repo,
|
|
'places_count' => $placesCount,
|
|
]);
|
|
}
|
|
|
|
#[Route('/modify/{osm_object_id}/{version}/{changesetID}', name: 'app_public_submit')]
|
|
public function submit($osm_object_id, $version, $changesetID): Response
|
|
{
|
|
|
|
$this->actionLogger->log('submit_object', [
|
|
'osm_id' => $osm_object_id,
|
|
'version' => $version,
|
|
'changesetID' => $changesetID
|
|
]);
|
|
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['osmId' => $osm_object_id]);
|
|
if (!$place) {
|
|
$this->addFlash('warning', 'Ce commerce n\'existe pas.');
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
// Récupérer les données POST
|
|
$request = Request::createFromGlobals();
|
|
|
|
$status = null;
|
|
$exception = false;
|
|
$exception_message = null;
|
|
$osm_kind = 'node';
|
|
// Vérifier si des données ont été soumises
|
|
if ($request->isMethod('POST')) {
|
|
$status = "non modifié";
|
|
$osm_kind = $request->request->get('osm_kind', 'node');
|
|
// Récupérer tous les tags du formulaire
|
|
$tags = [];
|
|
$request_post = $request->request->all();
|
|
$request_post = $this->motocultrice->map_post_values($request_post);
|
|
foreach ($request_post as $key => $value) {
|
|
if (strpos($key, 'commerce_tag_value__') === 0) {
|
|
$tagKey = str_replace('commerce_tag_value__', '', $key);
|
|
if (!empty($value)) {
|
|
$tags[$tagKey] = trim($value);
|
|
}
|
|
}
|
|
}
|
|
var_dump('POST brut', $_POST);
|
|
var_dump('request->request->all()', $request->request->all());
|
|
var_dump('tags extraits', $tags);
|
|
// DEBUG : enlever ce die après analyse
|
|
die('DEBUG avant envoi OSM');
|
|
|
|
// Récupérer le token OSM depuis les variables d'environnement
|
|
$osm_api_token = $_ENV['APP_OSM_BEARER'];
|
|
|
|
try {
|
|
$client = new Client();
|
|
|
|
// 1. Créer un nouveau changeset
|
|
$changesetXml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><osm version="0.6"></osm>');
|
|
$changeset = $changesetXml->addChild('changeset');
|
|
$tag = $changeset->addChild('tag');
|
|
$tag->addAttribute('k', 'created_by');
|
|
$tag->addAttribute('v', 'OSM Mon Commerce Web Editor');
|
|
|
|
$tag = $changeset->addChild('tag');
|
|
$tag->addAttribute('k', 'comment');
|
|
$tag->addAttribute('v', 'Modification dans #MonCommerceOSM');
|
|
|
|
$changesetResponse = $client->put('https://api.openstreetmap.org/api/0.6/changeset/create', [
|
|
'body' => $changesetXml->asXML(),
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $osm_api_token,
|
|
'Content-Type' => 'application/xml'
|
|
]
|
|
]);
|
|
|
|
$newChangesetId = $changesetResponse->getBody()->getContents();
|
|
|
|
// Récupérer les données actuelles de l'objet
|
|
$currentObjectData = $this->motocultrice->get_osm_object_data($osm_kind, $osm_object_id);
|
|
|
|
// 2. Modifier l'objet avec le nouveau changeset
|
|
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><osm version="0.6"></osm>');
|
|
$object = $xml->addChild($osm_kind);
|
|
$object->addAttribute('id', $osm_object_id);
|
|
$object->addAttribute('version', $version);
|
|
$object->addAttribute('changeset', $newChangesetId);
|
|
|
|
// Ajouter les coordonnées pour les nodes
|
|
if ($osm_kind === 'node') {
|
|
if (!isset($currentObjectData['@attributes']['lat']) || !isset($currentObjectData['@attributes']['lon'])) {
|
|
throw new \Exception("Impossible de récupérer les coordonnées du nœud");
|
|
}
|
|
$object->addAttribute('lat', $currentObjectData['@attributes']['lat']);
|
|
$object->addAttribute('lon', $currentObjectData['@attributes']['lon']);
|
|
}
|
|
|
|
// Ajouter les tags
|
|
foreach ($tags as $key => $value) {
|
|
if (!empty($key) && !empty($value)) {
|
|
$tag = $object->addChild('tag');
|
|
$tag->addAttribute('k', htmlspecialchars($key, ENT_XML1));
|
|
$tag->addAttribute('v', htmlspecialchars($value, ENT_XML1));
|
|
}
|
|
}
|
|
|
|
// Debug du XML généré
|
|
$xmlString = $xml->asXML();
|
|
|
|
$response = $client->put("https://api.openstreetmap.org/api/0.6/{$osm_kind}/" . $osm_object_id, [
|
|
'body' => $xmlString,
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $osm_api_token,
|
|
'Content-Type' => 'application/xml'
|
|
]
|
|
]);
|
|
|
|
// 3. Fermer le changeset
|
|
$client->put('https://api.openstreetmap.org/api/0.6/changeset/' . $newChangesetId . '/close', [
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $osm_api_token
|
|
]
|
|
]);
|
|
|
|
if ($response->getStatusCode() === 200) {
|
|
$status = "Les tags ont été mis à jour avec succès";
|
|
} else {
|
|
$status = "Erreur lors de la mise à jour des tags";
|
|
$this->actionLogger->log('ERROR_submit_object', [
|
|
'osm_id' => $osm_object_id,
|
|
'version' => $version,
|
|
'changesetID' => $changesetID,
|
|
'body_sent' => $xmlString,
|
|
'response' => $response->getBody()->getContents(),
|
|
]);
|
|
}
|
|
} catch (\Exception $e) {
|
|
$status = "Erreur lors de la communication avec l'API OSM: " . $e->getMessage();
|
|
$exception = true;
|
|
$exception_message = $e->getMessage();
|
|
|
|
// Debug de la réponse en cas d'erreur
|
|
if (method_exists($e, 'getResponse')) {
|
|
var_dump($e->getResponse()->getBody()->getContents());
|
|
// Faire un log d'action lors d'une erreur de soumission
|
|
$this->actionLogger->log('ERROR_submit_object_exception', [
|
|
'osm_id' => $osm_object_id ?? null,
|
|
'version' => $version ?? null,
|
|
'changesetID' => $changesetID ?? null,
|
|
'body_sent' => $xmlString ?? null,
|
|
'exception_message' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// après envoi on récupère les données
|
|
$commerce_overpass = $this->motocultrice->get_osm_object_data($osm_kind, $osm_object_id);
|
|
|
|
$place->update_place_from_overpass_data($commerce_overpass);
|
|
$this->entityManager->persist($place);
|
|
$this->entityManager->flush();
|
|
$this->entityManager->clear();
|
|
|
|
$stats = $place->getStats();
|
|
if (!$stats) {
|
|
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zip_code' => $place->getZipCode()]);
|
|
}
|
|
if (!$stats) {
|
|
$stats = new Stats();
|
|
$stats->setZone($place->getZipCode());
|
|
}
|
|
|
|
$stats->addPlace($place);
|
|
$place->setStats($stats);
|
|
$place->setModifiedDate(new \DateTime());
|
|
|
|
$stats->computeCompletionPercent();
|
|
$this->entityManager->persist($stats);
|
|
$this->entityManager->persist($place);
|
|
$this->entityManager->flush();
|
|
$this->entityManager->clear();
|
|
|
|
|
|
return $this->render('public/view.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'commerce' => $commerce_overpass,
|
|
'commerce_overpass' => $commerce_overpass,
|
|
'place' => $place,
|
|
'status' => $status,
|
|
'exception' => $exception,
|
|
'exception_message' => $exception_message,
|
|
'mapbox_token' => $_ENV['MAPBOX_TOKEN'],
|
|
'maptiler_token' => $_ENV['MAPTILER_TOKEN'],
|
|
'hide_filled_inputs' => false,
|
|
'excluded_tags_to_render' => $this->motocultrice->excluded_tags_to_render,
|
|
]);
|
|
}
|
|
|
|
#[Route('/request_email_to_modify/{osm_object_id}', name: 'app_public_request_email')]
|
|
public function request_email($osm_object_id, Request $request): Response
|
|
{
|
|
$this->actionLogger->log('request_email_to_modify', [
|
|
'osm_id' => $osm_object_id,
|
|
]);
|
|
|
|
if ($request->isMethod('POST')) {
|
|
$email = $request->request->get('email');
|
|
|
|
try {
|
|
// TODO: Implémenter l'envoi réel du mail
|
|
|
|
$this->addFlash(
|
|
'success',
|
|
'Un email vous a été envoyé avec les instructions pour modifier ce lieu.'
|
|
);
|
|
} catch (\Exception $e) {
|
|
$this->actionLogger->log('ERROR_request_email_to_modify', [
|
|
'osm_id' => $osm_object_id,
|
|
'exception_message' => $e->getMessage(),
|
|
]);
|
|
$this->addFlash(
|
|
'error',
|
|
'Une erreur est survenue lors de l\'envoi de l\'email. Veuillez réessayer plus tard.'
|
|
);
|
|
}
|
|
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
// TODO envoyer un email
|
|
return $this->render('public/request_email.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'commerce_id' => $osm_object_id,
|
|
]);
|
|
}
|
|
|
|
#route pour signaler que le commerce est fermé
|
|
#[Route('/closed_commerce/{osm_object_id}', name: 'app_public_closed_commerce')]
|
|
public function closed_commerce($osm_object_id): Response
|
|
{
|
|
$this->actionLogger->log('closed_commerce', [
|
|
'osm_id' => $osm_object_id,
|
|
]);
|
|
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['osm_id' => $osm_object_id]);
|
|
if (!$place) {
|
|
$this->addFlash('warning', 'Ce commerce n\'existe pas.');
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
$place->setClosed(true);
|
|
$place->setDead(true);
|
|
$this->entityManager->flush();
|
|
|
|
return $this->render('public/closed_commerce.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
]);
|
|
}
|
|
|
|
#[Route('/closed_commerces', name: 'app_public_closed_commerces')]
|
|
public function closedCommerces(): Response
|
|
{
|
|
// Récupérer tous les commerces marqués comme fermés
|
|
$closedPlaces = $this->entityManager->getRepository(Place::class)->findBy(['dead' => true]);
|
|
|
|
return $this->render('public/closed_commerces.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'closed_places' => $closedPlaces
|
|
]);
|
|
}
|
|
|
|
#[Route('/places_with_note', name: 'app_public_places_with_note')]
|
|
public function places_with_note(): Response
|
|
{
|
|
// Récupérer tous les commerces ayant une note
|
|
$places = $this->entityManager->getRepository(Place::class)->findBy(['has_note' => true]);
|
|
return $this->render('public/places_with_note.html.twig', [
|
|
'controller_name' => 'PublicController',
|
|
'places' => $places
|
|
]);
|
|
}
|
|
|
|
#[Route('/latest_changes', name: 'app_public_latest_changes')]
|
|
public function latestChanges(): Response
|
|
{
|
|
// Récupérer les commerces modifiés, triés par date de modification décroissante
|
|
$places_modified = $this->entityManager->getRepository(Place::class)
|
|
->createQueryBuilder('p')
|
|
->where('p.modified_date IS NOT NULL')
|
|
->orderBy('p.modified_date', 'DESC')
|
|
->setMaxResults(20)
|
|
->getQuery()
|
|
->getResult();
|
|
|
|
// Récupérer les commerces modifiés, triés par date de modification décroissante
|
|
$places_displayed = $this->entityManager->getRepository(Place::class)
|
|
->createQueryBuilder('p')
|
|
->where('p.displayed_date IS NOT NULL')
|
|
->orderBy('p.displayed_date', 'DESC')
|
|
->setMaxResults(20)
|
|
->getQuery()
|
|
->getResult();
|
|
|
|
return $this->render('public/latest_changes.html.twig', [
|
|
'places_modified' => $places_modified,
|
|
'places_displayed' => $places_displayed
|
|
]);
|
|
}
|
|
|
|
#[Route('/set_opted_out_place/{uuid}', name: 'app_public_set_opted_out_place')]
|
|
public function set_opted_out_place($uuid)
|
|
{
|
|
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['uuid_for_url' => $uuid]);
|
|
$this->actionLogger->log('set_place_opted_out', [
|
|
'uuid' => $uuid,
|
|
]);
|
|
|
|
if (!$place) {
|
|
$this->addFlash('warning', 'Ce commerce n\'existe pas.');
|
|
return $this->redirectToRoute('app_public_index');
|
|
}
|
|
|
|
$place->setOptedOut(true);
|
|
|
|
}
|
|
|
|
#[Route('/ask-for-help', name: 'app_public_ask_for_help')]
|
|
public function askForHelp(Request $request): Response
|
|
{
|
|
|
|
$this->actionLogger->log('ask_for_help', []);
|
|
return $this->redirect('https://www.openstreetmap.fr/contact');
|
|
}
|
|
|
|
#[Route('/logs/actions', name: 'app_public_action_logs')]
|
|
public function listActionLogs(): Response
|
|
{
|
|
$logs = $this->actionLogger->getLastLogs(100);
|
|
return $this->render('public/action_logs.html.twig', [
|
|
'logs' => $logs
|
|
]);
|
|
}
|
|
}
|