diff --git a/cake/libs/view/helpers/text.php b/cake/libs/view/helpers/text.php index 342ffd58e..34e7b66de 100644 --- a/cake/libs/view/helpers/text.php +++ b/cake/libs/view/helpers/text.php @@ -35,6 +35,10 @@ if (!class_exists('HtmlHelper')) { App::import('Helper', 'Html'); } +if (!class_exists('Multibyte')) { + App::import('Core', 'Multibyte'); +} + /** * Text helper library. * @@ -167,27 +171,27 @@ class TextHelper extends AppHelper { extract($ending); } if ($considerHtml) { - if (strlen(preg_replace('/<.*?>/', '', $text)) <= $length) { + if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) { return $text; } - $totalLength = strlen($ending); + $totalLength = mb_strlen($ending); $openTags = array(); $truncate = ''; preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER); foreach ($tags as $tag) { - if (preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) { - - } else if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) { - array_unshift($openTags, $tag[2]); - } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) { - $pos = array_search($closeTag[1], $openTags); - if ($pos !== false) { - array_splice($openTags, $pos, 1); + if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) { + if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) { + array_unshift($openTags, $tag[2]); + } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) { + $pos = array_search($closeTag[1], $openTags); + if ($pos !== false) { + array_splice($openTags, $pos, 1); + } } } $truncate .= $tag[1]; - $contentLength = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3])); + $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3])); if ($contentLength + $totalLength > $length) { $left = $length - $totalLength; $entitiesLength = 0; @@ -195,14 +199,14 @@ class TextHelper extends AppHelper { foreach ($entities[0] as $entity) { if ($entity[1] + 1 - $entitiesLength <= $left) { $left--; - $entitiesLength += strlen($entity[0]); + $entitiesLength += mb_strlen($entity[0]); } else { break; } } } - $truncate .= substr($tag[3], 0 , $left + $entitiesLength); + $truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength); break; } else { $truncate .= $tag[3]; @@ -214,17 +218,17 @@ class TextHelper extends AppHelper { } } else { - if (strlen($text) <= $length) { + if (mb_strlen($text) <= $length) { return $text; } else { - $truncate = substr($text, 0, $length - strlen($ending)); + $truncate = mb_substr($text, 0, $length - strlen($ending)); } } if (!$exact) { - $spacepos = strrpos($truncate, ' '); + $spacepos = mb_strrpos($truncate, ' '); if (isset($spacepos)) { if ($considerHtml) { - $bits = substr($truncate, $spacepos); + $bits = mb_substr($truncate, $spacepos); preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER); if (!empty($droppedTags)) { foreach ($droppedTags as $closingTag) { @@ -234,7 +238,7 @@ class TextHelper extends AppHelper { } } } - $truncate = substr($truncate, 0, $spacepos); + $truncate = mb_substr($truncate, 0, $spacepos); } } diff --git a/cake/tests/cases/libs/view/helpers/text.test.php b/cake/tests/cases/libs/view/helpers/text.test.php index 5b558f661..f83e079df 100644 --- a/cake/tests/cases/libs/view/helpers/text.test.php +++ b/cake/tests/cases/libs/view/helpers/text.test.php @@ -35,14 +35,14 @@ App::import('Helper', 'Text'); class TextTest extends CakeTestCase { /** * helper property - * + * * @var mixed null * @access public */ var $helper = null; /** * setUp method - * + * * @access public * @return void */ @@ -51,7 +51,7 @@ class TextTest extends CakeTestCase { } /** * testTruncate method - * + * * @access public * @return void */ @@ -65,7 +65,9 @@ class TextTest extends CakeTestCase { $text3 = '<b>© 2005-2007, Cake Software Foundation, Inc.</b><br />written by Alexander Wegener'; $text4 = '<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 />Great, or?'; $text5 = '0<b>1<i>2<span class="myclass">3</span>4<u>5</u>6</i>7</b>8<b>9</b>0'; - $text6 = "<p><strong>Extra dates have been announced for this year's tour.</strong></p><p>Tickets for the new shows in</p>"; + $text6 = '<p><strong>Extra dates have been announced for this year\'s tour.</strong></p><p>Tickets for the new shows in</p>'; + $text7 = 'El moño está en el lugar correcto. Eso fue lo que dijo la niña, ¿habrá dicho la verdad?'; + $text8 = 'Vive la R'.chr(195).chr(169).'publique de France'; $this->assertIdentical($this->Text->{$m}($text1, 15), 'The quick br...'); $this->assertIdentical($this->Text->{$m}($text1, 15, '...', false), 'The quick...'); @@ -87,6 +89,9 @@ class TextTest extends CakeTestCase { $this->assertIdentical($this->Text->{$m}($text5, 6, '', true, true), '0<b>1<i>2<span class="myclass">3</span>4<u>5</u></i></b>'); $this->assertIdentical($this->Text->{$m}($text5, 20, '', true, true), $text5); $this->assertIdentical($this->Text->{$m}($text6, 57, '...', false, true), "<p><strong>Extra dates have been announced for this year's...</strong></p>"); + $this->assertIdentical($this->Text->{$m}($text7, 255), $text7); + $this->assertIdentical($this->Text->{$m}($text7, 15), 'El moño está...'); + $this->assertIdentical($this->Text->{$m}($text8, 15), 'Vive la R'.chr(195).chr(169).'pu...'); if ($this->method == 'truncate') { $this->method = 'trim'; @@ -95,7 +100,7 @@ class TextTest extends CakeTestCase { } /** * testHighlight method - * + * * @access public * @return void */ @@ -119,7 +124,7 @@ class TextTest extends CakeTestCase { } /** * testHighlightConsiderHtml method - * + * * @access public * @return void */ @@ -134,7 +139,7 @@ class TextTest extends CakeTestCase { } /** * testStripLinks method - * + * * @access public * @return void */ @@ -161,7 +166,7 @@ class TextTest extends CakeTestCase { } /** * testAutoLink method - * + * * @access public * @return void */ @@ -178,7 +183,7 @@ class TextTest extends CakeTestCase { } /** * testAutoLinkUrls method - * + * * @access public * @return void */ @@ -216,7 +221,7 @@ class TextTest extends CakeTestCase { } /** * testAutoLinkEmails method - * + * * @access public * @return void */ @@ -238,7 +243,7 @@ class TextTest extends CakeTestCase { } /** * testHighlightCaseInsensitivity method - * + * * @access public * @return void */ @@ -254,7 +259,7 @@ class TextTest extends CakeTestCase { } /** * testExcerpt method - * + * * @access public * @return void */ @@ -283,7 +288,7 @@ class TextTest extends CakeTestCase { } /** * testExcerptCaseInsensitivity method - * + * * @access public * @return void */ @@ -300,7 +305,7 @@ class TextTest extends CakeTestCase { } /** * testListGeneration method - * + * * @access public * @return void */ @@ -313,7 +318,7 @@ class TextTest extends CakeTestCase { } /** * tearDown method - * + * * @access public * @return void */