Issues (18)

src/Utils/ExifHelper.php (1 issue)

Severity
1
<?php
2
3
namespace App\Utils;
4
5
use PHPExif\Exif;
6
7
/**
8
 * Wrapper for PHPExif's Exif class, which is a little annoying and
9
 * also has incorrect PHPDoc in a couple of places. Basically translates
10
 * all calls we use to return exactly the type we need, or null, to
11
 * make it nice and compatible with our existing code.
12
 */
13
class ExifHelper implements ExifHelperInterface
14
{
15
    /** @var Exif */
16
    private $exif;
17
18
    public function __construct(Exif $exif)
19
    {
20
        $this->exif = $exif;
21
    }
22
23
    public function getTitle():?string
24
    {
25
        $title = $this->exif->getTitle();
26
        if ($title === false) {
27
            return null;
28
        }
29
        // I cast to string to work around a weird bug in
30
        // what looks like exiftool, where PHPExif's use
31
        // of it uses its JSON output, and exiftool's
32
        // JSON returns titles that look like numbers
33
        // (e.g. "42") as integer (i.e. unquoted 42 in the
34
        // JSON.)
35
        return (string) $title;
36
    }
37
    public function getDescription():?string
38
    {
39
        $description = $this->exif->getCaption();
40
        if ($description === false) {
41
            return null;
42
        }
43
        return (string) $description;
44
    }
45
    public function getGPS():?array
46
    {
47
        $gps = []; // Match the default in our Image entity
48
        $gps_as_string = $this->exif->getGPS();
49
        if (is_string($gps_as_string)) {
50
            $gps = array_map('doubleval', explode(',', $gps_as_string));
51
        }
52
        return $gps;
53
    }
54
    public function getKeywords():?array
55
    {
56
        $keywords = $this->exif->getKeywords();
57
        if (is_string($keywords)) {
0 ignored issues
show
The condition is_string($keywords) is always false.
Loading history...
58
            // A single keyword comes back as a simple string, not an array. We
59
            // always return an array.
60
            $keywords = [ $keywords ];
61
        }
62
        if (is_array($keywords)) {
63
            return $keywords;
64
        }
65
        return []; // Match the default in our Image entity
66
    }
67
    public function getCreationDate():?\DateTime
68
    {
69
        $creationDate = $this->exif->getCreationDate();
70
        if ($creationDate instanceof \DateTime) {
71
            // PHPExif assumes that the camera time string is UTC. It's not for many
72
            // people's cameras, including mine. Re-interpret it as local time in
73
            // Bristol. Not much of a bodge given that this project is specifically
74
            // limited to a small geographical region!
75
            $converted = new \DateTime($creationDate->format("Y-m-d\TH:i:s"), new \DateTimeZone("Europe/London"));
76
            $converted->setTimezone(new \DateTimeZone("UTC"));
77
            return $converted;
78
        }
79
        return null;
80
    }
81
    public function getRating():?int
82
    {
83
        $raw = $this->exif->getRawData();
84
        if (array_key_exists('XMP-xmp:Rating', $raw)) {
85
            $rating = $raw['XMP-xmp:Rating'];
86
            if (is_int($rating)) {
87
                return $rating;
88
            }
89
        }
90
        return null;
91
    }
92
    public function getLocation(): ?string
93
    {
94
        $raw = $this->exif->getRawData();
95
        if (array_key_exists('IPTC:Sub-location', $raw)) {
96
            $location = $raw['IPTC:Sub-location'];
97
            if (is_string($location)) {
98
                return $location;
99
            }
100
        }
101
        return null;
102
    }
103
}