osm-labo/src/Controller/AdminController.php

782 lines
33 KiB
PHP
Raw Normal View History

2025-05-26 11:55:44 +02:00
<?php
2025-06-05 15:09:28 +02:00
2025-05-26 11:55:44 +02:00
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use App\Entity\Place;
use App\Entity\Stats;
2025-06-17 19:38:44 +02:00
use App\Entity\StatsHistory;
use App\Service\Motocultrice;
use Doctrine\ORM\EntityManagerInterface;
2025-06-21 11:28:31 +02:00
use Symfony\Component\HttpFoundation\Request;
use function uuid_create;
2025-05-26 11:55:44 +02:00
final class AdminController extends AbstractController
{
public function __construct(
private EntityManagerInterface $entityManager,
private Motocultrice $motocultrice
) {
}
#[Route('/admin/labourer-toutes-les-zones', name: 'app_admin_labourer_tout')]
public function labourer_tout(): Response
{
$updateExisting =true;
$stats_all = $this->entityManager->getRepository(Stats::class)->findAll();
echo 'on a trouvé ' . count($stats_all) . ' zones à labourer<br>';
foreach($stats_all as $stats) {
echo '<br> on laboure la zone '.$stats->getZone() . ' ';
$processedCount = 0;
$updatedCount = 0;
$insee_code = $stats->getZone();
// Vérifier si le code INSEE est un nombre valide
// Vérifier si les stats ont été modifiées il y a moins de 24h
if ($stats->getDateModified() !== null) {
$now = new \DateTime();
$diff = $now->diff($stats->getDateModified());
$hours = $diff->h + ($diff->days * 24);
if ($hours < 24) {
echo 'Stats modifiées il y a moins de 24h - on passe au suivant<br>';
continue;
}
}
if (!is_numeric($insee_code) || $insee_code == 'undefined' || $insee_code == '') {
echo 'Code INSEE invalide : ' . $insee_code . ' - on passe au suivant<br>';
continue;
}
$places_overpass = $this->motocultrice->labourer($stats->getZone());
$places = $places_overpass;
foreach ($places as $placeData) {
// Vérifier si le lieu existe déjà
$existingPlace = $this->entityManager->getRepository(Place::class)
->findOneBy(['osmId' => $placeData['id']]);
if (!$existingPlace) {
$place = new Place();
$place->setOsmId($placeData['id'])
->setOsmKind($placeData['type'])
->setZipCode($insee_code)
->setUuidForUrl($this->motocultrice->uuid_create())
->setModifiedDate(new \DateTime())
->setStats($stats)
->setDead(false)
->setOptedOut(false)
->setMainTag($this->motocultrice->find_main_tag($placeData['tags']) ?? '')
->setStreet($this->motocultrice->find_street($placeData['tags']) ?? '')
->setHousenumber($this->motocultrice->find_housenumber($placeData['tags']) ?? '')
->setSiret($this->motocultrice->find_siret($placeData['tags']) ?? '')
->setAskedHumainsSupport(false)
->setLastContactAttemptDate(null)
->setNote($this->motocultrice->find_tag($placeData['tags'], 'note') ? true : false)
->setNoteContent($this->motocultrice->find_tag($placeData['tags'], 'note') ?? '')
->setPlaceCount(0)
// ->setOsmData($placeData['modified'] ?? null)
;
// Mettre à jour les données depuis Overpass
$place->update_place_from_overpass_data($placeData);
$this->entityManager->persist($place);
$stats->addPlace($place);
$processedCount++;
} elseif ($updateExisting) {
// Mettre à jour les données depuis Overpass uniquement si updateExisting est true
$existingPlace->update_place_from_overpass_data($placeData);
2025-06-21 10:26:55 +02:00
$stats->addPlace($existingPlace);
$this->entityManager->persist($existingPlace);
$updatedCount++;
}
}
// mettre à jour les stats
// Récupérer tous les commerces de la zone
$commerces = $this->entityManager->getRepository(Place::class)->findBy(['zip_code' => $insee_code]);
// Récupérer les stats existantes pour la zone
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if(!$stats) {
$stats = new Stats();
$stats->setZone($insee_code);
}
$urls = $stats->getAllCTCUrlsMap();
$statsHistory = $this->entityManager->getRepository(StatsHistory::class)
->createQueryBuilder('sh')
->where('sh.stats = :stats')
->setParameter('stats', $stats)
->orderBy('sh.id', 'DESC')
->setMaxResults(365)
->getQuery()
->getResult();
// Calculer les statistiques
$calculatedStats = $this->motocultrice->calculateStats($commerces);
// Mettre à jour les stats pour la zone donnée
$stats->setPlacesCount($calculatedStats['places_count']);
$stats->setAvecHoraires($calculatedStats['counters']['avec_horaires']);
$stats->setAvecAdresse($calculatedStats['counters']['avec_adresse']);
$stats->setAvecSite($calculatedStats['counters']['avec_site']);
$stats->setAvecAccessibilite($calculatedStats['counters']['avec_accessibilite']);
$stats->setAvecNote($calculatedStats['counters']['avec_note']);
$stats->setCompletionPercent($calculatedStats['completion_percent']);
// Associer les stats à chaque commerce
foreach ($commerces as $commerce) {
$commerce->setStats($stats);
$this->entityManager->persist($commerce);
}
$stats->computeCompletionPercent();
2025-06-19 12:49:30 +02:00
// Calculer les statistiques de fraîcheur des données OSM
$timestamps = [];
foreach ($stats->getPlaces() as $place) {
if ($place->getOsmDataDate()) {
$timestamps[] = $place->getOsmDataDate()->getTimestamp();
}
}
if (!empty($timestamps)) {
// Date la plus ancienne (min)
$minTimestamp = min($timestamps);
$stats->setOsmDataDateMin(new \DateTime('@' . $minTimestamp));
// Date la plus récente (max)
$maxTimestamp = max($timestamps);
$stats->setOsmDataDateMax(new \DateTime('@' . $maxTimestamp));
// Date moyenne
$avgTimestamp = array_sum($timestamps) / count($timestamps);
$stats->setOsmDataDateAvg(new \DateTime('@' . (int)$avgTimestamp));
}
if($stats->getDateCreated() == null) {
$stats->setDateCreated(new \DateTime());
}
$stats->setDateModified(new \DateTime());
// Créer un historique des statistiques
$statsHistory = new StatsHistory();
$statsHistory->setDate(new \DateTime())
->setStats($stats);
// Compter les Places avec email et SIRET
$placesWithEmail = 0;
$placesWithSiret = 0;
foreach ($stats->getPlaces() as $place) {
if ($place->getEmail() && $place->getEmail() !== '') {
$placesWithEmail++;
}
if ($place->getSiret() && $place->getSiret() !== '') {
$placesWithSiret++;
}
}
$statsHistory->setPlacesCount($stats->getPlaces()->count())
->setOpeningHoursCount($stats->getAvecHoraires())
->setAddressCount($stats->getAvecAdresse())
->setWebsiteCount($stats->getAvecSite())
->setSiretCount($placesWithSiret)
->setEmailsCount($placesWithEmail)
// ->setAccessibiliteCount($stats->getAvecAccessibilite())
// ->setNoteCount($stats->getAvecNote())
->setCompletionPercent($stats->getCompletionPercent())
->setStats($stats);
$this->entityManager->persist($statsHistory);
$this->entityManager->persist($stats);
2025-06-19 12:49:30 +02:00
$this->entityManager->flush();
2025-06-19 12:49:30 +02:00
$message = 'Labourage terminé avec succès. ' . $processedCount . ' nouveaux lieux traités.';
if ($updateExisting) {
$message .= ' ' . $updatedCount . ' lieux existants mis à jour pour la zone '.$stats->getName().' ('.$stats->getZone().').';
}
$this->addFlash('success', $message);
}
$this->entityManager->flush();
$this->entityManager->flush();
$this->addFlash('success', 'Labourage des ' . count($stats_all) . ' zones terminé avec succès.');
return $this->redirectToRoute('app_public_dashboard');
}
2025-05-26 11:55:44 +02:00
#[Route('/admin', name: 'app_admin')]
public function index(): Response
{
return $this->render('admin/index.html.twig', [
'controller_name' => 'AdminController',
]);
}
2025-06-17 18:27:19 +02:00
#[Route('/admin/stats/{insee_code}', name: 'app_admin_stats')]
public function calculer_stats(string $insee_code): Response
{
// Récupérer tous les commerces de la zone
2025-06-21 11:28:31 +02:00
$commerces = $this->entityManager->getRepository(Place::class)->findBy(['zip_code' => $insee_code, 'dead' => false]);
// Récupérer les stats existantes pour la zone
2025-06-17 18:27:19 +02:00
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if(!$stats) {
2025-06-21 11:28:31 +02:00
// Si aucune stat n'existe, on en crée une vide pour éviter les erreurs, mais sans la sauvegarder
$stats = new Stats();
$stats->setZone($insee_code);
2025-06-21 11:28:31 +02:00
$stats->setName('Nouvelle zone non labourée');
}
2025-06-21 11:28:31 +02:00
$urls = $stats->getAllCTCUrlsMap();
$statsHistory = $this->entityManager->getRepository(StatsHistory::class)
->createQueryBuilder('sh')
->where('sh.stats = :stats')
->setParameter('stats', $stats)
->orderBy('sh.id', 'DESC')
->setMaxResults(365)
->getQuery()
->getResult();
/*
// La page de statistiques ne doit pas modifier les données, seulement les afficher.
// La mise à jour des statistiques se fait lors du labourage.
2025-06-17 18:27:19 +02:00
// Calculer les statistiques
$calculatedStats = $this->motocultrice->calculateStats($commerces);
// Mettre à jour les stats pour la zone donnée
$stats->setPlacesCount($calculatedStats['places_count']);
2025-06-21 11:28:31 +02:00
// ... (plus de setters) ...
$stats->setCompletionPercent($calculatedStats['completion_percent']);
2025-06-21 11:28:31 +02:00
// ... (boucle foreach sur commerces) ...
2025-06-21 11:28:31 +02:00
$stats->computeCompletionPercent();
$this->entityManager->persist($stats);
$this->entityManager->flush();
2025-06-21 11:28:31 +02:00
*/
2025-06-19 12:49:30 +02:00
2025-06-21 11:28:31 +02:00
// Données pour le graphique des modifications par trimestre
$modificationsByQuarter = [];
foreach ($stats->getPlaces() as $commerce) {
if ($commerce->getOsmDataDate()) {
$date = $commerce->getOsmDataDate();
$year = $date->format('Y');
$quarter = ceil($date->format('n') / 3);
$key = $year . '-Q' . $quarter;
if (!isset($modificationsByQuarter[$key])) {
$modificationsByQuarter[$key] = 0;
}
$modificationsByQuarter[$key]++;
2025-06-19 12:49:30 +02:00
}
}
2025-06-21 11:28:31 +02:00
ksort($modificationsByQuarter); // Trier par clé (année-trimestre)
2025-06-19 12:49:30 +02:00
2025-06-21 11:28:31 +02:00
$overpass_query = $this->motocultrice->get_query_places($insee_code);
$overpass_query_url = "https://overpass-turbo.eu/?Q=" . urlencode($overpass_query);
2025-05-27 12:17:46 +02:00
return $this->render('admin/stats.html.twig', [
'stats' => $stats,
2025-06-21 11:28:31 +02:00
'commerces' => $commerces,
'urls' => $urls,
'query_places' => $overpass_query,
'overpass_query' => $overpass_query,
'overpass_query_url' => $overpass_query_url,
'modificationsByQuarter' => json_encode($modificationsByQuarter),
'maptiler_token' => $_ENV['MAPTILER_TOKEN'],
2025-06-17 18:27:19 +02:00
'statsHistory' => $statsHistory,
2025-06-18 00:41:24 +02:00
'CTC_urls' => $urls,
]);
}
2025-06-01 23:35:15 +02:00
#[Route('/admin/placeType/{osm_kind}/{osm_id}', name: 'app_admin_by_osm_id')]
public function placeType(string $osm_kind, string $osm_id): Response
{
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['osm_kind' => $osm_kind, 'osmId' => $osm_id]);
if($place) {
return $this->redirectToRoute('app_admin_commerce', ['id' => $place->getId()]);
} else {
$this->addFlash('error', 'Le lieu n\'existe pas.');
return $this->redirectToRoute('app_public_index');
}
}
/**
* rediriger vers l'url unique quand on est admin
*/
2025-05-28 16:24:34 +02:00
#[Route('/admin/commerce/{id}', name: 'app_admin_commerce')]
public function commerce(int $id): Response
{
// Vérifier si on est en prod
if ($this->getParameter('kernel.environment') === 'prod') {
$this->addFlash('error', 'Vous n\'avez pas accès à cette page en production.');
return $this->redirectToRoute('app_public_index');
}
$commerce = $this->entityManager->getRepository(Place::class)->find($id);
if (!$commerce) {
throw $this->createNotFoundException('Commerce non trouvé');
}
// Redirection vers la page de modification avec les paramètres nécessaires
return $this->redirectToRoute('app_public_edit', [
'zipcode' => $commerce->getZipCode(),
'name' => $commerce->getName()!='' ? $commerce->getName() : '?',
2025-05-28 16:24:34 +02:00
'uuid' => $commerce->getUuidForUrl()
]);
}
/**
2025-06-17 18:27:19 +02:00
* récupérer les commerces de la zone selon le code INSEE, créer les nouveaux lieux, et mettre à jour les existants
*/
2025-06-17 18:27:19 +02:00
#[Route('/admin/labourer/{insee_code}', name: 'app_admin_labourer')]
2025-06-21 11:28:31 +02:00
public function labourer(Request $request, string $insee_code, bool $updateExisting = true): Response
{
2025-06-21 11:28:31 +02:00
$deleteMissing = $request->query->getBoolean('deleteMissing', true);
// Vérifier si le code INSEE est valide (composé uniquement de chiffres)
if (!ctype_digit($insee_code) || $insee_code == 'undefined' || $insee_code == '') {
$this->addFlash('error', 'Code INSEE invalide : il doit être composé uniquement de chiffres.');
return $this->redirectToRoute('app_public_index');
}
2025-06-05 16:20:20 +02:00
try {
// Récupérer ou créer les stats pour cette zone
2025-06-17 18:27:19 +02:00
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
2025-06-05 17:32:12 +02:00
2025-06-17 18:27:19 +02:00
$city = $this->motocultrice->get_city_osm_from_zip_code($insee_code);
2025-06-05 16:20:20 +02:00
if (!$stats) {
$stats = new Stats();
2025-06-17 19:38:44 +02:00
$stats->setDateCreated(new \DateTime());
$stats->setDateModified(new \DateTime());
2025-06-17 18:27:19 +02:00
$stats->setZone($insee_code)
2025-06-05 16:20:20 +02:00
->setPlacesCount(0)
->setAvecHoraires(0)
->setAvecAdresse(0)
->setAvecSite(0)
->setAvecAccessibilite(0)
->setAvecNote(0)
->setCompletionPercent(0);
2025-06-17 16:23:29 +02:00
$this->entityManager->persist($stats);
$this->entityManager->flush();
}
2025-06-05 17:32:12 +02:00
$stats->setName($city);
2025-06-17 16:23:29 +02:00
// Récupérer la population via l'API
$population = null;
try {
2025-06-17 18:27:19 +02:00
$apiUrl = 'https://geo.api.gouv.fr/communes/' . $insee_code;
2025-06-17 16:23:29 +02:00
$response = file_get_contents($apiUrl);
if ($response !== false) {
$data = json_decode($response, true);
if (isset($data['population'])) {
$population = (int)$data['population'];
$stats->setPopulation($population);
}
2025-06-17 18:27:19 +02:00
if (isset($data['siren'])) {
$stats->setSiren((int)$data['siren']);
}
if (isset($data['codeEpci'])) {
$stats->setCodeEpci((int)$data['codeEpci']);
}
if (isset($data['codesPostaux'])) {
$stats->setCodesPostaux(implode(';', $data['codesPostaux']));
}
2025-06-17 16:23:29 +02:00
}
} catch (\Exception $e) {
2025-06-17 18:27:19 +02:00
$this->addFlash('error', 'Erreur lors de la récupération des données de l\'API : ' . $e->getMessage());
2025-06-17 16:23:29 +02:00
}
2025-06-05 16:20:20 +02:00
// Récupérer toutes les données
2025-06-21 10:26:55 +02:00
$places_overpass = $this->motocultrice->labourer($insee_code);
2025-06-05 16:20:20 +02:00
$processedCount = 0;
$updatedCount = 0;
2025-06-21 10:26:55 +02:00
$deletedCount = 0;
$overpass_osm_ids = array_map(fn($place) => $place['id'], $places_overpass);
foreach ($places_overpass as $placeData) {
2025-06-05 16:20:20 +02:00
// Vérifier si le lieu existe déjà
$existingPlace = $this->entityManager->getRepository(Place::class)
->findOneBy(['osmId' => $placeData['id']]);
if (!$existingPlace) {
$place = new Place();
$place->setOsmId($placeData['id'])
->setOsmKind($placeData['type'])
2025-06-17 18:27:19 +02:00
->setZipCode($insee_code)
2025-06-05 16:20:20 +02:00
->setUuidForUrl($this->motocultrice->uuid_create())
->setModifiedDate(new \DateTime())
->setStats($stats)
->setDead(false)
->setOptedOut(false)
->setMainTag($this->motocultrice->find_main_tag($placeData['tags']) ?? '')
->setStreet($this->motocultrice->find_street($placeData['tags']) ?? '')
->setHousenumber($this->motocultrice->find_housenumber($placeData['tags']) ?? '')
->setSiret($this->motocultrice->find_siret($placeData['tags']) ?? '')
2025-06-05 16:20:20 +02:00
->setAskedHumainsSupport(false)
->setLastContactAttemptDate(null)
2025-06-21 10:26:55 +02:00
->setNote($this->motocultrice->find_tag($placeData['tags'], 'note') ? true : false)
->setNoteContent($this->motocultrice->find_tag($placeData['tags'], 'note') ?? '')
->setPlaceCount(0)
// ->setOsmData($placeData['modified'] ?? null)
;
2025-06-05 16:20:20 +02:00
// Mettre à jour les données depuis Overpass
$place->update_place_from_overpass_data($placeData);
2025-06-05 16:20:20 +02:00
$this->entityManager->persist($place);
$stats->addPlace($place);
$processedCount++;
} elseif ($updateExisting) {
2025-06-21 10:26:55 +02:00
// Mettre à jour les données depuis Overpass et s'assurer qu'il est marqué comme "vivant"
$existingPlace->setDead(false);
2025-06-05 16:20:20 +02:00
$existingPlace->update_place_from_overpass_data($placeData);
2025-06-21 10:26:55 +02:00
$stats->addPlace($existingPlace);
2025-06-05 16:20:20 +02:00
$this->entityManager->persist($existingPlace);
$updatedCount++;
2025-06-03 16:19:07 +02:00
}
}
2025-06-05 16:20:20 +02:00
2025-06-21 11:28:31 +02:00
// Supprimer les lieux qui ne sont plus dans la réponse Overpass, si activé
if ($deleteMissing) {
$db_places = $this->entityManager->getRepository(Place::class)->findBy(['zip_code' => $insee_code]);
foreach ($db_places as $db_place) {
if (!in_array($db_place->getOsmId(), $overpass_osm_ids)) {
$this->entityManager->remove($db_place);
$deletedCount++;
}
2025-06-21 10:26:55 +02:00
}
}
// Récupérer tous les commerces de la zone qui n'ont pas été supprimés
$commerces = $this->entityManager->getRepository(Place::class)->findBy(['zip_code' => $insee_code]);
// Récupérer les stats existantes pour la zone
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
if(!$stats) {
$stats = new Stats();
$stats->setZone($insee_code);
}
$urls = $stats->getAllCTCUrlsMap();
2025-06-05 16:20:20 +02:00
2025-06-21 10:26:55 +02:00
$statsHistory = $this->entityManager->getRepository(StatsHistory::class)
->createQueryBuilder('sh')
->where('sh.stats = :stats')
->setParameter('stats', $stats)
->orderBy('sh.id', 'DESC')
->setMaxResults(365)
->getQuery()
->getResult();
// Calculer les statistiques
$calculatedStats = $this->motocultrice->calculateStats($commerces);
// Mettre à jour les stats pour la zone donnée
$stats->setPlacesCount($calculatedStats['places_count']);
$stats->setAvecHoraires($calculatedStats['counters']['avec_horaires']);
$stats->setAvecAdresse($calculatedStats['counters']['avec_adresse']);
$stats->setAvecSite($calculatedStats['counters']['avec_site']);
$stats->setAvecAccessibilite($calculatedStats['counters']['avec_accessibilite']);
$stats->setAvecNote($calculatedStats['counters']['avec_note']);
$stats->setCompletionPercent($calculatedStats['completion_percent']);
// Associer les stats à chaque commerce
foreach ($commerces as $commerce) {
$commerce->setStats($stats);
$this->entityManager->persist($commerce);
}
2025-06-05 16:20:20 +02:00
$stats->computeCompletionPercent();
2025-06-05 17:32:12 +02:00
2025-06-19 12:49:30 +02:00
// Calculer les statistiques de fraîcheur des données OSM
$timestamps = [];
foreach ($stats->getPlaces() as $place) {
if ($place->getOsmDataDate()) {
$timestamps[] = $place->getOsmDataDate()->getTimestamp();
}
}
if (!empty($timestamps)) {
// Date la plus ancienne (min)
$minTimestamp = min($timestamps);
$stats->setOsmDataDateMin(new \DateTime('@' . $minTimestamp));
// Date la plus récente (max)
$maxTimestamp = max($timestamps);
$stats->setOsmDataDateMax(new \DateTime('@' . $maxTimestamp));
// Date moyenne
$avgTimestamp = array_sum($timestamps) / count($timestamps);
$stats->setOsmDataDateAvg(new \DateTime('@' . (int)$avgTimestamp));
}
2025-06-17 19:38:44 +02:00
if($stats->getDateCreated() == null) {
$stats->setDateCreated(new \DateTime());
}
$stats->setDateModified(new \DateTime());
2025-06-17 18:27:19 +02:00
// Créer un historique des statistiques
$statsHistory = new StatsHistory();
2025-06-17 19:38:44 +02:00
$statsHistory->setDate(new \DateTime())
->setStats($stats);
2025-06-19 11:07:54 +02:00
// Compter les Places avec email et SIRET
$placesWithEmail = 0;
$placesWithSiret = 0;
foreach ($stats->getPlaces() as $place) {
if ($place->getEmail() && $place->getEmail() !== '') {
$placesWithEmail++;
}
if ($place->getSiret() && $place->getSiret() !== '') {
$placesWithSiret++;
}
}
2025-06-17 18:27:19 +02:00
$statsHistory->setPlacesCount($stats->getPlaces()->count())
2025-06-17 19:38:44 +02:00
->setOpeningHoursCount($stats->getAvecHoraires())
->setAddressCount($stats->getAvecAdresse())
->setWebsiteCount($stats->getAvecSite())
2025-06-19 11:07:54 +02:00
->setSiretCount($placesWithSiret)
->setEmailsCount($placesWithEmail)
2025-06-17 19:38:44 +02:00
// ->setAccessibiliteCount($stats->getAvecAccessibilite())
// ->setNoteCount($stats->getAvecNote())
2025-06-17 18:27:19 +02:00
->setCompletionPercent($stats->getCompletionPercent())
->setStats($stats);
$this->entityManager->persist($statsHistory);
2025-06-17 19:38:44 +02:00
2025-06-05 16:20:20 +02:00
$this->entityManager->persist($stats);
$this->entityManager->flush();
$message = 'Labourage terminé avec succès. ' . $processedCount . ' nouveaux lieux traités.';
if ($updateExisting) {
2025-06-21 10:26:55 +02:00
$message .= ' ' . $updatedCount . ' lieux existants mis à jour.';
}
if ($deletedCount > 0) {
$message .= ' ' . $deletedCount . ' lieux ont été supprimés.';
2025-06-05 16:20:20 +02:00
}
2025-06-21 10:26:55 +02:00
$message .= ' Zone : '.$stats->getName().' ('.$stats->getZone().').';
2025-06-05 16:20:20 +02:00
$this->addFlash('success', $message);
} catch (\Exception $e) {
$this->addFlash('error', 'Erreur lors du labourage : ' . $e->getMessage());
2025-06-17 19:38:44 +02:00
die(var_dump($e));
}
2025-06-17 19:38:44 +02:00
// return $this->redirectToRoute('app_public_dashboard');
return $this->redirectToRoute('app_admin_stats', ['insee_code' => $insee_code]);
}
#[Route('/admin/delete/{id}', name: 'app_admin_delete')]
public function delete(int $id): Response
{
$commerce = $this->entityManager->getRepository(Place::class)->find($id);
2025-05-28 16:24:34 +02:00
if($commerce) {
$this->entityManager->remove($commerce);
$this->entityManager->flush();
2025-05-28 16:24:34 +02:00
$this->addFlash('success', 'Le lieu '.$commerce->getName().' a été supprimé avec succès de OSM Mes commerces, mais pas dans OpenStreetMap.');
} else {
$this->addFlash('error', 'Le lieu n\'existe pas.');
}
2025-05-28 16:24:34 +02:00
return $this->redirectToRoute('app_public_dashboard');
}
2025-06-17 18:27:19 +02:00
#[Route('/admin/delete_by_zone/{insee_code}', name: 'app_admin_delete_by_zone')]
public function delete_by_zone(string $insee_code): Response
{
2025-06-17 18:27:19 +02:00
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
2025-06-21 11:28:31 +02:00
if (!$stats) {
$this->addFlash('error', 'Aucune statistique trouvée pour la zone ' . $insee_code);
return $this->redirectToRoute('app_public_dashboard');
}
2025-06-21 11:28:31 +02:00
try {
// 1. Supprimer tous les StatsHistory associés
foreach ($stats->getStatsHistories() as $history) {
$this->entityManager->remove($history);
}
// 2. Supprimer tous les Places associées
foreach ($stats->getPlaces() as $place) {
$this->entityManager->remove($place);
}
// 3. Supprimer l'objet Stats lui-même
$this->entityManager->remove($stats);
// 4. Appliquer les changements à la base de données
$this->entityManager->flush();
$this->addFlash('success', 'La zone ' . $insee_code . ' et toutes les données associées ont été supprimées avec succès.');
} catch (\Exception $e) {
$this->addFlash('error', 'Une erreur est survenue lors de la suppression de la zone ' . $insee_code . ': ' . $e->getMessage());
}
2025-05-28 16:24:34 +02:00
return $this->redirectToRoute('app_public_dashboard');
}
#[Route('/admin/export', name: 'app_admin_export')]
public function export(): Response
{
$places = $this->entityManager->getRepository(Place::class)->findAll();
$csvData = [];
$csvData[] = [
'Nom',
'Email',
'Code postal',
'ID OSM',
'Type OSM',
'Date de modification',
'Date dernier contact',
'Note',
'Désabonné',
'Inactif',
'Support humain demandé',
'A des horaires',
'A une adresse',
'A un site web',
'A accessibilité',
'A une note'
];
foreach ($places as $place) {
$csvData[] = [
$place->getName(),
$place->getEmail(),
$place->getZipCode(),
$place->getOsmId(),
$place->getOsmKind(),
$place->getModifiedDate() ? $place->getModifiedDate()->format('Y-m-d H:i:s') : '',
$place->getLastContactAttemptDate() ? $place->getLastContactAttemptDate()->format('Y-m-d H:i:s') : '',
$place->getNote(),
$place->isOptedOut() ? 'Oui' : 'Non',
$place->isDead() ? 'Oui' : 'Non',
$place->isAskedHumainsSupport() ? 'Oui' : 'Non',
$place->hasOpeningHours() ? 'Oui' : 'Non',
$place->hasAddress() ? 'Oui' : 'Non',
$place->hasWebsite() ? 'Oui' : 'Non',
$place->hasWheelchair() ? 'Oui' : 'Non',
$place->hasNote() ? 'Oui' : 'Non'
];
}
$response = new Response();
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="export_places.csv"');
$handle = fopen('php://temp', 'r+');
foreach ($csvData as $row) {
fputcsv($handle, $row, ';');
}
rewind($handle);
$response->setContent(stream_get_contents($handle));
fclose($handle);
return $response;
}
2025-06-17 18:27:19 +02:00
#[Route('/admin/export_csv/{insee_code}', name: 'app_admin_export_csv')]
public function export_csv(string $insee_code): Response
2025-06-03 13:04:09 +02:00
{
2025-06-17 18:27:19 +02:00
$stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
$response = new Response($this->motocultrice->export($insee_code));
2025-06-03 13:04:09 +02:00
$response->headers->set('Content-Type', 'text/csv');
$slug_name = str_replace(' ', '-', $stats->getName());
2025-06-03 16:19:07 +02:00
2025-06-17 18:27:19 +02:00
$response->headers->set('Content-Disposition', 'attachment; filename="osm-commerces-export_' . $insee_code . '_' . $slug_name . '_' . date('Y-m-d_H-i-s') . '.csv"');
2025-06-03 13:04:09 +02:00
return $response;
}
#[Route('/admin/make_email_for_place/{id}', name: 'app_admin_make_email_for_place')]
public function make_email_for_place(Place $place): Response
{
return $this->render('admin/view_email_for_place.html.twig', ['place' => $place]);
}
#[Route('/admin/no_more_sollicitation_for_place/{id}', name: 'app_admin_no_more_sollicitation_for_place')]
public function no_more_sollicitation_for_place(Place $place): Response
{
$place->setOptedOut(true);
$this->entityManager->persist($place);
$this->entityManager->flush();
$this->addFlash('success', 'Votre lieu '.$place->getName().' ne sera plus sollicité pour mettre à jour ses informations.');
return $this->redirectToRoute('app_public_index');
}
#[Route('/admin/send_email_to_place/{id}', name: 'app_admin_send_email_to_place')]
public function send_email_to_place(Place $place, \Symfony\Component\Mailer\MailerInterface $mailer): Response
{
// Vérifier si le lieu est opted out
if ($place->isOptedOut()) {
$this->addFlash('error', 'Ce lieu a demandé à ne plus être sollicité pour mettre à jour ses informations.');
return $this->redirectToRoute('app_public_index');
}
// Vérifier si le lieu a déjà été contacté
if ($place->getLastContactAttemptDate() !== null) {
$this->addFlash('error', 'Ce lieu a déjà été contacté le ' . $place->getLastContactAttemptDate()->format('d/m/Y H:i:s'));
return $this->redirectToRoute('app_public_index');
}
// Générer le contenu de l'email avec le template
$emailContent = $this->renderView('admin/email_content.html.twig', [
'place' => $place
]);
// Envoyer l'email
$email = (new \Symfony\Component\Mime\Email())
->from('contact@openstreetmap.fr')
->to('contact+send_email@cipherbliss.com')
->subject('Mise à jour des informations de votre établissement dans OpenStreetMap')
->html($emailContent);
$mailer->send($email);
// Mettre à jour la date de dernier contact
$place->setLastContactAttemptDate(new \DateTime());
$this->entityManager->persist($place);
$this->entityManager->flush();
$this->addFlash('success', 'Email envoyé avec succès à ' . $place->getName() . ' le ' . $place->getLastContactAttemptDate()->format('d/m/Y H:i:s'));
return $this->redirectToRoute('app_public_index');
}
2025-05-26 11:55:44 +02:00
}