schneespur/release/schneespur-1.0.2/app/Services/ForecastService.php
Michael 7288b93500 Release v1.0.2: diagnostic infrastructure core
Add neutral diagnostic framework for future reporting modules:
- DiagnosticReporterInterface, Registry, Manager, PayloadSanitizer
- Laravel exception hook in bootstrap/app.php
- Module permission declarations (requires_permissions in module.json)
- Core diagnostic report points (module boot/install/update failures)
- Module documentation update (moduldoku.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-18 16:54:11 +00:00

67 lines
2.1 KiB
PHP

<?php
namespace App\Services;
use App\Models\Setting;
use App\Services\Weather\ConditionMapper;
use App\Services\Weather\WeatherProviderRegistry;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class ForecastService
{
private const DEFAULT_CACHE_TTL = 300;
public function __construct(
private readonly WeatherProviderRegistry $registry,
) {}
public function current(float $lat, float $lon): ?array
{
$providerSlug = $this->registry->activeSlug();
$cacheKey = "weather_forecast_{$providerSlug}";
$cacheTtl = (int) Setting::get('weather_cache_ttl', self::DEFAULT_CACHE_TTL);
try {
return Cache::remember($cacheKey, $cacheTtl, function () use ($lat, $lon) {
return $this->fetchViaProvider($lat, $lon);
});
} catch (\Throwable $e) {
Log::warning('ForecastService: cache layer failed, attempting direct fetch', [
'error' => $e->getMessage(),
'lat' => $lat,
'lon' => $lon,
]);
return $this->fetchViaProvider($lat, $lon);
}
}
private function fetchViaProvider(float $lat, float $lon): ?array
{
$provider = $this->registry->resolve();
$data = $provider->fetchCurrent($lat, $lon);
if ($data === null) {
return null;
}
return [
'temperature' => $data->temperature_c,
'precipitation' => $data->precipitation_mm,
'snow_depth' => $data->snowfall_mm,
'weather_code' => $data->weather_code ?? 0,
'wind_speed' => $data->wind_kmh,
'humidity' => $data->humidity_percent,
'icon' => ConditionMapper::icon($data->condition),
'label' => __('weather.wmo_' . ($data->weather_code ?? 0)),
'time' => $data->observed_at->format('Y-m-d\TH:i'),
'provider' => $data->provider,
];
}
public static function wmoIcon(int $code): string
{
return ConditionMapper::icon(ConditionMapper::fromWmoCode($code));
}
}