Intégration fonctionnalites V1
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class GeocodingService
|
||||
{
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function search(string $query): array
|
||||
{
|
||||
$query = trim($query);
|
||||
|
||||
if (strlen($query) < 3) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->client()->get(config('services.nominatim.url').'/search', [
|
||||
'q' => $query,
|
||||
'format' => 'json',
|
||||
'addressdetails' => 1,
|
||||
'limit' => 5,
|
||||
'countrycodes' => 'fr',
|
||||
]);
|
||||
} catch (ConnectionException|RequestException $exception) {
|
||||
Log::warning('Geocoding search failed.', [
|
||||
'query' => $query,
|
||||
'message' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! $response->successful()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect($response->json())
|
||||
->map(fn (array $item) => $this->formatResult($item))
|
||||
->filter(fn (array $item) => $item['address'] !== '')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{latitude: float, longitude: float}|null
|
||||
*/
|
||||
public function geocode(string $address, ?string $city = null, ?string $zipCode = null): ?array
|
||||
{
|
||||
$query = collect([$address, $zipCode, $city, 'France'])
|
||||
->filter(fn (?string $part) => $part !== null && trim($part) !== '')
|
||||
->implode(', ');
|
||||
|
||||
$results = $this->search($query);
|
||||
|
||||
if ($results === [] || $results[0]['latitude'] === null || $results[0]['longitude'] === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'latitude' => $results[0]['latitude'],
|
||||
'longitude' => $results[0]['longitude'],
|
||||
];
|
||||
}
|
||||
|
||||
private function client(): PendingRequest
|
||||
{
|
||||
return Http::withHeaders([
|
||||
'User-Agent' => config('services.nominatim.user_agent'),
|
||||
'Accept-Language' => 'fr',
|
||||
])
|
||||
->withOptions([
|
||||
'verify' => (bool) config('services.nominatim.verify_ssl', true),
|
||||
])
|
||||
->timeout(8)
|
||||
->connectTimeout(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $item
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatResult(array $item): array
|
||||
{
|
||||
$addressParts = $item['address'] ?? [];
|
||||
$street = trim(($addressParts['house_number'] ?? '').' '.($addressParts['road'] ?? ''));
|
||||
|
||||
if ($street === '') {
|
||||
$street = trim((string) ($item['name'] ?? ''));
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => (string) ($item['display_name'] ?? $street),
|
||||
'address' => $street,
|
||||
'city' => $addressParts['city']
|
||||
?? $addressParts['town']
|
||||
?? $addressParts['village']
|
||||
?? $addressParts['municipality']
|
||||
?? '',
|
||||
'zip_code' => (string) ($addressParts['postcode'] ?? ''),
|
||||
'latitude' => isset($item['lat']) ? (float) $item['lat'] : null,
|
||||
'longitude' => isset($item['lon']) ? (float) $item['lon'] : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user