Merge pull request #3977 from dhensby/pulls/3566

NEW LimitCharactersToClosestWord helper function
This commit is contained in:
Loz Calver 2015-03-09 11:40:58 +00:00
commit 9c70a91f1b
2 changed files with 60 additions and 2 deletions

View File

@ -17,6 +17,7 @@ abstract class StringField extends DBField {
*/
private static $casting = array(
"LimitCharacters" => "Text",
"LimitCharactersToClosestWord" => "Text",
'LimitWordCount' => 'Text',
'LimitWordCountXML' => 'HTMLText',
"LowerCase" => "Text",
@ -116,7 +117,6 @@ abstract class StringField extends DBField {
*/
public function LimitCharacters($limit = 20, $add = '...') {
$value = trim($this->value);
if($this->stat('escape_type') == 'xml') {
$value = strip_tags($value);
$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
@ -126,11 +126,40 @@ abstract class StringField extends DBField {
} else {
$value = (mb_strlen($value) > $limit) ? mb_substr($value, 0, $limit) . $add : $value;
}
return $value;
}
/**
* Limit this field's content by a number of characters and truncate
* the field to the closest complete word. All HTML tags are stripped
* from the field.
*
* @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
public function LimitCharactersToClosestWord($limit = 20, $add = '...') {
// Strip HTML tags if they exist in the field
$this->value = strip_tags($this->value);
// Determine if value exceeds limit before limiting characters
$exceedsLimit = mb_strlen($this->value) > $limit;
// Limit to character limit
$value = $this->LimitCharacters($limit, '');
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
if($exceedsLimit) {
$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
$value = rtrim(mb_substr($value, 0, mb_strrpos($value, " ")), "/[\.,-\/#!$%\^&\*;:{}=\-_`~()]\s") . $add;
$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
}
return $value;
}
/**
* Limit this field's content by a number of words.
*

View File

@ -21,6 +21,35 @@ class TextTest extends SapphireTest {
}
}
/**
* Test {@link Text->LimitCharactersToClosestWord()}
*/
public function testLimitCharactersToClosestWord() {
$cases = array(
/* Standard words limited, ellipsis added if truncated */
'Lorem ipsum dolor sit amet' => 'Lorem ipsum dolor sit...',
/* Complete words less than the character limit don't get truncated, ellipsis not added */
'Lorem ipsum' => 'Lorem ipsum',
'Lorem' => 'Lorem',
'' => '', // No words produces nothing!
/* HTML tags get stripped out, leaving the raw text */
'<p>Lorem ipsum dolor sit amet</p>' => 'Lorem ipsum dolor sit...',
'<p><span>Lorem ipsum dolor sit amet</span></p>' => 'Lorem ipsum dolor sit...',
'<p>Lorem ipsum</p>' => 'Lorem ipsum',
/* HTML entities are treated as a single character */
'Lorem &amp; ipsum dolor sit amet' => 'Lorem &amp; ipsum dolor...'
);
foreach($cases as $originalValue => $expectedValue) {
$textObj = new Text('Test');
$textObj->setValue($originalValue);
$this->assertEquals($expectedValue, $textObj->LimitCharactersToClosestWord(24));
}
}
/**
* Test {@link Text->LimitWordCount()}
*/