extractImageMetadata($this->record->image_path); if ($metadata === null) { return; } $this->record->update(['metadata' => $metadata]); } private function extractImageMetadata(mixed $imagePath): ?array { if (empty($imagePath)) { return null; } $path = is_array($imagePath) ? reset($imagePath) : $imagePath; $fullPath = Storage::disk('public')->path($path); if (!file_exists($fullPath)) { Log::warning('extractImageMetadata: file not found', ['path' => $fullPath]); return null; } $exif = @exif_read_data($fullPath, null, true); if ($exif === false) { Log::debug('extractImageMetadata: no EXIF data', ['path' => $fullPath]); return null; } return $exif; } private function extractGpsCoordinates(array $exif): ?array { $gps = $exif['GPS'] ?? null; if (!$gps) { return null; } $lat = $this->rationalToDecimal($gps['GPSLatitude'] ?? null); $lng = $this->rationalToDecimal($gps['GPSLongitude'] ?? null); if ($lat === null || $lng === null) { return null; } if (($gps['GPSLatitudeRef'] ?? 'N') === 'S') { $lat = -$lat; } if (($gps['GPSLongitudeRef'] ?? 'E') === 'W') { $lng = -$lng; } return ['lat' => $lat, 'lng' => $lng]; } private function rationalToDecimal(?array $rational): ?float { if (!$rational || count($rational) < 3) { return null; } return $this->rationalValue($rational[0]) + $this->rationalValue($rational[1]) / 60 + $this->rationalValue($rational[2]) / 3600; } private function rationalValue(string $rational): float { [$num, $den] = array_pad(explode('/', $rational, 2), 2, '1'); return $den != 0 ? (float) $num / (float) $den : 0.0; } }