172 lines
5.8 KiB
PHP
172 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class OpenTripMapService
|
|
{
|
|
private string $baseUrl;
|
|
private string $apiKey;
|
|
private int $cacheTtl;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->baseUrl = 'https://api.opentripmap.com/0.1/en/places';
|
|
$this->apiKey = config('services.opentripmap.key', env('OPENTRIPMAP_API_KEY'));
|
|
$this->cacheTtl = config('services.opentripmap.cache_ttl', 7) * 24 * 60; // Convert days to minutes
|
|
}
|
|
|
|
/**
|
|
* Get attractions near coordinates
|
|
*
|
|
* @param float $lat
|
|
* @param float $lon
|
|
* @param int $radius in meters (default 5000m = 5km)
|
|
* @param int $limit
|
|
* @return array
|
|
*/
|
|
public function getAttractions(float $lat, float $lon, int $radius = 5000, int $limit = 50): array
|
|
{
|
|
$cacheKey = "opentripmap:attractions:{$lat}:{$lon}:{$radius}:{$limit}";
|
|
|
|
return Cache::remember($cacheKey, $this->cacheTtl, function () use ($lat, $lon, $radius, $limit) {
|
|
try {
|
|
$response = Http::timeout(15)
|
|
->get("{$this->baseUrl}/radius", [
|
|
'apikey' => $this->apiKey,
|
|
'radius' => $radius,
|
|
'lon' => $lon,
|
|
'lat' => $lat,
|
|
'limit' => $limit,
|
|
'format' => 'json',
|
|
]);
|
|
|
|
if ($response->successful()) {
|
|
$features = $response->json('features', []);
|
|
$attractions = [];
|
|
|
|
foreach ($features as $feature) {
|
|
$properties = $feature['properties'] ?? [];
|
|
$geometry = $feature['geometry'] ?? [];
|
|
$coordinates = $geometry['coordinates'] ?? [];
|
|
|
|
if (!empty($properties['name'])) {
|
|
$attractions[] = [
|
|
'name' => $properties['name'],
|
|
'source_id' => $properties['xid'] ?? null,
|
|
'latitude' => $coordinates[1] ?? null,
|
|
'longitude' => $coordinates[0] ?? null,
|
|
'category' => $this->mapCategory($properties['kinds'] ?? ''),
|
|
'rating' => $properties['rate'] ?? null,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $attractions;
|
|
}
|
|
|
|
Log::warning("OpenTripMap API request failed", [
|
|
'status' => $response->status(),
|
|
'lat' => $lat,
|
|
'lon' => $lon,
|
|
]);
|
|
|
|
return [];
|
|
} catch (\Exception $e) {
|
|
Log::error("OpenTripMap API error", [
|
|
'error' => $e->getMessage(),
|
|
'lat' => $lat,
|
|
'lon' => $lon,
|
|
]);
|
|
|
|
return [];
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get detailed information about an attraction
|
|
*
|
|
* @param string $xid OpenTripMap attraction ID
|
|
* @return array|null
|
|
*/
|
|
public function getAttractionDetails(string $xid): ?array
|
|
{
|
|
$cacheKey = "opentripmap:details:{$xid}";
|
|
|
|
return Cache::remember($cacheKey, $this->cacheTtl, function () use ($xid) {
|
|
try {
|
|
$response = Http::timeout(10)
|
|
->get("{$this->baseUrl}/xid/{$xid}", [
|
|
'apikey' => $this->apiKey,
|
|
]);
|
|
|
|
if ($response->successful()) {
|
|
$data = $response->json();
|
|
|
|
return [
|
|
'name' => $data['name'] ?? null,
|
|
'description' => $data['wikipedia_extracts']['text'] ?? $data['info']['descr'] ?? null,
|
|
'image_url' => $data['preview']['source'] ?? $data['image'] ?? null,
|
|
'wikipedia_url' => $data['wikipedia'] ?? null,
|
|
'rating' => $data['rate'] ?? null,
|
|
];
|
|
}
|
|
|
|
return null;
|
|
} catch (\Exception $e) {
|
|
Log::error("OpenTripMap details error for xid: {$xid}", [
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Map OpenTripMap categories to our simplified categories
|
|
*
|
|
* @param string $kinds
|
|
* @return string
|
|
*/
|
|
private function mapCategory(string $kinds): string
|
|
{
|
|
$kinds = strtolower($kinds);
|
|
|
|
if (str_contains($kinds, 'museums')) {
|
|
return 'museum';
|
|
} elseif (str_contains($kinds, 'theatres_and_entertainments') || str_contains($kinds, 'cinemas')) {
|
|
return 'entertainment';
|
|
} elseif (str_contains($kinds, 'cultural') || str_contains($kinds, 'interesting_places')) {
|
|
return 'cultural';
|
|
} elseif (str_contains($kinds, 'architecture') || str_contains($kinds, 'historic')) {
|
|
return 'historic';
|
|
} elseif (str_contains($kinds, 'natural') || str_contains($kinds, 'nature_reserves')) {
|
|
return 'nature';
|
|
} elseif (str_contains($kinds, 'sport')) {
|
|
return 'sport';
|
|
} elseif (str_contains($kinds, 'food') || str_contains($kinds, 'restaurants')) {
|
|
return 'restaurant';
|
|
}
|
|
|
|
return 'other';
|
|
}
|
|
|
|
/**
|
|
* Clear cache for specific coordinates
|
|
*
|
|
* @param float $lat
|
|
* @param float $lon
|
|
* @return void
|
|
*/
|
|
public function clearCache(float $lat, float $lon): void
|
|
{
|
|
// Clear all related cache keys
|
|
Cache::forget("opentripmap:attractions:{$lat}:{$lon}:5000:50");
|
|
}
|
|
}
|