diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 4a9c1539593..867464fcc76 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -8850,7 +8850,7 @@ function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
global $CFG;
// if the plain text is shorter than the maximum length, return the whole text
- if (strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) {
+ if (textlib::strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) {
return $text;
}
@@ -8858,7 +8858,7 @@ function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
// and only tag in its 'line'
preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
- $total_length = strlen($ending);
+ $total_length = textlib::strlen($ending);
$truncate = '';
// This array stores information about open and close tags and their position
@@ -8877,19 +8877,19 @@ function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
} else if (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
// record closing tag
$tagdetails[] = (object)array('open'=>false,
- 'tag'=>strtolower($tag_matchings[1]), 'pos'=>strlen($truncate));
+ 'tag'=>textlib::strtolower($tag_matchings[1]), 'pos'=>textlib::strlen($truncate));
// if tag is an opening tag (f.e. )
} else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) {
// record opening tag
$tagdetails[] = (object)array('open'=>true,
- 'tag'=>strtolower($tag_matchings[1]), 'pos'=>strlen($truncate));
+ 'tag'=>textlib::strtolower($tag_matchings[1]), 'pos'=>textlib::strlen($truncate));
}
// add html-tag to $truncate'd text
$truncate .= $line_matchings[1];
}
// calculate the length of the plain text part of the line; handle entities as one character
- $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
+ $content_length = textlib::strlen(preg_replace('/&[0-9a-z]{2,8};|[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
if ($total_length+$content_length > $ideal) {
// the number of characters which are left
$left = $ideal - $total_length;
@@ -8900,14 +8900,14 @@ function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
foreach ($entities[0] as $entity) {
if ($entity[1]+1-$entities_length <= $left) {
$left--;
- $entities_length += strlen($entity[0]);
+ $entities_length += textlib::strlen($entity[0]);
} else {
// no more characters left
break;
}
}
}
- $truncate .= substr($line_matchings[2], 0, $left+$entities_length);
+ $truncate .= textlib::substr($line_matchings[2], 0, $left+$entities_length);
// maximum length is reached, so get off the loop
break;
} else {
@@ -8924,21 +8924,21 @@ function shorten_text($text, $ideal=30, $exact = false, $ending='...') {
// if the words shouldn't be cut in the middle...
if (!$exact) {
// ...search the last occurence of a space...
- for ($k=strlen($truncate);$k>0;$k--) {
- if (!empty($truncate[$k]) && ($char = $truncate[$k])) {
- if ($char == '.' or $char == ' ') {
+ for ($k=textlib::strlen($truncate);$k>0;$k--) {
+ if ($char = textlib::substr($truncate, $k, 1)) {
+ if ($char === '.' or $char === ' ') {
$breakpos = $k+1;
break;
- } else if (ord($char) >= 0xE0) { // Chinese/Japanese/Korean text
- $breakpos = $k; // can be truncated at any UTF-8
- break; // character boundary.
+ } else if (strlen($char) > 2) { // Chinese/Japanese/Korean text
+ $breakpos = $k+1; // can be truncated at any UTF-8
+ break; // character boundary.
}
}
}
if (isset($breakpos)) {
// ...and cut the text in this position
- $truncate = substr($truncate, 0, $breakpos);
+ $truncate = textlib::substr($truncate, 0, $breakpos);
}
}
diff --git a/lib/simpletest/testmoodlelib.php b/lib/simpletest/testmoodlelib.php
index 575238fb94c..3a2bd3e001d 100644
--- a/lib/simpletest/testmoodlelib.php
+++ b/lib/simpletest/testmoodlelib.php
@@ -953,6 +953,37 @@ class moodlelib_test extends UnitTestCase {
$text = "123456789
";//a string with no convenient breaks
$this->assertEqual("12345...
",
shorten_text($text, 8));
+
+ // ==== this must work with UTF-8 too! ======
+
+ // text without tags
+ $text = "Žluťoučký koníček přeskočil";
+ $this->assertEqual($text, shorten_text($text)); // 30 chars by default
+ $this->assertEqual("Žluťoučký koníče...", shorten_text($text, 19, true));
+ $this->assertEqual("Žluťoučký ...", shorten_text($text, 19, false));
+
+ $text = "
Žluťoučký koníček přeskočil potůček
"; + $this->assertEqual($text, shorten_text($text, 60)); + $this->assertEqual("Žluťoučký koníček ...
", shorten_text($text, 21)); + $this->assertEqual("Žluťoučký koníče...
", shorten_text($text, 19, true)); + $this->assertEqual("Žluťoučký ...
", shorten_text($text, 19, false)); + + // Japanese + $text = '言語設定言語設定abcdefghijkl'; + $this->assertEqual($text, shorten_text($text)); // 30 chars by default + $this->assertEqual("言語設定言語...", shorten_text($text, 9, true)); + $this->assertEqual("言語設定言語...", shorten_text($text, 9, false)); + $this->assertEqual("言語設定言語設定ab...", shorten_text($text, 13, true)); + $this->assertEqual("言語設定言語設定...", shorten_text($text, 13, false)); + + // Chinese + $text = '简体中文简体中文abcdefghijkl'; + $this->assertEqual($text, shorten_text($text)); // 30 chars by default + $this->assertEqual("简体中文简体...", shorten_text($text, 9, true)); + $this->assertEqual("简体中文简体...", shorten_text($text, 9, false)); + $this->assertEqual("简体中文简体中文ab...", shorten_text($text, 13, true)); + $this->assertEqual("简体中文简体中文...", shorten_text($text, 13, false)); + } function test_usergetdate() {