Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace core;
18
 
19
use GuzzleHttp\Psr7\Uri;
20
 
21
/**
22
 * Tests for moodle_url.
23
 *
24
 * @package   core
25
 * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
26
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 * @covers    \moodle_url
28
 */
29
final class moodle_url_test extends \advanced_testcase {
30
    /**
31
     * Test basic moodle_url construction.
32
     */
33
    public function test_moodle_url_constructor() {
34
        global $CFG;
35
 
36
        $url = new \moodle_url('/index.php');
37
        $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
38
 
39
        $url = new \moodle_url('/index.php', array());
40
        $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
41
 
42
        $url = new \moodle_url('/index.php', array('id' => 2));
43
        $this->assertSame($CFG->wwwroot.'/index.php?id=2', $url->out());
44
 
45
        $url = new \moodle_url('/index.php', array('id' => 'two'));
46
        $this->assertSame($CFG->wwwroot.'/index.php?id=two', $url->out());
47
 
48
        $url = new \moodle_url('/index.php', array('id' => 1, 'cid' => '2'));
49
        $this->assertSame($CFG->wwwroot.'/index.php?id=1&amp;cid=2', $url->out());
50
        $this->assertSame($CFG->wwwroot.'/index.php?id=1&cid=2', $url->out(false));
51
 
52
        $url = new \moodle_url('/index.php', null, 'test');
53
        $this->assertSame($CFG->wwwroot.'/index.php#test', $url->out());
54
 
55
        $url = new \moodle_url('/index.php', array('id' => 2), 'test');
56
        $this->assertSame($CFG->wwwroot.'/index.php?id=2#test', $url->out());
57
    }
58
 
59
    /**
60
     * Tests \moodle_url::get_path().
61
     */
62
    public function test_moodle_url_get_path() {
63
        $url = new \moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
64
        $this->assertSame('/my/file/is/here.txt', $url->get_path());
65
 
66
        $url = new \moodle_url('http://www.example.org/');
67
        $this->assertSame('/', $url->get_path());
68
 
69
        $url = new \moodle_url('http://www.example.org/pluginfile.php/slash/arguments');
70
        $this->assertSame('/pluginfile.php/slash/arguments', $url->get_path());
71
        $this->assertSame('/pluginfile.php', $url->get_path(false));
72
    }
73
 
74
    public function test_moodle_url_round_trip() {
75
        $strurl = 'http://moodle.org/course/view.php?id=5';
76
        $url = new \moodle_url($strurl);
77
        $this->assertSame($strurl, $url->out(false));
78
 
79
        $strurl = 'http://moodle.org/user/index.php?contextid=53&sifirst=M&silast=D';
80
        $url = new \moodle_url($strurl);
81
        $this->assertSame($strurl, $url->out(false));
82
    }
83
 
84
    /**
85
     * Test Moodle URL objects created with a param with empty value.
86
     */
87
    public function test_moodle_url_empty_param_values() {
88
        $strurl = 'http://moodle.org/course/view.php?id=0';
89
        $url = new \moodle_url($strurl, array('id' => 0));
90
        $this->assertSame($strurl, $url->out(false));
91
 
92
        $strurl = 'http://moodle.org/course/view.php?id';
93
        $url = new \moodle_url($strurl, array('id' => false));
94
        $this->assertSame($strurl, $url->out(false));
95
 
96
        $strurl = 'http://moodle.org/course/view.php?id';
97
        $url = new \moodle_url($strurl, array('id' => null));
98
        $this->assertSame($strurl, $url->out(false));
99
 
100
        $strurl = 'http://moodle.org/course/view.php?id';
101
        $url = new \moodle_url($strurl, array('id' => ''));
102
        $this->assertSame($strurl, $url->out(false));
103
 
104
        $strurl = 'http://moodle.org/course/view.php?id';
105
        $url = new \moodle_url($strurl);
106
        $this->assertSame($strurl, $url->out(false));
107
    }
108
 
109
    /**
110
     * Test set good scheme on Moodle URL objects.
111
     */
112
    public function test_moodle_url_set_good_scheme() {
113
        $url = new \moodle_url('http://moodle.org/foo/bar');
114
        $url->set_scheme('myscheme');
115
        $this->assertSame('myscheme://moodle.org/foo/bar', $url->out());
116
    }
117
 
118
    /**
119
     * Test set bad scheme on Moodle URL objects.
120
     */
121
    public function test_moodle_url_set_bad_scheme() {
122
        $url = new \moodle_url('http://moodle.org/foo/bar');
123
        $this->expectException(\coding_exception::class);
124
        $url->set_scheme('not a valid $ scheme');
125
    }
126
 
127
    public function test_moodle_url_round_trip_array_params() {
128
        $strurl = 'http://example.com/?a%5B1%5D=1&a%5B2%5D=2';
129
        $url = new \moodle_url($strurl);
130
        $this->assertSame($strurl, $url->out(false));
131
 
132
        $url = new \moodle_url('http://example.com/?a[1]=1&a[2]=2');
133
        $this->assertSame($strurl, $url->out(false));
134
 
135
        // For un-keyed array params, we expect 0..n keys to be returned.
136
        $strurl = 'http://example.com/?a%5B0%5D=0&a%5B1%5D=1';
137
        $url = new \moodle_url('http://example.com/?a[]=0&a[]=1');
138
        $this->assertSame($strurl, $url->out(false));
139
    }
140
 
141
    public function test_compare_url() {
142
        $url1 = new \moodle_url('index.php', array('var1' => 1, 'var2' => 2));
143
        $url2 = new \moodle_url('index2.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
144
 
145
        $this->assertFalse($url1->compare($url2, URL_MATCH_BASE));
146
        $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
147
        $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
148
 
149
        $url2 = new \moodle_url('index.php', array('var1' => 1, 'var3' => 3));
150
 
151
        $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
152
        $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
153
        $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
154
 
155
        $url2 = new \moodle_url('index.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
156
 
157
        $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
158
        $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
159
        $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
160
 
161
        $url2 = new \moodle_url('index.php', array('var2' => 2, 'var1' => 1));
162
 
163
        $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
164
        $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
165
        $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
166
 
167
        $url1->set_anchor('test');
168
        $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
169
        $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
170
        $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
171
 
172
        $url2->set_anchor('test');
173
        $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
174
        $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
175
        $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
176
    }
177
 
178
    public function test_out_as_local_url() {
179
        global $CFG;
180
        // Test http url.
181
        $url1 = new \moodle_url('/lib/tests/weblib_test.php');
182
        $this->assertSame('/lib/tests/weblib_test.php', $url1->out_as_local_url());
183
 
184
        // Test https url.
185
        $httpswwwroot = str_replace("http://", "https://", $CFG->wwwroot);
186
        $url2 = new \moodle_url($httpswwwroot.'/login/profile.php');
187
        $this->assertSame('/login/profile.php', $url2->out_as_local_url());
188
 
189
        // Test http url matching wwwroot.
190
        $url3 = new \moodle_url($CFG->wwwroot);
191
        $this->assertSame('', $url3->out_as_local_url());
192
 
193
        // Test http url matching wwwroot ending with slash (/).
194
        $url3 = new \moodle_url($CFG->wwwroot.'/');
195
        $this->assertSame('/', $url3->out_as_local_url());
196
    }
197
 
198
    public function test_out_as_local_url_error() {
199
        $url2 = new \moodle_url('http://www.google.com/lib/tests/weblib_test.php');
200
        $this->expectException(\coding_exception::class);
201
        $url2->out_as_local_url();
202
    }
203
 
204
    /**
205
     * You should get error with modified url
206
     */
207
    public function test_modified_url_out_as_local_url_error() {
208
        global $CFG;
209
 
210
        $modifiedurl = $CFG->wwwroot.'1';
211
        $url3 = new \moodle_url($modifiedurl.'/login/profile.php');
212
        $this->expectException(\coding_exception::class);
213
        $url3->out_as_local_url();
214
    }
215
 
216
    /**
217
     * Try get local url from external https url and you should get error
218
     */
219
    public function test_https_out_as_local_url_error() {
220
        $url4 = new \moodle_url('https://www.google.com/lib/tests/weblib_test.php');
221
        $this->expectException(\coding_exception::class);
222
        $url4->out_as_local_url();
223
    }
224
 
225
    public function test_moodle_url_get_scheme() {
226
        // Should return the scheme only.
227
        $url = new \moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
228
        $this->assertSame('http', $url->get_scheme());
229
 
230
        // Should work for secure URLs.
231
        $url = new \moodle_url('https://www.example.org:447/my/file/is/here.txt?really=1');
232
        $this->assertSame('https', $url->get_scheme());
233
 
234
        // Should return an empty string if no scheme is specified.
235
        $url = new \moodle_url('www.example.org:447/my/file/is/here.txt?really=1');
236
        $this->assertSame('', $url->get_scheme());
237
    }
238
 
239
    public function test_moodle_url_get_host() {
240
        // Should return the host part only.
241
        $url = new \moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
242
        $this->assertSame('www.example.org', $url->get_host());
243
    }
244
 
245
    public function test_moodle_url_get_port() {
246
        // Should return the port if one provided.
247
        $url = new \moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
248
        $this->assertSame(447, $url->get_port());
249
 
250
        // Should return an empty string if port not specified.
251
        $url = new \moodle_url('http://www.example.org/some/path/here.php');
252
        $this->assertSame('', $url->get_port());
253
    }
254
 
255
    /**
256
     * Test exporting params for templates.
257
     *
258
     * @dataProvider moodle_url_export_params_for_template_provider
259
     * @param string $url URL with params to test.
260
     * @param array $expected The expected result.
261
     */
262
    public function test_moodle_url_export_params_for_template(string $url, array $expected): void {
263
        // Should return params in the URL.
264
        $moodleurl = new \moodle_url($url);
265
        $this->assertSame($expected, $moodleurl->export_params_for_template());
266
    }
267
 
268
    /**
269
     * Data provider for moodle_url_export_params_for_template tests.
270
     *
271
     * @return array[] the array of test data.
272
     */
273
    public function moodle_url_export_params_for_template_provider(): array {
274
        $baseurl = "http://example.com";
275
        return [
276
                'With indexed array params' => [
277
                    'url' => "@{$baseurl}/?tags[0]=123&tags[1]=456",
278
                    'expected' => [
279
 
280
                        1 => ['name' => 'tags[1]', 'value' => '456']
281
                    ]
282
                ],
283
                'Without indexed array params' => [
284
                    'url' => "@{$baseurl}/?tags[]=123&tags[]=456",
285
                    'expected' => [
286
 
287
                        1 => ['name' => 'tags[1]', 'value' => '456']
288
                    ]
289
                ],
290
                'with no params' => [
291
                    'url' => "@{$baseurl}/",
292
                    'expected' => []
293
                ],
294
                'with no array params' => [
295
                    'url' => "@{$baseurl}/?param1=1&param2=2&param3=3",
296
                    'expected' => [
297
 
298
                        1 => ['name' => 'param2', 'value' => '2'],
299
                        2 => ['name' => 'param3', 'value' => '3'],
300
                    ]
301
                ],
302
                'array embedded with other params' => [
303
                    'url' => "@{$baseurl}/?param1=1&tags[0]=123&tags[1]=456&param2=2&param3=3",
304
                    'expected' => [
305
 
306
                        1 => ['name' => 'tags[0]', 'value' => '123'],
307
                        2 => ['name' => 'tags[1]', 'value' => '456'],
308
                        3 => ['name' => 'param2', 'value' => '2'],
309
                        4 => ['name' => 'param3', 'value' => '3'],
310
                    ]
311
                ],
312
                'params with array at the end' => [
313
                    'url' => "@{$baseurl}/?param1=1&tags[]=123&tags[]=456",
314
                    'expected' => [
315
 
316
                        1 => ['name' => 'tags[0]', 'value' => '123'],
317
                        2 => ['name' => 'tags[1]', 'value' => '456'],
318
                    ]
319
                ],
320
        ];
321
    }
322
 
323
    /**
324
     * Test the make_pluginfile_url function.
325
     *
326
     * @dataProvider make_pluginfile_url_provider
327
     * @param   bool    $slashargs
328
     * @param   array   $args Args to be provided to make_pluginfile_url
329
     * @param   string  $expected The expected result
330
     */
331
    public function test_make_pluginfile_url($slashargs, $args, $expected) {
332
        global $CFG;
333
 
334
        $this->resetAfterTest();
335
 
336
        $CFG->slasharguments = $slashargs;
337
        $url = call_user_func_array('\moodle_url::make_pluginfile_url', $args);
338
        $this->assertMatchesRegularExpression($expected, $url->out(true));
339
    }
340
 
341
    /**
342
     * Data provider for make_pluginfile_url tests.
343
     *
344
     * @return  array[]
345
     */
346
    public function make_pluginfile_url_provider() {
347
        $baseurl = "https://www.example.com/moodle/pluginfile.php";
348
        $tokenbaseurl = "https://www.example.com/moodle/tokenpluginfile.php";
349
        return [
350
            'Standard with slashargs' => [
351
                'slashargs' => true,
352
                'args' => [
353
                    1,
354
                    'mod_forum',
355
                    'posts',
356
                    422,
357
                    '/my/location/',
358
                    'file.png',
359
                ],
360
                'expected' => "@{$baseurl}/1/mod_forum/posts/422/my/location/file.png@",
361
            ],
362
            'Standard without slashargs' => [
363
                'slashargs' => false,
364
                'args' => [
365
                    1,
366
                    'mod_forum',
367
                    'posts',
368
                    422,
369
                    '/my/location/',
370
                    'file.png',
371
                ],
372
                'expected' => "@{$baseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png@",
373
            ],
374
            'Token included with slashargs' => [
375
                'slashargs' => true,
376
                'args' => [
377
                    1,
378
                    'mod_forum',
379
                    'posts',
380
                    422,
381
                    '/my/location/',
382
                    'file.png',
383
                    false,
384
                    true,
385
                ],
386
                'expected' => "@{$tokenbaseurl}/[^/]*/1/mod_forum/posts/422/my/location/file.png@",
387
            ],
388
            'Token included without slashargs' => [
389
                'slashargs' => false,
390
                'args' => [
391
                    1,
392
                    'mod_forum',
393
                    'posts',
394
                    422,
395
                    '/my/location/',
396
                    'file.png',
397
                    false,
398
                    true,
399
                ],
400
                'expected' => "@{$tokenbaseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png&amp;token=[a-z0-9]*@",
401
            ],
402
        ];
403
    }
404
 
405
    public function test_from_uri(): void {
406
        global $CFG;
407
 
408
        $uri = new Uri('http://www.example.org:447/my/file/is/here.txt?really=1');
409
        $url = \moodle_url::from_uri($uri);
410
        $this->assertSame('http://www.example.org:447/my/file/is/here.txt?really=1', $url->out(false));
411
        $this->assertEquals(1, $url->param('really'));
412
 
413
        $uri = new Uri('https://www.example.org/my/file/is/here.txt?really=1');
414
        $url = \moodle_url::from_uri($uri);
415
        $this->assertSame('https://www.example.org/my/file/is/here.txt?really=1', $url->out(false));
416
        $this->assertEquals(1, $url->param('really'));
417
 
418
        // Multiple params.
419
        $uri = new Uri('https://www.example.org/my/file/is/here.txt?really=1&another=2&&more=3&moar=4');
420
        $url = \moodle_url::from_uri($uri);
421
        $this->assertSame('https://www.example.org/my/file/is/here.txt?really=1&another=2&more=3&moar=4', $url->out(false));
422
        $this->assertEquals(1, $url->param('really'));
423
        $this->assertEquals(2, $url->param('another'));
424
        $this->assertEquals(3, $url->param('more'));
425
        $this->assertEquals(4, $url->param('moar'));
426
 
427
        // Anchors.
428
        $uri = new Uri("{$CFG->wwwroot}/course/view/#section-1");
429
        $url = \moodle_url::from_uri($uri);
430
        $this->assertSame("{$CFG->wwwroot}/course/view/#section-1", $url->out(false));
431
        $this->assertEmpty($url->params());
432
    }
433
 
434
    /**
435
     * @dataProvider url_fragment_parsing_provider
436
     */
437
    public function test_url_fragment_parsing(string $fragment, string $expected): void {
438
        $url = new \moodle_url('/index.php', null, $fragment);
439
 
440
        // Test the encoded fragment.
441
        $this->assertEquals(
442
            "#{$expected}",
443
            $url->get_encoded_anchor(),
444
        );
445
 
446
        // Test the value of ->raw_out() with escaping enabled.
447
        $parts = parse_url($url->raw_out(true), PHP_URL_FRAGMENT);
448
        $this->assertEquals($expected, parse_url($url->raw_out(true), PHP_URL_FRAGMENT));
449
 
450
        // Test the value of ->raw_out() with escaping disabled.
451
        $parts = parse_url($url->raw_out(false));
452
        $this->assertEquals($expected, $parts['fragment']);
453
 
454
        // Test the value of ->out() with escaping enabled.
455
        $parts = parse_url($url->out(true));
456
        $this->assertEquals($expected, $parts['fragment']);
457
 
458
        // Test the value of ->out() with escaping disabled.
459
        $parts = parse_url($url->out(false));
460
        $this->assertEquals($expected, $parts['fragment']);
461
    }
462
 
463
    /**
464
     * Data provider for url_fragment_parsing tests.
465
     *
466
     * @return array
467
     */
468
    public static function url_fragment_parsing_provider(): array {
469
        return [
470
            'Simple fragment' => ['test', 'test'],
471
            // RFC 3986 allows the following characters in a fragment without them being encoded:
472
            // pct-encoded: "%" HEXDIG HEXDIG
473
            // unreserved:  ALPHA / DIGIT / "-" / "." / "_" / "~" /
474
            // sub-delims:  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@"
475
            // fragment:    "/" / "?"
476
            //
477
            // These should not be encoded in the fragment unless they were already encoded.
478
            'Fragment with RFC3986 characters' => [
479
                'test-._~!$&\'()*+,;=:@/?',
480
                'test-._~!$&\'()*+,;=:@/?',
481
            ],
482
            'Contains % without HEXDIG HEXDIG' => [
483
                '%Percent',
484
                '%25Percent',
485
            ],
486
            'Contains multiple %' => [
487
                // % followed by a valid pct-encoded followed by two more %%.
488
                '%%23%%',
489
                '%25%23%25%25',
490
            ],
491
            'Fragment with already-encoded RFC3986 characters' => [
492
                rawurlencode('test-._~!$&\'()*+,;=:@/?'),
493
                rawurlencode('test-._~!$&\'()*+,;=:@/?'),
494
            ],
495
            'Fragment with encoded slashes' => ['test%2fwith%2fencoded%2fslashes', 'test%2fwith%2fencoded%2fslashes'],
496
            'Fragment with encoded characters' => ['test%20with%20encoded%20characters', 'test%20with%20encoded%20characters'],
497
 
498
            // The following are examples which _should_ become encoded.
499
            'Spaces become encoded' => ['test with spaces', 'test%20with%20spaces'],
500
            'Quotes become encoded' => ['test with "quotes"', 'test%20with%20%22quotes%22'],
501
        ];
502
    }
503
}