Passed
Branch 2.0.0-dev (b7b9ad)
by Jeroen
02:54
created

ImageValue::sanitizeMimeType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
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
        $this->setValue($value);
20
    }
21
22
    public function __toString(): string
23
    {
24
        return $this->value;
25
    }
26
27
    public function getValue(): string
28
    {
29
        return $this->value;
30
    }
31
32
    private function getValueType(string $value): string
33
    {
34
        if ($this->isBase64Encoded($value)) {
35
            return self::BASE_64_ENCODED;
36
        }
37
38
        if ($this->isURL($value)) {
39
            return self::URL;
40
        }
41
42
        if ($this->isLocalImagePath($value)) {
43
            return self::LOCAL_IMAGE_PATH;
44
        }
45
46
        return self::BASE_64_DECODED;
47
    }
48
49
    private function isBase64Encoded(string $content): bool
50
    {
51
        return strpos($content, 'data') === 0;
52
    }
53
54
    private function isLocalImagePath(string $localImagePath): bool
55
    {
56
        try {
57
            if (is_file($localImagePath)) {
58
                return true;
59
            }
60
        } catch (\Exception $e) {
61
            return false;
62
        }
63
64
        return false;
65
    }
66
67
    private function isURL(string $value): bool
68
    {
69
        return filter_var($value, FILTER_VALIDATE_URL) !== false;
70
    }
71
72
    private function isValidLocalImage(string $imagePath): bool
73
    {
74
        $mimeType = mime_content_type($imagePath);
75
        $this->sanitizeMimeType($mimeType);
76
77
        return $this->isValidMimeType($mimeType);
78
    }
79
80
    private function isValidImageURL(string $URL): bool
81
    {
82
        $headers = get_headers($URL, 1);
83
84
        if (array_key_exists('Content-Type', $headers)) {
85
            $mimeType = $headers['Content-Type'];
86
87
            if (is_array($mimeType)) {
88
                $mimeType = end($mimeType);
89
            }
90
        }
91
92
        $this->sanitizeMimeType($mimeType);
93
94
        return $this->isValidMimeType($mimeType);
95
    }
96
97
    private function isValidImageContent(string $value): bool
98
    {
99
        $finfo = new \finfo();
100
        $mimeType = $finfo->buffer($value, FILEINFO_MIME_TYPE);
101
        $this->sanitizeMimeType($mimeType);
102
103
        return $this->isValidMimeType($mimeType);
104
    }
105
106
    private function isValidMimeType(string $mimeType): bool
107
    {
108
        if (!is_string($mimeType) || substr($mimeType, 0, 6) !== 'image/') {
0 ignored issues
show
introduced by
The condition is_string($mimeType) is always true.
Loading history...
109
            return false;
110
        }
111
        ;
112
        return true;
113
    }
114
115
    private function sanitizeMimeType(string &$mimeType)
116
    {
117
        if (strpos($mimeType, ';') !== false) {
118
            $mimeType = strstr($mimeType, ';', true);
119
        }
120
    }
121
122
    private function setValue(string $value): void
123
    {
124
        $valueType = $this->getValueType($value);
125
126
        switch ($valueType) {
127
            case self::LOCAL_IMAGE_PATH:
128
                if (!$this->isValidLocalImage($value)) {
129
                    throw PropertyException::forInvalidImage();
130
                }
131
132
                try {
133
                    $value = file_get_contents(realpath($value));
134
                } catch (\Exception $e) {
135
                    throw PropertyException::forInvalidImage();
136
                }
137
138
                break;
139
            case self::BASE_64_DECODED:
140
                if (!$this->isValidImageContent($value)) {
141
                    throw PropertyException::forInvalidImage();
142
                }
143
144
                $value = base64_encode($value);
145
146
                break;
147
            case self::URL:
148
                if (!$this->isValidImageURL($value)) {
149
                    throw PropertyException::forInvalidImage();
150
                }
151
152
                break;
153
            default:
154
                break;
155
        }
156
157
        $this->value = $value;
158
    }
159
}
160