Test Failed
Pull Request — master (#6)
by mon
02:19
created

Type::getAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace FileEye\MimeMap;
4
5
/**
6
 * Class for working with MIME types
7
 */
8
class Type
9
{
10
    /**
11
     * Short format [e.g. image/jpeg] for strings.
12
     */
13
    const SHORT_TEXT = 0;
14
15
    /**
16
     * Full format [e.g. image/jpeg; p="1"] for strings.
17
     */
18
    const FULL_TEXT = 1;
19
20
    /**
21
     * Full format with comments [e.g. image/jpeg; p="1" (comment)] for strings.
22
     */
23
    const FULL_TEXT_WITH_COMMENTS = 2;
24
25
    /**
26
     * The MIME media type.
27
     *
28
     * @var string
29
     */
30
    protected $media;
31
32
    /**
33
     * The MIME media type comment.
34
     *
35
     * @var string
36
     */
37
    protected $mediaComment;
38
39
    /**
40
     * The MIME media sub-type.
41
     *
42
     * @var string
43
     */
44
    protected $subType;
45
46
    /**
47
     * The MIME media sub-type comment.
48
     *
49
     * @var string
50
     */
51
    protected $subTypeComment;
52 50
53
    /**
54 50
     * Optional MIME parameters
55 43
     *
56
     * @var TypeParameter[]
57
     */
58
    protected $parameters = [];
59
60
    /**
61
     * Constructor.
62
     *
63
     * The type string will be parsed and the appropriate class vars set.
64 50
     *
65
     * @param string $type MIME type
66
     */
67 50
    public function __construct($type)
68
    {
69 49
        $this->parse($type);
70 3
    }
71
72 46
    /**
73 1
     * Parse a mime-type and set the class variables.
74
     *
75
     * @param string $type MIME type to parse
76 45
     *
77 45
     * @return void
78 45
     */
79 43
    protected function parse($type)
80
    {
81
        // Media and SubType are separated by a slash '/'.
82
        $media = Parser::parseStringPart($type, 0, '/');
83
84
        if (!$media['string']) {
85
            throw new MalformedTypeException('Media type not found');
86
        }
87
        if (!$media['delimiter_matched']) {
88 45
            throw new MalformedTypeException('Slash \'/\' to separate media type and subtype not found');
89
        }
90
91 45
        $this->media = strtolower($media['string']);
92
        $this->mediaComment = $media['comment'];
93 44
94 1
        // SubType and Parameters are separated by semicolons ';'.
95
        $sub = Parser::parseStringPart($type, $media['end_offset'] + 1, ';');
96
97 43
        if (!$sub['string']) {
98 43
            throw new MalformedTypeException('Media subtype not found');
99
        }
100
101 43
        $this->subType = strtolower($sub['string']);
102 26
        $this->subTypeComment = $sub['comment'];
103 26
104 26
        // Loops through the parameter.
105 26
        while ($sub['delimiter_matched']) {
106
            $sub = Parser::parseStringPart($type, $sub['end_offset'] + 1, ';');
107 43
            $tmp = explode('=', $sub['string'], 2);
108
            $p_name = trim($tmp[0]);
109
            $p_val = trim($tmp[1]);
110
            if ($p_val[0] == '"' && $p_val[strlen($p_val) - 1] == '"') {
111
                $p_val = substr($p_val, 1, -1);
112
            }
113
            $p_val = str_replace('\\"', '"', $p_val);
114
            $this->addParameter($p_name, $p_val, $sub['comment']);
115
        }
116
    }
117
118
    /**
119
     * Does this type have any parameters?
120
     *
121
     * @return boolean true if type has parameters, false otherwise
122
     */
123
    public function hasParameters()
124
    {
125 50
        return (bool) $this->parameters;
126
    }
127 50
128 50
    /**
129 50
     * Get a MIME type's parameters
130 50
     *
131 50
     * @return TypeParameter[] Type's parameters
132
     */
133 50
    public function getParameters()
134 48
    {
135 46
        return $this->parameters;
136
    }
137 47
138 4
    /**
139 2
     * Get a MIME type's parameter
140
     *
141 2
     * @param string $name Parameter name
142
     *
143 4
     * @return TypeParameter|null
144 47
     */
145 4
    public function getParameter($name)
146 2
    {
147
        return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
148 4
    }
149 47
150 20
    /**
151 20
     * Get a MIME type's media.
152 20
     *
153
     * Note: 'media' refers to the portion before the first slash.
154 47
     *
155 20
     * @return string Type's media.
156 47
     */
157 9
    public function getMedia()
158 1
    {
159
        return $this->media;
160 8
    }
161 8
162
    /**
163 9
     * Get a MIME type's media comment.
164
     *
165
     * @return string Type's media comment.
166 47
     */
167 47
    public function getMediaComment()
168
    {
169 20
        return $this->mediaComment;
170
    }
171
172
    /**
173 50
     * Get a MIME type's subtype.
174 2
     *
175
     * @return string Type's subtype, null if invalid mime type.
176
     */
177
    public function getSubType()
178 49
    {
179 49
        return $this->subType;
180 49
    }
181 49
182
    /**
183
     * Get a MIME type's subtype comment.
184
     *
185
     * @return string Type's subtype comment, null if invalid mime type.
186
     */
187
    public function getSubTypeComment()
188
    {
189
        return $this->subTypeComment;
190
    }
191
192 26
    /**
193
     * Create a textual MIME type from object values
194 26
     *
195 26
     * This function performs the opposite function of parse().
196
     *
197
     * @param int $format The format of the output string.
198
     *
199
     * @return string MIME type string
200
     */
201
    public function toString($format = Type::FULL_TEXT)
202
    {
203
        $type = strtolower($this->media);
204
        if ($format > Type::FULL_TEXT && isset($this->mediaComment)) {
205 26
            $type .= ' (' .  $this->mediaComment . ')';
206
        }
207 26
        $type .= '/' . strtolower($this->subType);
208 26
        if ($format > Type::FULL_TEXT && isset($this->subTypeComment)) {
209 26
            $type .= ' (' .  $this->subTypeComment . ')';
210 26
        }
211
        if ($format > Type::SHORT_TEXT && count($this->parameters)) {
212
            foreach ($this->parameters as $parameter) {
213 26
                $type .= '; ' . $parameter->toString($format);
214 26
            }
215
        }
216
        return $type;
217
    }
218
219
    /**
220
     * Is this type experimental?
221
     *
222 28
     * Note: Experimental types are denoted by a leading 'x-' in the media or
223
     *       subtype, e.g. text/x-vcard or x-world/x-vrml.
224 28
     *
225
     * @return boolean true if type is experimental, false otherwise
226
     */
227
    public function isExperimental()
228
    {
229
        if (substr($this->getMedia(), 0, 2) == 'x-' || substr($this->getSubType(), 0, 2) == 'x-') {
230
            return true;
231
        }
232 29
        return false;
233
    }
234 29
235
    /**
236
     * Is this a vendor MIME type?
237
     *
238
     * Note: Vendor types are denoted with a leading 'vnd. in the subtype.
239
     *
240
     * @return boolean true if type is a vendor type, false otherwise
241
     */
242
    public function isVendor()
243
    {
244 23
        if (substr($this->getSubType(), 0, 4) == 'vnd.') {
245
            return true;
246 23
        }
247
        return false;
248
    }
249
250
    /**
251
     * Is this a wildcard type?
252
     *
253
     * @return boolean true if type is a wildcard, false otherwise
254
     */
255
    public function isWildcard()
256 37
    {
257
        // xxx also if a subtype can be submatched i.e. vnd.ms-excel.*
258 37
        if (($this->getMedia() === '*' && $this->getSubtype() === '*') || $this->getSubtype() === '*') {
259
            return true;
260
        }
261
        return false;
262
    }
263
264
    /**
265
     * Perform a wildcard match on a MIME type
266 28
     *
267
     * Example:
268 28
     * $type = new Type('image/png');
269
     * $type->wildcardMatch('image/*');
270
     *
271
     * @param string $card Wildcard to check against
272
     *
273
     * @return boolean true if there was a match, false otherwise
274
     */
275
    public function wildcardMatch($card)
276 38
    {
277
        $match_type = new static($card);
278 38
279
        if (!$match_type->isWildcard()) {
280
            return false;
281
        }
282
283
        if ($match_type->getMedia() === '*' && $match_type->getSubType() === '*') {
284
            return true;
285
        }
286 28
287
        if ($match_type->getMedia() === $this->getMedia()) {
288 28
            return true;
289
        }
290
291
        return false;
292
    }
293
294
    /**
295
     * Add a parameter to this type
296
     *
297
     * @param string $name    Parameter name
298 30
     * @param string $value   Parameter value
299
     * @param string $comment Comment for this parameter
300 30
     *
301
     * @return void
302
     */
303 30
    public function addParameter($name, $value, $comment = null)
304 30
    {
305 23
        $this->parameters[$name] = new TypeParameter($name, $value, $comment);
306 23
    }
307
308
    /**
309 30
     * Remove a parameter from this type
310
     *
311
     * @param string $name Parameter name
312
     *
313
     * @return void
314
     */
315
    public function removeParameter($name)
316
    {
317
        unset($this->parameters[$name]);
318
    }
319
320 1
    public function getDefaultExtension($strict = true)
321
    {
322 1
        $extensions = $this->getExtensions($strict);
323 1
        return isset($extensions[0]) ? $extensions[0] : null;
324
    }
325 1
326
    public function getExtensions($strict = true)
327
    {
328
        $type = $this->toString(static::SHORT_TEXT);
329
330
        $map = new MapHandler();
331
        if (!isset($map->get()['types'][$type])) {
332
            if ($strict) {
333
                throw new MappingException('MIME type ' . $type . ' not found in map');
334
            } else {
335 1
                return [];
336
            }
337 1
        }
338 1
        return $map->get()['types'][$type];
339
    }
340
}
341