MDL-69050 lang: Rename and deprecate filetypes_util methods
[moodle.git] / lib / form / tests / filetypes_util_test.php
CommitLineData
6c4a5fdf
DM
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Provides the {@link core_form\filetypes_util_testcase} class.
19 *
20 * @package core_form
21 * @category test
22 * @copyright 2017 David Mudrák <david@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26namespace core_form;
27
28use advanced_testcase;
29
30defined('MOODLE_INTERNAL') || die();
31
32global $CFG;
33
34/**
35 * Test cases for the {@link core_form\filetypes_util} class.
36 *
37 * @copyright 2017 David Mudrak <david@moodle.com>
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class filetypes_util_testcase extends advanced_testcase {
41
42 /**
43 * Test normalizing list of extensions.
44 */
45 public function test_normalize_file_types() {
46
47 $this->resetAfterTest(true);
48 $util = new filetypes_util();
49
50 $this->assertSame(['.odt'], $util->normalize_file_types('.odt'));
51 $this->assertSame(['.odt'], $util->normalize_file_types('odt'));
52 $this->assertSame(['.odt'], $util->normalize_file_types('.ODT'));
53 $this->assertSame(['.doc', '.jpg', '.mp3'], $util->normalize_file_types('doc, jpg, mp3'));
54 $this->assertSame(['.doc', '.jpg', '.mp3'], $util->normalize_file_types(['.doc', '.jpg', '.mp3']));
55 $this->assertSame(['.doc', '.jpg', '.mp3'], $util->normalize_file_types('doc, *.jpg, mp3'));
56 $this->assertSame(['.doc', '.jpg', '.mp3'], $util->normalize_file_types(['doc ', ' JPG ', '.mp3']));
57 $this->assertSame(['.rtf', '.pdf', '.docx'],
58 $util->normalize_file_types("RTF,.pdf\n...DocX,,,;\rPDF\trtf ...Rtf"));
59 $this->assertSame(['.tgz', '.tar.gz'], $util->normalize_file_types('tgz,TAR.GZ tar.gz .tar.gz tgz TGZ'));
60 $this->assertSame(['.notebook'], $util->normalize_file_types('"Notebook":notebook;NOTEBOOK;,\'NoTeBook\''));
61 $this->assertSame([], $util->normalize_file_types(''));
62 $this->assertSame([], $util->normalize_file_types([]));
63 $this->assertSame(['.0'], $util->normalize_file_types(0));
64 $this->assertSame(['.0'], $util->normalize_file_types('0'));
65 $this->assertSame(['.odt'], $util->normalize_file_types('*.odt'));
66 $this->assertSame([], $util->normalize_file_types('.'));
67 $this->assertSame(['.foo'], $util->normalize_file_types('. foo'));
68 $this->assertSame(['*'], $util->normalize_file_types('*'));
69 $this->assertSame([], $util->normalize_file_types('*~'));
70 $this->assertSame(['.pdf', '.ps'], $util->normalize_file_types('pdf *.ps foo* *bar .r??'));
71 $this->assertSame(['*'], $util->normalize_file_types('pdf *.ps foo* * *bar .r??'));
72 }
73
74 /**
75 * Test MIME type formal recognition.
76 */
77 public function test_looks_like_mimetype() {
78
79 $this->resetAfterTest(true);
80 $util = new filetypes_util();
81
82 $this->assertTrue($util->looks_like_mimetype('type/subtype'));
83 $this->assertTrue($util->looks_like_mimetype('type/x-subtype'));
84 $this->assertTrue($util->looks_like_mimetype('type/x-subtype+xml'));
85 $this->assertTrue($util->looks_like_mimetype('type/vnd.subtype.xml'));
86 $this->assertTrue($util->looks_like_mimetype('type/vnd.subtype+xml'));
87
88 $this->assertFalse($util->looks_like_mimetype('.gif'));
89 $this->assertFalse($util->looks_like_mimetype('audio'));
90 $this->assertFalse($util->looks_like_mimetype('foo/bar/baz'));
91 }
92
93 /**
94 * Test getting/checking group.
95 */
96 public function test_is_filetype_group() {
97
98 $this->resetAfterTest(true);
99 $util = new filetypes_util();
100
101 $audio = $util->is_filetype_group('audio');
102 $this->assertNotFalse($audio);
103 $this->assertInternalType('array', $audio->extensions);
104 $this->assertInternalType('array', $audio->mimetypes);
105
106 $this->assertFalse($util->is_filetype_group('.gif'));
107 $this->assertFalse($util->is_filetype_group('somethingveryunlikelytoeverexist'));
108 }
109
110
111 /**
112 * Test describing list of extensions.
113 */
114 public function test_describe_file_types() {
115
116 $this->resetAfterTest(true);
117 $util = new filetypes_util();
118
119 force_current_language('en');
120
121 // Check that it is able to describe individual file extensions.
122 $desc = $util->describe_file_types('jpg .jpeg *.jpe PNG;.gif, mudrd8mz');
123 $this->assertTrue($desc->hasdescriptions);
124
125 $desc = $desc->descriptions;
126 $this->assertEquals(4, count($desc));
127
128 $this->assertEquals('File', $desc[0]->description);
129 $this->assertEquals('.mudrd8mz', $desc[0]->extensions);
130
131 $this->assertEquals('Image (JPEG)', $desc[2]->description);
132 $this->assertContains('.jpg', $desc[2]->extensions);
133 $this->assertContains('.jpeg', $desc[2]->extensions);
134 $this->assertContains('.jpe', $desc[2]->extensions);
135
136 // Check that it can describe groups and mimetypes too.
137 $desc = $util->describe_file_types('audio text/plain');
138 $this->assertTrue($desc->hasdescriptions);
139
140 $desc = $desc->descriptions;
141 $this->assertEquals(2, count($desc));
142
143 $this->assertEquals('Audio files', $desc[0]->description);
144 $this->assertContains('.mp3', $desc[0]->extensions);
145 $this->assertContains('.wav', $desc[0]->extensions);
146 $this->assertContains('.ogg', $desc[0]->extensions);
147
148 $this->assertEquals('Text file', $desc[1]->description);
149 $this->assertContains('.txt', $desc[1]->extensions);
150
151 // Empty.
152 $desc = $util->describe_file_types('');
153 $this->assertFalse($desc->hasdescriptions);
154 $this->assertEmpty($desc->descriptions);
155
156 // Any.
157 $desc = $util->describe_file_types('*');
158 $this->assertTrue($desc->hasdescriptions);
159 $this->assertNotEmpty($desc->descriptions[0]->description);
160 $this->assertEmpty($desc->descriptions[0]->extensions);
161
162 // Unknown mimetype.
163 $desc = $util->describe_file_types('application/x-something-really-unlikely-ever-exist');
164 $this->assertTrue($desc->hasdescriptions);
165 $this->assertEquals('application/x-something-really-unlikely-ever-exist', $desc->descriptions[0]->description);
166 $this->assertEmpty($desc->descriptions[0]->extensions);
167 }
e3ad9db6
DM
168
169 /**
170 * Test expanding mime types into extensions.
171 */
172 public function test_expand() {
173
174 $this->resetAfterTest(true);
175 $util = new filetypes_util();
176
177 $this->assertSame([], $util->expand(''));
178
179 $expanded = $util->expand('document .cdr text/plain');
180 $this->assertNotContains('document', $expanded);
181 $this->assertNotContains('text/plain', $expanded);
182 $this->assertContains('.doc', $expanded);
183 $this->assertContains('.odt', $expanded);
184 $this->assertContains('.txt', $expanded);
185 $this->assertContains('.cdr', $expanded);
186
187 $expanded = $util->expand('document .cdr text/plain', true, false);
188 $this->assertContains('document', $expanded);
189 $this->assertNotContains('text/plain', $expanded);
190 $this->assertContains('.doc', $expanded);
191 $this->assertContains('.odt', $expanded);
192 $this->assertContains('.txt', $expanded);
193 $this->assertContains('.cdr', $expanded);
194
195 $expanded = $util->expand('document .cdr text/plain', false, true);
196 $this->assertNotContains('document', $expanded);
197 $this->assertContains('text/plain', $expanded);
198 $this->assertContains('.doc', $expanded);
199 $this->assertContains('.odt', $expanded);
200 $this->assertContains('.txt', $expanded);
201 $this->assertContains('.cdr', $expanded);
202
203 $this->assertSame([], $util->expand('foo/bar', true, false));
204 $this->assertSame(['foo/bar'], $util->expand('foo/bar', true, true));
205 }
206
207 /**
208 * Test checking that a type is among others.
209 */
781545d3 210 public function test_is_listed() {
e3ad9db6
DM
211
212 $this->resetAfterTest(true);
213 $util = new filetypes_util();
214
215 // These should be intuitively true.
781545d3
DM
216 $this->assertTrue($util->is_listed('txt', 'text/plain'));
217 $this->assertTrue($util->is_listed('txt', 'doc txt rtf'));
218 $this->assertTrue($util->is_listed('.txt', '.doc;.txt;.rtf'));
219 $this->assertTrue($util->is_listed('audio', 'text/plain audio video'));
220 $this->assertTrue($util->is_listed('text/plain', 'text/plain audio video'));
221 $this->assertTrue($util->is_listed('jpg jpe jpeg', 'image/jpeg'));
222 $this->assertTrue($util->is_listed(['jpg', 'jpe', '.png'], 'image'));
e3ad9db6
DM
223
224 // These should be intuitively false.
781545d3 225 $this->assertFalse($util->is_listed('.gif', 'text/plain'));
e3ad9db6
DM
226
227 // Not all text/plain formats are in the document group.
781545d3 228 $this->assertFalse($util->is_listed('text/plain', 'document'));
e3ad9db6
DM
229
230 // Not all documents (and also the group itself) is not a plain text.
781545d3 231 $this->assertFalse($util->is_listed('document', 'text/plain'));
e3ad9db6 232
8cf36e9c
DM
233 // This may look wrong at the first sight as you might expect that the
234 // mimetype should simply map to an extension ...
781545d3 235 $this->assertFalse($util->is_listed('image/jpeg', '.jpg'));
8cf36e9c
DM
236
237 // But it is principally same situation as this (there is no 1:1 mapping).
781545d3
DM
238 $this->assertFalse($util->is_listed('.c', '.txt'));
239 $this->assertTrue($util->is_listed('.txt .c', 'text/plain'));
240 $this->assertFalse($util->is_listed('text/plain', '.c'));
8cf36e9c 241
e3ad9db6 242 // Any type is included if the filter is empty.
781545d3
DM
243 $this->assertTrue($util->is_listed('txt', ''));
244 $this->assertTrue($util->is_listed('txt', '*'));
8cf36e9c 245
781545d3
DM
246 // Empty value is part of any list.
247 $this->assertTrue($util->is_listed('', '.txt'));
8cf36e9c
DM
248 }
249
250 /**
781545d3 251 * Test getting types not present in a list.
8cf36e9c 252 */
781545d3 253 public function test_get_not_listed() {
8cf36e9c
DM
254
255 $this->resetAfterTest(true);
256 $util = new filetypes_util();
257
781545d3
DM
258 $this->assertEmpty($util->get_not_listed('txt', 'text/plain'));
259 $this->assertEmpty($util->get_not_listed('txt', '.doc .txt .rtf'));
260 $this->assertEmpty($util->get_not_listed('txt', 'text/plain'));
261 $this->assertEmpty($util->get_not_listed(['jpg', 'jpe', 'jpeg'], 'image/jpeg'));
262 $this->assertEmpty($util->get_not_listed('', 'foo/bar'));
263 $this->assertEmpty($util->get_not_listed('.foobar', ''));
264 $this->assertEmpty($util->get_not_listed('.foobar', '*'));
8cf36e9c
DM
265
266 // Returned list is normalized so extensions have the dot added.
781545d3 267 $this->assertContains('.exe', $util->get_not_listed('exe', '.c .h'));
8cf36e9c 268
781545d3
DM
269 // If this looks wrong to you, see {@see self::test_is_listed()} for more details on this behaviour.
270 $this->assertContains('image/jpeg', $util->get_not_listed('image/jpeg', '.jpg .jpeg'));
e3ad9db6
DM
271 }
272
273 /**
274 * Test populating the tree for the browser.
275 */
276 public function test_data_for_browser() {
277
278 $this->resetAfterTest(true);
279 $util = new filetypes_util();
280
281 $data = $util->data_for_browser();
282 $this->assertContainsOnly('object', $data);
283 foreach ($data as $group) {
284 $this->assertObjectHasAttribute('key', $group);
285 $this->assertObjectHasAttribute('types', $group);
286 if ($group->key !== '') {
287 $this->assertTrue($group->selectable);
288 }
289 }
290
b8c31dfe
JD
291 // Confirm that the reserved type '.xxx' isn't present in the 'Other files' section.
292 $types = array_reduce($data, function($carry, $group) {
293 if ($group->name === 'Other files') {
294 return $group->types;
295 }
296 });
297 $typekeys = array_map(function($type) {
298 return $type->key;
299 }, $types);
300 $this->assertNotContains('.xxx', $typekeys);
301
e3ad9db6
DM
302 // All these three files are in both "image" and also "web_image"
303 // groups. We display both groups.
304 $data = $util->data_for_browser('jpg png gif', true, '.gif');
24ce9b8a 305 $this->assertEquals(3, count($data));
e3ad9db6
DM
306 $this->assertTrue($data[0]->key !== $data[1]->key);
307 foreach ($data as $group) {
24ce9b8a 308 $this->assertTrue(($group->key === 'image' || $group->key === 'web_image' || $group->key === 'optimised_image'));
e3ad9db6
DM
309 $this->assertEquals(3, count($group->types));
310 $this->assertFalse($group->selectable);
311 foreach ($group->types as $ext) {
312 if ($ext->key === '.gif') {
313 $this->assertTrue($ext->selected);
314 } else {
315 $this->assertFalse($ext->selected);
316 }
317 }
318 }
319
24ce9b8a
SA
320 // The groups web_image and optimised_image are a subset of the group image. The
321 // file extensions that fall into these groups will be displayed thrice.
e3ad9db6
DM
322 $data = $util->data_for_browser('web_image');
323 foreach ($data as $group) {
24ce9b8a 324 $this->assertTrue(($group->key === 'image' || $group->key === 'web_image' || $group->key === 'optimised_image'));
e3ad9db6
DM
325 }
326
327 // Check that "All file types" are displayed first.
328 $data = $util->data_for_browser();
329 $group = array_shift($data);
330 $this->assertEquals('*', $group->key);
331
332 // Check that "All file types" is not displayed if should not.
333 $data = $util->data_for_browser(null, false);
334 $group = array_shift($data);
335 $this->assertNotEquals('*', $group->key);
336
337 // Groups with an extension selected start expanded. The "Other files"
338 // starts expanded. The rest start collapsed.
339 $data = $util->data_for_browser(null, false, '.png');
340 foreach ($data as $group) {
341 if ($group->key === 'document') {
342 $this->assertfalse($group->expanded);
343 } else if ($group->key === '') {
344 $this->assertTrue($group->expanded);
345 }
346 foreach ($group->types as $ext) {
347 foreach ($group->types as $ext) {
348 if ($ext->key === '.png') {
349 $this->assertTrue($ext->selected);
350 $this->assertTrue($group->expanded);
351 }
352 }
353 }
354 }
355 }
86bb4f5b
JO
356
357 /**
358 * Data provider for testing test_is_allowed_file_type.
359 *
360 * @return array
361 */
362 public function is_allowed_file_type_provider() {
363 return [
781545d3 364 'Filetype not in extension list' => [
86bb4f5b 365 'filename' => 'test.xml',
781545d3 366 'list' => '.png .jpg',
86bb4f5b
JO
367 'expected' => false
368 ],
781545d3 369 'Filetype not in mimetype list' => [
86bb4f5b 370 'filename' => 'test.xml',
781545d3 371 'list' => 'image/png',
86bb4f5b
JO
372 'expected' => false
373 ],
781545d3 374 'Filetype not in group list' => [
86bb4f5b 375 'filename' => 'test.xml',
781545d3 376 'list' => 'web_file',
86bb4f5b
JO
377 'expected' => false
378 ],
781545d3 379 'Filetype in list as extension' => [
86bb4f5b 380 'filename' => 'test.xml',
781545d3 381 'list' => 'xml',
86bb4f5b
JO
382 'expected' => true
383 ],
781545d3 384 'Empty list should allow all' => [
86bb4f5b 385 'filename' => 'test.xml',
781545d3 386 'list' => '',
86bb4f5b
JO
387 'expected' => true
388 ],
781545d3 389 'Filetype in list but later on' => [
86bb4f5b 390 'filename' => 'test.xml',
781545d3 391 'list' => 'gif;jpeg,image/png xml xlsx',
86bb4f5b
JO
392 'expected' => true
393 ],
781545d3 394 'Filetype in list as mimetype' => [
86bb4f5b 395 'filename' => 'test.xml',
781545d3 396 'list' => 'image/png application/xml',
86bb4f5b
JO
397 'expected' => true
398 ],
781545d3 399 'Filetype in list as group' => [
86bb4f5b 400 'filename' => 'test.html',
781545d3 401 'list' => 'video,web_file',
86bb4f5b
JO
402 'expected' => true
403 ],
404 ];
405 }
406
407 /**
408 * Test is_allowed_file_type().
409 * @dataProvider is_allowed_file_type_provider
410 * @param string $filename The filename to check
781545d3 411 * @param string $list The space , or ; separated list of types supported
86bb4f5b
JO
412 * @param boolean $expected The expected result. True if the file is allowed, false if not.
413 */
781545d3 414 public function test_is_allowed_file_type($filename, $list, $expected) {
86bb4f5b 415 $util = new filetypes_util();
781545d3 416 $this->assertSame($expected, $util->is_allowed_file_type($filename, $list));
86bb4f5b
JO
417 }
418
419 /**
420 * Data provider for testing test_get_unknown_file_types.
421 *
422 * @return array
423 */
424 public function get_unknown_file_types_provider() {
425 return [
a1004698
DM
426 'Empty list' => [
427 'filetypes' => '',
428 'expected' => [],
429 ],
430 'Any file type' => [
431 'filetypes' => '*',
432 'expected' => [],
433 ],
86bb4f5b
JO
434 'Unknown extension' => [
435 'filetypes' => '.rat',
436 'expected' => ['.rat']
437 ],
438 'Multiple unknown extensions' => [
439 'filetypes' => '.ricefield .rat',
440 'expected' => ['.ricefield', '.rat']
441 ],
442 'Existant extension' => [
443 'filetypes' => '.xml',
444 'expected' => []
445 ],
446 'Existant group' => [
447 'filetypes' => 'web_file',
448 'expected' => []
449 ],
450 'Nonexistant mimetypes' => [
451 'filetypes' => 'ricefield/rat',
452 'expected' => ['ricefield/rat']
453 ],
454 'Existant mimetype' => [
455 'filetypes' => 'application/xml',
456 'expected' => []
457 ],
458 'Multiple unknown mimetypes' => [
459 'filetypes' => 'ricefield/rat cam/ball',
460 'expected' => ['ricefield/rat', 'cam/ball']
461 ],
462 'Strange characters in unknown extension/group' => [
463 'filetypes' => '©ç√√ß∂å√©åß©√',
464 'expected' => ['.©ç√√ß∂å√©åß©√']
465 ],
466 'Some existant some not' => [
467 'filetypes' => '.txt application/xml web_file ©ç√√ß∂å√©åß©√ .png ricefield/rat document',
468 'expected' => ['.©ç√√ß∂å√©åß©√', 'ricefield/rat']
469 ],
b8c31dfe
JD
470 'Reserved file type xxx included' => [
471 'filetypes' => '.xxx .html .jpg',
472 'expected' => ['.xxx']
473 ]
86bb4f5b
JO
474 ];
475 }
476
477 /**
478 * Test get_unknown_file_types().
479 * @dataProvider get_unknown_file_types_provider
480 * @param string $filetypes The filetypes to check
481 * @param array $expected The expected result. The list of non existant file types.
482 */
483 public function test_get_unknown_file_types($filetypes, $expected) {
484 $util = new filetypes_util();
485 $this->assertSame($expected, $util->get_unknown_file_types($filetypes));
486 }
781545d3
DM
487
488 /**
489 * Test that a debugging noticed is displayed when calling is_whitelisted().
490 */
491 public function test_deprecation_is_whitelisted() {
492
493 $util = new filetypes_util();
494 $this->assertTrue($util->is_whitelisted('txt', 'text/plain'));
495 $this->assertDebuggingCalled('filetypes_util::is_whitelisted() is deprecated. ' .
496 'Please use filetypes_util::is_listed() instead.', DEBUG_DEVELOPER);
497 }
498
499 /**
500 * Test that a debugging noticed is displayed when calling get_not_whitelisted().
501 */
502 public function test_deprecation_get_not_whitelisted() {
503
504 $util = new filetypes_util();
505 $this->assertEmpty($util->get_not_whitelisted('txt', 'text/plain'));
506 $this->assertDebuggingCalled('filetypes_util::get_not_whitelisted() is deprecated. ' .
507 'Please use filetypes_util::get_not_listed() instead.', DEBUG_DEVELOPER);
508 }
6c4a5fdf 509}