Skip to content

Commit

Permalink
Merge pull request #752 from dereuromark/2.3-truncate-tail
Browse files Browse the repository at this point in the history
String::tail()
  • Loading branch information
markstory committed Aug 16, 2012
2 parents c83e941 + 2a570e6 commit 9e96c47
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 16 deletions.
69 changes: 64 additions & 5 deletions lib/Cake/Test/Case/Utility/StringTest.php
Expand Up @@ -379,7 +379,7 @@ public function testTruncate() {
$this->assertSame($this->Text->truncate($text2, 10, array('exact' => false)), '...');
$this->assertSame($this->Text->truncate($text3, 20), '<b>&copy; 2005-20...');
$this->assertSame($this->Text->truncate($text4, 15), '<img src="my...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '')), '0<b>1<');
$this->assertSame($this->Text->truncate($text5, 6, array('ellipsis' => '')), '0<b>1<');
$this->assertSame($this->Text->truncate($text1, 15, array('html' => true)), 'The quick br...');
$this->assertSame($this->Text->truncate($text1, 15, array('exact' => false, 'html' => true)), 'The quick...');
$this->assertSame($this->Text->truncate($text2, 10, array('html' => true)), 'Heiz&ouml;lr...');
Expand All @@ -388,8 +388,8 @@ public function testTruncate() {
$this->assertSame($this->Text->truncate($text4, 15, array('html' => true)), '<img src="mypic.jpg"> This image ...');
$this->assertSame($this->Text->truncate($text4, 45, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But t...</b>');
$this->assertSame($this->Text->truncate($text4, 90, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But the following image tag should be conform <img src="mypic.jpg" alt="Me, myself and I" /></b><br />Grea...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '', 'html' => true)), '0<b>1<i>2<span class="myclass">3</span>4<u>5</u></i></b>');
$this->assertSame($this->Text->truncate($text5, 20, array('ending' => '', 'html' => true)), $text5);
$this->assertSame($this->Text->truncate($text5, 6, array('ellipsis' => '', 'html' => true)), '0<b>1<i>2<span class="myclass">3</span>4<u>5</u></i></b>');
$this->assertSame($this->Text->truncate($text5, 20, array('ellipsis' => '', 'html' => true)), $text5);
$this->assertSame($this->Text->truncate($text6, 57, array('exact' => false, 'html' => true)), "<p><strong>Extra dates have been announced for this year's...</strong></p>");
$this->assertSame($this->Text->truncate($text7, 255), $text7);
$this->assertSame($this->Text->truncate($text7, 15), 'El moño está...');
Expand All @@ -399,7 +399,7 @@ public function testTruncate() {

$text = '<p><span style="font-size: medium;"><a>Iamatestwithnospacesandhtml</a></span></p>';
$result = $this->Text->truncate($text, 10, array(
'ending' => '...',
'ellipsis' => '...',
'exact' => false,
'html' => true
));
Expand All @@ -422,7 +422,7 @@ public function testTruncate() {
<p><span style="font-size: medium;"><a>http://www.amazon.com/Steve-
Jobs-Walter-Isaacson/dp/1451648537</a></span></p>';
$result = $this->Text->truncate($text, 500, array(
'ending' => '... ',
'ellipsis' => '... ',
'exact' => false,
'html' => true
));
Expand All @@ -441,6 +441,65 @@ public function testTruncate() {
podeís adquirirla.</span></p>
<p><span style="font-size: medium;"><a>... </a></span></p>';
$this->assertEquals($expected, $result);

// test deprecated `ending` (`ellipsis` taking precedence if both are defined)
$result = $this->Text->truncate($text1, 31, array(
'ending' => '.',
'exact' => false,
));
$expected = 'The quick brown fox jumps.';
$this->assertEquals($expected, $result);

$result = $this->Text->truncate($text1, 31, array(
'ellipsis' => '..',
'ending' => '.',
'exact' => false,
));
$expected = 'The quick brown fox jumps..';
$this->assertEquals($expected, $result);
}

/**
* testTail method
*
* @return void
*/
public function testTail() {
$text1 = 'The quick brown fox jumps over the lazy dog';
$text2 = 'Heiz&ouml;lr&uuml;cksto&szlig;abd&auml;mpfung';
$text3 = 'El moño está en el lugar correcto. Eso fue lo que dijo la niña, ¿habrá dicho la verdad?';
$text4 = 'Vive la R' . chr(195) . chr(169) . 'publique de France';
$text5 = 'НОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыь';

$result = $this->Text->tail($text1, 13);
$this->assertEquals('...e lazy dog', $result);

$result = $this->Text->tail($text1, 13, array('exact' => false));
$this->assertEquals('...lazy dog', $result);

$result = $this->Text->tail($text1, 100);
$this->assertEquals('The quick brown fox jumps over the lazy dog', $result);

$result = $this->Text->tail($text2, 10);
$this->assertEquals('...;mpfung', $result);

$result = $this->Text->tail($text2, 10, array('exact' => false));
$this->assertEquals('...', $result);

$result = $this->Text->tail($text3, 255);
$this->assertEquals($text3, $result);

$result = $this->Text->tail($text3, 21);
$this->assertEquals('...á dicho la verdad?', $result);

$result = $this->Text->tail($text4, 25);
$this->assertEquals('...a R' . chr(195) . chr(169) . 'publique de France', $result);

$result = $this->Text->tail($text5, 10);
$this->assertEquals('...цчшщъыь', $result);

$result = $this->Text->tail($text5, 6, array('ellipsis' => ''));
$this->assertEquals('чшщъыь', $result);
}

/**
Expand Down
65 changes: 54 additions & 11 deletions lib/Cake/Utility/String.php
Expand Up @@ -418,15 +418,55 @@ public static function stripLinks($text) {
return preg_replace('|<a\s+[^>]+>|im', '', preg_replace('|<\/a>|im', '', $text));
}

/**
* Truncates text starting from the end.
*
* Cuts a string to the length of $length and replaces the first characters
* with the ellipsis if the text is longer than length.
*
* ### Options:
*
* - `ellipsis` Will be used as Beginning and prepended to the trimmed string
* - `exact` If false, $text will not be cut mid-word
*
* @param string $text String to truncate.
* @param integer $length Length of returned string, including ellipsis.
* @param array $options An array of options.
* @return string Trimmed string.
*/
public static function tail($text, $length = 100, $options = array()) {
$default = array(
'ellipsis' => '...', 'exact' => true
);
$options = array_merge($default, $options);
extract($options);

if (!function_exists('mb_strlen')) {
class_exists('Multibyte');
}

if (mb_strlen($text) <= $length) {
return $text;
} else {
$truncate = mb_substr($text, mb_strlen($text) - $length + mb_strlen($ellipsis));
}
if (!$exact) {
$spacepos = mb_strpos($truncate, ' ');
$truncate = $spacepos === false ? '' : trim(mb_substr($truncate, $spacepos));
}

return $ellipsis . $truncate;
}

/**
* Truncates text.
*
* Cuts a string to the length of $length and replaces the last characters
* with the ending if the text is longer than length.
* with the ellipsis if the text is longer than length.
*
* ### Options:
*
* - `ending` Will be used as Ending and appended to the trimmed string
* - `ellipsis` Will be used as Ending and appended to the trimmed string (`ending` is deprecated)
* - `exact` If false, $text will not be cut mid-word
* - `html` If true, HTML tags would be handled correctly
*
Expand All @@ -438,8 +478,11 @@ public static function stripLinks($text) {
*/
public static function truncate($text, $length = 100, $options = array()) {
$default = array(
'ending' => '...', 'exact' => true, 'html' => false
'ellipsis' => '...', 'exact' => true, 'html' => false
);
if (isset($options['ending'])) {
$default['ellipsis'] = $options['ending'];
}
$options = array_merge($default, $options);
extract($options);

Expand All @@ -451,7 +494,7 @@ class_exists('Multibyte');
if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
$totalLength = mb_strlen(strip_tags($ending));
$totalLength = mb_strlen(strip_tags($ellipsis));
$openTags = array();
$truncate = '';

Expand Down Expand Up @@ -498,7 +541,7 @@ class_exists('Multibyte');
if (mb_strlen($text) <= $length) {
return $text;
} else {
$truncate = mb_substr($text, 0, $length - mb_strlen($ending));
$truncate = mb_substr($text, 0, $length - mb_strlen($ellipsis));
}
}
if (!$exact) {
Expand Down Expand Up @@ -530,7 +573,7 @@ class_exists('Multibyte');
}
$truncate = mb_substr($truncate, 0, $spacepos);
}
$truncate .= $ending;
$truncate .= $ellipsis;

if ($html) {
foreach ($openTags as $tag) {
Expand All @@ -548,23 +591,23 @@ class_exists('Multibyte');
* @param string $text String to search the phrase in
* @param string $phrase Phrase that will be searched for
* @param integer $radius The amount of characters that will be returned on each side of the founded phrase
* @param string $ending Ending that will be appended
* @param string $ellipsis Ending that will be appended
* @return string Modified string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt
*/
public static function excerpt($text, $phrase, $radius = 100, $ending = '...') {
public static function excerpt($text, $phrase, $radius = 100, $ellipsis = '...') {
if (empty($text) || empty($phrase)) {
return self::truncate($text, $radius * 2, array('ending' => $ending));
return self::truncate($text, $radius * 2, array('ellipsis' => $ellipsis));
}

$append = $prepend = $ending;
$append = $prepend = $ellipsis;

$phraseLen = mb_strlen($phrase);
$textLen = mb_strlen($text);

$pos = mb_strpos(mb_strtolower($text), mb_strtolower($phrase));
if ($pos === false) {
return mb_substr($text, 0, $radius) . $ending;
return mb_substr($text, 0, $radius) . $ellipsis;
}

$startPos = $pos - $radius;
Expand Down

0 comments on commit 9e96c47

Please sign in to comment.