"was:shop", "information" => "was:information", "office" => "was:office", "amenity" => "was:amenity", "craft" => "was:craft", "operator" => "was:operator", "clothes" => "was:clothes", "cuisine" => "was:cuisine", "official_name" => "was:official_name", "short_name" => "was:short_name", "alt_name" => "was:alt_name" ]; public function export($zone) { $query = $this->get_export_query($zone); try { $response = $this->client->request('GET', 'https://overpass-api.de/api/interpreter', [ 'query' => [ 'data' => $query ] ]); return $response->getContent(); } catch (\Exception $e) { return "Erreur lors de la requête Overpass : " . $e->getMessage(); } } public function get_export_query($zone) { return <<.searchArea; {$this->overpass_base_places} out skel qt; QUERY; } public function get_query_places($zone) { return '[out:json][timeout:25]; area["ref:INSEE"="'.$zone.'"]->.searchArea; '.$this->overpass_base_places.' out center tags;'; } private $more_tags = ['image', 'ref:FR:SIRET']; public function __construct( private HttpClientInterface $client, private EntityManagerInterface $entityManager ) { } public function map_post_values($request_post) { $has_ask_angela = false; $remove_ask_angela = false; $has_opening_hours = false; $modified_request_post = []; foreach ($request_post as $key => $value) { if (strpos($key, 'custom__ask_angela') === 0 ) { if($value == 'ask_angela'){ $has_ask_angela = true; }else{ $remove_ask_angela = true; } } if (strpos($key, 'custom__opening_hours') === 0 && $value != '') { $has_opening_hours = true; } $modified_request_post[$key] = $value; } if($has_ask_angela) { $modified_request_post['commerce_tag_value__harassment_prevention'] = 'ask_angela'; } if($remove_ask_angela) { unset($modified_request_post['commerce_tag_value__harassment_prevention']); } if($has_opening_hours) { $modified_request_post['commerce_tag_value__opening_hours'] = $request_post['commerce_tag_value__opening_hours']; } return $modified_request_post; } public function labourer(string $zone): array { try { $response = $this->client->request('POST', $this->overpassApiUrl, [ 'body' => ['data' => $this->get_query_places($zone)] ]); $data = json_decode($response->getContent(), true); $places = []; if (isset($data['elements'])) { foreach ($data['elements'] as $element) { if (isset($element['tags'])) { $email = ""; $places[] = [ 'id' => $element['id'], 'type' => $element['type'], 'name' => $element['tags']['name'] ?? '', 'email' => $email, 'lat' => $element['lat'] ?? null, 'lon' => $element['lon'] ?? null, 'tags' => $element['tags'] ]; } } } return $places; } catch (\Exception $e) { throw new \Exception("Erreur lors de la requête Overpass : " . $e->getMessage()); } } public function get_city_osm_from_zip_code($zip_code) { // Requête Overpass pour obtenir la zone administrative de niveau 8 avec un nom $query = "[out:json][timeout:25]; area[\"ref:INSEE\"=\"{$zip_code}\"]->.searchArea; ( relation[\"admin_level\"=\"8\"][\"name\"][\"type\"=\"boundary\"][\"boundary\"=\"administrative\"](area.searchArea); ); out body; >; out skel qt;"; $response = $this->client->request('POST', $this->overpassApiUrl, [ 'body' => ['data' => $query] ]); $data = json_decode($response->getContent(), true); if (isset($data['elements']) && !empty($data['elements'])) { $city = $data['elements'][0]['tags']['name']; return $city; } return null; } public function get_osm_object_data($osm_kind = 'node', $osm_object_id = 12855459190) { $object_id = "https://www.openstreetmap.org/api/0.6/".$osm_kind."/".$osm_object_id; try { $response = $this->client->request('GET', $object_id); $xml = simplexml_load_string($response->getContent()); $json = json_encode($xml); $osm_object_data = json_decode($json, true); } catch (\Exception $e) { throw new \Exception("Impossible de récupérer les données OSM : " . $e->getMessage()); } // convertir les tags en clés et valeurs, remplir avec les tags de base $osm_object_data['tags_converted'] = $this->base_tags; // Initialiser le tableau des tags convertis if (isset($osm_object_data['node'])) { $osm_object_data['node']['tags_converted'] = []; } elseif (isset($osm_object_data['way'])) { $osm_object_data['way']['tags_converted'] = []; } if(isset($osm_object_data['node'])){ // Vérifier si le nœud a des tags if (!isset($osm_object_data['node']['tag'])) { $osm_object_data['node']['tags_converted'] = []; return $osm_object_data['node']; } // Si un seul tag, le convertir en tableau if (isset($osm_object_data['node']['tag']['@attributes'])) { $osm_object_data['node']['tag'] = [$osm_object_data['node']['tag']]; } foreach ($osm_object_data['node']['tag'] as $tag) { $osm_object_data['node']['tags_converted'][$tag['@attributes']['k']] = $tag['@attributes']['v']; } $osm_object_data['node']['tags_converted'] = $this->migrate_tags($osm_object_data['node']['tags_converted']); return $osm_object_data['node']; } if(isset($osm_object_data['way'])){ // Vérifier si le way a des tags if (!isset($osm_object_data['way']['tag'])) { $osm_object_data['way']['tags_converted'] = []; return $osm_object_data['way']; } // Si un seul tag, le convertir en tableau if (isset($osm_object_data['way']['tag']['@attributes'])) { $osm_object_data['way']['tag'] = [$osm_object_data['way']['tag']]; } foreach ($osm_object_data['way']['tag'] as $attribute) { $osm_object_data['way']['tags_converted'][$attribute['@attributes']['k']] = $attribute['@attributes']['v']; } $osm_object_data['way']['tags_converted'] = $this->migrate_tags($osm_object_data['way']['tags_converted']); return $osm_object_data['way']; } return $osm_object_data; } public function find_main_tag($tags) { if(isset($tags['amenity']) && $tags['amenity'] != '') { return $tags['amenity']; } if(isset($tags['shop']) && $tags['shop'] != '') { return $tags['shop']; } if(isset($tags['tourism']) && $tags['tourism'] != '') { return $tags['tourism']; } if(isset($tags['healthcare']) && $tags['healthcare'] != '') { return $tags['healthcare']; } if(isset($tags['office']) && $tags['office'] != '') { return $tags['office']; } return null; } public function migrate_tags($osm_object_data) { // migrer email vers contact:email if(isset($osm_object_data['email']) && !isset($osm_object_data['contact:email'])){ $osm_object_data['contact:email'] = $osm_object_data['email']; unset($osm_object_data['email']); } // migrer phone vers contact:phone if(isset($osm_object_data['phone']) && !isset($osm_object_data['contact:phone'])){ $osm_object_data['contact:phone'] = $osm_object_data['phone']; unset($osm_object_data['phone']); } // migrer website vers contact:website if(isset($osm_object_data['website']) && !isset($osm_object_data['contact:website'])){ $osm_object_data['contact:website'] = $osm_object_data['website']; unset($osm_object_data['website']); } // migrer addr:housenumber vers contact:housenumber if(isset($osm_object_data['addr:housenumber']) && !isset($osm_object_data['contact:housenumber'])){ $osm_object_data['contact:housenumber'] = $osm_object_data['addr:housenumber']; unset($osm_object_data['addr:housenumber']); } // migrer addr:street vers contact:street if(isset($osm_object_data['addr:street']) && !isset($osm_object_data['contact:street'])){ $osm_object_data['contact:street'] = $osm_object_data['addr:street']; unset($osm_object_data['addr:street']); } return $osm_object_data; } public static function uuid_create_static() { return $this->uuid_create(); } public function uuid_create() { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', // 32 bits for "time_low" mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), // 16 bits for "time_mid" mt_rand( 0, 0xffff ), // 16 bits for "time_hi_and_version", // four most significant bits holds version number 4 mt_rand( 0, 0x0fff ) | 0x4000, // 16 bits, 8 bits for "clk_seq_hi_res", // 8 bits for "clk_seq_low", // two most significant bits holds zero and one for variant DCE1.1 mt_rand( 0, 0x3fff ) | 0x8000, // 48 bits for "node" 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()); } } public function calculateStats(array $places): array { $counters = [ 'avec_horaires' => 0, 'avec_adresse' => 0, 'avec_site' => 0, 'avec_accessibilite' => 0, 'avec_note' => 0 ]; foreach ($places as $place) { if ($place->hasOpeningHours()) { $counters['avec_horaires']++; } if ($place->hasAddress()) { $counters['avec_adresse']++; } if ($place->hasWebsite()) { $counters['avec_site']++; } if ($place->hasWheelchair()) { $counters['avec_accessibilite']++; } if ($place->hasNote()) { $counters['avec_note']++; } } $totalPlaces = count($places); $completionPercent = 0; if ($totalPlaces > 0) { $totalCriteria = 5; // nombre total de critères $totalCompleted = array_sum($counters); $completionPercent = round(($totalCompleted / ($totalPlaces * $totalCriteria)) * 100); } return [ 'places_count' => $totalPlaces, 'completion_percent' => $completionPercent, 'counters' => $counters ]; } }