MDL-35145 add extra delete_user() parameter validation
[moodle.git] / lib / tests / moodlelib_test.php
CommitLineData
a3d5830a
PS
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 (some of) ../moodlelib.php.
19 *
20 * @package core
21 * @category phpunit
22 * @copyright &copy; 2006 The Open University
23 * @author T.J.Hunt@open.ac.uk
24 * @author nicolas@moodle.com
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30require_once($CFG->libdir . '/moodlelib.php');
31
32
4b027431 33class moodlelib_testcase extends advanced_testcase {
a3d5830a
PS
34
35 public static $includecoverage = array('lib/moodlelib.php');
36
37 var $user_agents = array(
38 'MSIE' => array(
39 '5.0' => array('Windows 98' => 'Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)'),
40 '5.5' => array('Windows 2000' => 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)'),
41 '6.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'),
42 '7.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)'),
43 '8.0' => array('Windows Vista' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)'),
44 '9.0' => array('Windows 7' => 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))'),
45
46 ),
47 'Firefox' => array(
48 '1.0.6' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6'),
49 '1.5' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5'),
50 '1.5.0.1' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1'),
51 '2.0' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1',
52 'Ubuntu Linux AMD64' => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1) Gecko/20060601 Firefox/2.0 (Ubuntu-edgy)'),
53 '3.0.6' => array('SUSE' => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.6) Gecko/2009012700 SUSE/3.0.6-1.4 Firefox/3.0.6'),
54 ),
55 'Safari' => array(
56 '312' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312'),
57 '412' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412')
58 ),
59 'Safari iOS' => array(
60 '528' => array('iPhone' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; cs-cz) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16'),
61 '533' => array('iPad' => 'Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5'),
62 ),
63 'WebKit Android' => array(
64 '525' => array('G1 Phone' => 'Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 – G1 Phone'),
65 '530' => array('Nexus' => 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 –Nexus'),
66 ),
67 'Chrome' => array(
68 '8' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10'),
69 ),
70 'Opera' => array(
71 '8.51' => array('Windows XP' => 'Opera/8.51 (Windows NT 5.1; U; en)'),
72 '9.0' => array('Windows XP' => 'Opera/9.0 (Windows NT 5.1; U; en)',
73 'Debian Linux' => 'Opera/9.01 (X11; Linux i686; U; en)')
74 )
75 );
76
77 function test_cleanremoteaddr() {
78 //IPv4
79 $this->assertEquals(cleanremoteaddr('1023.121.234.1'), null);
80 $this->assertEquals(cleanremoteaddr('123.121.234.01 '), '123.121.234.1');
81
82 //IPv6
83 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:0:0'), null);
84 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:abh'), null);
85 $this->assertEquals(cleanremoteaddr('0:0:0:::0:0:1'), null);
86 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:0', true), '::');
87 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:1:1', true), '::1:1');
88 $this->assertEquals(cleanremoteaddr('abcd:00ef:0:0:0:0:0:0', true), 'abcd:ef::');
89 $this->assertEquals(cleanremoteaddr('1:0:0:0:0:0:0:1', true), '1::1');
90 $this->assertEquals(cleanremoteaddr('::10:1', false), '0:0:0:0:0:0:10:1');
91 $this->assertEquals(cleanremoteaddr('01:1::', false), '1:1:0:0:0:0:0:0');
92 $this->assertEquals(cleanremoteaddr('10::10', false), '10:0:0:0:0:0:0:10');
93 $this->assertEquals(cleanremoteaddr('::ffff:192.168.1.1', true), '::ffff:c0a8:11');
94 }
95
96 function test_address_in_subnet() {
97 /// 1: xxx.xxx.xxx.xxx/nn or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/nnn (number of bits in net mask)
98 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.1/32'));
99 $this->assertFalse(address_in_subnet('123.121.23.1', '123.121.23.0/32'));
100 $this->assertTrue(address_in_subnet('10.10.10.100', '123.121.23.45/0'));
101 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/24'));
102 $this->assertFalse(address_in_subnet('123.121.34.1', '123.121.234.0/24'));
103 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/30'));
104 $this->assertFalse(address_in_subnet('123.121.23.8', '123.121.23.0/30'));
105 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128'));
106 $this->assertFalse(address_in_subnet('bab:baba::baba', 'bab:baba::cece/128'));
107 $this->assertTrue(address_in_subnet('baba:baba::baba', 'cece:cece::cece/0'));
108 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128'));
109 $this->assertTrue(address_in_subnet('baba:baba::00ba', 'baba:baba::/120'));
110 $this->assertFalse(address_in_subnet('baba:baba::aba', 'baba:baba::/120'));
111 $this->assertTrue(address_in_subnet('baba::baba:00ba', 'baba::baba:0/112'));
112 $this->assertFalse(address_in_subnet('baba::aba:00ba', 'baba::baba:0/112'));
113 $this->assertFalse(address_in_subnet('aba::baba:0000', 'baba::baba:0/112'));
114
115 // fixed input
116 $this->assertTrue(address_in_subnet('123.121.23.1 ', ' 123.121.23.0 / 24'));
117 $this->assertTrue(address_in_subnet('::ffff:10.1.1.1', ' 0:0:0:000:0:ffff:a1:10 / 126'));
118
119 // incorrect input
120 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/-2'));
121 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/64'));
122 $this->assertFalse(address_in_subnet('123.121.234.x', '123.121.234.1/24'));
123 $this->assertFalse(address_in_subnet('123.121.234.0', '123.121.234.xx/24'));
124 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/xx0'));
125 $this->assertFalse(address_in_subnet('::1', '::aa:0/xx0'));
126 $this->assertFalse(address_in_subnet('::1', '::aa:0/-5'));
127 $this->assertFalse(address_in_subnet('::1', '::aa:0/130'));
128 $this->assertFalse(address_in_subnet('x:1', '::aa:0/130'));
129 $this->assertFalse(address_in_subnet('::1', '::ax:0/130'));
130
131
132 /// 2: xxx.xxx.xxx.xxx-yyy or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::xxxx-yyyy (a range of IP addresses in the last group)
133 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12-14'));
134 $this->assertTrue(address_in_subnet('123.121.234.13', '123.121.234.12-14'));
135 $this->assertTrue(address_in_subnet('123.121.234.14', '123.121.234.12-14'));
136 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.12-14'));
137 $this->assertFalse(address_in_subnet('123.121.234.20', '123.121.234.12-14'));
138 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.234.12-14'));
139 $this->assertFalse(address_in_subnet('123.12.234.12', '123.121.234.12-14'));
140 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba-babe'));
141 $this->assertTrue(address_in_subnet('baba:baba::babc', 'baba:baba::baba-babe'));
142 $this->assertTrue(address_in_subnet('baba:baba::babe', 'baba:baba::baba-babe'));
143 $this->assertFalse(address_in_subnet('bab:baba::bab0', 'bab:baba::baba-babe'));
144 $this->assertFalse(address_in_subnet('bab:baba::babf', 'bab:baba::baba-babe'));
145 $this->assertFalse(address_in_subnet('bab:baba::bfbe', 'bab:baba::baba-babe'));
146 $this->assertFalse(address_in_subnet('bfb:baba::babe', 'bab:baba::baba-babe'));
147
148 // fixed input
149 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12 - 14 '));
150 $this->assertTrue(address_in_subnet('bab:baba::babe', 'bab:baba::baba - babe '));
151
152 // incorrect input
153 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-234.14'));
154 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-256'));
155 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12--256'));
156
157
158 /// 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx. (incomplete address, a bit non-technical ;-)
159 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12'));
160 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.23.13'));
161 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.'));
162 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234'));
163 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121'));
164 $this->assertTrue(address_in_subnet('123.121.234.12', '123'));
165 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234.'));
166 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234'));
167 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba::bab'));
168 $this->assertFalse(address_in_subnet('baba:baba::ba', 'baba:baba::bc'));
169 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba'));
170 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:'));
171 $this->assertFalse(address_in_subnet('bab:baba::bab', 'baba:'));
172
173
174 /// multiple subnets
175 $this->assertTrue(address_in_subnet('123.121.234.12', '::1/64, 124., 123.121.234.10-30'));
176 $this->assertTrue(address_in_subnet('124.121.234.12', '::1/64, 124., 123.121.234.10-30'));
177 $this->assertTrue(address_in_subnet('::2', '::1/64, 124., 123.121.234.10-30'));
178 $this->assertFalse(address_in_subnet('12.121.234.12', '::1/64, 124., 123.121.234.10-30'));
179
180
181 /// other incorrect input
182 $this->assertFalse(address_in_subnet('123.123.123.123', ''));
183 }
184
185 /**
186 * Modifies $_SERVER['HTTP_USER_AGENT'] manually to check if check_browser_version
187 * works as expected.
188 */
189 function test_check_browser_version()
190 {
191 global $CFG;
192
193 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['412']['Mac OS X'];
194 $this->assertTrue(check_browser_version('Safari'));
195 $this->assertTrue(check_browser_version('WebKit'));
196 $this->assertTrue(check_browser_version('Safari', '312'));
197 $this->assertFalse(check_browser_version('Safari', '500'));
198 $this->assertFalse(check_browser_version('Chrome'));
199 $this->assertFalse(check_browser_version('Safari iOS'));
200
201 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari iOS']['528']['iPhone'];
202 $this->assertTrue(check_browser_version('Safari iOS'));
203 $this->assertTrue(check_browser_version('WebKit'));
204 $this->assertTrue(check_browser_version('Safari iOS', '527'));
205 $this->assertFalse(check_browser_version('Safari iOS', 590));
206 $this->assertFalse(check_browser_version('Safari', '312'));
207 $this->assertFalse(check_browser_version('Safari', '500'));
208 $this->assertFalse(check_browser_version('Chrome'));
209
210 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['WebKit Android']['530']['Nexus'];
211 $this->assertTrue(check_browser_version('WebKit'));
212 $this->assertTrue(check_browser_version('WebKit Android', '527'));
213 $this->assertFalse(check_browser_version('WebKit Android', 590));
214 $this->assertFalse(check_browser_version('Safari'));
215 $this->assertFalse(check_browser_version('Chrome'));
216
217 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
218 $this->assertTrue(check_browser_version('Chrome'));
219 $this->assertTrue(check_browser_version('WebKit'));
220 $this->assertTrue(check_browser_version('Chrome', 8));
221 $this->assertFalse(check_browser_version('Chrome', 10));
222 $this->assertFalse(check_browser_version('Safari', '1'));
223
224 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
225 $this->assertTrue(check_browser_version('Opera'));
226 $this->assertTrue(check_browser_version('Opera', '8.0'));
227 $this->assertFalse(check_browser_version('Opera', '10.0'));
228
229 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['6.0']['Windows XP SP2'];
230 $this->assertTrue(check_browser_version('MSIE'));
231 $this->assertTrue(check_browser_version('MSIE', '5.0'));
232 $this->assertFalse(check_browser_version('MSIE', '7.0'));
233
234 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['5.0']['Windows 98'];
235 $this->assertFalse(check_browser_version('MSIE'));
236 $this->assertTrue(check_browser_version('MSIE', 0));
237 $this->assertTrue(check_browser_version('MSIE', '5.0'));
238 $this->assertFalse(check_browser_version('MSIE', '7.0'));
239
240 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['9.0']['Windows 7'];
241 $this->assertTrue(check_browser_version('MSIE'));
242 $this->assertTrue(check_browser_version('MSIE', 0));
243 $this->assertTrue(check_browser_version('MSIE', '5.0'));
244 $this->assertTrue(check_browser_version('MSIE', '9.0'));
245 $this->assertFalse(check_browser_version('MSIE', '10'));
246
247 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
248 $this->assertTrue(check_browser_version('Firefox'));
249 $this->assertTrue(check_browser_version('Firefox', '1.5'));
250 $this->assertFalse(check_browser_version('Firefox', '3.0'));
251 }
252
253 function test_get_browser_version_classes() {
254 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['412']['Mac OS X'];
255 $this->assertEquals(array('safari'), get_browser_version_classes());
256
257 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
258 $this->assertEquals(array('safari'), get_browser_version_classes());
259
260 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari iOS']['528']['iPhone'];
261 $this->assertEquals(array('safari', 'ios'), get_browser_version_classes());
262
263 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['WebKit Android']['530']['Nexus'];
264 $this->assertEquals(array('safari', 'android'), get_browser_version_classes());
265
266 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
267 $this->assertEquals(array('safari'), get_browser_version_classes());
268
269 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
270 $this->assertEquals(array('opera'), get_browser_version_classes());
271
272 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['6.0']['Windows XP SP2'];
273 $this->assertEquals(array('ie', 'ie6'), get_browser_version_classes());
274
275 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['7.0']['Windows XP SP2'];
276 $this->assertEquals(array('ie', 'ie7'), get_browser_version_classes());
277
278 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['8.0']['Windows Vista'];
279 $this->assertEquals(array('ie', 'ie8'), get_browser_version_classes());
280
281 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
282 $this->assertEquals(array('gecko', 'gecko18'), get_browser_version_classes());
283
284 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['3.0.6']['SUSE'];
285 $this->assertEquals(array('gecko', 'gecko19'), get_browser_version_classes());
286 }
287
288 function test_get_device_type() {
289 // IE8 (common pattern ~1.5% of IE7/8 users have embedded IE6 agent))
290 $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; BT Openworld BB; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Hotbar 10.2.197.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)';
291 $this->assertEquals('default', get_device_type());
292 // Genuine IE6
293 $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.0.3705; Media Center PC 2.8)';
294 $this->assertEquals('legacy', get_device_type());
295 }
296
297 function test_fix_utf8() {
298 // make sure valid data including other types is not changed
299 $this->assertSame(null, fix_utf8(null));
300 $this->assertSame(1, fix_utf8(1));
301 $this->assertSame(1.1, fix_utf8(1.1));
302 $this->assertSame(true, fix_utf8(true));
303 $this->assertSame('', fix_utf8(''));
0aff15c2 304 $this->assertSame('abc', fix_utf8('abc'));
a3d5830a
PS
305 $array = array('do', 're', 'mi');
306 $this->assertSame($array, fix_utf8($array));
307 $object = new stdClass();
308 $object->a = 'aa';
309 $object->b = 'bb';
310 $this->assertEquals($object, fix_utf8($object));
311
312 // valid utf8 string
313 $this->assertSame("žlutý koníček přeskočil potůček \n\t\r\0", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0"));
314
315 // invalid utf8 string
0aff15c2 316 $this->assertSame('aš', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.');
a3d5830a
PS
317 }
318
319 function test_optional_param() {
320 global $CFG;
321
322 $_POST['username'] = 'post_user';
323 $_GET['username'] = 'get_user';
324 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_POST['username']);
325
326 unset($_POST['username']);
327 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_GET['username']);
328
329 unset($_GET['username']);
330 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), 'default_user');
331
332 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
333 $_POST['username'] = 'post_user';
334 try {
335 optional_param('username', 'default_user', null);
336 $this->fail('coding_exception expected');
337 } catch (coding_exception $ex) {
338 $this->assertTrue(true);
339 }
340 try {
341 @optional_param('username', 'default_user');
342 $this->fail('coding_exception expected');
343 } catch (coding_exception $ex) {
344 $this->assertTrue(true);
345 }
346 try {
347 @optional_param('username');
348 $this->fail('coding_exception expected');
349 } catch (coding_exception $ex) {
350 $this->assertTrue(true);
351 }
352 try {
353 optional_param('', 'default_user', PARAM_RAW);
354 $this->fail('coding_exception expected');
355 } catch (coding_exception $ex) {
356 $this->assertTrue(true);
357 }
358
359 // make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3
360 $debugging = isset($CFG->debug) ? $CFG->debug : null;
361 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
362 $CFG->debug = DEBUG_DEVELOPER;
363 $CFG->debugdisplay = true;
364
365 ob_start();
366 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_POST['username']);
367 $d = ob_end_clean();
368 $this->assertTrue($d !== '');
369
370 if ($debugging !== null) {
371 $CFG->debug = $debugging;
372 } else {
373 unset($CFG->debug);
374 }
375 if ($debugdisplay !== null) {
376 $CFG->debugdisplay = $debugdisplay;
377 } else {
378 unset($CFG->debugdisplay);
379 }
380 }
381
382 function test_optional_param_array() {
383 global $CFG;
384
385 $_POST['username'] = array('a'=>'post_user');
386 $_GET['username'] = array('a'=>'get_user');
387 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), $_POST['username']);
388
389 unset($_POST['username']);
390 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), $_GET['username']);
391
392 unset($_GET['username']);
393 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), array('a'=>'default_user'));
394
395 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
396 $_POST['username'] = array('a'=>'post_user');
397 try {
398 optional_param_array('username', array('a'=>'default_user'), null);
399 $this->fail('coding_exception expected');
400 } catch (coding_exception $ex) {
401 $this->assertTrue(true);
402 }
403 try {
404 @optional_param_array('username', array('a'=>'default_user'));
405 $this->fail('coding_exception expected');
406 } catch (coding_exception $ex) {
407 $this->assertTrue(true);
408 }
409 try {
410 @optional_param_array('username');
411 $this->fail('coding_exception expected');
412 } catch (coding_exception $ex) {
413 $this->assertTrue(true);
414 }
415 try {
416 optional_param_array('', array('a'=>'default_user'), PARAM_RAW);
417 $this->fail('coding_exception expected');
418 } catch (coding_exception $ex) {
419 $this->assertTrue(true);
420 }
421
422 // do not allow nested arrays
423 try {
424 $_POST['username'] = array('a'=>array('b'=>'post_user'));
425 optional_param_array('username', array('a'=>'default_user'), PARAM_RAW);
426 $this->fail('coding_exception expected');
427 } catch (coding_exception $ex) {
428 $this->assertTrue(true);
429 }
430
431 // do not allow non-arrays
432 $debugging = isset($CFG->debug) ? $CFG->debug : null;
433 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
434 $CFG->debug = DEBUG_DEVELOPER;
435 $CFG->debugdisplay = true;
436
437 ob_start();
438 $_POST['username'] = 'post_user';
439 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), array('a'=>'default_user'));
440 $d = ob_end_clean();
441 $this->assertTrue($d !== '');
442
443 // make sure array keys are sanitised
444 ob_start();
445 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user');
446 $this->assertSame(optional_param_array('username', array(), PARAM_RAW), array('a1_-'=>'post_user'));
447 $d = ob_end_clean();
448 $this->assertTrue($d !== '');
449
450 if ($debugging !== null) {
451 $CFG->debug = $debugging;
452 } else {
453 unset($CFG->debug);
454 }
455 if ($debugdisplay !== null) {
456 $CFG->debugdisplay = $debugdisplay;
457 } else {
458 unset($CFG->debugdisplay);
459 }
460 }
461
462 function test_required_param() {
463 global $CFG;
464
465 $_POST['username'] = 'post_user';
466 $_GET['username'] = 'get_user';
467 $this->assertSame(required_param('username', PARAM_RAW), 'post_user');
468
469 unset($_POST['username']);
470 $this->assertSame(required_param('username', PARAM_RAW), 'get_user');
471
472 unset($_GET['username']);
473 try {
474 $this->assertSame(required_param('username', PARAM_RAW), 'default_user');
475 $this->fail('moodle_exception expected');
476 } catch (moodle_exception $ex) {
477 $this->assertTrue(true);
478 }
479
480 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
481 $_POST['username'] = 'post_user';
482 try {
483 @required_param('username');
484 $this->fail('coding_exception expected');
485 } catch (coding_exception $ex) {
486 $this->assertTrue(true);
487 }
488 try {
489 required_param('username', '');
490 $this->fail('coding_exception expected');
491 } catch (coding_exception $ex) {
492 $this->assertTrue(true);
493 }
494 try {
495 required_param('', PARAM_RAW);
496 $this->fail('coding_exception expected');
497 } catch (coding_exception $ex) {
498 $this->assertTrue(true);
499 }
500
501 // make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3
502 $debugging = isset($CFG->debug) ? $CFG->debug : null;
503 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
504 $CFG->debug = DEBUG_DEVELOPER;
505 $CFG->debugdisplay = true;
506
507 ob_start();
508 $this->assertSame(required_param('username', PARAM_RAW), $_POST['username']);
509 $d = ob_end_clean();
510 $this->assertTrue($d !== '');
511
512 if ($debugging !== null) {
513 $CFG->debug = $debugging;
514 } else {
515 unset($CFG->debug);
516 }
517 if ($debugdisplay !== null) {
518 $CFG->debugdisplay = $debugdisplay;
519 } else {
520 unset($CFG->debugdisplay);
521 }
522 }
523
524 function test_required_param_array() {
525 global $CFG;
526
527 $_POST['username'] = array('a'=>'post_user');
528 $_GET['username'] = array('a'=>'get_user');
529 $this->assertSame(required_param_array('username', PARAM_RAW), $_POST['username']);
530
531 unset($_POST['username']);
532 $this->assertSame(required_param_array('username', PARAM_RAW), $_GET['username']);
533
534 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
535 $_POST['username'] = array('a'=>'post_user');
536 try {
537 required_param_array('username', null);
538 $this->fail('coding_exception expected');
539 } catch (coding_exception $ex) {
540 $this->assertTrue(true);
541 }
542 try {
543 @required_param_array('username');
544 $this->fail('coding_exception expected');
545 } catch (coding_exception $ex) {
546 $this->assertTrue(true);
547 }
548 try {
549 required_param_array('', PARAM_RAW);
550 $this->fail('coding_exception expected');
551 } catch (coding_exception $ex) {
552 $this->assertTrue(true);
553 }
554
555 // do not allow nested arrays
556 try {
557 $_POST['username'] = array('a'=>array('b'=>'post_user'));
558 required_param_array('username', PARAM_RAW);
559 $this->fail('coding_exception expected');
560 } catch (coding_exception $ex) {
561 $this->assertTrue(true);
562 }
563
564 // do not allow non-arrays
565 try {
566 $_POST['username'] = 'post_user';
567 required_param_array('username', PARAM_RAW);
568 $this->fail('moodle_exception expected');
569 } catch (moodle_exception $ex) {
570 $this->assertTrue(true);
571 }
572
573 // do not allow non-arrays
574 $debugging = isset($CFG->debug) ? $CFG->debug : null;
575 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
576 $CFG->debug = DEBUG_DEVELOPER;
577 $CFG->debugdisplay = true;
578
579 // make sure array keys are sanitised
580 ob_start();
581 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user');
582 $this->assertSame(required_param_array('username', PARAM_RAW), array('a1_-'=>'post_user'));
583 $d = ob_end_clean();
584 $this->assertTrue($d !== '');
585
586 if ($debugging !== null) {
587 $CFG->debug = $debugging;
588 } else {
589 unset($CFG->debug);
590 }
591 if ($debugdisplay !== null) {
592 $CFG->debugdisplay = $debugdisplay;
593 } else {
594 unset($CFG->debugdisplay);
595 }
596 }
597
598 function test_clean_param() {
599 // forbid objects and arrays
600 try {
601 clean_param(array('x', 'y'), PARAM_RAW);
602 $this->fail('coding_exception expected');
603 } catch (coding_exception $ex) {
604 $this->assertTrue(true);
605 }
606 try {
607 $param = new stdClass();
608 $param->id = 1;
609 clean_param($param, PARAM_RAW);
610 $this->fail('coding_exception expected');
611 } catch (coding_exception $ex) {
612 $this->assertTrue(true);
613 }
614
615 // require correct type
616 try {
617 clean_param('x', 'xxxxxx');
618 $this->fail('moodle_exception expected');
619 } catch (moodle_exception $ex) {
620 $this->assertTrue(true);
621 }
622 try {
623 @clean_param('x');
624 $this->fail('moodle_exception expected');
625 } catch (moodle_exception $ex) {
626 $this->assertTrue(true);
627 }
628
629 }
630
631 function test_clean_param_array() {
632 $this->assertSame(clean_param_array(null, PARAM_RAW), array());
633 $this->assertSame(clean_param_array(array('a', 'b'), PARAM_RAW), array('a', 'b'));
634 $this->assertSame(clean_param_array(array('a', array('b')), PARAM_RAW, true), array('a', array('b')));
635
636 // require correct type
637 try {
638 clean_param_array(array('x'), 'xxxxxx');
639 $this->fail('moodle_exception expected');
640 } catch (moodle_exception $ex) {
641 $this->assertTrue(true);
642 }
643 try {
644 @clean_param_array(array('x'));
645 $this->fail('moodle_exception expected');
646 } catch (moodle_exception $ex) {
647 $this->assertTrue(true);
648 }
649
650 try {
651 clean_param_array(array('x', array('y')), PARAM_RAW);
652 $this->fail('coding_exception expected');
653 } catch (coding_exception $ex) {
654 $this->assertTrue(true);
655 }
656
657 // test recursive
658 }
659
660 function test_clean_param_raw() {
661 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_RAW),
662 '#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)');
663 }
664
665 function test_clean_param_trim() {
666 $this->assertEquals(clean_param(" Frog toad \r\n ", PARAM_RAW_TRIMMED), 'Frog toad');
667 }
668
669 function test_clean_param_clean() {
670 // PARAM_CLEAN is an ugly hack, do not use in new code (skodak)
671 // instead use more specific type, or submit sothing that can be verified properly
672 $this->assertEquals(clean_param('xx<script>', PARAM_CLEAN), 'xx');
673 }
674
675 function test_clean_param_alpha() {
676 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHA),
677 'DSFMOSDJ');
678 }
679
680 function test_clean_param_alphanum() {
681 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHANUM),
682 '978942897DSFMOSDJ');
683 }
684
685 function test_clean_param_alphaext() {
686 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHAEXT),
687 'DSFMOSDJ');
688 }
689
690 function test_clean_param_sequence() {
691 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_SEQUENCE),
692 ',9789,42897');
693 }
694
695 function test_clean_param_component() {
696 // please note the cleaning of component names is very strict, no guessing here
697 $this->assertSame(clean_param('mod_forum', PARAM_COMPONENT), 'mod_forum');
698 $this->assertSame(clean_param('block_online_users', PARAM_COMPONENT), 'block_online_users');
699 $this->assertSame(clean_param('block_blond_online_users', PARAM_COMPONENT), 'block_blond_online_users');
700 $this->assertSame(clean_param('mod_something2', PARAM_COMPONENT), 'mod_something2');
701 $this->assertSame(clean_param('forum', PARAM_COMPONENT), 'forum');
702 $this->assertSame(clean_param('user', PARAM_COMPONENT), 'user');
703 $this->assertSame(clean_param('rating', PARAM_COMPONENT), 'rating');
704 $this->assertSame(clean_param('mod_2something', PARAM_COMPONENT), '');
705 $this->assertSame(clean_param('2mod_something', PARAM_COMPONENT), '');
706 $this->assertSame(clean_param('mod_something_xx', PARAM_COMPONENT), '');
707 $this->assertSame(clean_param('auth_something__xx', PARAM_COMPONENT), '');
708 $this->assertSame(clean_param('mod_Something', PARAM_COMPONENT), '');
709 $this->assertSame(clean_param('mod_somethíng', PARAM_COMPONENT), '');
710 $this->assertSame(clean_param('auth_xx-yy', PARAM_COMPONENT), '');
711 $this->assertSame(clean_param('_auth_xx', PARAM_COMPONENT), '');
712 $this->assertSame(clean_param('a2uth_xx', PARAM_COMPONENT), '');
713 $this->assertSame(clean_param('auth_xx_', PARAM_COMPONENT), '');
714 $this->assertSame(clean_param('auth_xx.old', PARAM_COMPONENT), '');
715 $this->assertSame(clean_param('_user', PARAM_COMPONENT), '');
716 $this->assertSame(clean_param('2rating', PARAM_COMPONENT), '');
717 $this->assertSame(clean_param('user_', PARAM_COMPONENT), '');
718 }
719
720 function test_clean_param_plugin() {
721 // please note the cleaning of plugin names is very strict, no guessing here
722 $this->assertSame(clean_param('forum', PARAM_PLUGIN), 'forum');
723 $this->assertSame(clean_param('forum2', PARAM_PLUGIN), 'forum2');
724 $this->assertSame(clean_param('online_users', PARAM_PLUGIN), 'online_users');
725 $this->assertSame(clean_param('blond_online_users', PARAM_PLUGIN), 'blond_online_users');
726 $this->assertSame(clean_param('online__users', PARAM_PLUGIN), '');
727 $this->assertSame(clean_param('forum ', PARAM_PLUGIN), '');
728 $this->assertSame(clean_param('forum.old', PARAM_PLUGIN), '');
729 $this->assertSame(clean_param('xx-yy', PARAM_PLUGIN), '');
730 $this->assertSame(clean_param('2xx', PARAM_PLUGIN), '');
731 $this->assertSame(clean_param('Xx', PARAM_PLUGIN), '');
732 $this->assertSame(clean_param('_xx', PARAM_PLUGIN), '');
733 $this->assertSame(clean_param('xx_', PARAM_PLUGIN), '');
734 }
735
736 function test_clean_param_area() {
737 // please note the cleaning of area names is very strict, no guessing here
738 $this->assertSame(clean_param('something', PARAM_AREA), 'something');
739 $this->assertSame(clean_param('something2', PARAM_AREA), 'something2');
740 $this->assertSame(clean_param('some_thing', PARAM_AREA), 'some_thing');
741 $this->assertSame(clean_param('some_thing_xx', PARAM_AREA), 'some_thing_xx');
742 $this->assertSame(clean_param('_something', PARAM_AREA), '');
743 $this->assertSame(clean_param('something_', PARAM_AREA), '');
744 $this->assertSame(clean_param('2something', PARAM_AREA), '');
745 $this->assertSame(clean_param('Something', PARAM_AREA), '');
746 $this->assertSame(clean_param('some-thing', PARAM_AREA), '');
747 $this->assertSame(clean_param('somethííng', PARAM_AREA), '');
748 $this->assertSame(clean_param('something.x', PARAM_AREA), '');
749 }
750
751 function test_clean_param_text() {
752 $this->assertEquals(PARAM_TEXT, PARAM_MULTILANG);
753 //standard
754 $this->assertEquals(clean_param('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', PARAM_TEXT), 'xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>');
755 $this->assertEquals(clean_param('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', PARAM_TEXT), '<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>');
756 $this->assertEquals(clean_param('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', PARAM_TEXT), 'xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>');
757 //malformed
758 $this->assertEquals(clean_param('<span lang="en" class="multilang">aa</span>', PARAM_TEXT), '<span lang="en" class="multilang">aa</span>');
759 $this->assertEquals(clean_param('<span lang="en" class="nothing" class="multilang">aa</span>', PARAM_TEXT), 'aa');
760 $this->assertEquals(clean_param('<lang lang="en" class="multilang">aa</lang>', PARAM_TEXT), 'aa');
761 $this->assertEquals(clean_param('<lang lang="en!!">aa</lang>', PARAM_TEXT), 'aa');
762 $this->assertEquals(clean_param('<span lang="en==" class="multilang">aa</span>', PARAM_TEXT), 'aa');
763 $this->assertEquals(clean_param('a<em>b</em>c', PARAM_TEXT), 'abc');
764 $this->assertEquals(clean_param('a><xx >c>', PARAM_TEXT), 'a>c>'); // standard strip_tags() behaviour
765 $this->assertEquals(clean_param('a<b', PARAM_TEXT), 'a');
766 $this->assertEquals(clean_param('a>b', PARAM_TEXT), 'a>b');
767 $this->assertEquals(clean_param('<lang lang="en">a>a</lang>', PARAM_TEXT), '<lang lang="en">a>a</lang>'); // standard strip_tags() behaviour
768 $this->assertEquals(clean_param('<lang lang="en">a<a</lang>', PARAM_TEXT), 'a');
769 $this->assertEquals(clean_param('<lang lang="en">a<br>a</lang>', PARAM_TEXT), '<lang lang="en">aa</lang>');
770 }
771
772 function test_clean_param_url() {
773 // Test PARAM_URL and PARAM_LOCALURL a bit
774 $this->assertEquals(clean_param('http://google.com/', PARAM_URL), 'http://google.com/');
775 $this->assertEquals(clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_URL), 'http://some.very.long.and.silly.domain/with/a/path/');
776 $this->assertEquals(clean_param('http://localhost/', PARAM_URL), 'http://localhost/');
777 $this->assertEquals(clean_param('http://0.255.1.1/numericip.php', PARAM_URL), 'http://0.255.1.1/numericip.php');
778 $this->assertEquals(clean_param('/just/a/path', PARAM_URL), '/just/a/path');
779 $this->assertEquals(clean_param('funny:thing', PARAM_URL), '');
780 }
781
782 function test_clean_param_localurl() {
783 global $CFG;
784 $this->assertEquals(clean_param('http://google.com/', PARAM_LOCALURL), '');
785 $this->assertEquals(clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_LOCALURL), '');
786 $this->assertEquals(clean_param($CFG->wwwroot, PARAM_LOCALURL), $CFG->wwwroot);
787 $this->assertEquals(clean_param('/just/a/path', PARAM_LOCALURL), '/just/a/path');
788 $this->assertEquals(clean_param('funny:thing', PARAM_LOCALURL), '');
789 $this->assertEquals(clean_param('course/view.php?id=3', PARAM_LOCALURL), 'course/view.php?id=3');
790 }
791
792 function test_clean_param_file() {
793 $this->assertEquals(clean_param('correctfile.txt', PARAM_FILE), 'correctfile.txt');
794 $this->assertEquals(clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_FILE), 'badfile.txt');
795 $this->assertEquals(clean_param('../parentdirfile.txt', PARAM_FILE), 'parentdirfile.txt');
796 //The following behaviours have been maintained although they seem a little odd
797 $this->assertEquals(clean_param('funny:thing', PARAM_FILE), 'funnything');
798 $this->assertEquals(clean_param('./currentdirfile.txt', PARAM_FILE), '.currentdirfile.txt');
799 $this->assertEquals(clean_param('c:\temp\windowsfile.txt', PARAM_FILE), 'ctempwindowsfile.txt');
800 $this->assertEquals(clean_param('/home/user/linuxfile.txt', PARAM_FILE), 'homeuserlinuxfile.txt');
801 $this->assertEquals(clean_param('~/myfile.txt', PARAM_FILE), '~myfile.txt');
802 }
803
804 function test_clean_param_username() {
805 global $CFG;
806 $currentstatus = $CFG->extendedusernamechars;
807
808 // Run tests with extended character == FALSE;
809 $CFG->extendedusernamechars = FALSE;
810 $this->assertEquals(clean_param('johndoe123', PARAM_USERNAME), 'johndoe123' );
811 $this->assertEquals(clean_param('john.doe', PARAM_USERNAME), 'john.doe');
812 $this->assertEquals(clean_param('john-doe', PARAM_USERNAME), 'john-doe');
813 $this->assertEquals(clean_param('john- doe', PARAM_USERNAME), 'john-doe');
814 $this->assertEquals(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
815 $this->assertEquals(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
816 $this->assertEquals(clean_param('john~doe', PARAM_USERNAME), 'johndoe');
817 $this->assertEquals(clean_param('john´doe', PARAM_USERNAME), 'johndoe');
818 $this->assertEquals(clean_param('john#$%&() ', PARAM_USERNAME), 'john');
819 $this->assertEquals(clean_param('JOHNdóé ', PARAM_USERNAME), 'johnd');
820 $this->assertEquals(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýá\9e?\9eý??\9adoe ', PARAM_USERNAME), 'john.-_a_x-d@_doe');
821
822
823 // Test success condition, if extendedusernamechars == ENABLE;
824 $CFG->extendedusernamechars = TRUE;
825 $this->assertEquals(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
826 $this->assertEquals(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
827 $this->assertEquals(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john#$%&()+_^');
828 $this->assertEquals(clean_param('john~doe', PARAM_USERNAME), 'john~doe');
829 $this->assertEquals(clean_param('joHN´doe', PARAM_USERNAME), 'john´doe');
830 $this->assertEquals(clean_param('johnDOE', PARAM_USERNAME), 'johndoe');
831 $this->assertEquals(clean_param('johndóé ', PARAM_USERNAME), 'johndóé');
832
833 $CFG->extendedusernamechars = $currentstatus;
834 }
835
836 function test_clean_param_stringid() {
837 // Test string identifiers validation
838 // valid strings:
839 $this->assertEquals(clean_param('validstring', PARAM_STRINGID), 'validstring');
840 $this->assertEquals(clean_param('mod/foobar:valid_capability', PARAM_STRINGID), 'mod/foobar:valid_capability');
841 $this->assertEquals(clean_param('CZ', PARAM_STRINGID), 'CZ');
842 $this->assertEquals(clean_param('application/vnd.ms-powerpoint', PARAM_STRINGID), 'application/vnd.ms-powerpoint');
843 $this->assertEquals(clean_param('grade2', PARAM_STRINGID), 'grade2');
844 // invalid strings:
845 $this->assertEquals(clean_param('trailing ', PARAM_STRINGID), '');
846 $this->assertEquals(clean_param('space bar', PARAM_STRINGID), '');
847 $this->assertEquals(clean_param('0numeric', PARAM_STRINGID), '');
848 $this->assertEquals(clean_param('*', PARAM_STRINGID), '');
849 $this->assertEquals(clean_param(' ', PARAM_STRINGID), '');
850 }
851
852 function test_clean_param_timezone() {
853 // Test timezone validation
854 $testvalues = array (
855 'America/Jamaica' => 'America/Jamaica',
856 'America/Argentina/Cordoba' => 'America/Argentina/Cordoba',
857 'America/Port-au-Prince' => 'America/Port-au-Prince',
858 'America/Argentina/Buenos_Aires' => 'America/Argentina/Buenos_Aires',
859 'PST8PDT' => 'PST8PDT',
860 'Wrong.Value' => '',
861 'Wrong/.Value' => '',
862 'Wrong(Value)' => '',
863 '0' => '0',
864 '0.0' => '0.0',
865 '0.5' => '0.5',
866 '-12.5' => '-12.5',
867 '+12.5' => '+12.5',
868 '13.5' => '',
869 '-13.5' => '',
870 '0.2' => '');
871
872 foreach ($testvalues as $testvalue => $expectedvalue) {
873 $actualvalue = clean_param($testvalue, PARAM_TIMEZONE);
874 $this->assertEquals($actualvalue, $expectedvalue);
875 }
876 }
877
878 function test_validate_param() {
879 try {
880 $param = validate_param('11a', PARAM_INT);
881 $this->fail('invalid_parameter_exception expected');
882 } catch (invalid_parameter_exception $ex) {
883 $this->assertTrue(true);
884 }
885 try {
886 $param = validate_param('11', PARAM_INT);
887 $this->assertEquals($param, 11);
888 } catch (invalid_parameter_exception $ex) {
889 $this->fail('invalid_parameter_exception not expected');
890 }
891 try {
892 $param = validate_param(null, PARAM_INT, false);
893 $this->fail('invalid_parameter_exception expected');
894 } catch (invalid_parameter_exception $ex) {
895 $this->assertTrue(true);
896 }
897 try {
898 $param = validate_param(null, PARAM_INT, true);
899 $this->assertTrue($param===null);
900 } catch (invalid_parameter_exception $ex) {
901 $this->fail('invalid_parameter_exception expected');
902 }
903 try {
904 $param = validate_param(array(), PARAM_INT);
905 $this->fail('invalid_parameter_exception expected');
906 } catch (invalid_parameter_exception $ex) {
907 $this->assertTrue(true);
908 }
909 try {
910 $param = validate_param(new stdClass, PARAM_INT);
911 $this->fail('invalid_parameter_exception expected');
912 } catch (invalid_parameter_exception $ex) {
913 $this->assertTrue(true);
914 }
9a97fa5a
PS
915 try {
916 $param = validate_param('1.0', PARAM_FLOAT);
917 $this->assertSame(1.0, $param);
918
919 // Make sure valid floats do not cause exception.
920 validate_param(1.0, PARAM_FLOAT);
921 validate_param(10, PARAM_FLOAT);
922 validate_param('0', PARAM_FLOAT);
923 validate_param('119813454.545464564564546564545646556564465465456465465465645645465645645645', PARAM_FLOAT);
924 validate_param('011.1', PARAM_FLOAT);
925 validate_param('11', PARAM_FLOAT);
926 validate_param('+.1', PARAM_FLOAT);
927 validate_param('-.1', PARAM_FLOAT);
928 validate_param('1e10', PARAM_FLOAT);
929 validate_param('.1e+10', PARAM_FLOAT);
930 validate_param('1E-1', PARAM_FLOAT);
931 $this->assertTrue(true);
932 } catch (invalid_parameter_exception $ex) {
933 $this->fail('Valid float notation not accepted');
934 }
935 try {
936 $param = validate_param('1,2', PARAM_FLOAT);
937 $this->fail('invalid_parameter_exception expected');
938 } catch (invalid_parameter_exception $ex) {
939 $this->assertTrue(true);
940 }
941 try {
942 $param = validate_param('', PARAM_FLOAT);
943 $this->fail('invalid_parameter_exception expected');
944 } catch (invalid_parameter_exception $ex) {
945 $this->assertTrue(true);
946 }
947 try {
948 $param = validate_param('.', PARAM_FLOAT);
949 $this->fail('invalid_parameter_exception expected');
950 } catch (invalid_parameter_exception $ex) {
951 $this->assertTrue(true);
952 }
953 try {
954 $param = validate_param('e10', PARAM_FLOAT);
955 $this->fail('invalid_parameter_exception expected');
956 } catch (invalid_parameter_exception $ex) {
957 $this->assertTrue(true);
958 }
959 try {
960 $param = validate_param('abc', PARAM_FLOAT);
961 $this->fail('invalid_parameter_exception expected');
962 } catch (invalid_parameter_exception $ex) {
963 $this->assertTrue(true);
964 }
a3d5830a
PS
965 }
966
967 function test_shorten_text() {
968 $text = "short text already no tags";
969 $this->assertEquals($text, shorten_text($text));
970
971 $text = "<p>short <b>text</b> already</p><p>with tags</p>";
972 $this->assertEquals($text, shorten_text($text));
973
974 $text = "long text without any tags blah de blah blah blah what";
975 $this->assertEquals('long text without any tags ...', shorten_text($text));
976
977 $text = "<div class='frog'><p><blockquote>Long text with tags that will ".
978 "be chopped off but <b>should be added back again</b></blockquote></p></div>";
979 $this->assertEquals("<div class='frog'><p><blockquote>Long text with " .
980 "tags that ...</blockquote></p></div>", shorten_text($text));
981
982 $text = "some text which shouldn't &nbsp; break there";
983 $this->assertEquals("some text which shouldn't &nbsp; ...",
984 shorten_text($text, 31));
985 $this->assertEquals("some text which shouldn't ...",
986 shorten_text($text, 30));
987
988 // This case caused a bug up to 1.9.5
989 $text = "<h3>standard 'break-out' sub groups in TGs?</h3>&nbsp;&lt;&lt;There are several";
990 $this->assertEquals("<h3>standard 'break-out' sub groups in ...</h3>",
991 shorten_text($text, 43));
992
993 $text = "<h1>123456789</h1>";//a string with no convenient breaks
994 $this->assertEquals("<h1>12345...</h1>",
995 shorten_text($text, 8));
996
997 // ==== this must work with UTF-8 too! ======
998
999 // text without tags
1000 $text = "Žluťoučký koníček přeskočil";
1001 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
1002 $this->assertEquals("Žluťoučký koníče...", shorten_text($text, 19, true));
1003 $this->assertEquals("Žluťoučký ...", shorten_text($text, 19, false));
1004 // And try it with 2-less (that are, in bytes, the middle of a sequence)
1005 $this->assertEquals("Žluťoučký koní...", shorten_text($text, 17, true));
1006 $this->assertEquals("Žluťoučký ...", shorten_text($text, 17, false));
1007
1008 $text = "<p>Žluťoučký koníček <b>přeskočil</b> potůček</p>";
1009 $this->assertEquals($text, shorten_text($text, 60));
1010 $this->assertEquals("<p>Žluťoučký koníček ...</p>", shorten_text($text, 21));
1011 $this->assertEquals("<p>Žluťoučký koníče...</p>", shorten_text($text, 19, true));
1012 $this->assertEquals("<p>Žluťoučký ...</p>", shorten_text($text, 19, false));
1013 // And try it with 2-less (that are, in bytes, the middle of a sequence)
1014 $this->assertEquals("<p>Žluťoučký koní...</p>", shorten_text($text, 17, true));
1015 $this->assertEquals("<p>Žluťoučký ...</p>", shorten_text($text, 17, false));
1016 // And try over one tag (start/end), it does proper text len
1017 $this->assertEquals("<p>Žluťoučký koníček <b>př...</b></p>", shorten_text($text, 23, true));
1018 $this->assertEquals("<p>Žluťoučký koníček <b>přeskočil</b> pot...</p>", shorten_text($text, 34, true));
1019 // And in the middle of one tag
1020 $this->assertEquals("<p>Žluťoučký koníček <b>přeskočil...</b></p>", shorten_text($text, 30, true));
1021
1022 // Japanese
1023 $text = '言語設定言語設定abcdefghijkl';
1024 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
1025 $this->assertEquals("言語設定言語...", shorten_text($text, 9, true));
1026 $this->assertEquals("言語設定言語...", shorten_text($text, 9, false));
1027 $this->assertEquals("言語設定言語設定ab...", shorten_text($text, 13, true));
1028 $this->assertEquals("言語設定言語設定...", shorten_text($text, 13, false));
1029
1030 // Chinese
1031 $text = '简体中文简体中文abcdefghijkl';
1032 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
1033 $this->assertEquals("简体中文简体...", shorten_text($text, 9, true));
1034 $this->assertEquals("简体中文简体...", shorten_text($text, 9, false));
1035 $this->assertEquals("简体中文简体中文ab...", shorten_text($text, 13, true));
1036 $this->assertEquals("简体中文简体中文...", shorten_text($text, 13, false));
1037
1038 }
1039
1040 function test_usergetdate() {
1041 global $USER, $CFG, $DB;
1042
1043 //Check if forcetimezone is set then save it and set it to use user timezone
1044 $cfgforcetimezone = null;
1045 if (isset($CFG->forcetimezone)) {
1046 $cfgforcetimezone = $CFG->forcetimezone;
1047 $CFG->forcetimezone = 99; //get user default timezone.
1048 }
1049
1050 $olduser = $USER;
1051 $USER = $DB->get_record('user', array('id'=>2)); //admin
1052
1053 $userstimezone = $USER->timezone;
1054 $USER->timezone = 2;//set the timezone to a known state
1055
1056 // The string version of date comes from server locale setting and does
1057 // not respect user language, so it is necessary to reset that.
1058 $oldlocale = setlocale(LC_TIME, '0');
1059 setlocale(LC_TIME, 'en_AU.UTF-8');
1060
1061 $ts = 1261540267; //the time this function was created
1062
1063 $arr = usergetdate($ts,1);//specify the timezone as an argument
1064 $arr = array_values($arr);
1065
1066 list($seconds,$minutes,$hours,$mday,$wday,$mon,$year,$yday,$weekday,$month) = $arr;
03764014
EL
1067 $this->assertSame($seconds, 7);
1068 $this->assertSame($minutes, 51);
1069 $this->assertSame($hours, 4);
1070 $this->assertSame($mday, 23);
1071 $this->assertSame($wday, 3);
1072 $this->assertSame($mon, 12);
1073 $this->assertSame($year, 2009);
1074 $this->assertSame($yday, 356);
1075 $this->assertSame($weekday, 'Wednesday');
1076 $this->assertSame($month, 'December');
a3d5830a
PS
1077 $arr = usergetdate($ts);//gets the timezone from the $USER object
1078 $arr = array_values($arr);
1079
1080 list($seconds,$minutes,$hours,$mday,$wday,$mon,$year,$yday,$weekday,$month) = $arr;
03764014
EL
1081 $this->assertSame($seconds, 7);
1082 $this->assertSame($minutes, 51);
1083 $this->assertSame($hours, 5);
1084 $this->assertSame($mday, 23);
1085 $this->assertSame($wday, 3);
1086 $this->assertSame($mon, 12);
1087 $this->assertSame($year, 2009);
1088 $this->assertSame($yday, 356);
1089 $this->assertSame($weekday, 'Wednesday');
1090 $this->assertSame($month, 'December');
a3d5830a
PS
1091 //set the timezone back to what it was
1092 $USER->timezone = $userstimezone;
1093
1094 //restore forcetimezone if changed.
1095 if (!is_null($cfgforcetimezone)) {
1096 $CFG->forcetimezone = $cfgforcetimezone;
1097 }
1098
1099 setlocale(LC_TIME, $oldlocale);
1100
1101 $USER = $olduser;
1102 }
1103
1104 public function test_normalize_component() {
1105
1106 // moodle core
1107 $this->assertEquals(normalize_component('moodle'), array('core', null));
1108 $this->assertEquals(normalize_component('core'), array('core', null));
1109
1110 // moodle core subsystems
1111 $this->assertEquals(normalize_component('admin'), array('core', 'admin'));
1112 $this->assertEquals(normalize_component('core_admin'), array('core', 'admin'));
1113
1114 // activity modules and their subplugins
1115 $this->assertEquals(normalize_component('workshop'), array('mod', 'workshop'));
1116 $this->assertEquals(normalize_component('mod_workshop'), array('mod', 'workshop'));
1117 $this->assertEquals(normalize_component('workshopform_accumulative'), array('workshopform', 'accumulative'));
1118 $this->assertEquals(normalize_component('quiz'), array('mod', 'quiz'));
1119 $this->assertEquals(normalize_component('quiz_grading'), array('quiz', 'grading'));
1120 $this->assertEquals(normalize_component('data'), array('mod', 'data'));
1121 $this->assertEquals(normalize_component('datafield_checkbox'), array('datafield', 'checkbox'));
1122
1123 // other plugin types
1124 $this->assertEquals(normalize_component('auth_mnet'), array('auth', 'mnet'));
1125 $this->assertEquals(normalize_component('enrol_self'), array('enrol', 'self'));
1126 $this->assertEquals(normalize_component('block_html'), array('block', 'html'));
1127 $this->assertEquals(normalize_component('block_mnet_hosts'), array('block', 'mnet_hosts'));
1128 $this->assertEquals(normalize_component('local_amos'), array('local', 'amos'));
1129
1130 // unknown components are supposed to be activity modules
1131 $this->assertEquals(normalize_component('whothefuckwouldcomewithsuchastupidnameofcomponent'),
1132 array('mod', 'whothefuckwouldcomewithsuchastupidnameofcomponent'));
1133 $this->assertEquals(normalize_component('whothefuck_wouldcomewithsuchastupidnameofcomponent'),
1134 array('mod', 'whothefuck_wouldcomewithsuchastupidnameofcomponent'));
1135 $this->assertEquals(normalize_component('whothefuck_would_come_withsuchastupidnameofcomponent'),
1136 array('mod', 'whothefuck_would_come_withsuchastupidnameofcomponent'));
1137 }
1138
1139 protected function get_fake_preference_test_userid() {
1140 global $DB;
1141
1142 // we need some nonexistent user id
1143 $id = 2147483647 - 666;
1144 if ($DB->get_records('user', array('id'=>$id))) {
1145 //weird!
1146 return false;
1147 }
1148 return $id;
1149 }
1150
1151 public function test_mark_user_preferences_changed() {
1152 $this->resetAfterTest(true);
1153 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1154 $this->fail('Can not find unused user id for the preferences test');
1155 return;
1156 }
1157
1158 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1159 mark_user_preferences_changed($otheruserid);
1160
1161 $this->assertEquals(get_cache_flag('userpreferenceschanged', $otheruserid, time()-10), 1);
1162 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1163 }
1164
1165 public function test_check_user_preferences_loaded() {
1166 global $DB;
1167 $this->resetAfterTest(true);
1168
1169 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1170 $this->fail('Can not find unused user id for the preferences test');
1171 return;
1172 }
1173
1174 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1175 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1176
1177 $user = new stdClass();
1178 $user->id = $otheruserid;
1179
1180 // load
1181 check_user_preferences_loaded($user);
1182 $this->assertTrue(isset($user->preference));
1183 $this->assertTrue(is_array($user->preference));
1184 $this->assertTrue(isset($user->preference['_lastloaded']));
1185 $this->assertEquals(count($user->preference), 1);
1186
1187 // add preference via direct call
1188 $DB->insert_record('user_preferences', array('name'=>'xxx', 'value'=>'yyy', 'userid'=>$user->id));
1189
1190 // no cache reload yet
1191 check_user_preferences_loaded($user);
1192 $this->assertEquals(count($user->preference), 1);
1193
1194 // forced reloading of cache
1195 unset($user->preference);
1196 check_user_preferences_loaded($user);
1197 $this->assertEquals(count($user->preference), 2);
1198 $this->assertEquals($user->preference['xxx'], 'yyy');
1199
1200 // add preference via direct call
1201 $DB->insert_record('user_preferences', array('name'=>'aaa', 'value'=>'bbb', 'userid'=>$user->id));
1202
1203 // test timeouts and modifications from different session
1204 set_cache_flag('userpreferenceschanged', $user->id, 1, time() + 1000);
1205 $user->preference['_lastloaded'] = $user->preference['_lastloaded'] - 20;
1206 check_user_preferences_loaded($user);
1207 $this->assertEquals(count($user->preference), 2);
1208 check_user_preferences_loaded($user, 10);
1209 $this->assertEquals(count($user->preference), 3);
1210 $this->assertEquals($user->preference['aaa'], 'bbb');
1211 set_cache_flag('userpreferenceschanged', $user->id, null);
1212 }
1213
1214 public function test_set_user_preference() {
1215 global $DB, $USER;
1216 $this->resetAfterTest(true);
1217
1218 $olduser = $USER;
1219 $USER = $DB->get_record('user', array('id'=>2)); //admin
1220
1221 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1222 $this->fail('Can not find unused user id for the preferences test');
1223 return;
1224 }
1225
1226 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1227 set_cache_flag('userpreferenceschanged', $otheruserid, null);
1228
1229 $user = new stdClass();
1230 $user->id = $otheruserid;
1231
1232 set_user_preference('aaa', 'bbb', $otheruserid);
1233 $this->assertEquals('bbb', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'aaa')));
1234 $this->assertEquals('bbb', get_user_preferences('aaa', null, $otheruserid));
1235
1236 set_user_preference('xxx', 'yyy', $user);
1237 $this->assertEquals('yyy', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
1238 $this->assertEquals('yyy', get_user_preferences('xxx', null, $otheruserid));
1239 $this->assertTrue(is_array($user->preference));
1240 $this->assertEquals($user->preference['aaa'], 'bbb');
1241 $this->assertEquals($user->preference['xxx'], 'yyy');
1242
1243 set_user_preference('xxx', NULL, $user);
1244 $this->assertSame(false, $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
1245 $this->assertSame(null, get_user_preferences('xxx', null, $otheruserid));
1246
1247 set_user_preference('ooo', true, $user);
1248 $prefs = get_user_preferences(null, null, $otheruserid);
1249 $this->assertSame($prefs['aaa'], $user->preference['aaa']);
1250 $this->assertSame($prefs['ooo'], $user->preference['ooo']);
1251 $this->assertSame($prefs['ooo'], '1');
1252
1253 set_user_preference('null', 0, $user);
1254 $this->assertSame('0', get_user_preferences('null', null, $otheruserid));
1255
1256 $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid));
1257
1258 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1259 set_cache_flag('userpreferenceschanged', $otheruserid, null);
1260
1261 // test $USER default
1262 set_user_preference('_test_user_preferences_pref', 'ok');
1263 $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']);
1264 unset_user_preference('_test_user_preferences_pref');
1265 $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref']));
1266
1267 // Test 1333 char values (no need for unicode, there are already tests for that in DB tests)
1268 $longvalue = str_repeat('a', 1333);
1269 set_user_preference('_test_long_user_preference', $longvalue);
1270 $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference'));
1271 $this->assertEquals($longvalue,
1272 $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference')));
1273
1274 // Test > 1333 char values, coding_exception expected
1275 $longvalue = str_repeat('a', 1334);
1276 try {
1277 set_user_preference('_test_long_user_preference', $longvalue);
1278 $this->assertFail('Exception expected - longer than 1333 chars not allowed as preference value');
1279 } catch (Exception $e) {
1280 $this->assertTrue($e instanceof coding_exception);
1281 }
1282
1283 //test invalid params
1284 try {
1285 set_user_preference('_test_user_preferences_pref', array());
1286 $this->assertFail('Exception expected - array not valid preference value');
1287 } catch (Exception $ex) {
1288 $this->assertTrue(true);
1289 }
1290 try {
1291 set_user_preference('_test_user_preferences_pref', new stdClass);
1292 $this->assertFail('Exception expected - class not valid preference value');
1293 } catch (Exception $ex) {
1294 $this->assertTrue(true);
1295 }
1296 try {
1297 set_user_preference('_test_user_preferences_pref', 1, array('xx'=>1));
1298 $this->assertFail('Exception expected - user instance expected');
1299 } catch (Exception $ex) {
1300 $this->assertTrue(true);
1301 }
1302 try {
1303 set_user_preference('_test_user_preferences_pref', 1, 'abc');
1304 $this->assertFail('Exception expected - user instance expected');
1305 } catch (Exception $ex) {
1306 $this->assertTrue(true);
1307 }
1308 try {
1309 set_user_preference('', 1);
1310 $this->assertFail('Exception expected - invalid name accepted');
1311 } catch (Exception $ex) {
1312 $this->assertTrue(true);
1313 }
1314 try {
1315 set_user_preference('1', 1);
1316 $this->assertFail('Exception expected - invalid name accepted');
1317 } catch (Exception $ex) {
1318 $this->assertTrue(true);
1319 }
1320
1321 $USER = $olduser;
1322 }
1323
1324 public function test_get_extra_user_fields() {
1325 global $CFG, $USER, $DB;
1326 $oldshowuseridentity = $CFG->showuseridentity;
1327
1328 $olduser = $USER;
1329 $USER = $DB->get_record('user', array('id'=>2)); //admin
1330
1331 // It would be really nice if there were a way to 'mock' has_capability
1332 // checks (either to return true or false) but as there is not, this
1333 // test doesn't test the capability check. Presumably, anyone running
1334 // unit tests will have the capability.
1335 $context = context_system::instance();
1336
1337 // No fields
1338 $CFG->showuseridentity = '';
1339 $this->assertEquals(array(), get_extra_user_fields($context));
1340
1341 // One field
1342 $CFG->showuseridentity = 'frog';
1343 $this->assertEquals(array('frog'), get_extra_user_fields($context));
1344
1345 // Two fields
1346 $CFG->showuseridentity = 'frog,zombie';
1347 $this->assertEquals(array('frog', 'zombie'), get_extra_user_fields($context));
1348
1349 // No fields, except
1350 $CFG->showuseridentity = '';
1351 $this->assertEquals(array(), get_extra_user_fields($context, array('frog')));
1352
1353 // One field
1354 $CFG->showuseridentity = 'frog';
1355 $this->assertEquals(array(), get_extra_user_fields($context, array('frog')));
1356
1357 // Two fields
1358 $CFG->showuseridentity = 'frog,zombie';
1359 $this->assertEquals(array('zombie'), get_extra_user_fields($context, array('frog')));
1360
1361 // As long as this test passes, the value will be set back. This is only
1362 // in-memory anyhow
1363 $CFG->showuseridentity = $oldshowuseridentity;
1364
1365 $USER = $olduser;
1366 }
1367
1368 public function test_get_extra_user_fields_sql() {
1369 global $CFG, $USER, $DB;
1370
1371 $olduser = $USER;
1372 $USER = $DB->get_record('user', array('id'=>2)); //admin
1373
1374 $oldshowuseridentity = $CFG->showuseridentity;
1375 $context = context_system::instance();
1376
1377 // No fields
1378 $CFG->showuseridentity = '';
1379 $this->assertEquals('', get_extra_user_fields_sql($context));
1380
1381 // One field
1382 $CFG->showuseridentity = 'frog';
1383 $this->assertEquals(', frog', get_extra_user_fields_sql($context));
1384
1385 // Two fields with table prefix
1386 $CFG->showuseridentity = 'frog,zombie';
1387 $this->assertEquals(', u1.frog, u1.zombie', get_extra_user_fields_sql($context, 'u1'));
1388
1389 // Two fields with field prefix
1390 $CFG->showuseridentity = 'frog,zombie';
1391 $this->assertEquals(', frog AS u_frog, zombie AS u_zombie',
1392 get_extra_user_fields_sql($context, '', 'u_'));
1393
1394 // One field excluded
1395 $CFG->showuseridentity = 'frog';
1396 $this->assertEquals('', get_extra_user_fields_sql($context, '', '', array('frog')));
1397
1398 // Two fields, one excluded, table+field prefix
1399 $CFG->showuseridentity = 'frog,zombie';
1400 $this->assertEquals(', u1.zombie AS u_zombie',
1401 get_extra_user_fields_sql($context, 'u1', 'u_', array('frog')));
1402
1403 // As long as this test passes, the value will be set back. This is only
1404 // in-memory anyhow
1405 $CFG->showuseridentity = $oldshowuseridentity;
1406 $USER = $olduser;
1407 }
1408
1409 public function test_userdate() {
1410 global $USER, $CFG, $DB;
1411
1412 $olduser = $USER;
1413 $USER = $DB->get_record('user', array('id'=>2)); //admin
1414
1415 $testvalues = array(
1416 array(
1417 'time' => '1309514400',
1418 'usertimezone' => 'America/Moncton',
1419 'timezone' => '0.0', //no dst offset
1420 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM'
1421 ),
1422 array(
1423 'time' => '1309514400',
1424 'usertimezone' => 'America/Moncton',
1425 'timezone' => '99', //dst offset and timezone offset.
1426 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM'
1427 ),
1428 array(
1429 'time' => '1309514400',
1430 'usertimezone' => 'America/Moncton',
1431 'timezone' => 'America/Moncton', //dst offset and timezone offset.
1432 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM'
1433 ),
1434 array(
1435 'time' => '1293876000 ',
1436 'usertimezone' => 'America/Moncton',
1437 'timezone' => '0.0', //no dst offset
1438 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM'
1439 ),
1440 array(
1441 'time' => '1293876000 ',
1442 'usertimezone' => 'America/Moncton',
1443 'timezone' => '99', //no dst offset in jan, so just timezone offset.
1444 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM'
1445 ),
1446 array(
1447 'time' => '1293876000 ',
1448 'usertimezone' => 'America/Moncton',
1449 'timezone' => 'America/Moncton', //no dst offset in jan
1450 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM'
1451 ),
1452 array(
1453 'time' => '1293876000 ',
1454 'usertimezone' => '2',
1455 'timezone' => '99', //take user timezone
1456 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
1457 ),
1458 array(
1459 'time' => '1293876000 ',
1460 'usertimezone' => '-2',
1461 'timezone' => '99', //take user timezone
1462 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM'
1463 ),
1464 array(
1465 'time' => '1293876000 ',
1466 'usertimezone' => '-10',
1467 'timezone' => '2', //take this timezone
1468 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
1469 ),
1470 array(
1471 'time' => '1293876000 ',
1472 'usertimezone' => '-10',
1473 'timezone' => '-2', //take this timezone
1474 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM'
1475 ),
1476 array(
1477 'time' => '1293876000 ',
1478 'usertimezone' => '-10',
1479 'timezone' => 'random/time', //this should show server time
1480 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM'
1481 ),
1482 array(
1483 'time' => '1293876000 ',
1484 'usertimezone' => '14', //server time zone
1485 'timezone' => '99', //this should show user time
1486 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM'
1487 ),
1488 );
1489
1490 //Check if forcetimezone is set then save it and set it to use user timezone
1491 $cfgforcetimezone = null;
1492 if (isset($CFG->forcetimezone)) {
1493 $cfgforcetimezone = $CFG->forcetimezone;
1494 $CFG->forcetimezone = 99; //get user default timezone.
1495 }
1496 //store user default timezone to restore later
1497 $userstimezone = $USER->timezone;
1498
1499 // The string version of date comes from server locale setting and does
1500 // not respect user language, so it is necessary to reset that.
1501 $oldlocale = setlocale(LC_TIME, '0');
1502 setlocale(LC_TIME, 'en_AU.UTF-8');
1503
1504 //set default timezone to Australia/Perth, else time calculated
1505 //will not match expected values. Before that save system defaults.
1506 $systemdefaulttimezone = date_default_timezone_get();
1507 date_default_timezone_set('Australia/Perth');
1508
1509 foreach ($testvalues as $vals) {
1510 $USER->timezone = $vals['usertimezone'];
1511 $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']);
1512
1513 //On different systems case of AM PM changes so compare case insensitive
1514 $vals['expectedoutput'] = textlib::strtolower($vals['expectedoutput']);
1515 $actualoutput = textlib::strtolower($actualoutput);
1516
1517 $this->assertEquals($vals['expectedoutput'], $actualoutput,
1518 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
1519 Please check if timezones are updated (Site adminstration -> location -> update timezone)");
1520 }
1521
1522 //restore user timezone back to what it was
1523 $USER->timezone = $userstimezone;
1524
1525 //restore forcetimezone
1526 if (!is_null($cfgforcetimezone)) {
1527 $CFG->forcetimezone = $cfgforcetimezone;
1528 }
1529
1530 //restore system default values.
1531 date_default_timezone_set($systemdefaulttimezone);
1532 setlocale(LC_TIME, $oldlocale);
1533
1534 $USER = $olduser;
1535 }
1536
1537 public function test_make_timestamp() {
1538 global $USER, $CFG, $DB;
1539
1540 $olduser = $USER;
1541 $USER = $DB->get_record('user', array('id'=>2)); //admin
1542
1543 $testvalues = array(
1544 array(
1545 'usertimezone' => 'America/Moncton',
1546 'year' => '2011',
1547 'month' => '7',
1548 'day' => '1',
1549 'hour' => '10',
1550 'minutes' => '00',
1551 'seconds' => '00',
7b05e146
FM
1552 'timezone' => '0.0',
1553 'applydst' => false, //no dst offset
1554 'expectedoutput' => '1309514400' // 6pm at UTC+0
a3d5830a
PS
1555 ),
1556 array(
1557 'usertimezone' => 'America/Moncton',
1558 'year' => '2011',
1559 'month' => '7',
1560 'day' => '1',
1561 'hour' => '10',
1562 'minutes' => '00',
1563 'seconds' => '00',
1564 'timezone' => '99', //user default timezone
1565 'applydst' => false, //don't apply dst
1566 'expectedoutput' => '1309528800'
1567 ),
1568 array(
1569 'usertimezone' => 'America/Moncton',
1570 'year' => '2011',
1571 'month' => '7',
1572 'day' => '1',
1573 'hour' => '10',
1574 'minutes' => '00',
1575 'seconds' => '00',
1576 'timezone' => '99', //user default timezone
1577 'applydst' => true, //apply dst
1578 'expectedoutput' => '1309525200'
1579 ),
1580 array(
1581 'usertimezone' => 'America/Moncton',
1582 'year' => '2011',
1583 'month' => '7',
1584 'day' => '1',
1585 'hour' => '10',
1586 'minutes' => '00',
1587 'seconds' => '00',
1588 'timezone' => 'America/Moncton', //string timezone
1589 'applydst' => true, //apply dst
1590 'expectedoutput' => '1309525200'
1591 ),
1592 array(
1593 'usertimezone' => '2',//no dst applyed
1594 'year' => '2011',
1595 'month' => '7',
1596 'day' => '1',
1597 'hour' => '10',
1598 'minutes' => '00',
1599 'seconds' => '00',
1600 'timezone' => '99', //take user timezone
1601 'applydst' => true, //apply dst
1602 'expectedoutput' => '1309507200'
1603 ),
1604 array(
1605 'usertimezone' => '-2',//no dst applyed
1606 'year' => '2011',
1607 'month' => '7',
1608 'day' => '1',
1609 'hour' => '10',
1610 'minutes' => '00',
1611 'seconds' => '00',
1612 'timezone' => '99', //take usertimezone
1613 'applydst' => true, //apply dst
1614 'expectedoutput' => '1309521600'
1615 ),
1616 array(
1617 'usertimezone' => '-10',//no dst applyed
1618 'year' => '2011',
1619 'month' => '7',
1620 'day' => '1',
1621 'hour' => '10',
1622 'minutes' => '00',
1623 'seconds' => '00',
1624 'timezone' => '2', //take this timezone
1625 'applydst' => true, //apply dst
1626 'expectedoutput' => '1309507200'
1627 ),
1628 array(
1629 'usertimezone' => '-10',//no dst applyed
1630 'year' => '2011',
1631 'month' => '7',
1632 'day' => '1',
1633 'hour' => '10',
1634 'minutes' => '00',
1635 'seconds' => '00',
1636 'timezone' => '-2', //take this timezone
1637 'applydst' => true, //apply dst,
1638 'expectedoutput' => '1309521600'
1639 ),
1640 array(
1641 'usertimezone' => '-10',//no dst applyed
1642 'year' => '2011',
1643 'month' => '7',
1644 'day' => '1',
1645 'hour' => '10',
1646 'minutes' => '00',
1647 'seconds' => '00',
1648 'timezone' => 'random/time', //This should show server time
1649 'applydst' => true, //apply dst,
1650 'expectedoutput' => '1309485600'
1651 ),
1652 array(
1653 'usertimezone' => '14',//server time
1654 'year' => '2011',
1655 'month' => '7',
1656 'day' => '1',
1657 'hour' => '10',
1658 'minutes' => '00',
1659 'seconds' => '00',
1660 'timezone' => '99', //get user time
1661 'applydst' => true, //apply dst,
1662 'expectedoutput' => '1309485600'
1663 )
1664 );
1665
1666 //Check if forcetimezone is set then save it and set it to use user timezone
1667 $cfgforcetimezone = null;
1668 if (isset($CFG->forcetimezone)) {
1669 $cfgforcetimezone = $CFG->forcetimezone;
1670 $CFG->forcetimezone = 99; //get user default timezone.
1671 }
1672
1673 //store user default timezone to restore later
1674 $userstimezone = $USER->timezone;
1675
1676 // The string version of date comes from server locale setting and does
1677 // not respect user language, so it is necessary to reset that.
1678 $oldlocale = setlocale(LC_TIME, '0');
1679 setlocale(LC_TIME, 'en_AU.UTF-8');
1680
1681 //set default timezone to Australia/Perth, else time calulated
1682 //will not match expected values. Before that save system defaults.
1683 $systemdefaulttimezone = date_default_timezone_get();
1684 date_default_timezone_set('Australia/Perth');
1685
1686 //Test make_timestamp with all testvals and assert if anything wrong.
1687 foreach ($testvalues as $vals) {
1688 $USER->timezone = $vals['usertimezone'];
1689 $actualoutput = make_timestamp(
1690 $vals['year'],
1691 $vals['month'],
1692 $vals['day'],
1693 $vals['hour'],
1694 $vals['minutes'],
1695 $vals['seconds'],
1696 $vals['timezone'],
1697 $vals['applydst']
1698 );
1699
1700 //On different systems case of AM PM changes so compare case insenitive
1701 $vals['expectedoutput'] = textlib::strtolower($vals['expectedoutput']);
1702 $actualoutput = textlib::strtolower($actualoutput);
1703
1704 $this->assertEquals($vals['expectedoutput'], $actualoutput,
1705 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
1706 Please check if timezones are updated (Site adminstration -> location -> update timezone)");
1707 }
1708
1709 //restore user timezone back to what it was
1710 $USER->timezone = $userstimezone;
1711
1712 //restore forcetimezone
1713 if (!is_null($cfgforcetimezone)) {
1714 $CFG->forcetimezone = $cfgforcetimezone;
1715 }
1716
1717 //restore system default values.
1718 date_default_timezone_set($systemdefaulttimezone);
1719 setlocale(LC_TIME, $oldlocale);
1720
1721 $USER = $olduser;
1722 }
1723
1724 /**
1725 * Test get_string and most importantly the implementation of the lang_string
1726 * object.
1727 */
1728 public function test_get_string() {
1729 global $COURSE;
1730
1731 // Make sure we are using English
1732 $originallang = $COURSE->lang;
1733 $COURSE->lang = 'en';
1734
1735 $yes = get_string('yes');
1736 $yesexpected = 'Yes';
1737 $this->assertEquals(getType($yes), 'string');
1738 $this->assertEquals($yes, $yesexpected);
1739
1740 $yes = get_string('yes', 'moodle');
1741 $this->assertEquals(getType($yes), 'string');
1742 $this->assertEquals($yes, $yesexpected);
1743
1744 $yes = get_string('yes', 'core');
1745 $this->assertEquals(getType($yes), 'string');
1746 $this->assertEquals($yes, $yesexpected);
1747
1748 $yes = get_string('yes', '');
1749 $this->assertEquals(getType($yes), 'string');
1750 $this->assertEquals($yes, $yesexpected);
1751
1752 $yes = get_string('yes', null);
1753 $this->assertEquals(getType($yes), 'string');
1754 $this->assertEquals($yes, $yesexpected);
1755
1756 $yes = get_string('yes', null, 1);
1757 $this->assertEquals(getType($yes), 'string');
1758 $this->assertEquals($yes, $yesexpected);
1759
1760 $days = 1;
1761 $numdays = get_string('numdays', 'core', '1');
1762 $numdaysexpected = $days.' days';
1763 $this->assertEquals(getType($numdays), 'string');
1764 $this->assertEquals($numdays, $numdaysexpected);
1765
1766 $yes = get_string('yes', null, null, true);
1767 $this->assertEquals(get_class($yes), 'lang_string');
1768 $this->assertEquals((string)$yes, $yesexpected);
1769
1770 // Test using a lang_string object as the $a argument for a normal
1771 // get_string call (returning string)
1772 $test = new lang_string('yes', null, null, true);
1773 $testexpected = get_string('numdays', 'core', get_string('yes'));
1774 $testresult = get_string('numdays', null, $test);
1775 $this->assertEquals(getType($testresult), 'string');
1776 $this->assertEquals($testresult, $testexpected);
1777
1778 // Test using a lang_string object as the $a argument for an object
1779 // get_string call (returning lang_string)
1780 $test = new lang_string('yes', null, null, true);
1781 $testexpected = get_string('numdays', 'core', get_string('yes'));
1782 $testresult = get_string('numdays', null, $test, true);
1783 $this->assertEquals(get_class($testresult), 'lang_string');
1784 $this->assertEquals("$testresult", $testexpected);
1785
1786 // Make sure that object properties that can't be converted don't cause
1787 // errors
1788 // Level one: This is as deep as current language processing goes
1789 $test = new stdClass;
1790 $test->one = 'here';
1791 $string = get_string('yes', null, $test, true);
1792 $this->assertEquals($string, $yesexpected);
1793
1794 // Make sure that object properties that can't be converted don't cause
1795 // errors.
1796 // Level two: Language processing doesn't currently reach this deep.
1797 // only immediate scalar properties are worked with.
1798 $test = new stdClass;
1799 $test->one = new stdClass;
1800 $test->one->two = 'here';
1801 $string = get_string('yes', null, $test, true);
1802 $this->assertEquals($string, $yesexpected);
1803
1804 // Make sure that object properties that can't be converted don't cause
1805 // errors.
1806 // Level three: It should never ever go this deep, but we're making sure
1807 // it doesn't cause any probs anyway.
1808 $test = new stdClass;
1809 $test->one = new stdClass;
1810 $test->one->two = new stdClass;
1811 $test->one->two->three = 'here';
1812 $string = get_string('yes', null, $test, true);
1813 $this->assertEquals($string, $yesexpected);
1814
1815 // Make sure that object properties that can't be converted don't cause
1816 // errors and check lang_string properties.
1817 // Level one: This is as deep as current language processing goes
1818 $test = new stdClass;
1819 $test->one = new lang_string('yes');
1820 $string = get_string('yes', null, $test, true);
1821 $this->assertEquals($string, $yesexpected);
1822
1823 // Make sure that object properties that can't be converted don't cause
1824 // errors and check lang_string properties.
1825 // Level two: Language processing doesn't currently reach this deep.
1826 // only immediate scalar properties are worked with.
1827 $test = new stdClass;
1828 $test->one = new stdClass;
1829 $test->one->two = new lang_string('yes');
1830 $string = get_string('yes', null, $test, true);
1831 $this->assertEquals($string, $yesexpected);
1832
1833 // Make sure that object properties that can't be converted don't cause
1834 // errors and check lang_string properties.
1835 // Level three: It should never ever go this deep, but we're making sure
1836 // it doesn't cause any probs anyway.
1837 $test = new stdClass;
1838 $test->one = new stdClass;
1839 $test->one->two = new stdClass;
1840 $test->one->two->three = new lang_string('yes');
1841 $string = get_string('yes', null, $test, true);
1842 $this->assertEquals($string, $yesexpected);
1843
1844 // Make sure that array properties that can't be converted don't cause
1845 // errors
1846 $test = array();
1847 $test['one'] = new stdClass;
1848 $test['one']->two = 'here';
1849 $string = get_string('yes', null, $test, true);
1850 $this->assertEquals($string, $yesexpected);
1851
1852 // Same thing but as above except using an object... this is allowed :P
1853 $string = get_string('yes', null, null, true);
1854 $object = new stdClass;
1855 $object->$string = 'Yes';
1856 $this->assertEquals($string, $yesexpected);
1857 $this->assertEquals($object->$string, $yesexpected);
1858
1859 // Reset the language
1860 $COURSE->lang = $originallang;
1861 }
1862
1863 /**
1864 * @expectedException PHPUnit_Framework_Error_Warning
1865 * @return void
1866 */
1867 public function test_get_string_limitation() {
1868 // This is one of the limitations to the lang_string class. It can't be
1869 // used as a key
1870 $array = array(get_string('yes', null, null, true) => 'yes');
1871 }
637da99e 1872
1873 /**
1874 * Test localised float formatting.
1875 */
1876 public function test_format_float() {
1877 global $SESSION, $CFG;
1878
1879 // Special case for null
1880 $this->assertEquals('', format_float(null));
1881
1882 // Default 1 decimal place
1883 $this->assertEquals('5.4', format_float(5.43));
1884 $this->assertEquals('5.0', format_float(5.001));
1885
1886 // Custom number of decimal places
1887 $this->assertEquals('5.43000', format_float(5.43, 5));
1888
1889 // Option to strip ending zeros after rounding
1890 $this->assertEquals('5.43', format_float(5.43, 5, true, true));
1891 $this->assertEquals('5', format_float(5.0001, 3, true, true));
1892
1893 // It is not possible to directly change the result of get_string in
1894 // a unit test. Instead, we create a language pack for language 'xx' in
1895 // dataroot and make langconfig.php with the string we need to change.
1896 // The example separator used here is 'X'; on PHP 5.3 and before this
1897 // must be a single byte character due to PHP bug/limitation in
1898 // number_format, so you can't use UTF-8 characters.
1899 $SESSION->lang = 'xx';
1900 $langconfig = "<?php\n\$string['decsep'] = 'X';";
1901 $langfolder = $CFG->dataroot . '/lang/xx';
1902 check_dir_exists($langfolder);
1903 file_put_contents($langfolder . '/langconfig.php', $langconfig);
1904
1905 // Localisation on (default)
1906 $this->assertEquals('5X43000', format_float(5.43, 5));
1907 $this->assertEquals('5X43', format_float(5.43, 5, true, true));
1908
1909 // Localisation off
1910 $this->assertEquals('5.43000', format_float(5.43, 5, false));
1911 $this->assertEquals('5.43', format_float(5.43, 5, false, true));
1912 }
a3d5830a 1913}