From b1965abe06c6600224eb4c11747a63795ce57571 Mon Sep 17 00:00:00 2001 From: Tykayn Date: Mon, 26 May 2025 16:22:01 +0200 Subject: [PATCH] up edit form --- config/packages/framework.yaml | 2 +- src/Controller/PublicController.php | 52 ++++++++--- src/Service/Motocultrice.php | 95 +++++++++++++++++++++ templates/public/edit.html.twig | 128 ++++++++++++++++++++++++++-- translations/messages.en.yaml | 90 ++++++++++++------- translations/messages.fr.yaml | 7 ++ 6 files changed, 325 insertions(+), 49 deletions(-) diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 965dc41..5086845 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -8,7 +8,7 @@ framework: default_locale: 'fr' translator: default_path: '%kernel.project_dir%/translations' - fallbacks: ['fr'] + fallbacks: ['en'] # Enables session support. Note that the session will ONLY be started if you read or write from it. # Remove or comment this section to explicitly disable session support. diff --git a/src/Controller/PublicController.php b/src/Controller/PublicController.php index cb27b3e..d6a7462 100644 --- a/src/Controller/PublicController.php +++ b/src/Controller/PublicController.php @@ -46,6 +46,7 @@ class PublicController extends AbstractController return $this->render('public/edit.html.twig', [ 'commerce' => $commerce, 'name' => $name, + 'osm_kind' => $place->getOsmKind(), "mapbox_token" => $_ENV['MAPBOX_TOKEN'], "maptiler_token" => $_ENV['MAPTILER_TOKEN'], ]); @@ -74,14 +75,31 @@ class PublicController extends AbstractController 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 = []; foreach ($request->request->all() 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; } } @@ -102,7 +120,7 @@ class PublicController extends AbstractController $tag = $changeset->addChild('tag'); $tag->addAttribute('k', 'comment'); - $tag->addAttribute('v', 'Modification des tags via l\'interface web'); + $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(), @@ -114,19 +132,29 @@ class PublicController extends AbstractController $newChangesetId = $changesetResponse->getBody()->getContents(); - // 2. Modifier le nœud avec le nouveau changeset + // 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(''); - $node = $xml->addChild('node'); - $node->addAttribute('id', $osm_object_id); - $node->addAttribute('version', $version); - $node->addAttribute('changeset', $newChangesetId); - $node->addAttribute('lat', '49.6504926'); - $node->addAttribute('lon', '-1.5722526'); + $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 = $node->addChild('tag'); + $tag = $object->addChild('tag'); $tag->addAttribute('k', htmlspecialchars($key, ENT_XML1)); $tag->addAttribute('v', htmlspecialchars($value, ENT_XML1)); } @@ -134,9 +162,9 @@ class PublicController extends AbstractController // Debug du XML généré $xmlString = $xml->asXML(); - var_dump($xmlString); + // echo('xml :
'.$xmlString); - $response = $client->put('https://api.openstreetmap.org/api/0.6/node/' . $osm_object_id, [ + $response = $client->put("https://api.openstreetmap.org/api/0.6/{$osm_kind}/" . $osm_object_id, [ 'body' => $xmlString, 'headers' => [ 'Authorization' => 'Bearer ' . $osm_api_token, @@ -166,7 +194,7 @@ class PublicController extends AbstractController } // après envoi on récupère les données - $commerce = $this->motocultrice->get_osm_object_data($osm_object_id); + $commerce = $this->motocultrice->get_osm_object_data($osm_kind, $osm_object_id); return $this->render('public/view.html.twig', [ 'controller_name' => 'PublicController', 'commerce' => $commerce, diff --git a/src/Service/Motocultrice.php b/src/Service/Motocultrice.php index 19a379f..1124218 100644 --- a/src/Service/Motocultrice.php +++ b/src/Service/Motocultrice.php @@ -8,6 +8,7 @@ use Doctrine\ORM\EntityManagerInterface; class Motocultrice { private $overpassApiUrl = 'https://overpass-api.de/api/interpreter'; + private $osmApiUrl = 'https://www.openstreetmap.org/api/0.6'; public function __construct( private HttpClientInterface $client, @@ -141,4 +142,98 @@ QUERY; mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) ); } + + public function formatOsmDataForSubmit(array $data): array + { + // Garder uniquement les tags essentiels + $essentialTags = [ + 'name', + 'opening_hours', + 'phone', + 'contact:email', + 'contact:phone', + 'website', + 'contact:website', + 'wheelchair', + 'addr:housenumber', + 'addr:street', + 'addr:city', + 'addr:postcode', + 'amenity', + 'shop', + 'tourism', + 'source', + 'ref:FR:SIRET' + ]; + + $formattedData = [ + 'node' => [ + '@attributes' => [ + 'id' => $data['@attributes']['id'], + 'version' => $data['@attributes']['version'], + 'changeset' => $data['@attributes']['changeset'], + 'lat' => $data['@attributes']['lat'], + 'lon' => $data['@attributes']['lon'] + ], + 'tag' => [] + ] + ]; + + // Filtrer et ajouter uniquement les tags essentiels + if (isset($data['tag'])) { + foreach ($data['tag'] as $tag) { + if (in_array($tag['@attributes']['k'], $essentialTags)) { + $formattedData['node']['tag'][] = $tag; + } + } + } + + return $formattedData; + } + + private function arrayToXml(array $data): string + { + $xml = new \SimpleXMLElement(''); + + if (isset($data['node'])) { + $node = $xml->addChild('node'); + foreach ($data['node']['@attributes'] as $key => $value) { + $node->addAttribute($key, $value); + } + + if (isset($data['node']['tag'])) { + foreach ($data['node']['tag'] as $tag) { + $tagElement = $node->addChild('tag'); + $tagElement->addAttribute('k', $tag['@attributes']['k']); + $tagElement->addAttribute('v', $tag['@attributes']['v']); + } + } + } + + return $xml->asXML(); + } + + public function submitOsmData(array $data): void + { + $formattedData = $this->formatOsmDataForSubmit($data); + $xmlData = $this->arrayToXml($formattedData); + + try { + $response = $this->client->request('PUT', + "{$this->osmApiUrl}/node/{$data['@attributes']['id']}", + [ + 'body' => $xmlData, + 'headers' => [ + 'Content-Type' => 'application/xml; charset=utf-8' + ] + ] + ); + + if ($response->getStatusCode() !== 200) { + throw new \Exception("Erreur lors de la soumission des données : " . $response->getContent()); + } + } catch (\Exception $e) { + throw new \Exception("Erreur lors de la communication avec l'API OSM : " . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/templates/public/edit.html.twig b/templates/public/edit.html.twig index 13baa09..f29e7ea 100644 --- a/templates/public/edit.html.twig +++ b/templates/public/edit.html.twig @@ -9,6 +9,10 @@ .hidden { display: none; } + input[type="checkbox"] { + width: 20px; + height: 20px; + } {% endblock %} @@ -54,6 +58,7 @@
+
- {% if commerce.tags_converted.image %} + {% if commerce.tags_converted.image is defined %} Image du lieu {% endif %} -

