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 * Unit tests for /lib/classes/filetypes.php.
19 *
20 * @package core
21 * @copyright 2014 The Open University
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27global $CFG;
28require_once($CFG->libdir . '/filelib.php');
29
30/**
31 * Unit tests for /lib/classes/filetypes.php.
32 *
33 * @package core
34 * @copyright 2014 The Open University
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 */
37class core_filetypes_testcase extends advanced_testcase {
38
39    public function test_add_type() {
40        $this->resetAfterTest();
41
42        // Check the filetypes to be added do not exist yet (basically this
43        // ensures we're testing the cache clear).
44        $types = get_mimetypes_array();
45        $this->assertArrayNotHasKey('frog', $types);
46        $this->assertArrayNotHasKey('zombie', $types);
47
48        // Add two filetypes (minimal, then all options).
49        core_filetypes::add_type('frog', 'application/x-frog', 'document');
50        core_filetypes::add_type('zombie', 'application/x-zombie', 'document',
51            array('document', 'image'), 'image', 'A zombie', true);
52
53        // Check they now exist, and check data.
54        $types = get_mimetypes_array();
55        $this->assertEquals('application/x-frog', $types['frog']['type']);
56        $this->assertEquals('document', $types['frog']['icon']);
57        $this->assertEquals(array('document', 'image'), $types['zombie']['groups']);
58        $this->assertEquals('image', $types['zombie']['string']);
59        $this->assertEquals(true, $types['zombie']['defaulticon']);
60        $this->assertEquals('A zombie', $types['zombie']['customdescription']);
61
62        // Test adding again causes exception.
63        try {
64            core_filetypes::add_type('frog', 'application/x-frog', 'document');
65            $this->fail();
66        } catch (coding_exception $e) {
67            $this->assertStringContainsString('already exists', $e->getMessage());
68            $this->assertStringContainsString('frog', $e->getMessage());
69        }
70
71        // Test bogus extension causes exception.
72        try {
73            core_filetypes::add_type('.frog', 'application/x-frog', 'document');
74            $this->fail();
75        } catch (coding_exception $e) {
76            $this->assertStringContainsString('Invalid extension', $e->getMessage());
77            $this->assertStringContainsString('..frog', $e->getMessage());
78        }
79        try {
80            core_filetypes::add_type('', 'application/x-frog', 'document');
81            $this->fail();
82        } catch (coding_exception $e) {
83            $this->assertStringContainsString('Invalid extension', $e->getMessage());
84        }
85
86        // Test there is an exception if you add something with defaulticon when
87        // there is already a type that has it.
88        try {
89            core_filetypes::add_type('gecko', 'text/plain', 'document',
90                    array(), '', '', true);
91            $this->fail();
92        } catch (coding_exception $e) {
93            $this->assertStringContainsString('default icon set', $e->getMessage());
94            $this->assertStringContainsString('text/plain', $e->getMessage());
95        }
96    }
97
98    public function test_update_type() {
99        $this->resetAfterTest();
100
101        // Check previous value for the MIME type of Word documents.
102        $types = get_mimetypes_array();
103        $this->assertEquals('application/msword', $types['doc']['type']);
104
105        // Change it.
106        core_filetypes::update_type('doc', 'doc', 'application/x-frog', 'document');
107
108        // Check the MIME type is now set and also the other (not specified)
109        // options, like groups, were removed.
110        $types = get_mimetypes_array();
111        $this->assertEquals('application/x-frog', $types['doc']['type']);
112        $this->assertArrayNotHasKey('groups', $types['doc']);
113
114        // This time change the extension.
115        core_filetypes::update_type('doc', 'docccc', 'application/x-frog', 'document');
116        $types = get_mimetypes_array();
117        $this->assertEquals('application/x-frog', $types['docccc']['type']);
118        $this->assertArrayNotHasKey('doc', $types);
119
120        // Test unknown extension.
121        try {
122            core_filetypes::update_type('doc', 'doc', 'application/x-frog', 'document');
123            $this->fail();
124        } catch (coding_exception $e) {
125            $this->assertStringContainsString('not found', $e->getMessage());
126            $this->assertStringContainsString('doc', $e->getMessage());
127        }
128
129        // Test bogus extension causes exception.
130        try {
131            core_filetypes::update_type('docccc', '.frog', 'application/x-frog', 'document');
132            $this->fail();
133        } catch (coding_exception $e) {
134            $this->assertStringContainsString('Invalid extension', $e->getMessage());
135            $this->assertStringContainsString('.frog', $e->getMessage());
136        }
137        try {
138            core_filetypes::update_type('docccc', '', 'application/x-frog', 'document');
139            $this->fail();
140        } catch (coding_exception $e) {
141            $this->assertStringContainsString('Invalid extension', $e->getMessage());
142        }
143
144        // Test defaulticon changes.
145        try {
146            core_filetypes::update_type('docccc', 'docccc', 'text/plain', 'document',
147                    array(), '', '', true);
148            $this->fail();
149        } catch (coding_exception $e) {
150            $this->assertStringContainsString('default icon set', $e->getMessage());
151            $this->assertStringContainsString('text/plain', $e->getMessage());
152        }
153    }
154
155    public function test_delete_type() {
156        $this->resetAfterTest();
157
158        // Filetype exists.
159        $types = get_mimetypes_array();
160        $this->assertArrayHasKey('doc', $types);
161
162        // Remove it.
163        core_filetypes::delete_type('doc');
164        $types = get_mimetypes_array();
165        $this->assertArrayNotHasKey('doc', $types);
166
167        // Test removing one that doesn't exist causes exception.
168        try {
169            core_filetypes::delete_type('doc');
170            $this->fail();
171        } catch (coding_exception $e) {
172            $this->assertStringContainsString('not found', $e->getMessage());
173            $this->assertStringContainsString('doc', $e->getMessage());
174        }
175
176        // Try a custom type (slightly different).
177        core_filetypes::add_type('frog', 'application/x-frog', 'document');
178        $types = get_mimetypes_array();
179        $this->assertArrayHasKey('frog', $types);
180        core_filetypes::delete_type('frog');
181        $types = get_mimetypes_array();
182        $this->assertArrayNotHasKey('frog', $types);
183    }
184
185    public function test_revert_type_to_default() {
186        $this->resetAfterTest();
187
188        // Delete and then revert.
189        core_filetypes::delete_type('doc');
190        $this->assertArrayNotHasKey('doc', get_mimetypes_array());
191        core_filetypes::revert_type_to_default('doc');
192        $this->assertArrayHasKey('doc', get_mimetypes_array());
193
194        // Update and then revert.
195        core_filetypes::update_type('asm', 'asm', 'text/plain', 'sourcecode', array(), '', 'An asm file');
196        $types = get_mimetypes_array();
197        $this->assertEquals('An asm file', $types['asm']['customdescription']);
198        core_filetypes::revert_type_to_default('asm');
199        $types = get_mimetypes_array();
200        $this->assertArrayNotHasKey('customdescription', $types['asm']);
201
202        // Test reverting a non-default type causes exception.
203        try {
204            core_filetypes::revert_type_to_default('frog');
205            $this->fail();
206        } catch (coding_exception $e) {
207            $this->assertStringContainsString('not a default type', $e->getMessage());
208            $this->assertStringContainsString('frog', $e->getMessage());
209        }
210    }
211
212    /**
213     * Check that the logic cleans up the variable by deleting parts that are
214     * no longer needed.
215     */
216    public function test_cleanup() {
217        global $CFG;
218        $this->resetAfterTest();
219
220        // The custom filetypes setting is empty to start with.
221        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
222
223        // Add a custom filetype, then delete it.
224        core_filetypes::add_type('frog', 'application/x-frog', 'document');
225        $this->assertObjectHasAttribute('customfiletypes', $CFG);
226        core_filetypes::delete_type('frog');
227        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
228
229        // Change a standard filetype, then change it back.
230        core_filetypes::update_type('asm', 'asm', 'text/plain', 'document');
231        $this->assertObjectHasAttribute('customfiletypes', $CFG);
232        core_filetypes::update_type('asm', 'asm', 'text/plain', 'sourcecode');
233        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
234
235        // Delete a standard filetype, then add it back (the same).
236        core_filetypes::delete_type('asm');
237        $this->assertObjectHasAttribute('customfiletypes', $CFG);
238        core_filetypes::add_type('asm', 'text/plain', 'sourcecode');
239        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
240
241        // Revert a changed type.
242        core_filetypes::update_type('asm', 'asm', 'text/plain', 'document');
243        $this->assertObjectHasAttribute('customfiletypes', $CFG);
244        core_filetypes::revert_type_to_default('asm');
245        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
246
247        // Revert a deleted type.
248        core_filetypes::delete_type('asm');
249        $this->assertObjectHasAttribute('customfiletypes', $CFG);
250        core_filetypes::revert_type_to_default('asm');
251        $this->assertObjectNotHasAttribute('customfiletypes', $CFG);
252    }
253}
254