diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 6f446a0e29b..3139fd8e23d 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -8375,10 +8375,27 @@ function moodle_setlocale($locale='') {
* Words are defined as things between whitespace.
*
* @category string
- * @param string $string The text to be searched for words.
+ * @param string $string The text to be searched for words. May be HTML.
* @return int The count of words in the specified string
*/
function count_words($string) {
+ // Before stripping tags, add a space after the close tag of anything that is not obviously inline.
+ // Also, br is a special case because it definitely delimits a word, but has no close tag.
+ $string = preg_replace('~
+ ( # Capture the tag we match.
+ # Start of close tag.
+ (?! # Do not match any of these specific close tag names.
+ a> | b> | del> | em> | i> |
+ ins> | s> | small> |
+ strong> | sub> | sup> | u>
+ )
+ \w+ # But, apart from those execptions, match any tag name.
+ > # End of close tag.
+ |
+
|
# Special cases that are not close tags.
+ )
+ ~x', '$1 ', $string); // Add a space after the close tag.
+ // Now remove HTML tags.
$string = strip_tags($string);
// Decode HTML entities.
$string = html_entity_decode($string);
diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php
index 8c02d58b1b8..d3733c768a2 100644
--- a/lib/tests/moodlelib_test.php
+++ b/lib/tests/moodlelib_test.php
@@ -3792,7 +3792,7 @@ class core_moodlelib_testcase extends advanced_testcase {
}
/**
- * Test function count_words().
+ * Test function {@see count_words()}.
*
* @dataProvider count_words_testcases
* @param int $expectedcount number of words in $string.
@@ -3809,16 +3809,30 @@ class core_moodlelib_testcase extends advanced_testcase {
*/
public function count_words_testcases(): array {
return [
+ [0, ''],
+ [4, 'one two three four'],
[3, "one two three'four"],
[3, 'one+two three’four'],
[2, 'one"two three-four'],
[4, 'one@two three_four'],
[4, 'one\two three/four'],
+ [4, '
one two
three four
one two
three four
one two
three four
one two
three four
'], + [4, 'one two
three four
'], + [4, 'one
four.
'], + [1, 'emphasis.
'], + [1, 'emphasis.
'], + [1, 'emphasis.
'], + [1, 'emphasis.
'], + [2, "one\ntwo"], + [1, "SO42-"], ]; }