{{ 'display.tags'|trans }}

-
- {% for attributes in commerce.tag %} - {% for kv in attributes %} +

{{ 'display.attributes'|trans }}

+ +
+
+ +
+
+ +
+
+ +
+
+ + {# cas d'une mairie + #} + + {% if commerce.tags_converted.amenity is defined %} + {% if commerce.tags_converted.amenity == 'townhall' %} +
+
+ + + +
+
+ {% endif %} + + {% if commerce.tags_converted.amenity == 'restaurant' %} +
+
+ +
+
+ + {{'display.help.cuisine'|trans}} +
+
+ {% endif %} + {% endif %} +
+
+ +
+

{{ 'display.ask_angela'|trans }}

+

{{ 'display.ask_angela_description'|trans }}

+

+ {{ 'display.ask_angela_more_info'|trans }} +

+ +
+
+ + + +
+
+
+ +
+

{{ 'display.wheelchair'|trans }}

+
+
+ + + +
+
+
+
+

{{ 'display.opening_hours'|trans }}

+

{{ 'display.opening_hours_description'|trans }}

+ + + Lundi de + + + à + . + + + et + + + à + . + + +
+ +
+
+

{{ 'display.address'|trans }}

+
+
+ + + +
+
+
+
+ {% for attributes in commerce.tag %} + {% for kv in attributes %} {% if kv.k == 'opening_hours' %} {{ 'display.keys.opening_hours'|trans }} {% else %} @@ -87,7 +203,7 @@ {% endif %} {% endfor %} {% endfor %} -
+
diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index aacf144..bc6cae3 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -1,33 +1,63 @@ display: - title: "OSM My Shop" - home: "Home" - stats: "Statistics" - contact_humans: "Contact OSM France humans for help" - modify: "Modify" - welcome: "Welcome to the shops!" - modify_commerce: "Modify your shop" - tags: "Tags" - submit: "Submit" - last_modification: "Last modification" - days_ago: "%days% days ago" - by: "by" - view_on_osm: "View on OpenStreetMap" + title: 'OSM My Shop' + home: 'Home' + stats: 'Statistics' + welcome: 'Welcome to the shops!' + contact_humans: 'Contact OSM France humans for help' + modify: 'Modify' + modify_commerce: 'Modify your shop' + tags: 'Tags' + submit: 'Submit' + last_modification: 'Last modification' + days_ago: '%days% days ago' + by: 'by' + view_on_osm: 'View on OpenStreetMap' + please_select: 'Please select' + wheelchair: 'Wheelchair access' + ask_angela: 'Ask Angela' + ask_angela_description: 'This place is participating in the national campaign "Ask Angela" to help the prevention of harassment' + ask_angela_more_info: 'More information on the campaign' + address: 'Address' + attributes: 'Attributes' + opening_hours: 'Opening hours' + opening_hours_description: 'Good opening hours are important for customers to find you.' + values: + wheelchair: + yes: 'the place is fully accessible in wheelchair' + limited: 'the place is accessible in wheelchair but with some limitations' + no: 'the place is not accessible in wheelchair' + angela: + yes: 'Yes' + no: 'No' + building: + main: 'Main' + annex: 'Annex' + cuisine: 'Cuisine' keys: - tags: "tags" - name: "Name" - address: "Address" - phone: "Phone" - contact:email: "Email" - contact:phone: "Contact phone" - address:housenumber: "Street number" - address:street: "Street" - address:city: "City" - address:postcode: "Postal code" - website: "Website" - contact:website: "Contact website" - opening_hours: "Opening hours" - shop: "Shop type" - tourism: "Tourism" + tags: 'tags' + name: 'Name' + address: 'Address' + phone: 'Phone' + building: 'Building' + contact:email: 'Email' + contact:phone: 'Contact phone' + address:housenumber: 'Street number' + address:street: 'Street' + address:city: 'City' + address:postcode: 'Postal code' + website: 'Website' + contact:website: 'Contact website' + opening_hours: 'Opening hours' + shop: 'Shop type' + tourism: 'Tourism' + wheelchair: 'Wheelchair access' + addr:housenumber: 'Street number' + addr:street: 'Street' + addr:city: 'City' + addr:postcode: 'Postal code' + amenity: 'Amenity' + source: 'Source' + ref:FR:SIRET: 'SIRET' disclaimer: - title: "Warning" - text: "This site is a work in progress, this is a demonstration on a fictional object using OpenStreetMap API data." \ No newline at end of file + title: 'Warning' + text: 'This site is a work in progress, this is a demonstration on a fictional object using OpenStreetMap API data.' \ No newline at end of file diff --git a/translations/messages.fr.yaml b/translations/messages.fr.yaml index 293b088..3cedfa3 100644 --- a/translations/messages.fr.yaml +++ b/translations/messages.fr.yaml @@ -12,6 +12,12 @@ display: days_ago: "il y a %days% jours" by: "par" view_on_osm: "Voir sur OpenStreetMap" + please_select: "Veuillez sélectionner" + values: + wheelchair: "Accès PMR" + yes: "le lieu est totalement praticable en fauteuil roulant" + limited: "le lieu est accessible en fauteuil roulant mais pas partout" + no: "le lieu n'est pas accessible en fauteuil roulant" keys: tags: "étiquettes" name: "Nom" @@ -28,6 +34,7 @@ display: opening_hours: "Horaires d'ouverture" shop: "Type de commerce" tourism: "Tourisme" + wheelchair: "Accès PMR" disclaimer: title: "Attention" text: "Ce site est un travail en cours, ceci est une démonstration sur un objet fictif qui utilise les données de l'API OpenStreetMap."