Files
FlightsAPI/app/Services/FlightStatsService.php
2026-05-18 14:31:53 +10:00

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;
}
}