From c78b9e470d2012abd8615be02b2dbfec32a1d895 Mon Sep 17 00:00:00 2001 From: sam002 Date: Mon, 27 Feb 2017 15:16:31 +0300 Subject: [PATCH] Fixes #13657: Fixed `yii\helpers\StringHelper::truncateHtml()` skip extra tags at the end --- framework/CHANGELOG.md | 1 + framework/helpers/BaseStringHelper.php | 19 ++++++++++++++----- tests/framework/helpers/StringHelperTest.php | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index c4807313d9..971f451269 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.12 under development -------------------------- +- Bug #13657: Fixed `yii\helpers\StringHelper::truncateHtml()` skip extra tags at the end (sam002) - Bug #7946 Fixed a bug when the `form` attribute was not propagated to the hidden input of the checkbox (Kolyunya) - Bug #13087: Fixed getting active validators for safe attribute (developeruz) - Bug #13571: Fix `yii\db\mssql\QueryBuilder::checkIntegrity` for all tables (boboldehampsink) diff --git a/framework/helpers/BaseStringHelper.php b/framework/helpers/BaseStringHelper.php index e06da6ed6e..3dca93158a 100644 --- a/framework/helpers/BaseStringHelper.php +++ b/framework/helpers/BaseStringHelper.php @@ -160,10 +160,8 @@ class BaseStringHelper $truncated = []; foreach ($tokens as $token) { if ($token instanceof \HTMLPurifier_Token_Start) { //Tag begins - if ($totalCount < $count) { - $openTokens[$token->name] = isset($openTokens[$token->name]) ? $openTokens[$token->name] + 1 : 1; - $truncated[] = $token; - } + $openTokens[$token->name] = isset($openTokens[$token->name]) ? $openTokens[$token->name] + 1 : 1; + $truncated[] = $token; } elseif ($token instanceof \HTMLPurifier_Token_Text && $totalCount <= $count) { //Text if (false === $encoding) { preg_match('/^(\s*)/um', $token->data, $prefixSpace) ?: $prefixSpace = ['','']; @@ -178,12 +176,23 @@ class BaseStringHelper } elseif ($token instanceof \HTMLPurifier_Token_End) { //Tag ends if (!empty($openTokens[$token->name])) { $openTokens[$token->name]--; + if ($openTokens[$token->name] <= 0) { + unset($openTokens[$token->name]); + } $truncated[] = $token; } } elseif ($token instanceof \HTMLPurifier_Token_Empty) { //Self contained tags, i.e. etc. $truncated[] = $token; } - if (0 === $openTokens && $totalCount >= $count) { + if ($totalCount >= $count) { + if (0 < count($openTokens)) { + foreach (array_reverse($openTokens) as $name => $countTag) { + while ($countTag > 0) { + $truncated[] = new \HTMLPurifier_Token_End($name); + $countTag--; + } + } + } break; } } diff --git a/tests/framework/helpers/StringHelperTest.php b/tests/framework/helpers/StringHelperTest.php index 1e505871b1..27a060d207 100644 --- a/tests/framework/helpers/StringHelperTest.php +++ b/tests/framework/helpers/StringHelperTest.php @@ -117,6 +117,8 @@ class StringHelperTest extends TestCase $this->assertEquals('This is a test for...', StringHelper::truncate('This is a test for a sentance', 18, '...', null, true)); $this->assertEquals('

This is a test

...', StringHelper::truncate('

This is a test

', 22, '...', null, true)); + + $this->assertEquals('
...', StringHelper::truncate('

', 8, '...', null, true)); } public function testTruncateWords()