Merge branch 'MDL-86559-501-test2' of https://github.com/andimendunia/moodle into MOODLE_501_STABLE
This commit is contained in:
@@ -54,12 +54,36 @@ class text_filter extends \core_filters\text_filter {
|
||||
}
|
||||
|
||||
if ($filterslist) {
|
||||
return $text = filter_phrases($text, $filterslist);
|
||||
// Modify each filter's regex pattern to match any whitespace sequence where there are spaces.
|
||||
// This allows matching activity names regardless of whether users type single spaces, double spaces,
|
||||
// or non-breaking spaces (which HTML editors often insert).
|
||||
$filterslist = filter_prepare_phrases_for_filtering($filterslist);
|
||||
foreach ($filterslist as $filterobject) {
|
||||
if ($filterobject->workregexp !== null) {
|
||||
$filterobject->workregexp = self::replace_spaces_with_whitespace($filterobject->workregexp);
|
||||
}
|
||||
}
|
||||
|
||||
return filter_phrases($text, $filterslist, null, null, false, true);
|
||||
} else {
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace literal spaces in a regex with general whitespace match.
|
||||
*
|
||||
* @param string $regex The regex pattern containing literal spaces.
|
||||
* @return string The regex pattern with spaces replaced.
|
||||
*/
|
||||
protected static function replace_spaces_with_whitespace($regex): string {
|
||||
return preg_replace_callback('/ +/', function($matches): string {
|
||||
$count = strlen($matches[0]);
|
||||
// Matches regular space, non-breaking space (U+00A0), or other whitespace.
|
||||
return '(?:[\s\xC2\xA0]{' . $count . '})';
|
||||
}, $regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the cached activity list for a course
|
||||
*
|
||||
@@ -115,6 +139,9 @@ class text_filter extends \core_filters\text_filter {
|
||||
foreach ($sortedactivities as $cm) {
|
||||
$title = s(trim(strip_tags($cm->name)));
|
||||
$currentname = trim($cm->name);
|
||||
// Normalize whitespace in activity names to handle double spaces and non-breaking spaces.
|
||||
// This ensures that activities with multiple consecutive spaces can still be matched
|
||||
// even when users type the name with different whitespace (e.g., single space, NBSP).
|
||||
$entitisedname = s($currentname);
|
||||
// Avoid empty or unlinkable activity names.
|
||||
if (!empty($title)) {
|
||||
@@ -133,4 +160,4 @@ class text_filter extends \core_filters\text_filter {
|
||||
}
|
||||
return $activitylist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,71 @@ final class text_filter_test extends \advanced_testcase {
|
||||
$this->assertEquals($page->name, $matches[3][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the test_links_with_whitespace.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function links_with_whitespace_provider(): array {
|
||||
return [
|
||||
'Regular spaces' => [
|
||||
'Assignment 1',
|
||||
'<p>Go to Assignment 1</p>',
|
||||
true,
|
||||
],
|
||||
'Two regular spaces' => [
|
||||
'Assignment 1',
|
||||
'<p>Go to Assignment 1</p>',
|
||||
true,
|
||||
],
|
||||
'NBSP + regular spaces' => [
|
||||
'Assignment 1',
|
||||
"<p>Go to Assignment\xC2\xA0 1</p>",
|
||||
true,
|
||||
],
|
||||
'Multiple spaces' => [
|
||||
'Assignment 1 - History',
|
||||
'<p>Go to Assignment 1 - History</p>',
|
||||
true,
|
||||
],
|
||||
'Mismatched spaces 1' => [
|
||||
'Assignment 1',
|
||||
'<p>Go to Assignment 1</p>',
|
||||
false,
|
||||
],
|
||||
'Mismatched spaces 2' => [
|
||||
'Assignment 1',
|
||||
'<p>Go to Assignment 1</p>',
|
||||
false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that links can be matched with various whitespace combinations.
|
||||
*
|
||||
* @dataProvider links_with_whitespace_provider
|
||||
* @param string $activityname
|
||||
* @param string $html
|
||||
* @param bool $expectedresult
|
||||
*/
|
||||
public function test_links_with_whitespace(string $activityname, string $html, bool $expectedresult): void {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$context = \context_course::instance($course->id);
|
||||
|
||||
$this->getDataGenerator()->create_module(
|
||||
'page',
|
||||
['course' => $course->id, 'name' => $activityname]
|
||||
);
|
||||
|
||||
$filtered = format_text($html, FORMAT_HTML, ['context' => $context]);
|
||||
$haslink = strpos($filtered, '<a class="autolink"') !== false;
|
||||
|
||||
$this->assertEquals($expectedresult, $haslink);
|
||||
}
|
||||
|
||||
public function test_cache(): void {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
@@ -166,4 +231,4 @@ final class text_filter_test extends \advanced_testcase {
|
||||
$this->assertEquals($page1->name, $matches[1][0]);
|
||||
$this->assertEquals($page2->name, $matches[1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user