diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc index 80cc52cb81..310c9cd858 100644 --- a/core/includes/theme.maintenance.inc +++ b/core/includes/theme.maintenance.inc @@ -5,7 +5,6 @@ * Theming for maintenance pages. */ -use Drupal\Component\Utility\Unicode; use Drupal\Core\Site\Settings; /** @@ -29,7 +28,6 @@ function _drupal_maintenance_theme() { require_once __DIR__ . '/file.inc'; require_once __DIR__ . '/module.inc'; require_once __DIR__ . '/database.inc'; - Unicode::check(); // Install and update pages are treated differently to prevent theming overrides. if (defined('MAINTENANCE_MODE') && (MAINTENANCE_MODE == 'install' || MAINTENANCE_MODE == 'update')) { diff --git a/core/lib/Drupal/Component/Utility/Unicode.php b/core/lib/Drupal/Component/Utility/Unicode.php index e136a8971b..7cf2351603 100644 --- a/core/lib/Drupal/Component/Utility/Unicode.php +++ b/core/lib/Drupal/Component/Utility/Unicode.php @@ -87,13 +87,6 @@ class Unicode { */ const STATUS_ERROR = -1; - /** - * Holds the multibyte capabilities of the current environment. - * - * @var int - */ - protected static $status = 0; - /** * Gets the current status of unicode/multibyte support on this environment. * @@ -107,7 +100,13 @@ class Unicode { * An error occurred. No unicode support. */ public static function getStatus() { - return static::$status; + switch (static::check()) { + case 'mb_strlen': + return Unicode::STATUS_SINGLEBYTE; + case '': + return Unicode::STATUS_MULTIBYTE; + } + return Unicode::STATUS_ERROR; } /** @@ -123,12 +122,16 @@ public static function getStatus() { * * @param int $status * The new status of multibyte support. + * + * @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In + * Drupal 9 there will be no way to set the status and in Drupal 8 this + * ability has been removed because mb_*() functions are supplied using + * Symfony's polyfill. + * + * @see https://www.drupal.org/node/2850048 */ public static function setStatus($status) { - if (!in_array($status, [static::STATUS_SINGLEBYTE, static::STATUS_MULTIBYTE, static::STATUS_ERROR])) { - throw new \InvalidArgumentException('Invalid status value for unicode support.'); - } - static::$status = $status; + @trigger_error('\Drupal\Component\Utility\Unicode::setStatus() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In Drupal 9 there will be no way to set the status and in Drupal 8 this ability has been removed because mb_*() functions are supplied using Symfony\'s polyfill. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); } /** @@ -143,38 +146,33 @@ public static function setStatus($status) { * Otherwise, an empty string. */ public static function check() { + // Set appropriate configuration. + mb_internal_encoding('utf-8'); + mb_language('uni'); + // Check for mbstring extension. - if (!function_exists('mb_strlen')) { - static::$status = static::STATUS_SINGLEBYTE; + if (!extension_loaded('mbstring')) { return 'mb_strlen'; } // Check mbstring configuration. if (ini_get('mbstring.func_overload') != 0) { - static::$status = static::STATUS_ERROR; return 'mbstring.func_overload'; } if (ini_get('mbstring.encoding_translation') != 0) { - static::$status = static::STATUS_ERROR; return 'mbstring.encoding_translation'; } // mbstring.http_input and mbstring.http_output are deprecated and empty by // default in PHP 5.6. if (version_compare(PHP_VERSION, '5.6.0') == -1) { if (ini_get('mbstring.http_input') != 'pass') { - static::$status = static::STATUS_ERROR; return 'mbstring.http_input'; } if (ini_get('mbstring.http_output') != 'pass') { - static::$status = static::STATUS_ERROR; return 'mbstring.http_output'; } } - // Set appropriate configuration. - mb_internal_encoding('utf-8'); - mb_language('uni'); - static::$status = static::STATUS_MULTIBYTE; return ''; } @@ -224,17 +222,7 @@ public static function encodingFromBOM($data) { * Converted data or FALSE. */ public static function convertToUtf8($data, $encoding) { - if (function_exists('iconv')) { - return @iconv($encoding, 'utf-8', $data); - } - elseif (function_exists('mb_convert_encoding')) { - return @mb_convert_encoding($data, 'utf-8', $encoding); - } - elseif (function_exists('recode_string')) { - return @recode_string($encoding . '..utf-8', $data); - } - // Cannot convert. - return FALSE; + return @iconv($encoding, 'utf-8', $data); } /** @@ -281,15 +269,15 @@ public static function truncateBytes($string, $len) { * * @return int * The length of the string. + * + * @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use + * mb_strlen() instead. + * + * @see https://www.drupal.org/node/2850048 */ public static function strlen($text) { - if (static::getStatus() == static::STATUS_MULTIBYTE) { - return mb_strlen($text); - } - else { - // Do not count UTF-8 continuation bytes. - return strlen(preg_replace("/[\x80-\xBF]/", '', $text)); - } + @trigger_error('\Drupal\Component\Utility\Unicode::strlen() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strlen() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); + return mb_strlen($text); } /** @@ -300,18 +288,15 @@ public static function strlen($text) { * * @return string * The string in uppercase. + * + * @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use + * mb_strtoupper() instead. + * + * @see https://www.drupal.org/node/2850048 */ public static function strtoupper($text) { - if (static::getStatus() == static::STATUS_MULTIBYTE) { - return mb_strtoupper($text); - } - else { - // Use C-locale for ASCII-only uppercase. - $text = strtoupper($text); - // Case flip Latin-1 accented letters. - $text = preg_replace_callback('/\xC3[\xA0-\xB6\xB8-\xBE]/', '\Drupal\Component\Utility\Unicode::caseFlip', $text); - return $text; - } + @trigger_error('\Drupal\Component\Utility\Unicode::strtoupper() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtoupper() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); + return mb_strtoupper($text); } /** @@ -322,18 +307,15 @@ public static function strtoupper($text) { * * @return string * The string in lowercase. + * + * @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use + * mb_strtolower() instead. + * + * @see https://www.drupal.org/node/2850048 */ public static function strtolower($text) { - if (static::getStatus() == static::STATUS_MULTIBYTE) { - return mb_strtolower($text); - } - else { - // Use C-locale for ASCII-only lowercase. - $text = strtolower($text); - // Case flip Latin-1 accented letters. - $text = preg_replace_callback('/\xC3[\x80-\x96\x98-\x9E]/', '\Drupal\Component\Utility\Unicode::caseFlip', $text); - return $text; - } + @trigger_error('\Drupal\Component\Utility\Unicode::strtolower() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtolower() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); + return mb_strtolower($text); } /** @@ -346,7 +328,7 @@ public static function strtolower($text) { * The string with the first character as uppercase. */ public static function ucfirst($text) { - return static::strtoupper(static::substr($text, 0, 1)) . static::substr($text, 1); + return mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1); } /** @@ -362,7 +344,7 @@ public static function ucfirst($text) { */ public static function lcfirst($text) { // Note: no mbstring equivalent! - return static::strtolower(static::substr($text, 0, 1)) . static::substr($text, 1); + return mb_strtolower(mb_substr($text, 0, 1)) . mb_substr($text, 1); } /** @@ -379,7 +361,7 @@ public static function lcfirst($text) { public static function ucwords($text) { $regex = '/(^|[' . static::PREG_CLASS_WORD_BOUNDARY . '])([^' . static::PREG_CLASS_WORD_BOUNDARY . '])/u'; return preg_replace_callback($regex, function (array $matches) { - return $matches[1] . Unicode::strtoupper($matches[2]); + return $matches[1] . mb_strtoupper($matches[2]); }, $text); } @@ -399,92 +381,15 @@ public static function ucwords($text) { * * @return string * The shortened string. + * + * @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use + * mb_substr() instead. + * + * @see https://www.drupal.org/node/2850048 */ public static function substr($text, $start, $length = NULL) { - if (static::getStatus() == static::STATUS_MULTIBYTE) { - return $length === NULL ? mb_substr($text, $start) : mb_substr($text, $start, $length); - } - else { - $strlen = strlen($text); - // Find the starting byte offset. - $bytes = 0; - if ($start > 0) { - // Count all the characters except continuation bytes from the start - // until we have found $start characters or the end of the string. - $bytes = -1; $chars = -1; - while ($bytes < $strlen - 1 && $chars < $start) { - $bytes++; - $c = ord($text[$bytes]); - if ($c < 0x80 || $c >= 0xC0) { - $chars++; - } - } - } - elseif ($start < 0) { - // Count all the characters except continuation bytes from the end - // until we have found abs($start) characters. - $start = abs($start); - $bytes = $strlen; $chars = 0; - while ($bytes > 0 && $chars < $start) { - $bytes--; - $c = ord($text[$bytes]); - if ($c < 0x80 || $c >= 0xC0) { - $chars++; - } - } - } - $istart = $bytes; - - // Find the ending byte offset. - if ($length === NULL) { - $iend = $strlen; - } - elseif ($length > 0) { - // Count all the characters except continuation bytes from the starting - // index until we have found $length characters or reached the end of - // the string, then backtrace one byte. - $iend = $istart - 1; - $chars = -1; - $last_real = FALSE; - while ($iend < $strlen - 1 && $chars < $length) { - $iend++; - $c = ord($text[$iend]); - $last_real = FALSE; - if ($c < 0x80 || $c >= 0xC0) { - $chars++; - $last_real = TRUE; - } - } - // Backtrace one byte if the last character we found was a real - // character and we don't need it. - if ($last_real && $chars >= $length) { - $iend--; - } - } - elseif ($length < 0) { - // Count all the characters except continuation bytes from the end - // until we have found abs($start) characters, then backtrace one byte. - $length = abs($length); - $iend = $strlen; $chars = 0; - while ($iend > 0 && $chars < $length) { - $iend--; - $c = ord($text[$iend]); - if ($c < 0x80 || $c >= 0xC0) { - $chars++; - } - } - // Backtrace one byte if we are not at the beginning of the string. - if ($iend > 0) { - $iend--; - } - } - else { - // $length == 0, return an empty string. - return ''; - } - - return substr($text, $istart, max(0, $iend - $istart + 1)); - } + @trigger_error('\Drupal\Component\Utility\Unicode::substr() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_substr() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); + return mb_substr($text, $start, $length); } /** @@ -526,15 +431,15 @@ public static function truncate($string, $max_length, $wordsafe = FALSE, $add_el $max_length = max($max_length, 0); $min_wordsafe_length = max($min_wordsafe_length, 0); - if (static::strlen($string) <= $max_length) { + if (mb_strlen($string) <= $max_length) { // No truncation needed, so don't add ellipsis, just return. return $string; } if ($add_ellipsis) { // Truncate ellipsis in case $max_length is small. - $ellipsis = static::substr('…', 0, $max_length); - $max_length -= static::strlen($ellipsis); + $ellipsis = mb_substr('…', 0, $max_length); + $max_length -= mb_strlen($ellipsis); $max_length = max($max_length, 0); } @@ -553,11 +458,11 @@ public static function truncate($string, $max_length, $wordsafe = FALSE, $add_el $string = $matches[1]; } else { - $string = static::substr($string, 0, $max_length); + $string = mb_substr($string, 0, $max_length); } } else { - $string = static::substr($string, 0, $max_length); + $string = mb_substr($string, 0, $max_length); } if ($add_ellipsis) { @@ -583,7 +488,7 @@ public static function truncate($string, $max_length, $wordsafe = FALSE, $add_el * $str2, and 0 if they are equal. */ public static function strcasecmp($str1, $str2) { - return strcmp(static::strtoupper($str1), static::strtoupper($str2)); + return strcmp(mb_strtoupper($str1), mb_strtoupper($str2)); } /** @@ -715,18 +620,15 @@ public static function validateUtf8($text) { * The position where $needle occurs in $haystack, always relative to the * beginning (independent of $offset), or FALSE if not found. Note that * a return value of 0 is not the same as FALSE. + * + * @deprecated in Drupal 8.6.0, will be removed before Drupal 9.0.0. Use + * mb_strpos() instead. + * + * @see https://www.drupal.org/node/2850048 */ public static function strpos($haystack, $needle, $offset = 0) { - if (static::getStatus() == static::STATUS_MULTIBYTE) { - return mb_strpos($haystack, $needle, $offset); - } - else { - // Remove Unicode continuation characters, to be compatible with - // Unicode::strlen() and Unicode::substr(). - $haystack = preg_replace("/[\x80-\xBF]/", '', $haystack); - $needle = preg_replace("/[\x80-\xBF]/", '', $needle); - return strpos($haystack, $needle, $offset); - } + @trigger_error('\Drupal\Component\Utility\Unicode::strpos() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strpos() instead. See https://www.drupal.org/node/2850048.', E_USER_DEPRECATED); + return mb_strpos($haystack, $needle, $offset); } } diff --git a/core/lib/Drupal/Component/Utility/composer.json b/core/lib/Drupal/Component/Utility/composer.json index 3b8b5de5b8..b89e813903 100644 --- a/core/lib/Drupal/Component/Utility/composer.json +++ b/core/lib/Drupal/Component/Utility/composer.json @@ -7,7 +7,9 @@ "require": { "php": ">=5.5.9", "paragonie/random_compat": "^1.0|^2.0", - "drupal/core-render": "^8.2" + "drupal/core-render": "^8.2", + "symfony/polyfill-iconv": "~1.0", + "symfony/polyfill-mbstring": "~1.0" }, "autoload": { "psr-4": { diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 37ed0e97a6..55f446e2b7 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -5,7 +5,6 @@ use Composer\Autoload\ClassLoader; use Drupal\Component\Assertion\Handle; use Drupal\Component\FileCache\FileCacheFactory; -use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Cache\DatabaseBackend; use Drupal\Core\Config\BootstrapConfigStorageFactory; @@ -989,8 +988,9 @@ public static function bootEnvironment($app_root = NULL) { // numbers handling. setlocale(LC_ALL, 'C'); - // Detect string handling method. - Unicode::check(); + // Set appropriate configuration for multi-byte strings. + mb_internal_encoding('utf-8'); + mb_language('uni'); // Indicate that code is operating in a test child site. if (!defined('DRUPAL_TEST_IN_CHILD_SITE')) { diff --git a/core/modules/image/src/Plugin/ImageEffect/ConvertImageEffect.php b/core/modules/image/src/Plugin/ImageEffect/ConvertImageEffect.php index 28d51792c8..cb7a067847 100644 --- a/core/modules/image/src/Plugin/ImageEffect/ConvertImageEffect.php +++ b/core/modules/image/src/Plugin/ImageEffect/ConvertImageEffect.php @@ -64,7 +64,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $extensions = \Drupal::service('image.toolkit.manager')->getDefaultToolkit()->getSupportedExtensions(); $options = array_combine( $extensions, - array_map(['\Drupal\Component\Utility\Unicode', 'strtoupper'], $extensions) + array_map('mb_strtoupper', $extensions) ); $form['extension'] = [ '#type' => 'select', diff --git a/core/modules/migrate/tests/src/Unit/process/CallbackTest.php b/core/modules/migrate/tests/src/Unit/process/CallbackTest.php index 91eb2e7603..97a2d0316e 100644 --- a/core/modules/migrate/tests/src/Unit/process/CallbackTest.php +++ b/core/modules/migrate/tests/src/Unit/process/CallbackTest.php @@ -7,6 +7,7 @@ namespace Drupal\Tests\migrate\Unit\process; +use Drupal\Component\Utility\Unicode; use Drupal\migrate\Plugin\migrate\process\Callback; /** @@ -37,9 +38,9 @@ public function testCallbackWithFunction() { * Test callback with a class method as callable. */ public function testCallbackWithClassMethod() { - $this->plugin->setCallable(['\Drupal\Component\Utility\Unicode', 'strtolower']); - $value = $this->plugin->transform('FooBar', $this->migrateExecutable, $this->row, 'destinationproperty'); - $this->assertSame('foobar', $value); + $this->plugin->setCallable([Unicode::class, 'ucfirst']); + $value = $this->plugin->transform('foobar', $this->migrateExecutable, $this->row, 'destinationproperty'); + $this->assertSame('Foobar', $value); } } diff --git a/core/modules/node/tests/src/Kernel/SummaryLengthTest.php b/core/modules/node/tests/src/Kernel/SummaryLengthTest.php index fa15c0e6ab..eecb0d0188 100644 --- a/core/modules/node/tests/src/Kernel/SummaryLengthTest.php +++ b/core/modules/node/tests/src/Kernel/SummaryLengthTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\node\Kernel; -use Drupal\Component\Utility\Unicode; use Drupal\Core\Datetime\Entity\DateFormat; use Drupal\KernelTests\KernelTestBase; use Drupal\node\Entity\Node; @@ -72,9 +71,6 @@ protected function setUp() { 'label' => 'Fallback', 'pattern' => 'Y-m-d', ])->save(); - - // Enable multibyte support. - Unicode::setStatus(Unicode::STATUS_MULTIBYTE); } /** diff --git a/core/modules/search/search.module b/core/modules/search/search.module index 5be9206bc3..3980243c92 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -846,7 +846,7 @@ function _search_find_match_with_simplify($key, $text, $boundary, $langcode = NU $new_key = Unicode::strtolower($temp); $new_key = \Drupal::service('transliteration')->removeDiacritics($new_key); if (preg_match('/' . $preceded_by_boundary . preg_quote($new_key, '/') . $followed_by_boundary . '/u', ' ' . $new_text . ' ')) { - $position = Unicode::strpos($new_text, $new_key); + $position = mb_strpos($new_text, $new_key); return Unicode::substr($text, $position, Unicode::strlen($new_key)); } diff --git a/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php b/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php index 960d1812ad..3dc731ce96 100644 --- a/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php @@ -15,56 +15,11 @@ class UnicodeTest extends TestCase { /** - * {@inheritdoc} - * - * @covers ::check - */ - protected function setUp() { - // Initialize unicode component. - Unicode::check(); - } - - /** - * Getting and settings the multibyte environment status. - * - * @dataProvider providerTestStatus - * @covers ::getStatus - * @covers ::setStatus - */ - public function testStatus($value, $expected, $invalid = FALSE) { - if ($invalid) { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - } - else { - $this->setExpectedException('InvalidArgumentException'); - } - } - Unicode::setStatus($value); - $this->assertEquals($expected, Unicode::getStatus()); - } - - /** - * Data provider for testStatus(). - * - * @see testStatus() - * - * @return array - * An array containing: - * - The status value to set. - * - The status value to expect after setting the new value. - * - (optional) Boolean indicating invalid status. Defaults to FALSE. + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::setStatus() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In Drupal 9 there will be no way to set the status and in Drupal 8 this ability has been removed because mb_*() functions are supplied using Symfony's polyfill. See https://www.drupal.org/node/2850048. */ - public function providerTestStatus() { - return [ - [Unicode::STATUS_SINGLEBYTE, Unicode::STATUS_SINGLEBYTE], - [rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE], - [rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE], - [Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE], - [rand(10, 100), Unicode::STATUS_MULTIBYTE, TRUE], - [Unicode::STATUS_ERROR, Unicode::STATUS_ERROR], - [Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE], - ]; + public function testSetStatus() { + Unicode::setStatus(Unicode::STATUS_SINGLEBYTE); } /** @@ -101,10 +56,10 @@ public function providerTestMimeHeader() { * @dataProvider providerStrtolower * @covers ::strtolower * @covers ::caseFlip + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::strtolower() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtolower() instead. See https://www.drupal.org/node/2850048. */ - public function testStrtolower($text, $expected, $multibyte = FALSE) { - $status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE; - Unicode::setStatus($status); + public function testStrtolower($text, $expected) { $this->assertEquals($expected, Unicode::strtolower($text)); } @@ -114,22 +69,14 @@ public function testStrtolower($text, $expected, $multibyte = FALSE) { * @see testStrtolower() * * @return array - * An array containing a string, its lowercase version and whether it should - * be processed as multibyte. + * An array containing a string and its lowercase version. */ public function providerStrtolower() { - $cases = [ + return [ ['tHe QUIcK bRoWn', 'the quick brown'], ['FrançAIS is ÜBER-åwesome', 'français is über-åwesome'], + ['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αβγδεζηθικλμνξοσὠ'], ]; - foreach ($cases as $case) { - // Test the same string both in multibyte and singlebyte conditions. - array_push($case, TRUE); - $cases[] = $case; - } - // Add a multibyte string. - $cases[] = ['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αβγδεζηθικλμνξοσὠ', TRUE]; - return $cases; } /** @@ -138,10 +85,10 @@ public function providerStrtolower() { * @dataProvider providerStrtoupper * @covers ::strtoupper * @covers ::caseFlip + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::strtoupper() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtoupper() instead. See https://www.drupal.org/node/2850048. */ - public function testStrtoupper($text, $expected, $multibyte = FALSE) { - $status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE; - Unicode::setStatus($status); + public function testStrtoupper($text, $expected) { $this->assertEquals($expected, Unicode::strtoupper($text)); } @@ -151,22 +98,14 @@ public function testStrtoupper($text, $expected, $multibyte = FALSE) { * @see testStrtoupper() * * @return array - * An array containing a string, its uppercase version and whether it should - * be processed as multibyte. + * An array containing a string and its uppercase version. */ public function providerStrtoupper() { - $cases = [ + return [ ['tHe QUIcK bRoWn', 'THE QUICK BROWN'], ['FrançAIS is ÜBER-åwesome', 'FRANÇAIS IS ÜBER-ÅWESOME'], + ['αβγδεζηθικλμνξοσὠ', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'], ]; - foreach ($cases as $case) { - // Test the same string both in multibyte and singlebyte conditions. - array_push($case, TRUE); - $cases[] = $case; - } - // Add a multibyte string. - $cases[] = ['αβγδεζηθικλμνξοσὠ', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE]; - return $cases; } /** @@ -204,9 +143,7 @@ public function providerUcfirst() { * @dataProvider providerLcfirst * @covers ::lcfirst */ - public function testLcfirst($text, $expected, $multibyte = FALSE) { - $status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE; - Unicode::setStatus($status); + public function testLcfirst($text, $expected) { $this->assertEquals($expected, Unicode::lcfirst($text)); } @@ -216,8 +153,7 @@ public function testLcfirst($text, $expected, $multibyte = FALSE) { * @see testLcfirst() * * @return array - * An array containing a string, its lowercase version and whether it should - * be processed as multibyte. + * An array containing a string and its lowercase version. */ public function providerLcfirst() { return [ @@ -226,7 +162,7 @@ public function providerLcfirst() { ['Über', 'über'], ['Åwesome', 'åwesome'], // Add a multibyte string. - ['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE], + ['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'], ]; } @@ -236,9 +172,7 @@ public function providerLcfirst() { * @dataProvider providerUcwords * @covers ::ucwords */ - public function testUcwords($text, $expected, $multibyte = FALSE) { - $status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE; - Unicode::setStatus($status); + public function testUcwords($text, $expected) { $this->assertEquals($expected, Unicode::ucwords($text)); } @@ -248,8 +182,7 @@ public function testUcwords($text, $expected, $multibyte = FALSE) { * @see testUcwords() * * @return array - * An array containing a string, its capitalized version and whether it should - * be processed as multibyte. + * An array containing a string and its capitalized version. */ public function providerUcwords() { return [ @@ -260,7 +193,7 @@ public function providerUcwords() { // Make sure we don't mangle extra spaces. ['frànçAIS is über-åwesome', 'FrànçAIS Is Über-Åwesome'], // Add a multibyte string. - ['σion', 'Σion', TRUE], + ['σion', 'Σion'], ]; } @@ -269,13 +202,10 @@ public function providerUcwords() { * * @dataProvider providerStrlen * @covers ::strlen + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::strlen() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strlen() instead. See https://www.drupal.org/node/2850048. */ public function testStrlen($text, $expected) { - // Run through multibyte code path. - Unicode::setStatus(Unicode::STATUS_MULTIBYTE); - $this->assertEquals($expected, Unicode::strlen($text)); - // Run through singlebyte code path. - Unicode::setStatus(Unicode::STATUS_SINGLEBYTE); $this->assertEquals($expected, Unicode::strlen($text)); } @@ -300,13 +230,10 @@ public function providerStrlen() { * * @dataProvider providerSubstr * @covers ::substr + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::substr() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_substr() instead. See https://www.drupal.org/node/2850048. */ public function testSubstr($text, $start, $length, $expected) { - // Run through multibyte code path. - Unicode::setStatus(Unicode::STATUS_MULTIBYTE); - $this->assertEquals($expected, Unicode::substr($text, $start, $length)); - // Run through singlebyte code path. - Unicode::setStatus(Unicode::STATUS_SINGLEBYTE); $this->assertEquals($expected, Unicode::substr($text, $start, $length)); } @@ -553,13 +480,10 @@ public function providerTestConvertToUtf8() { * * @dataProvider providerStrpos * @covers ::strpos + * @group legacy + * @expectedDeprecation \Drupal\Component\Utility\Unicode::strpos() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strpos() instead. See https://www.drupal.org/node/2850048. */ public function testStrpos($haystack, $needle, $offset, $expected) { - // Run through multibyte code path. - Unicode::setStatus(Unicode::STATUS_MULTIBYTE); - $this->assertEquals($expected, Unicode::strpos($haystack, $needle, $offset)); - // Run through singlebyte code path. - Unicode::setStatus(Unicode::STATUS_SINGLEBYTE); $this->assertEquals($expected, Unicode::strpos($haystack, $needle, $offset)); } diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php index 7eb6ecb70c..f46d1e8f11 100644 --- a/core/tests/bootstrap.php +++ b/core/tests/bootstrap.php @@ -169,6 +169,10 @@ function drupal_phpunit_populate_class_loader() { // @see \Drupal\Core\DrupalKernel::bootEnvironment() setlocale(LC_ALL, 'C'); +// Set appropriate configuration for multi-byte strings. +mb_internal_encoding('utf-8'); +mb_language('uni'); + // Set the default timezone. While this doesn't cause any tests to fail, PHP // complains if 'date.timezone' is not set in php.ini. The Australia/Sydney // timezone is chosen so all tests are run using an edge case scenario (UTC+10