From c5f8d7df20cfaea7e2189795e188bb78a51fc4d1 Mon Sep 17 00:00:00 2001 From: Anton Date: Sat, 7 Aug 2021 17:54:10 +0300 Subject: [PATCH] Fix #18807: Fix replacing source whitespaces and optimize code of `yii\helpers\BaseStringHelper::mb_ucwords()` --- framework/CHANGELOG.md | 1 + framework/helpers/BaseStringHelper.php | 20 ++++++++++++++------ tests/framework/helpers/StringHelperTest.php | 5 +++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 81d11b4d04..a1b8cadc88 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -24,6 +24,7 @@ Yii Framework 2 Change Log - Enh #18274: Added `profilingAware` option to `yii\log\Logger` to prevent breaking the profiling block messages pair when flushing them (bizley) - Enh #18789: Added JSONP support in `yii\web\JsonParser::parse()` (WinterSilence) - Bug #18274: Fix `yii\log\Logger` to calculate profile timings no matter the value of the flush interval (bizley) +- Bug #18807: Fix replacing source whitespaces and optimize code of `yii\helpers\BaseStringHelper::mb_ucwords()` (WinterSilence) 2.0.42.1 May 06, 2021 diff --git a/framework/helpers/BaseStringHelper.php b/framework/helpers/BaseStringHelper.php index 48a12e6422..8ab4db035d 100644 --- a/framework/helpers/BaseStringHelper.php +++ b/framework/helpers/BaseStringHelper.php @@ -457,17 +457,25 @@ class BaseStringHelper * @param string $string the string to be proceeded * @param string $encoding Optional, defaults to "UTF-8" * @return string - * @see https://secure.php.net/manual/en/function.ucwords.php + * @see https://www.php.net/manual/en/function.ucwords * @since 2.0.16 */ public static function mb_ucwords($string, $encoding = 'UTF-8') { - $words = preg_split("/\s/u", $string, -1, PREG_SPLIT_NO_EMPTY); + $string = (string) $string; + if (empty($string)) { + return $string; + } - $titelized = array_map(function ($word) use ($encoding) { - return static::mb_ucfirst($word, $encoding); - }, $words); + $parts = preg_split('/(\s+[^\w]+\s+|^[^\w]+\s+|\s+)/u', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + $ucfirstEven = !trim(mb_substr($parts[0], -1, 1, $encoding)); + foreach ($parts as $key => $value) { + $isEven = (bool)($key % 2); + if ($ucfirstEven === $isEven) { + $parts[$key] = static::mb_ucfirst($value, $encoding); + } + } - return implode(' ', $titelized); + return implode('', $parts); } } diff --git a/tests/framework/helpers/StringHelperTest.php b/tests/framework/helpers/StringHelperTest.php index 90dc42e08e..faac9bf6f9 100644 --- a/tests/framework/helpers/StringHelperTest.php +++ b/tests/framework/helpers/StringHelperTest.php @@ -429,8 +429,13 @@ class StringHelperTest extends TestCase return [ ['foo', 'Foo'], ['foo bar', 'Foo Bar'], + ['!foo bar-baz', '!foo Bar-baz'], + [' foo BAR', ' Foo BAR'], + [' ! foo BAR', ' ! Foo BAR'], + ["\tfoo\nbar baz", "\tFoo\nBar Baz"], ['👍🏻 foo bar', '👍🏻 Foo Bar'], ['', ''], + ['0', '0'], [null, ''], ['здесь我 multibyte我 строка', 'Здесь我 Multibyte我 Строка'], ];