Merge branch 'MDL-81316-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE
This commit is contained in:
@@ -24,7 +24,7 @@ namespace core;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \moodle_url
|
||||
*/
|
||||
class moodle_url_test extends \advanced_testcase {
|
||||
final class moodle_url_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test basic moodle_url construction.
|
||||
*/
|
||||
@@ -399,4 +399,71 @@ class moodle_url_test extends \advanced_testcase {
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider url_fragment_parsing_provider
|
||||
*/
|
||||
public function test_url_fragment_parsing(string $fragment, string $expected): void {
|
||||
$url = new \moodle_url('/index.php', null, $fragment);
|
||||
|
||||
// Test the encoded fragment.
|
||||
$this->assertEquals(
|
||||
"#{$expected}",
|
||||
$url->get_encoded_anchor(),
|
||||
);
|
||||
|
||||
// Test the value of ->raw_out() with escaping enabled.
|
||||
$parts = parse_url($url->raw_out(true), PHP_URL_FRAGMENT);
|
||||
$this->assertEquals($expected, parse_url($url->raw_out(true), PHP_URL_FRAGMENT));
|
||||
|
||||
// Test the value of ->raw_out() with escaping disabled.
|
||||
$parts = parse_url($url->raw_out(false));
|
||||
$this->assertEquals($expected, $parts['fragment']);
|
||||
|
||||
// Test the value of ->out() with escaping enabled.
|
||||
$parts = parse_url($url->out(true));
|
||||
$this->assertEquals($expected, $parts['fragment']);
|
||||
|
||||
// Test the value of ->out() with escaping disabled.
|
||||
$parts = parse_url($url->out(false));
|
||||
$this->assertEquals($expected, $parts['fragment']);
|
||||
|
||||
$url->set_anchor($fragment);
|
||||
$this->assertEquals(
|
||||
"#{$expected}",
|
||||
$url->get_encoded_anchor(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for url_fragment_parsing tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function url_fragment_parsing_provider(): array {
|
||||
return [
|
||||
'Simple fragment' => ['test', 'test'],
|
||||
// RFC 3986 allows the following characters in a fragment without them being encoded:
|
||||
// pct-encoded: "%" HEXDIG HEXDIG
|
||||
// unreserved: ALPHA / DIGIT / "-" / "." / "_" / "~" /
|
||||
// sub-delims: "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@"
|
||||
// fragment: "/" / "?"
|
||||
//
|
||||
// These should not be encoded in the fragment unless they were already encoded.
|
||||
'Fragment with RFC3986 characters' => [
|
||||
'test-._~!$&\'()*+,;=:@/?',
|
||||
'test-._~!$&\'()*+,;=:@/?',
|
||||
],
|
||||
'Fragment with already-encoded RFC3986 characters' => [
|
||||
rawurlencode('test-._~!$&\'()*+,;=:@/?'),
|
||||
rawurlencode('test-._~!$&\'()*+,;=:@/?'),
|
||||
],
|
||||
'Fragment with encoded slashes' => ['test%2fwith%2fencoded%2fslashes', 'test%2fwith%2fencoded%2fslashes'],
|
||||
'Fragment with encoded characters' => ['test%20with%20encoded%20characters', 'test%20with%20encoded%20characters'],
|
||||
|
||||
// The following are examples which _should_ become encoded.
|
||||
'Spaces become encoded' => ['test with spaces', 'test%20with%20spaces'],
|
||||
'Quotes become encoded' => ['test with "quotes"', 'test%20with%20%22quotes%22'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+37
-13
@@ -618,13 +618,44 @@ class moodle_url {
|
||||
if ($querystring !== '') {
|
||||
$uri .= '?' . $querystring;
|
||||
}
|
||||
if (!is_null($this->anchor)) {
|
||||
$uri .= '#'.$this->anchor;
|
||||
}
|
||||
|
||||
$uri .= $this->get_encoded_anchor();
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the anchor according to RFC 3986.
|
||||
*
|
||||
* @return string The encoded anchor
|
||||
*/
|
||||
public function get_encoded_anchor(): string {
|
||||
if (is_null($this->anchor)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// RFC 3986 allows the following characters in a fragment without them being encoded:
|
||||
// pct-encoded: "%" HEXDIG HEXDIG
|
||||
// unreserved: ALPHA / DIGIT / "-" / "." / "_" / "~" /
|
||||
// sub-delims: "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@"
|
||||
// fragment: "/" / "?"
|
||||
//
|
||||
// All other characters should be encoded.
|
||||
// These should not be encoded in the fragment unless they were already encoded.
|
||||
|
||||
$allowed = 'a-zA-Z0-9\\-._~!$&\'()*+,;=:@\/?%';
|
||||
$anchor = '#';
|
||||
$anchor .= preg_replace_callback(
|
||||
'/[^' . $allowed . ']/',
|
||||
function ($matches) {
|
||||
return rawurlencode($matches[0]);
|
||||
},
|
||||
$this->anchor
|
||||
);
|
||||
|
||||
return $anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns url without parameters, everything before '?'.
|
||||
*
|
||||
@@ -638,8 +669,8 @@ class moodle_url {
|
||||
$uri .= $this->host ? $this->host : '';
|
||||
$uri .= $this->port ? ':'.$this->port : '';
|
||||
$uri .= $this->path ? $this->path : '';
|
||||
if ($includeanchor and !is_null($this->anchor)) {
|
||||
$uri .= '#' . $this->anchor;
|
||||
if ($includeanchor) {
|
||||
$uri .= $this->get_encoded_anchor();
|
||||
}
|
||||
|
||||
return $uri;
|
||||
@@ -715,15 +746,8 @@ class moodle_url {
|
||||
if (is_null($anchor)) {
|
||||
// Remove.
|
||||
$this->anchor = null;
|
||||
} else if ($anchor === '') {
|
||||
// Special case, used as empty link.
|
||||
$this->anchor = '';
|
||||
} else if (preg_match('|[a-zA-Z\_\:][a-zA-Z0-9\_\-\.\:]*|', $anchor)) {
|
||||
// Match the anchor against the NMTOKEN spec.
|
||||
$this->anchor = $anchor;
|
||||
} else {
|
||||
// Bad luck, no valid anchor found.
|
||||
$this->anchor = null;
|
||||
$this->anchor = $anchor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user