@@ -16,8 +16,23 @@ public static function isAvailable(): bool {
16
16
}
17
17
18
18
public function execute (File $ file ): array {
19
+ $ exifData = [];
19
20
$ fileDescriptor = $ file ->fopen ('rb ' );
20
- $ data = exif_read_data ($ fileDescriptor , 'COMPUTED ' , true );
21
+
22
+ // Copy image data into tmp stream as exif_read_data don't work properly with our streams wrappers.
23
+ $ nativeFileDescriptorStream = fopen ('php://temp ' , 'rw ' );
24
+ $ result = stream_copy_to_stream (
25
+ $ fileDescriptor ,
26
+ $ nativeFileDescriptorStream ,
27
+ );
28
+
29
+ if ($ result === false ) {
30
+ fclose ($ nativeFileDescriptorStream );
31
+ throw new \Exception ("Failed to copy into tmp stream from fileid: " . $ file ->getId ());
32
+ }
33
+
34
+ $ data = exif_read_data ($ nativeFileDescriptorStream , 'ANY_TAG ' , true );
35
+ fclose ($ nativeFileDescriptorStream );
21
36
22
37
$ size = new FileMetadata ();
23
38
$ size ->setGroupName ('size ' );
@@ -31,29 +46,63 @@ public function execute(File $file): array {
31
46
'width ' => $ sizeResult [0 ],
32
47
'height ' => $ sizeResult [1 ],
33
48
]);
49
+
50
+ $ exifData ['size ' ] = $ size ;
34
51
}
35
52
36
- return [
37
- 'size ' => $ size ,
38
- ];
53
+ } elseif (array_key_exists ('COMPUTED ' , $ data )) {
54
+ if (array_key_exists ('Width ' , $ data ['COMPUTED ' ]) && array_key_exists ('Height ' , $ data ['COMPUTED ' ])) {
55
+ $ size ->setMetadata ([
56
+ 'width ' => $ data ['COMPUTED ' ]['Width ' ],
57
+ 'height ' => $ data ['COMPUTED ' ]['Height ' ],
58
+ ]);
59
+
60
+ $ exifData ['size ' ] = $ size ;
61
+ }
39
62
}
40
63
41
- if (array_key_exists ('COMPUTED ' , $ data )
42
- && array_key_exists ('Width ' , $ data ['COMPUTED ' ])
43
- && array_key_exists ('Height ' , $ data ['COMPUTED ' ])
64
+ if ($ data && array_key_exists ('GPS ' , $ data )
65
+ && array_key_exists ('GPSLatitude ' , $ data ['GPS ' ]) && array_key_exists ( ' GPSLatitudeRef ' , $ data [ ' GPS ' ])
66
+ && array_key_exists ('GPSLongitude ' , $ data ['GPS ' ]) && array_key_exists ( ' GPSLongitudeRef ' , $ data [ ' GPS ' ])
44
67
) {
45
- $ size ->setMetadata ([
46
- 'width ' => $ data ['COMPUTED ' ]['Width ' ],
47
- 'height ' => $ data ['COMPUTED ' ]['Height ' ],
68
+ $ gps = new FileMetadata ();
69
+ $ gps ->setGroupName ('gps ' );
70
+ $ gps ->setId ($ file ->getId ());
71
+ $ gps ->setMetadata ([
72
+ 'coordinate ' => [
73
+ 'latitude ' => $ this ->gpsDegreesToDecimal ($ data ['GPS ' ]['GPSLatitude ' ], $ data ['GPS ' ]['GPSLatitudeRef ' ]),
74
+ 'longitude ' => $ this ->gpsDegreesToDecimal ($ data ['GPS ' ]['GPSLongitude ' ], $ data ['GPS ' ]['GPSLongitudeRef ' ]),
75
+ ],
48
76
]);
77
+
78
+ $ exifData ['gps ' ] = $ gps ;
49
79
}
50
80
51
- return [
52
- 'size ' => $ size ,
53
- ];
81
+ return $ exifData ;
54
82
}
55
83
56
84
public static function getMimetypesSupported (): string {
57
85
return '/image\/.*/ ' ;
58
86
}
87
+
88
+ /**
89
+ * @param array|string $coordinate
90
+ */
91
+ private static function gpsDegreesToDecimal (array $ coordinates , string $ hemisphere ): float {
92
+ if (is_string ($ coordinates )) {
93
+ $ coordinates = array_map ("trim " , explode (", " , $ coordinates ));
94
+ }
95
+
96
+ if (count ($ coordinates ) !== 3 ) {
97
+ throw new \Exception ('Invalid coordinate format: ' . $ coordinates );
98
+ }
99
+
100
+ [$ degrees , $ minutes , $ seconds ] = array_map (function (string $ rawDegree ) {
101
+ $ parts = explode ('/ ' , $ rawDegree );
102
+ return floatval ($ parts [0 ])/floatval ($ parts [1 ] ?? 1 );
103
+ }, $ coordinates );
104
+
105
+ $ sign = ($ hemisphere === 'W ' || $ hemisphere === 'S ' ) ? -1 : 1 ;
106
+ return $ sign * ($ degrees + $ minutes /60 + $ seconds /3600 );
107
+ }
59
108
}
0 commit comments