87 lines
2.2 KiB
PHP
87 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\PhotoGeoData\Pages\Concerns;
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
trait HandlesImageMetadata
|
|
{
|
|
protected function syncMetadataFromImage(): void
|
|
{
|
|
$metadata = $this->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;
|
|
}
|
|
}
|