"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 get_query_places($zone) { return <<.france; area["postal_code"="{$zone}"](area.france)->.searchArea; ( nw["amenity"~"^(cafe|bar|restaurant|library|cinema|fast_food|post_office|marketplace|community_centre|theatre|bank|townhall)$"](area.searchArea); nw["shop"](area.searchArea); nw["healthcare"](area.searchArea); nw["office"](area.searchArea); ); out body; >; out skel qt; QUERY; } 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 { $use_places_without_email_to_reference = $_ENV['USE_PLACES_WITHOUT_EMAIL_TO_REFERENCE'] ?? false; if (!$zone) { throw new \InvalidArgumentException("La zone ne peut pas être vide"); } // Nettoyer et échapper la zone pour la requête $zone = addslashes(trim($zone)); // //area["postal_code"="{$zone}"]->.searchArea; $query = $this->get_query_places($zone); if($use_places_without_email_to_reference) { $query = $this->get_query_places($zone); } try { $response = $this->client->request('POST', $this->overpassApiUrl, [ 'body' => ['data' => $query] ]); $data = json_decode($response->getContent(), true); $places = []; if (isset($data['elements'])) { foreach ($data['elements'] as $element) { if (isset($element['tags'])) { $email = ""; if( ! $use_places_without_email_to_reference){ $email = $element['tags']['contact:email'] ?? $element['tags']['email'] ?? null; // On passe si pas d'email if (!$email) { continue; } } $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) { var_dump($essai_query); var_dump($e->getMessage()); die(); 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[\"postal_code\"=\"{$zip_code}\"]->.searchArea; ( relation[\"admin_level\"=\"8\"][\"name\"][\"type\"=\"boundary\"][\"boundary\"=\"administrative\"](area.searchArea); ); out body; >; out skel qt;"; // $query = "area[\"postal_code\"=\"{$zip_code}\"]->.searchArea;"; $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; // dump($object_id); // die(); 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 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 ]; } }