osm-commerces/src/Controller/PublicController.php
2025-05-27 11:18:29 +02:00

266 lines
11 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;
class PublicController extends AbstractController
{
public function __construct(
private EntityManagerInterface $entityManager,
private Motocultrice $motocultrice
) {
}
#[Route('/', name: 'app_public_index')]
public function index(): Response
{
$commerce = $this->motocultrice->get_osm_object_data();
return $this->render('public/index.html.twig', [
'controller_name' => 'PublicController',
'commerce' => $commerce,
'mapbox_token' => $_ENV['MAPBOX_TOKEN'],
'maptiler_token' => $_ENV['MAPTILER_TOKEN'],
]);
}
#[Route('/edit/{zipcode}/{name}/{uuid}', name: 'app_public_edit')]
public function edit_with_uuid($zipcode, $name, $uuid): Response
{
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['uuid_for_url' => $uuid]);
if (!$place) {
$this->addFlash('warning', 'Ce lien de modification n\'existe pas.');
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']);
return $this->render('public/edit.html.twig', [
'commerce_overpass' => $commerce_overpass,
'name' => $name,
'commerce' => $place,
'osm_kind' => $place->getOsmKind(),
"mapbox_token" => $_ENV['MAPBOX_TOKEN'],
"maptiler_token" => $_ENV['MAPTILER_TOKEN'],
]);
}
#[Route('/dashboard', name: 'app_public_dashboard')]
public function dashboard(): Response
{
// get stats
$stats = $this->entityManager->getRepository(Stats::class)->findAll();
$places = $this->entityManager->getRepository(Place::class)->findBy([], ['zip_code' => 'ASC', 'name' => 'ASC']);
return $this->render('public/dashboard.html.twig', [
'controller_name' => 'PublicController',
'stats' => $stats,
'places' => $places,
]);
}
#[Route('/modify/{osm_object_id}/{version}/{changesetID}', name: 'app_public_submit')]
public function submit($osm_object_id, $version, $changesetID): Response
{
// Récupérer les données POST
$request = Request::createFromGlobals();
// Vérifier si des données ont été soumises
if ($request->isMethod('POST')) {
$status = "non modifié";
// Récupérer le type d'objet (node ou way)
$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) {
// var_dump($key, $value);
if (strpos($key, 'commerce_tag_value__') === 0) {
$tagKey = str_replace('commerce_tag_value__', '', $key);
if (!empty($value)) {
// Validation des données selon le type de tag
if ($tagKey === 'addr:postcode') {
// Vérifier que c'est bien un code postal français (5 chiffres)
if (!preg_match('/^\d{5}$/', $value)) {
$status = "Erreur : Le code postal doit être composé de 5 chiffres";
continue;
}
} elseif ($tagKey === 'contact:phone' || $tagKey === 'phone') {
// Nettoyer le numéro de téléphone
$value = preg_replace('/[^0-9+]/', '', $value);
} elseif (strpos($value, 'http://') === 0) {
$value = str_replace('http://', 'https://', $value);
}
$tags[$tagKey] = $value;
}
}
}
// Récupérer le token OSM depuis les variables d'environnement
$osm_api_token = $_ENV['APP_OSM_BEARER'];
$exception = false;
$exception_message = "";
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 des tags via l\'interface web #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();
// echo('xml : <br>'.$xmlString);
$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";
}
} 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());
}
}
}
// après envoi on récupère les données
$commerce = $this->motocultrice->get_osm_object_data($osm_kind, $osm_object_id);
return $this->render('public/view.html.twig', [
'controller_name' => 'PublicController',
'commerce' => $commerce,
'status' => $status,
'exception' => $exception,
'exception_message' => $exception_message,
'mapbox_token' => $_ENV['MAPBOX_TOKEN'],
'maptiler_token' => $_ENV['MAPTILER_TOKEN'],
]);
}
#[Route('/request_email_to_modify/{osm_object_id}', name: 'app_public_request_email')]
public function request_email($osm_object_id): Response
{
if ($this->getRequest()->isMethod('POST')) {
$email = $this->getRequest()->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->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,
]);
}
}