Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -23,7 +23,7 @@ class Color {
|
|||
// Hash prefix is optional.
|
||||
$hex = ltrim($hex, '#');
|
||||
// Must be either RGB or RRGGBB.
|
||||
$length = Unicode::strlen($hex);
|
||||
$length = mb_strlen($hex);
|
||||
$valid = $valid && ($length === 3 || $length === 6);
|
||||
// Must be a valid hex value.
|
||||
$valid = $valid && ctype_xdigit($hex);
|
||||
|
@ -94,4 +94,28 @@ class Color {
|
|||
return '#' . str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the hex color length to 6 characters for comparison.
|
||||
*
|
||||
* @param string $hex
|
||||
* The hex color to normalize.
|
||||
*
|
||||
* @return string
|
||||
* The 6 character hex color.
|
||||
*/
|
||||
public static function normalizeHexLength($hex) {
|
||||
// Ignore '#' prefixes.
|
||||
$hex = ltrim($hex, '#');
|
||||
|
||||
if (strlen($hex) === 3) {
|
||||
$hex[5] = $hex[2];
|
||||
$hex[4] = $hex[2];
|
||||
$hex[3] = $hex[1];
|
||||
$hex[2] = $hex[1];
|
||||
$hex[1] = $hex[0];
|
||||
}
|
||||
|
||||
return '#' . $hex;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class Html {
|
|||
public static function getClass($class) {
|
||||
$class = (string) $class;
|
||||
if (!isset(static::$classes[$class])) {
|
||||
static::$classes[$class] = static::cleanCssIdentifier(Unicode::strtolower($class));
|
||||
static::$classes[$class] = static::cleanCssIdentifier(mb_strtolower($class));
|
||||
}
|
||||
return static::$classes[$class];
|
||||
}
|
||||
|
@ -79,9 +79,10 @@ class Html {
|
|||
/**
|
||||
* Prepares a string for use as a CSS identifier (element, class, or ID name).
|
||||
*
|
||||
* http://www.w3.org/TR/CSS21/syndata.html#characters shows the syntax for
|
||||
* valid CSS identifiers (including element names, classes, and IDs in
|
||||
* selectors.)
|
||||
* Link below shows the syntax for valid CSS identifiers (including element
|
||||
* names, classes, and IDs in selectors).
|
||||
*
|
||||
* @see http://www.w3.org/TR/CSS21/syndata.html#characters
|
||||
*
|
||||
* @param string $identifier
|
||||
* The identifier to clean.
|
||||
|
@ -124,7 +125,7 @@ class Html {
|
|||
// Identifiers cannot start with a digit, two hyphens, or a hyphen followed by a digit.
|
||||
$identifier = preg_replace([
|
||||
'/^[0-9]/',
|
||||
'/^(-[0-9])|^(--)/'
|
||||
'/^(-[0-9])|^(--)/',
|
||||
], ['_', '__'], $identifier);
|
||||
return $identifier;
|
||||
}
|
||||
|
@ -215,7 +216,7 @@ class Html {
|
|||
* @see self::getUniqueId()
|
||||
*/
|
||||
public static function getId($id) {
|
||||
$id = str_replace([' ', '_', '[', ']'], ['-', '-', '-', ''], Unicode::strtolower($id));
|
||||
$id = str_replace([' ', '_', '[', ']'], ['-', '-', '-', ''], mb_strtolower($id));
|
||||
|
||||
// As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
|
||||
// only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
|
||||
|
@ -451,9 +452,9 @@ EOD;
|
|||
* The updated (X)HTML snippet.
|
||||
*/
|
||||
public static function transformRootRelativeUrlsToAbsolute($html, $scheme_and_host) {
|
||||
assert('empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"]))', '$scheme_and_host contains scheme, host and port at most.');
|
||||
assert('isset(parse_url($scheme_and_host)["scheme"])', '$scheme_and_host is absolute and hence has a scheme.');
|
||||
assert('isset(parse_url($scheme_and_host)["host"])', '$base_url is absolute and hence has a host.');
|
||||
assert(empty(array_diff(array_keys(parse_url($scheme_and_host)), ["scheme", "host", "port"])), '$scheme_and_host contains scheme, host and port at most.');
|
||||
assert(isset(parse_url($scheme_and_host)["scheme"]), '$scheme_and_host is absolute and hence has a scheme.');
|
||||
assert(isset(parse_url($scheme_and_host)["host"]), '$base_url is absolute and hence has a host.');
|
||||
|
||||
$html_dom = Html::load($html);
|
||||
$xpath = new \DOMXpath($html_dom);
|
||||
|
|
|
@ -69,7 +69,7 @@ class NestedArray {
|
|||
public static function &getValue(array &$array, array $parents, &$key_exists = NULL) {
|
||||
$ref = &$array;
|
||||
foreach ($parents as $parent) {
|
||||
if (is_array($ref) && array_key_exists($parent, $ref)) {
|
||||
if (is_array($ref) && (isset($ref[$parent]) || array_key_exists($parent, $ref))) {
|
||||
$ref = &$ref[$parent];
|
||||
}
|
||||
else {
|
||||
|
@ -219,7 +219,7 @@ class NestedArray {
|
|||
public static function unsetValue(array &$array, array $parents, &$key_existed = NULL) {
|
||||
$unset_key = array_pop($parents);
|
||||
$ref = &self::getValue($array, $parents, $key_existed);
|
||||
if ($key_existed && is_array($ref) && array_key_exists($unset_key, $ref)) {
|
||||
if ($key_existed && is_array($ref) && (isset($ref[$unset_key]) || array_key_exists($unset_key, $ref))) {
|
||||
$key_existed = TRUE;
|
||||
unset($ref[$unset_key]);
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ class NestedArray {
|
|||
// Renumber integer keys as array_merge_recursive() does unless
|
||||
// $preserve_integer_keys is set to TRUE. Note that PHP automatically
|
||||
// converts array keys that are integer strings (e.g., '1') to integers.
|
||||
if (is_integer($key) && !$preserve_integer_keys) {
|
||||
if (is_int($key) && !$preserve_integer_keys) {
|
||||
$result[] = $value;
|
||||
}
|
||||
// Recurse when both values are arrays.
|
||||
|
|
|
@ -50,7 +50,7 @@ class Number {
|
|||
// can't be represented with single precision floats are acceptable. The
|
||||
// fractional part of a float has 24 bits. That means remainders smaller than
|
||||
// $step * 2^-24 are acceptable.
|
||||
$computed_acceptable_error = (double)($step / pow(2.0, 24));
|
||||
$computed_acceptable_error = (double) ($step / pow(2.0, 24));
|
||||
|
||||
return $computed_acceptable_error >= $remainder || $remainder >= ($step - $computed_acceptable_error);
|
||||
}
|
||||
|
|
|
@ -143,7 +143,9 @@ class Random {
|
|||
|
||||
$vowels = ["a", "e", "i", "o", "u"];
|
||||
$cons = ["b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr",
|
||||
"cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl", "sh"];
|
||||
"cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr",
|
||||
"sl", "cl", "sh",
|
||||
];
|
||||
|
||||
$num_vowels = count($vowels);
|
||||
$num_cons = count($cons);
|
||||
|
@ -219,7 +221,8 @@ class Random {
|
|||
"utrum", "uxor", "valde", "valetudo", "validus", "vel", "velit",
|
||||
"veniam", "venio", "vereor", "vero", "verto", "vicis", "vindico",
|
||||
"virtus", "voco", "volutpat", "vulpes", "vulputate", "wisi", "ymo",
|
||||
"zelus"];
|
||||
"zelus",
|
||||
];
|
||||
$dictionary_flipped = array_flip($dictionary);
|
||||
$greeking = '';
|
||||
|
||||
|
@ -256,7 +259,6 @@ class Random {
|
|||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a placeholder image.
|
||||
*
|
||||
|
|
|
@ -13,6 +13,8 @@ use Drupal\Component\Render\MarkupInterface;
|
|||
* @link sanitization sanitization functions @endlink or the @link theme_render theme and render systems @endlink
|
||||
* so that the output can can be themed, escaped, and altered properly.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2549395
|
||||
*
|
||||
* @see TwigExtension::escapeFilter()
|
||||
* @see twig_render_template()
|
||||
* @see sanitization
|
||||
|
@ -34,8 +36,11 @@ class SafeMarkup {
|
|||
* @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
||||
* Instead, you should just check if a variable is an instance of
|
||||
* \Drupal\Component\Render\MarkupInterface.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2549395
|
||||
*/
|
||||
public static function isSafe($string, $strategy = 'html') {
|
||||
@trigger_error('SafeMarkup::isSafe() is scheduled for removal in Drupal 9.0.0. Instead, you should just check if a variable is an instance of \Drupal\Component\Render\MarkupInterface. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
|
||||
return $string instanceof MarkupInterface;
|
||||
}
|
||||
|
||||
|
@ -58,9 +63,11 @@ class SafeMarkup {
|
|||
* possible, \Drupal\Component\Utility\Html::escape() can be used in places
|
||||
* where explicit escaping is needed.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2549395
|
||||
* @see drupal_validate_utf8()
|
||||
*/
|
||||
public static function checkPlain($text) {
|
||||
@trigger_error('SafeMarkup::checkPlain() is scheduled for removal in Drupal 9.0.0. Rely on Twig\'s auto-escaping feature, or use the @link theme_render #plain_text @endlink key when constructing a render array that contains plain text in order to use the renderer\'s auto-escaping feature. If neither of these are possible, \Drupal\Component\Utility\Html::escape() can be used in places where explicit escaping is needed. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
|
||||
return new HtmlEscapedText($text);
|
||||
}
|
||||
|
||||
|
@ -84,8 +91,11 @@ class SafeMarkup {
|
|||
*
|
||||
* @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Component\Render\FormattableMarkup.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2549395
|
||||
*/
|
||||
public static function format($string, array $args) {
|
||||
@trigger_error('SafeMarkup::format() is scheduled for removal in Drupal 9.0.0. Use \Drupal\Component\Render\FormattableMarkup. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);
|
||||
return new FormattableMarkup($string, $args);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class Timer {
|
|||
* @param $name
|
||||
* The name of the timer.
|
||||
*/
|
||||
static public function start($name) {
|
||||
public static function start($name) {
|
||||
static::$timers[$name]['start'] = microtime(TRUE);
|
||||
static::$timers[$name]['count'] = isset(static::$timers[$name]['count']) ? ++static::$timers[$name]['count'] : 1;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class Timer {
|
|||
* @return int
|
||||
* The current timer value in ms.
|
||||
*/
|
||||
static public function read($name) {
|
||||
public static function read($name) {
|
||||
if (isset(static::$timers[$name]['start'])) {
|
||||
$stop = microtime(TRUE);
|
||||
$diff = round(($stop - static::$timers[$name]['start']) * 1000, 2);
|
||||
|
@ -57,7 +57,7 @@ class Timer {
|
|||
* A timer array. The array contains the number of times the timer has been
|
||||
* started and stopped (count) and the accumulated timer value in ms (time).
|
||||
*/
|
||||
static public function stop($name) {
|
||||
public static function stop($name) {
|
||||
if (isset(static::$timers[$name]['start'])) {
|
||||
$stop = microtime(TRUE);
|
||||
$diff = round(($stop - static::$timers[$name]['start']) * 1000, 2);
|
||||
|
|
|
@ -87,13 +87,6 @@ EOD;
|
|||
*/
|
||||
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 @@ EOD;
|
|||
* 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 @@ EOD;
|
|||
*
|
||||
* @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 @@ EOD;
|
|||
* 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 @@ EOD;
|
|||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,7 +252,9 @@ EOD;
|
|||
return substr($string, 0, $len);
|
||||
}
|
||||
// Scan backwards to beginning of the byte sequence.
|
||||
while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0);
|
||||
// @todo Make the code more readable in https://www.drupal.org/node/2911497.
|
||||
while (--$len >= 0 && ord($string[$len]) >= 0x80 && ord($string[$len]) < 0xC0) {
|
||||
}
|
||||
|
||||
return substr($string, 0, $len);
|
||||
}
|
||||
|
@ -279,15 +269,15 @@ EOD;
|
|||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,18 +288,15 @@ EOD;
|
|||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,18 +307,15 @@ EOD;
|
|||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -344,7 +328,7 @@ EOD;
|
|||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -360,7 +344,7 @@ EOD;
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -376,8 +360,8 @@ EOD;
|
|||
*/
|
||||
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 preg_replace_callback($regex, function (array $matches) {
|
||||
return $matches[1] . mb_strtoupper($matches[2]);
|
||||
}, $text);
|
||||
}
|
||||
|
||||
|
@ -397,92 +381,15 @@ EOD;
|
|||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -524,15 +431,15 @@ EOD;
|
|||
$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);
|
||||
}
|
||||
|
||||
|
@ -546,16 +453,16 @@ EOD;
|
|||
// Find the last word boundary, if there is one within $min_wordsafe_length
|
||||
// to $max_length characters. preg_match() is always greedy, so it will
|
||||
// find the longest string possible.
|
||||
$found = preg_match('/^(.{' . $min_wordsafe_length . ',' . $max_length . '})[' . Unicode::PREG_CLASS_WORD_BOUNDARY . ']/u', $string, $matches);
|
||||
$found = preg_match('/^(.{' . $min_wordsafe_length . ',' . $max_length . '})[' . Unicode::PREG_CLASS_WORD_BOUNDARY . ']/us', $string, $matches);
|
||||
if ($found) {
|
||||
$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) {
|
||||
|
@ -580,8 +487,8 @@ EOD;
|
|||
* Returns < 0 if $str1 is less than $str2; > 0 if $str1 is greater than
|
||||
* $str2, and 0 if they are equal.
|
||||
*/
|
||||
public static function strcasecmp($str1 , $str2) {
|
||||
return strcmp(static::strtoupper($str1), static::strtoupper($str2));
|
||||
public static function strcasecmp($str1, $str2) {
|
||||
return strcmp(mb_strtoupper($str1), mb_strtoupper($str2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -601,18 +508,24 @@ EOD;
|
|||
*
|
||||
* @param string $string
|
||||
* The header to encode.
|
||||
* @param bool $shorten
|
||||
* If TRUE, only return the first chunk of a multi-chunk encoded string.
|
||||
*
|
||||
* @return string
|
||||
* The mime-encoded header.
|
||||
*/
|
||||
public static function mimeHeaderEncode($string) {
|
||||
public static function mimeHeaderEncode($string, $shorten = FALSE) {
|
||||
if (preg_match('/[^\x20-\x7E]/', $string)) {
|
||||
$chunk_size = 47; // floor((75 - strlen("=?UTF-8?B??=")) * 0.75);
|
||||
// floor((75 - strlen("=?UTF-8?B??=")) * 0.75);
|
||||
$chunk_size = 47;
|
||||
$len = strlen($string);
|
||||
$output = '';
|
||||
while ($len > 0) {
|
||||
$chunk = static::truncateBytes($string, $chunk_size);
|
||||
$output .= ' =?UTF-8?B?' . base64_encode($chunk) . "?=\n";
|
||||
if ($shorten) {
|
||||
break;
|
||||
}
|
||||
$c = strlen($chunk);
|
||||
$string = substr($string, $c);
|
||||
$len -= $c;
|
||||
|
@ -707,18 +620,15 @@ EOD;
|
|||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class UrlHelper {
|
|||
/**
|
||||
* Parses an array into a valid, rawurlencoded query string.
|
||||
*
|
||||
* rawurlencode() is RFC3986 compliant, and as a consequence RFC3987
|
||||
* Function rawurlencode() is RFC3986 compliant, and as a consequence RFC3987
|
||||
* compliant. The latter defines the required format of "URLs" in HTML5.
|
||||
* urlencode() is almost the same as rawurlencode(), except that it encodes
|
||||
* spaces as "+" instead of "%20". This makes its result non compliant to
|
||||
|
@ -148,6 +148,11 @@ class UrlHelper {
|
|||
$scheme_delimiter_position = strpos($url, '://');
|
||||
$query_delimiter_position = strpos($url, '?');
|
||||
if ($scheme_delimiter_position !== FALSE && ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position)) {
|
||||
// Split off the fragment, if any.
|
||||
if (strpos($url, '#') !== FALSE) {
|
||||
list($url, $options['fragment']) = explode('#', $url, 2);
|
||||
}
|
||||
|
||||
// Split off everything before the query string into 'path'.
|
||||
$parts = explode('?', $url);
|
||||
|
||||
|
@ -158,12 +163,7 @@ class UrlHelper {
|
|||
}
|
||||
// If there is a query string, transform it into keyed query parameters.
|
||||
if (isset($parts[1])) {
|
||||
$query_parts = explode('#', $parts[1]);
|
||||
parse_str($query_parts[0], $options['query']);
|
||||
// Take over the fragment, if there is any.
|
||||
if (isset($query_parts[1])) {
|
||||
$options['fragment'] = $query_parts[1];
|
||||
}
|
||||
parse_str($parts[1], $options['query']);
|
||||
}
|
||||
}
|
||||
// Internal URLs.
|
||||
|
@ -248,6 +248,16 @@ class UrlHelper {
|
|||
* Exception thrown when a either $url or $bath_url are not fully qualified.
|
||||
*/
|
||||
public static function externalIsLocal($url, $base_url) {
|
||||
// Some browsers treat \ as / so normalize to forward slashes.
|
||||
$url = str_replace('\\', '/', $url);
|
||||
|
||||
// Leading control characters may be ignored or mishandled by browsers, so
|
||||
// assume such a path may lead to an non-local location. The \p{C} character
|
||||
// class matches all UTF-8 control, unassigned, and private characters.
|
||||
if (preg_match('/^\p{C}/u', $url) !== 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$url_parts = parse_url($url);
|
||||
$base_parts = parse_url($base_url);
|
||||
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
"description": "Mostly static utility classes for string, xss, array, image, and other commonly needed manipulations.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0+",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"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": {
|
||||
|
|
Reference in a new issue