$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 { 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)); $query = <<.searchArea; ( // Recherche des commerces et services avec email nw["amenity"]["contact:email"](area.searchArea); nw["amenity"]["email"](area.searchArea); nw["shop"]["contact:email"](area.searchArea); nw["shop"]["email"](area.searchArea); nw["office"]["contact:email"](area.searchArea); nw["office"]["email"](area.searchArea); // Recherche des commerces et services sans email pour référence nw["amenity"](area.searchArea); nw["shop"](area.searchArea); nw["office"](area.searchArea); ); out body; >; out skel qt; QUERY; 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 = $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) { throw new \Exception("Erreur lors de la requête Overpass : " . $e->getMessage()); } } 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'])){ foreach ($osm_object_data['node']['tag'] as $attribute) { $osm_object_data['node']['tags_converted'][$attribute['@attributes']['k']] = $attribute['@attributes']['v']; } return $osm_object_data['node']; } if(isset($osm_object_data['way'])){ foreach ($osm_object_data['way']['tag'] as $attribute) { $osm_object_data['way']['tags_converted'][$attribute['@attributes']['k']] = $attribute['@attributes']['v']; } return $osm_object_data['way']; } return $osm_object_data; } 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 ]; } }