Passed
Branch 2.0.0-dev (8e5e1f)
by Jeroen
03:00
created

ImageValue::isBase64Encoded()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace JeroenDesloovere\VCard\Property\Value;
4
5
use JeroenDesloovere\VCard\Exception\PropertyException;
6
7
class ImageValue
8
{
9
    /** @var string - The raw image value or the external URL */
10
    private $value;
11
12
    private const BASE_64_DECODED = 'base_64_decoded';
13
    private const BASE_64_ENCODED = 'base_64_encoded';
14
    private const LOCAL_IMAGE_PATH = 'local_image_path';
15
    private const URL = 'url';
16
17
    public function __construct(string $value)
18
    {
19
        $valueType = $this->getValueType($value);
20
21
        switch ($valueType) {
22
            case self::BASE_64_DECODED:
23
                $this->setValueImageContent($value);
24
                break;
25
            case self::BASE_64_ENCODED:
26
                $this->value = $value;
27
                break;
28
            case self::LOCAL_IMAGE_PATH:
29
                $this->setValueLocalImage($value);
30
                break;
31
            case self::URL:
32
                $this->setValueImageURL($value);
33
                break;
34
            default:
35
                throw PropertyException::forInvalidImage();
36
                break;
37
        }
38
    }
39
40
    public function __toString(): string
41
    {
42
        return $this->value;
43
    }
44
45
    public function getValue(): string
46
    {
47
        return $this->value;
48
    }
49
50
    private function setValueLocalImage(string $value): void
51
    {
52
        if (!$this->isValidLocalImage($value)) {
53
            throw PropertyException::forInvalidImage();
54
        }
55
56
        try {
57
            $this->value = file_get_contents(realpath($value));
58
        } catch (\Exception $e) {
59
            throw PropertyException::forInvalidImage();
60
        }
61
    }
62
63
    private function setValueImageContent(string $value): void
64
    {
65
        if (!$this->isValidImageContent($value)) {
66
            throw PropertyException::forInvalidImage();
67
        }
68
69
        $this->value = base64_encode($value);
70
    }
71
72
    private function setValueImageURL(string $value): void
73
    {
74
        if (!$this->isValidImageURL($value)) {
75
            throw PropertyException::forInvalidImage();
76
        }
77
78
        $this->value = $value;
79
    }
80
81
    private function getValueType(string $value): string
82
    {
83
        if ($this->isBase64Encoded($value)) {
84
            return self::BASE_64_ENCODED;
85
        }
86
87
        if ($this->isURL($value)) {
88
            return self::URL;
89
        }
90
91
        if ($this->isLocalImagePath($value)) {
92
            return self::LOCAL_IMAGE_PATH;
93
        }
94
95
        return self::BASE_64_DECODED;
96
    }
97
98
    private function isBase64Encoded(string $content): bool
99
    {
100
        return strpos($content, 'data') === 0;
101
    }
102
103
    private function isLocalImagePath(string $localImagePath): bool
104
    {
105
        try {
106
            if (is_file($localImagePath)) {
107
                return true;
108
            }
109
        } catch (\Exception $e) {
110
            return false;
111
        }
112
113
        return false;
114
    }
115
116
    private function isURL(string $value): bool
117
    {
118
        return filter_var($value, FILTER_VALIDATE_URL) !== false;
119
    }
120
121
    private function isValidLocalImage(string $imagePath): bool
122
    {
123
        $mimeType = mime_content_type($imagePath);
124
        $this->sanitizeMimeType($mimeType);
125
126
        return $this->isValidMimeType($mimeType);
127
    }
128
129
    private function isValidImageURL(string $URL): bool
130
    {
131
        $headers = get_headers($URL, 1);
132
133
        if (array_key_exists('Content-Type', $headers)) {
134
            $mimeType = $headers['Content-Type'];
135
136
            if (is_array($mimeType)) {
137
                $mimeType = end($mimeType);
138
            }
139
        }
140
141
        $this->sanitizeMimeType($mimeType);
142
143
        return $this->isValidMimeType($mimeType);
144
    }
145
146
    private function isValidImageContent(string $value): bool
147
    {
148
        $finfo = new \finfo();
149
        $mimeType = $finfo->buffer($value, FILEINFO_MIME_TYPE);
150
        $this->sanitizeMimeType($mimeType);
151
152
        return $this->isValidMimeType($mimeType);
153
    }
154
155
    private function isValidMimeType(string $mimeType): bool
156
    {
157
        return is_string($mimeType) && strpos($mimeType, 'image/') === 0;
158
    }
159
160
    private function sanitizeMimeType(string &$mimeType): void
161
    {
162
        if (strpos($mimeType, ';') !== false) {
163
            $mimeType = strstr($mimeType, ';', true);
164
        }
165
    }
166
}
167