Make String::wrap() unicode aware. Solves #3981.

This commit is contained in:
Renan Gonçalves 2013-10-01 19:11:44 +02:00
parent 727d02df14
commit a73e926467
2 changed files with 123 additions and 3 deletions

View file

@ -314,6 +314,67 @@ class StringTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
/**
* test that wordWrap() works the same as built-in wordwrap function
*
* @dataProvider wordWrapProvider
* @return void
*/
public function testWordWrap($text, $width, $break = "\n", $cut = false) {
$result = String::wordWrap($text, $width, $break, $cut);
$expected = wordwrap($text, $width, $break, $cut);
$this->assertTextEquals($expected, $result, 'Text not wrapped same as built-in function.');
}
/**
* data provider for testWordWrap method
*
* @return array
*/
public function wordWrapProvider() {
return array(
array(
'The quick brown fox jumped over the lazy dog.',
33
),
array(
'A very long woooooooooooord.',
8
),
array(
'A very long woooooooooooord. Right.',
8
),
);
}
/**
* test that wordWrap() properly handle unicode strings.
*
* @return void
*/
public function testWordWrapUnicodeAware() {
$text = 'Но вим омниюм факёльиси элыктрам, мюнырэ лэгыры векж ыт. Выльёт квюандо нюмквуам ты кюм. Зыд эю рыбюм.';
$result = String::wordWrap($text, 33, "\n", true);
$expected = <<<TEXT
Но вим омниюм факёльиси элыктрам,
мюнырэ лэгыры векж ыт. Выльёт квю
андо нюмквуам ты кюм. Зыд эю рыбю
м.
TEXT;
$this->assertTextEquals($expected, $result, 'Text not wrapped.');
$text = 'Но вим омниюм факёльиси элыктрам, мюнырэ лэгыры векж ыт. Выльёт квюандо нюмквуам ты кюм. Зыд эю рыбюм.';
$result = String::wordWrap($text, 33, "\n");
$expected = <<<TEXT
Но вим омниюм факёльиси элыктрам,
мюнырэ лэгыры векж ыт. Выльёт
квюандо нюмквуам ты кюм. Зыд эю
рыбюм.
TEXT;
$this->assertTextEquals($expected, $result, 'Text not wrapped.');
}
/**
* test wrap method.
*
@ -337,6 +398,16 @@ TEXT;
'the song that never' . "\n" .
' ends.';
$this->assertTextEquals($expected, $result, 'Text not wrapped.');
$text = 'Но вим омниюм факёльиси элыктрам, мюнырэ лэгыры векж ыт. Выльёт квюандо нюмквуам ты кюм. Зыд эю рыбюм.';
$result = String::wrap($text, 33);
$expected = <<<TEXT
Но вим омниюм факёльиси элыктрам,
мюнырэ лэгыры векж ыт. Выльёт
квюандо нюмквуам ты кюм. Зыд эю
рыбюм.
TEXT;
$this->assertTextEquals($expected, $result, 'Text not wrapped.');
}
/**

View file

@ -319,12 +319,12 @@ class String {
*
* ### Options
*
* - `width` The width to wrap to. Defaults to 72
* - `width` The width to wrap to. Defaults to 72.
* - `wordWrap` Only wrap on words breaks (spaces) Defaults to true.
* - `indent` String to indent with. Defaults to null.
* - `indentAt` 0 based index to start indenting at. Defaults to 0.
*
* @param string $text Text the text to format.
* @param string $text The text to format.
* @param array|integer $options Array of options to use, or an integer to wrap the text to.
* @return string Formatted text.
*/
@ -334,7 +334,7 @@ class String {
}
$options += array('width' => 72, 'wordWrap' => true, 'indent' => null, 'indentAt' => 0);
if ($options['wordWrap']) {
$wrapped = wordwrap($text, $options['width'], "\n");
$wrapped = self::wordWrap($text, $options['width'], "\n");
} else {
$wrapped = trim(chunk_split($text, $options['width'] - 1, "\n"));
}
@ -348,6 +348,55 @@ class String {
return $wrapped;
}
/**
* Unicode aware version of wordwrap.
*
* @param string $text The text to format.
* @param integer $width The width to wrap to. Defaults to 72.
* @param string $break The line is broken using the optional break parameter. Defaults to '\n'.
* @param boolean $cut If the cut is set to true, the string is always wrapped at the specified width.
* @return string Formatted text.
*/
public static function wordWrap($text, $width = 72, $break = "\n", $cut = false) {
if ($cut) {
$parts = array();
while (mb_strlen($text) > 0) {
$part = mb_substr($text, 0, $width);
$parts[] = trim($part);
$text = trim(mb_substr($text, mb_strlen($part)));
}
return implode($break, $parts);
}
$parts = array();
while (mb_strlen($text) > 0) {
if ($width >= mb_strlen($text)) {
$parts[] = trim($text);
break;
}
$part = mb_substr($text, 0, $width);
$nextChar = mb_substr($text, $width, 1);
if ($nextChar !== ' ') {
$breakAt = mb_strrpos($part, ' ');
if ($breakAt === false) {
$breakAt = mb_strpos($text, ' ', $width);
}
if ($breakAt === false) {
$parts[] = trim($text);
break;
}
$part = mb_substr($text, 0, $breakAt);
}
$part = trim($part);
$parts[] = $part;
$text = trim(mb_substr($text, mb_strlen($part)));
}
return implode($break, $parts);
}
/**
* Highlights a given phrase in a text. You can specify any expression in highlighter that
* may include the \1 expression to include the $phrase found.