MDL-31718 utf-8 support in shorten_text()
This commit is contained in:
+14
-14
@@ -8739,7 +8739,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;
|
||||
}
|
||||
|
||||
@@ -8747,7 +8747,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
|
||||
@@ -8766,19 +8766,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. <b>)
|
||||
} 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};|&#x[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
|
||||
$content_length = textlib::strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[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;
|
||||
@@ -8789,14 +8789,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 {
|
||||
@@ -8813,21 +8813,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -953,6 +953,37 @@ class moodlelib_test extends UnitTestCase {
|
||||
$text = "<h1>123456789</h1>";//a string with no convenient breaks
|
||||
$this->assertEqual("<h1>12345...</h1>",
|
||||
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 = "<p>Žluťoučký koníček <b>přeskočil</b> potůček</p>";
|
||||
$this->assertEqual($text, shorten_text($text, 60));
|
||||
$this->assertEqual("<p>Žluťoučký koníček ...</p>", shorten_text($text, 21));
|
||||
$this->assertEqual("<p>Žluťoučký koníče...</p>", shorten_text($text, 19, true));
|
||||
$this->assertEqual("<p>Žluťoučký ...</p>", 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() {
|
||||
|
||||
Reference in New Issue
Block a user