Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #387 from shama/patch-text-truncate

Prevent TextHelper::truncate() from breaking HTML
  • Loading branch information...
commit cf5bddcb55cb3655fd4e9390b0dca3f22e6e94a0 2 parents fc0c3c9 + 4dfb842
@markstory markstory authored
View
47 Cake/Test/Case/View/Helper/TextHelperTest.php
@@ -60,7 +60,7 @@ public function testTruncate() {
$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>';
$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';
+ $text8 = 'Vive la R' . chr(195) . chr(169) . 'publique de France';
$text9 = 'НОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыь';
$this->assertSame($this->Text->truncate($text1, 15), 'The quick br...');
@@ -86,6 +86,51 @@ public function testTruncate() {
$this->assertSame($this->Text->truncate($text7, 15), 'El moño está...');
$this->assertSame($this->Text->truncate($text8, 15), 'Vive la R'.chr(195).chr(169).'pu...');
$this->assertSame($this->Text->truncate($text9, 10), 'НОПРСТУ...');
+
+ $text = '<p><span style="font-size: medium;"><a>Iamatestwithnospacesandhtml</a></span></p>';
+ $result = $this->Text->truncate($text, 10, array(
+ 'ending' => '...',
+ 'exact' => false,
+ 'html' => true
+ ));
+ $expected = '<p><span style="font-size: medium;"><a>...</a></span></p>';
+ $this->assertEquals($expected, $result);
+
+ $text = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
+Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
+este artículo de El País.</span></p>
+<p><span style="font-size: medium;"><span style="font-size:
+large;">Por qué Steve era distinto.</span></span></p>
+<p><span style="font-size: medium;"><a href="http://www.elpais.com/
+articulo/primer/plano/Steve/era/distinto/elpepueconeg/
+20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
+Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
+<p><span style="font-size: medium;">Ya se ha publicado la biografía de
+Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
+Isaacson</strong>", aquí os dejamos la dirección de amazon donde
+podeís adquirirla.</span></p>
+<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' => '... ',
+ 'exact' => false,
+ 'html' => true
+ ));
+ $expected = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
+Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
+este artículo de El País.</span></p>
+<p><span style="font-size: medium;"><span style="font-size:
+large;">Por qué Steve era distinto.</span></span></p>
+<p><span style="font-size: medium;"><a href="http://www.elpais.com/
+articulo/primer/plano/Steve/era/distinto/elpepueconeg/
+20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
+Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
+<p><span style="font-size: medium;">Ya se ha publicado la biografía de
+Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
+Isaacson</strong>", aquí os dejamos la dirección de amazon donde
+podeís adquirirla.</span></p>
+<p><span style="font-size: medium;"><a>... </a></span></p>';
+ $this->assertEquals($expected, $result);
}
/**
View
24 Cake/View/Helper/TextHelper.php
@@ -275,20 +275,32 @@ class_exists('Multibyte');
}
if (!$exact) {
$spacepos = mb_strrpos($truncate, ' ');
- if (isset($spacepos)) {
- if ($html) {
- $bits = mb_substr($truncate, $spacepos);
- preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
- if (!empty($droppedTags)) {
+ if ($html) {
+ $truncateCheck = mb_substr($truncate, 0, $spacepos);
+ $lastOpenTag = mb_strrpos($truncateCheck, '<');
+ $lastCloseTag = mb_strrpos($truncateCheck, '>');
+ if ($lastOpenTag > $lastCloseTag) {
+ preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
+ $lastTag = array_pop($lastTagMatches[0]);
+ $spacepos = mb_strrpos($truncate, $lastTag) + mb_strlen($lastTag);
+ }
+ $bits = mb_substr($truncate, $spacepos);
+ preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
+ if (!empty($droppedTags)) {
+ if (!empty($openTags)) {
foreach ($droppedTags as $closingTag) {
if (!in_array($closingTag[1], $openTags)) {
array_unshift($openTags, $closingTag[1]);
}
}
+ } else {
+ foreach ($droppedTags as $closingTag) {
+ array_push($openTags, $closingTag[1]);
+ }
}
}
- $truncate = mb_substr($truncate, 0, $spacepos);
}
+ $truncate = mb_substr($truncate, 0, $spacepos);
}
$truncate .= $ending;
Please sign in to comment.
Something went wrong with that request. Please try again.