112 lines
3.1 KiB
PHP
112 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\DTOs\FlightStatData;
|
|
use App\Models\Aircraft;
|
|
use App\Models\IataEquipmentCode;
|
|
use Carbon\CarbonImmutable;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class FlightStatsService
|
|
{
|
|
|
|
public function fetchOtherDays(string $airlineCode, string $flightNumber): array
|
|
{
|
|
$url = sprintf(
|
|
'https://www.flightstats.com/v2/api-next/flight-tracker/other-days/%s/%s',
|
|
$airlineCode,
|
|
$flightNumber,
|
|
);
|
|
|
|
$response = Http::withOptions([
|
|
'verify' => config('app.verify_ssl'),
|
|
])->get($url);
|
|
|
|
if (!$response->successful()) {
|
|
return [];
|
|
}
|
|
|
|
$data = $response->json('data');
|
|
|
|
if (!is_array($data)) {
|
|
return [];
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function fetchFlightData(string $airlineCode, string $flightNumber, ?CarbonImmutable $date = null): ?FlightStatData
|
|
{
|
|
$specificDate = $date !== null;
|
|
$date ??= now()->utc()->toImmutable();
|
|
|
|
$data = $this->fetchForDate($airlineCode, $flightNumber, $date);
|
|
|
|
if ($data || $specificDate) return $data;
|
|
|
|
$otherDays = $this->fetchOtherDays($airlineCode, $flightNumber);
|
|
|
|
$pastDays = collect($otherDays)
|
|
->filter(fn($day) => !empty($day['flights']))
|
|
->sortByDesc(fn($day) => $day['year'] . $day['date1']);
|
|
|
|
foreach ($pastDays as $day) {
|
|
$pastDate = CarbonImmutable::createFromFormat('Y-d-M', $day['year'] . '-' . $day['date1']);
|
|
$result = $this->fetchForDate($airlineCode, $flightNumber, $pastDate);
|
|
if ($result) return $result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function fetchForDate(string $airlineCode, string $flightNumber, CarbonImmutable $date): ?FlightStatData
|
|
{
|
|
$url = sprintf(
|
|
'https://www.flightstats.com/v2/api-next/flight-tracker/%s/%s/%d/%d/%d',
|
|
$airlineCode,
|
|
$flightNumber,
|
|
$date->year,
|
|
$date->month,
|
|
$date->day,
|
|
);
|
|
|
|
$response = Http::withOptions([
|
|
'verify' => config('app.verify_ssl'),
|
|
])->get($url);
|
|
|
|
if (!$response->successful()) {
|
|
Log::warning("FlightStats request failed for {$airlineCode}{$flightNumber}: HTTP {$response->status()}");
|
|
return null;
|
|
}
|
|
|
|
$flightData = $response->json('data');
|
|
|
|
if (empty($flightData)) return null;
|
|
|
|
return FlightStatData::fromApiResponse($flightData);
|
|
}
|
|
|
|
public function guessAircraftFromIata(string $iataCode): ?Aircraft
|
|
{
|
|
$equipment = IataEquipmentCode::where('iata_code', $iataCode)->first();
|
|
|
|
if (!$equipment) {
|
|
Log::info("Unknown IATA equipment code: {$iataCode}");
|
|
return null;
|
|
}
|
|
|
|
$aircraft = Aircraft::where('designator', $equipment->icao_code)
|
|
->orderByDesc('preferred')
|
|
->orderBy('id')
|
|
->first();
|
|
|
|
if (!$aircraft) {
|
|
Log::info("No aircraft found for ICAO: {$equipment->icao_code} (IATA: {$iataCode})");
|
|
}
|
|
|
|
return $aircraft;
|
|
}
|
|
}
|