mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-06-20 01:44:42 +02:00
up edit form
This commit is contained in:
parent
fd72a1cedc
commit
b1965abe06
6 changed files with 325 additions and 49 deletions
|
@ -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.
|
||||
|
|
|
@ -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('<?xml version="1.0" encoding="UTF-8"?><osm version="0.6"></osm>');
|
||||
$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 : <br>'.$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,
|
||||
|
|
|
@ -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('<?xml version="1.0" encoding="UTF-8"?><osm></osm>');
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,10 @@
|
|||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -54,6 +58,7 @@
|
|||
</div>
|
||||
|
||||
<form action="{{ path('app_public_submit', {'osm_object_id': commerce['@attributes'].id, 'version': commerce['@attributes'].version, 'changesetID': commerce['@attributes'].changeset }) }}" method="post" class="needs-validation">
|
||||
<input type="hidden" name="osm_kind" value="{{ osm_kind }}">
|
||||
<div class="mb-3">
|
||||
<label for="commerce_id" class="form-label">{{ 'display.modify_commerce'|trans }}:
|
||||
<strong>{{ commerce.tags_converted.name }}</strong>
|
||||
|
@ -64,14 +69,125 @@
|
|||
</div>
|
||||
|
||||
|
||||
{% if commerce.tags_converted.image %}
|
||||
{% if commerce.tags_converted.image is defined %}
|
||||
<img src="{{ commerce.tags_converted.image }}" alt="Image du lieu" class="img-fluid mb-3">
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ 'display.tags'|trans }}</h2>
|
||||
<fieldset>
|
||||
{% for attributes in commerce.tag %}
|
||||
{% for kv in attributes %}
|
||||
<h2>{{ 'display.attributes'|trans }}</h2>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__name">{{'display.keys.name'|trans}}</label>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" name="commerce_tag_value__name" value=" {% if commerce.tags_converted.name is defined %}{{ commerce.tags_converted.name }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# cas d'une mairie
|
||||
#}
|
||||
|
||||
{% if commerce.tags_converted.amenity is defined %}
|
||||
{% if commerce.tags_converted.amenity == 'townhall' %}
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__building">{{'display.keys.building'|trans}}</label>
|
||||
|
||||
<select class="form-control" placeholder="{{'display.please_select'|trans}}" name="commerce_tag_value__building">
|
||||
<option value="">{{'display.please_select'|trans}}</option>
|
||||
<option value="main">{{'display.values.building.main'|trans}}</option>
|
||||
<option value="annex">{{'display.values.building.annex'|trans}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if commerce.tags_converted.amenity == 'restaurant' %}
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__cuisine">{{'display.keys.cuisine'|trans}}</label>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" name="commerce_tag_value__cuisine"
|
||||
placeholder="française;italienne;japonaise"
|
||||
value="{% if commerce.tags_converted.cuisine is defined %}{{ commerce.tags_converted.cuisine }}{% endif %}">
|
||||
<small class="form-text text-muted">{{'display.help.cuisine'|trans}}</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ask_angela">
|
||||
<h2>{{ 'display.ask_angela'|trans }}</h2>
|
||||
<p class="description">{{ 'display.ask_angela_description'|trans }}</p>
|
||||
<p class="more-info">
|
||||
<a href="https://www.openstreetmap.fr/contact/" target="_blank">{{ 'display.ask_angela_more_info'|trans }}</a>
|
||||
</p>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__angela">{{'display.ask_angela'|trans}}</label>
|
||||
|
||||
<input type="checkbox" name="commerce_tag_value__angela" value="yes">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="wheelchair">
|
||||
<h2>{{ 'display.wheelchair'|trans }}</h2>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__wheelchair">{{'display.keys.wheelchair'|trans}}</label>
|
||||
|
||||
<select class="form-control" placeholder="{{'display.please_select'|trans}}" name="commerce_tag_value__wheelchair" value="{% if commerce.tags_converted.wheelchair is defined %}{{ commerce.tags_converted.wheelchair }}{% endif %}">
|
||||
<option value="">{{'display.please_select'|trans}}</option>
|
||||
<option value="yes">{{'display.values.wheelchair.yes'|trans}}</option>
|
||||
<option value="limited">{{'display.values.wheelchair.limited'|trans}}</option>
|
||||
<option value="no">{{'display.values.wheelchair.no'|trans}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="opening_hours">
|
||||
<h2>{{ 'display.opening_hours'|trans }}</h2>
|
||||
<p class="description">{{ 'display.opening_hours_description'|trans }}</p>
|
||||
|
||||
<input type="checkbox" name="commerce_tag_value__opening_hours_1" value="yes">
|
||||
Lundi de
|
||||
|
||||
<input type="number" name="commerce_tag_value__opening_hours_1_midday_hour" value="">
|
||||
à
|
||||
<input type="number" name="commerce_tag_value__opening_hours_1_midday_minute" value="">.
|
||||
|
||||
<input type="checkbox" name="commerce_tag_value__opening_hours_1_midday" value="yes">
|
||||
et
|
||||
|
||||
<input type="number" name="commerce_tag_value__opening_hours_1_midday_hour" value="">
|
||||
à
|
||||
<input type="number" name="commerce_tag_value__opening_hours_1_midday_minute" value="">.
|
||||
|
||||
<input type="checkbox" name="commerce_tag_value__opening_hours_1_evening" value="yes">
|
||||
<hr>
|
||||
|
||||
</div>
|
||||
<div id="addresses">
|
||||
<h2>{{ 'display.address'|trans }}</h2>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="commerce_tag_value__addr:housenumber">{{'display.keys.addr:housenumber'|trans}}</label>
|
||||
|
||||
<label for="commerce_tag_value__addr:street">{{'display.keys.addr:street'|trans}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset>
|
||||
{% 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 %}
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<button type="submit" class="btn btn-primary">{{ 'display.submit'|trans }}</button>
|
||||
</form>
|
||||
|
|
|
@ -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."
|
||||
title: 'Warning'
|
||||
text: 'This site is a work in progress, this is a demonstration on a fictional object using OpenStreetMap API data.'
|
|
@ -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."
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue