1 | <?php declare(strict_types=1); |
||
2 | |||
3 | namespace FileEye\MimeMap\Test; |
||
4 | |||
5 | use FileEye\MimeMap\Extension; |
||
6 | use FileEye\MimeMap\MalformedTypeException; |
||
7 | use FileEye\MimeMap\Map\MimeMapInterface; |
||
8 | use FileEye\MimeMap\MapHandler; |
||
9 | use FileEye\MimeMap\MappingException; |
||
10 | use FileEye\MimeMap\Type; |
||
11 | |||
12 | /** |
||
13 | * @backupStaticAttributes enabled |
||
14 | */ |
||
15 | class MapHandlerTest extends MimeMapTestBase |
||
16 | { |
||
17 | /** |
||
18 | * @var MimeMapInterface |
||
19 | */ |
||
20 | protected $map; |
||
21 | |||
22 | public function setUp(): void |
||
23 | { |
||
24 | $this->map = MapHandler::map(); |
||
25 | } |
||
26 | |||
27 | public function testMap(): void |
||
28 | { |
||
29 | $this->assertStringContainsString('DefaultMap.php', $this->map->getFileName()); |
||
30 | } |
||
31 | |||
32 | public function testSort(): void |
||
33 | { |
||
34 | $this->map->addTypeExtensionMapping('aaa/aaa', '000a')->sort(); |
||
35 | $this->assertSame('aaa/aaa', $this->map->listTypes()[0]); |
||
36 | $this->assertSame('000a', $this->map->listExtensions()[0]); |
||
37 | } |
||
38 | |||
39 | public function testAdd(): void |
||
40 | { |
||
41 | // Adding a new type with a new extension. |
||
42 | $this->map->addTypeExtensionMapping('bingo/bongo', 'bngbng'); |
||
43 | $this->assertSame(['bngbng'], (new Type('bingo/bongo'))->getExtensions()); |
||
44 | $this->assertSame('bngbng', (new Type('bingo/bongo'))->getDefaultExtension()); |
||
45 | $this->assertSame(['bingo/bongo'], (new Extension('bngbng'))->getTypes()); |
||
46 | $this->assertSame('bingo/bongo', (new Extension('bngbng'))->getDefaultType()); |
||
47 | |||
48 | // Adding an already existing mapping should not duplicate entries. |
||
49 | $this->map->addTypeExtensionMapping('bingo/bongo', 'bngbng'); |
||
50 | $this->assertSame(['bngbng'], (new Type('bingo/bongo'))->getExtensions()); |
||
51 | $this->assertSame(['bingo/bongo'], (new Extension('bngbng'))->getTypes()); |
||
52 | |||
53 | // Adding another extension to existing type. |
||
54 | $this->map->addTypeExtensionMapping('bingo/bongo', 'bigbog'); |
||
55 | $this->assertSame(['bngbng', 'bigbog'], (new Type('bingo/bongo'))->getExtensions()); |
||
56 | $this->assertSame(['bingo/bongo'], (new Extension('bigbog'))->getTypes()); |
||
57 | |||
58 | // Adding another type to existing extension. |
||
59 | $this->map->addTypeExtensionMapping('boing/being', 'bngbng'); |
||
60 | $this->assertSame(['bngbng'], (new Type('boing/being'))->getExtensions()); |
||
61 | $this->assertSame(['bingo/bongo', 'boing/being'], (new Extension('bngbng'))->getTypes()); |
||
62 | } |
||
63 | |||
64 | public function testRemove(): void |
||
65 | { |
||
66 | $this->assertSame(['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'asc'], (new Type('text/plain'))->getExtensions()); |
||
67 | $this->assertSame('txt', (new Type('text/plain'))->getDefaultExtension()); |
||
68 | $this->assertSame(['text/plain'], (new Extension('txt'))->getTypes()); |
||
69 | $this->assertSame('text/plain', (new Extension('txt'))->getDefaultType()); |
||
70 | |||
71 | // Remove an existing type-extension pair. |
||
72 | $this->assertTrue($this->map->removeTypeExtensionMapping('text/plain', 'txt')); |
||
73 | $this->assertSame(['text', 'conf', 'def', 'list', 'log', 'in', 'asc'], (new Type('text/plain'))->getExtensions()); |
||
74 | |||
75 | // Try removing a non-existing extension. |
||
76 | $this->assertFalse($this->map->removeTypeExtensionMapping('text/plain', 'axx')); |
||
77 | |||
78 | // Remove an existing alias. |
||
79 | $this->assertSame(['application/x-pdf', 'image/pdf', 'application/acrobat', 'application/nappdf'], (new Type('application/pdf'))->getAliases()); |
||
80 | $this->assertTrue($this->map->removeTypeAlias('application/pdf', 'application/x-pdf')); |
||
81 | $this->assertSame(['image/pdf', 'application/acrobat', 'application/nappdf'], (new Type('application/pdf'))->getAliases()); |
||
82 | |||
83 | // Try removing a non-existing alias. |
||
84 | $this->assertFalse($this->map->removeTypeAlias('application/pdf', 'foo/bar')); |
||
85 | $this->assertSame(['image/pdf', 'application/acrobat', 'application/nappdf'], (new Type('application/pdf'))->getAliases()); |
||
86 | |||
87 | // Try removing a non-existing type. |
||
88 | $this->assertFalse($this->map->removeType('axx/axx')); |
||
89 | } |
||
90 | |||
91 | public function testGetExtensionTypesAfterTypeExtensionMappingRemoval(): void |
||
92 | { |
||
93 | $this->expectException(MappingException::class); |
||
94 | $this->expectExceptionMessage("No MIME type mapped to extension txt"); |
||
95 | $this->assertTrue($this->map->removeTypeExtensionMapping('text/plain', 'txt')); |
||
96 | $types = (new Extension('txt'))->getTypes(); |
||
0 ignored issues
–
show
Unused Code
introduced
by
![]() |
|||
97 | } |
||
98 | |||
99 | public function testGetExtensionDefaultTypeAfterTypeExtensionMappingRemoval(): void |
||
100 | { |
||
101 | $this->expectException(MappingException::class); |
||
102 | $this->expectExceptionMessage("No MIME type mapped to extension txt"); |
||
103 | $this->assertTrue($this->map->removeTypeExtensionMapping('text/plain', 'txt')); |
||
104 | $defaultType = (new Extension('txt'))->getDefaultType(); |
||
0 ignored issues
–
show
|
|||
105 | } |
||
106 | |||
107 | public function testGetTypeExtensionsAfterTypeRemoval(): void |
||
108 | { |
||
109 | $this->expectException(MappingException::class); |
||
110 | $this->expectExceptionMessage("No MIME type found for text/plain in map"); |
||
111 | $this->assertTrue($this->map->removeType('text/plain')); |
||
112 | $extensions = (new Type('text/plain'))->getExtensions(); |
||
0 ignored issues
–
show
|
|||
113 | } |
||
114 | |||
115 | public function testGetExtensionTypesAfterTypeRemoval(): void |
||
116 | { |
||
117 | $this->expectException(MappingException::class); |
||
118 | $this->expectExceptionMessage('No MIME type mapped to extension def'); |
||
119 | $this->assertTrue($this->map->removeType('text/plain')); |
||
120 | $types = (new Extension('DEf'))->getTypes(); |
||
0 ignored issues
–
show
|
|||
121 | } |
||
122 | |||
123 | public function testGetExtensionDefaultTypeAfterTypeRemoval(): void |
||
124 | { |
||
125 | $this->expectException(MappingException::class); |
||
126 | $this->expectExceptionMessage('No MIME type mapped to extension def'); |
||
127 | $this->assertTrue($this->map->removeType('text/plain')); |
||
128 | $defaultType = (new Extension('DeF'))->getDefaultType(); |
||
0 ignored issues
–
show
|
|||
129 | } |
||
130 | |||
131 | public function testGetTypeExtensionsAfterTypeWithAliasRemoval(): void |
||
132 | { |
||
133 | $this->expectException(MappingException::class); |
||
134 | $this->expectExceptionMessage('No MIME type found for text/markdown in map'); |
||
135 | $this->assertTrue($this->map->hasAlias('text/x-markdown')); |
||
136 | $this->assertTrue($this->map->removeType('text/markdown')); |
||
137 | $this->assertFalse($this->map->hasAlias('text/x-markdown')); |
||
138 | $extensions = (new Type('text/markdown'))->getExtensions(); |
||
0 ignored issues
–
show
|
|||
139 | } |
||
140 | |||
141 | public function testGetAliasExtensionsAfterTypeWithAliasRemoval(): void |
||
142 | { |
||
143 | $this->expectException(MappingException::class); |
||
144 | $this->expectExceptionMessage("No MIME type found for text/x-markdown in map"); |
||
145 | $this->assertTrue($this->map->hasAlias('text/x-markdown')); |
||
146 | $this->assertTrue($this->map->removeType('text/markdown')); |
||
147 | $this->assertFalse($this->map->hasAlias('text/x-markdown')); |
||
148 | $extensions = (new Type('text/x-markdown'))->getExtensions(); |
||
0 ignored issues
–
show
|
|||
149 | } |
||
150 | |||
151 | public function testGetExtensionTypesAfterTypeWithAliasRemoval(): void |
||
152 | { |
||
153 | $this->expectException(MappingException::class); |
||
154 | $this->expectExceptionMessage("No MIME type mapped to extension md"); |
||
155 | $this->assertTrue($this->map->hasAlias('text/x-markdown')); |
||
156 | $this->assertTrue($this->map->removeType('text/markdown')); |
||
157 | $this->assertFalse($this->map->hasAlias('text/x-markdown')); |
||
158 | $types = (new Extension('MD'))->getTypes(); |
||
0 ignored issues
–
show
|
|||
159 | } |
||
160 | |||
161 | public function testGetExtensionDefaultTypeAfterTypeWithAliasRemoval(): void |
||
162 | { |
||
163 | $this->expectException(MappingException::class); |
||
164 | $this->expectExceptionMessage("No MIME type mapped to extension md"); |
||
165 | $this->assertTrue($this->map->hasAlias('text/x-markdown')); |
||
166 | $this->assertTrue($this->map->removeType('text/markdown')); |
||
167 | $this->assertFalse($this->map->hasAlias('text/x-markdown')); |
||
168 | $defaultType = (new Extension('md'))->getDefaultType(); |
||
0 ignored issues
–
show
|
|||
169 | } |
||
170 | |||
171 | public function testHasType(): void |
||
172 | { |
||
173 | $this->assertTrue($this->map->hasType('text/plain')); |
||
174 | $this->assertFalse($this->map->hasType('foo/bar')); |
||
175 | } |
||
176 | |||
177 | public function testHasAlias(): void |
||
178 | { |
||
179 | $this->assertTrue($this->map->hasAlias('application/acrobat')); |
||
180 | $this->assertFalse($this->map->hasAlias('foo/bar')); |
||
181 | } |
||
182 | |||
183 | public function testHasExtension(): void |
||
184 | { |
||
185 | $this->assertTrue($this->map->hasExtension('jpg')); |
||
186 | $this->assertFalse($this->map->hasExtension('jpgjpg')); |
||
187 | } |
||
188 | |||
189 | public function testSetExtensionDefaultType(): void |
||
190 | { |
||
191 | $this->assertSame(['text/vnd.dvb.subtitle', 'image/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], (new Extension('sub'))->getTypes()); |
||
192 | $this->map->setExtensionDefaultType('SUB', 'image/vnd.dvb.subtitle'); |
||
193 | $this->assertSame(['image/vnd.dvb.subtitle', 'text/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], (new Extension('SUB'))->getTypes()); |
||
194 | } |
||
195 | |||
196 | public function testReAddAliasToType(): void |
||
197 | { |
||
198 | $this->assertSame(['image/psd', 'image/x-psd', 'image/photoshop', 'image/x-photoshop', 'application/photoshop', 'application/x-photoshop',], (new Type('image/vnd.adobe.photoshop'))->getAliases()); |
||
199 | $this->map->addTypeAlias('image/vnd.adobe.photoshop', 'application/x-photoshop'); |
||
200 | $this->assertSame(['image/psd', 'image/x-psd', 'image/photoshop', 'image/x-photoshop', 'application/photoshop', 'application/x-photoshop',], (new Type('image/vnd.adobe.photoshop'))->getAliases()); |
||
201 | } |
||
202 | |||
203 | public function testAddAliasToMultipleTypes(): void |
||
204 | { |
||
205 | $this->assertSame([], (new Type('text/plain'))->getAliases()); |
||
206 | $this->expectException(MappingException::class); |
||
207 | $this->expectExceptionMessage("Cannot set 'application/x-photoshop' as alias for 'text/plain', it is an alias of 'image/vnd.adobe.photoshop' already"); |
||
208 | $this->map->addTypeAlias('text/plain', 'application/x-photoshop'); |
||
209 | $this->assertSame([], (new Type('text/plain'))->getAliases()); |
||
210 | } |
||
211 | |||
212 | public function testAddAliasToMissingType(): void |
||
213 | { |
||
214 | $this->expectException(MappingException::class); |
||
215 | $this->expectExceptionMessage("Cannot set 'baz/qoo' as alias for 'bar/foo', 'bar/foo' not defined"); |
||
216 | $this->map->addTypeAlias('bar/foo', 'baz/qoo'); |
||
217 | } |
||
218 | |||
219 | public function testAddAliasIsATypeAlready(): void |
||
220 | { |
||
221 | $this->expectException(MappingException::class); |
||
222 | $this->expectExceptionMessage("Cannot set 'text/plain' as alias for 'text/richtext', 'text/plain' is already defined as a type"); |
||
223 | $this->map->addTypeAlias('text/richtext', 'text/plain'); |
||
224 | } |
||
225 | |||
226 | public function testAddDescriptionToAlias(): void |
||
227 | { |
||
228 | $this->expectException(MappingException::class); |
||
229 | $this->expectExceptionMessage("Cannot add description for 'application/acrobat', 'application/acrobat' is an alias"); |
||
230 | $this->map->addTypeDescription('application/acrobat', 'description of alias'); |
||
231 | } |
||
232 | |||
233 | public function testSetExtensionDefaultTypeNoExtension(): void |
||
234 | { |
||
235 | $this->expectException(MappingException::class); |
||
236 | $this->map->setExtensionDefaultType('zxzx', 'image/vnd.dvb.subtitle'); |
||
237 | } |
||
238 | |||
239 | public function testSetExtensionDefaultTypeNoType(): void |
||
240 | { |
||
241 | $this->expectException(MappingException::class); |
||
242 | $this->map->setExtensionDefaultType('sub', 'image/bingo'); |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Check that a type alias can be set as extension default. |
||
247 | */ |
||
248 | public function testSetExtensionDefaultTypeToAlias(): void |
||
249 | { |
||
250 | $this->assertSame(['application/pdf'], (new Extension('pdf'))->getTypes()); |
||
251 | |||
252 | $this->map->setExtensionDefaultType('pdf', 'application/x-pdf'); |
||
253 | $this->assertSame(['application/x-pdf', 'application/pdf'], (new Extension('pdf'))->getTypes()); |
||
254 | $this->assertSame('application/x-pdf', (new Extension('pdf'))->getDefaultType()); |
||
255 | |||
256 | $this->map->setExtensionDefaultType('pdf', 'image/pdf'); |
||
257 | $this->assertSame(['image/pdf', 'application/x-pdf', 'application/pdf'], (new Extension('pdf'))->getTypes()); |
||
258 | $this->assertSame('image/pdf', (new Extension('pdf'))->getDefaultType()); |
||
259 | |||
260 | // Remove the alias, should be removed from extension types. |
||
261 | $this->assertTrue($this->map->removeTypeAlias('application/pdf', 'application/x-pdf')); |
||
262 | $this->assertSame(['image/pdf', 'application/pdf'], (new Extension('pdf'))->getTypes()); |
||
263 | $this->assertSame('image/pdf', (new Extension('pdf'))->getDefaultType()); |
||
264 | |||
265 | // Add a fake MIME type to 'psd', an alias to that, then remove |
||
266 | // 'image/vnd.adobe.photoshop'. |
||
267 | $this->assertSame(['image/vnd.adobe.photoshop'], (new Extension('psd'))->getTypes()); |
||
268 | $this->assertSame('image/vnd.adobe.photoshop', (new Extension('psd'))->getDefaultType()); |
||
269 | $this->map->setExtensionDefaultType('psd', 'image/psd'); |
||
270 | $this->assertSame(['image/psd', 'image/vnd.adobe.photoshop'], (new Extension('psd'))->getTypes()); |
||
271 | $this->assertSame('image/psd', (new Extension('psd'))->getDefaultType()); |
||
272 | $this->map->addTypeExtensionMapping('bingo/bongo', 'psd'); |
||
273 | $this->assertSame(['image/psd', 'image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
274 | $this->map->addTypeAlias('bingo/bongo', 'bar/foo'); |
||
275 | $this->assertSame(['image/psd', 'image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
276 | $this->map->setExtensionDefaultType('psd', 'bar/foo'); |
||
277 | $this->assertSame(['bar/foo', 'image/psd', 'image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
278 | $this->assertTrue($this->map->removeType('image/vnd.adobe.photoshop')); |
||
279 | $this->assertSame(['bar/foo', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Check removing an aliased type mapping. |
||
284 | */ |
||
285 | public function testRemoveAliasedTypeMapping(): void |
||
286 | { |
||
287 | $this->map->addTypeExtensionMapping('bingo/bongo', 'psd'); |
||
288 | $this->assertSame(['image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
289 | $this->map->addTypeAlias('bingo/bongo', 'bar/foo'); |
||
290 | $this->assertSame(['image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
291 | $this->map->setExtensionDefaultType('psd', 'bar/foo'); |
||
292 | $this->assertSame(['bar/foo', 'image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
293 | $this->map->removeTypeExtensionMapping('bar/foo', 'psd'); |
||
294 | $this->assertSame(['image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Check that a removing a type mapping also remove its aliases. |
||
299 | */ |
||
300 | public function testRemoveUnaliasedTypeMapping(): void |
||
301 | { |
||
302 | // Add a fake MIME type to 'psd', an alias to that, then remove |
||
303 | // 'image/vnd.adobe.photoshop'. |
||
304 | $this->map->addTypeExtensionMapping('bingo/bongo', 'psd'); |
||
305 | $this->assertSame(['image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
306 | $this->map->addTypeAlias('bingo/bongo', 'bar/foo'); |
||
307 | $this->assertSame(['image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
308 | $this->map->setExtensionDefaultType('psd', 'bar/foo'); |
||
309 | $this->assertSame(['bar/foo', 'image/vnd.adobe.photoshop', 'bingo/bongo'], (new Extension('psd'))->getTypes()); |
||
310 | $this->map->removeTypeExtensionMapping('bingo/bongo', 'psd'); |
||
311 | $this->assertSame(['image/vnd.adobe.photoshop'], (new Extension('psd'))->getTypes()); |
||
312 | } |
||
313 | |||
314 | public function testSetExtensionDefaultTypeToInvalidAlias(): void |
||
315 | { |
||
316 | $this->expectException(MappingException::class); |
||
317 | $this->expectExceptionMessage("Cannot set 'image/psd' as default type for extension 'pdf', its unaliased type 'image/vnd.adobe.photoshop' is not associated to 'pdf'"); |
||
318 | $this->map->setExtensionDefaultType('pdf', 'image/psd'); |
||
319 | } |
||
320 | |||
321 | public function testSetTypeDefaultExtension(): void |
||
322 | { |
||
323 | $this->assertSame(['jpeg', 'jpg', 'jpe'], (new Type('image/jpeg'))->getExtensions()); |
||
324 | $this->map->setTypeDefaultExtension('image/jpeg', 'jpg'); |
||
325 | $this->assertSame(['jpg', 'jpeg', 'jpe'], (new Type('image/JPEG'))->getExtensions()); |
||
326 | } |
||
327 | |||
328 | public function testSetTypeDefaultExtensionNoExtension(): void |
||
329 | { |
||
330 | $this->expectException(MappingException::class); |
||
331 | $this->map->setTypeDefaultExtension('image/jpeg', 'zxzx'); |
||
332 | } |
||
333 | |||
334 | public function testSetTypeDefaultExtensionNoType(): void |
||
335 | { |
||
336 | $this->expectException(MappingException::class); |
||
337 | $this->map->setTypeDefaultExtension('image/bingo', 'jpg'); |
||
338 | } |
||
339 | |||
340 | public function testAddExtensionToAlias(): void |
||
341 | { |
||
342 | $this->expectException(MappingException::class); |
||
343 | $this->expectExceptionMessage("Cannot map 'pdf' to 'application/acrobat', 'application/acrobat' is an alias"); |
||
344 | $this->map->addTypeExtensionMapping('application/acrobat', 'pdf'); |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * Data provider for testAddMalformedTypeExtensionMapping. |
||
349 | * |
||
350 | * @return array<string,array<string>> |
||
351 | */ |
||
352 | public function malformedTypeProvider(): array |
||
353 | { |
||
354 | return [ |
||
355 | 'empty string' => [''], |
||
356 | 'n' => ['n'], |
||
357 | 'no media' => ['/n'], |
||
358 | 'no sub type' => ['n/'], |
||
359 | 'no comment closing bracket a' => ['image (open ()/*'], |
||
360 | 'no comment closing bracket b' => ['image / * (open (())'], |
||
361 | ]; |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * @dataProvider malformedTypeProvider |
||
366 | */ |
||
367 | public function testAddMalformedTypeExtensionMapping(string $type): void |
||
368 | { |
||
369 | $this->expectException(MalformedTypeException::class); |
||
370 | $this->map->addTypeExtensionMapping($type, 'xxx'); |
||
371 | } |
||
372 | } |
||
373 |