Initial Drupal 11 with DDEV setup
This commit is contained in:
314
vendor/mck89/peast/lib/Peast/Syntax/Utils.php
vendored
Normal file
314
vendor/mck89/peast/lib/Peast/Syntax/Utils.php
vendored
Normal file
@ -0,0 +1,314 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of the Peast package
|
||||
*
|
||||
* (c) Marco Marchiò <marco.mm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information refer to the LICENSE file
|
||||
* distributed with this source code
|
||||
*/
|
||||
namespace Peast\Syntax;
|
||||
|
||||
/**
|
||||
* Utilities class.
|
||||
*
|
||||
* @author Marco Marchiò <marco.mm89@gmail.com>
|
||||
*/
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* Converts a string to an array of UTF-8 characters
|
||||
*
|
||||
* @param string $str String to convert
|
||||
* @param bool $strictEncoding If false and the string contains invalid
|
||||
* UTF-8 characters, it will replace those
|
||||
* characters with the one defined in the
|
||||
* mbstring.substitute_character setting
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws EncodingException
|
||||
*/
|
||||
static public function stringToUTF8Array($str, $strictEncoding = true)
|
||||
{
|
||||
if ($str === "") {
|
||||
return array();
|
||||
}
|
||||
$ret = preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (preg_last_error() === PREG_BAD_UTF8_ERROR) {
|
||||
if (!$strictEncoding) {
|
||||
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
|
||||
$ret = self::stringToUTF8Array($str, false);
|
||||
} else {
|
||||
throw new EncodingException("String contains invalid UTF-8");
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an unicode code point to UTF-8
|
||||
*
|
||||
* @param int $num Unicode code point
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
static public function unicodeToUtf8($num)
|
||||
{
|
||||
//From: http://stackoverflow.com/questions/1805802/php-convert-unicode-codepoint-to-utf-8#answer-7153133
|
||||
if ($num <= 0x7F) {
|
||||
return chr($num);
|
||||
} elseif ($num <= 0x7FF) {
|
||||
return chr(($num >> 6) + 192) .
|
||||
chr(($num & 63) + 128);
|
||||
} elseif ($num <= 0xFFFF) {
|
||||
return chr(($num >> 12) + 224) .
|
||||
chr((($num >> 6) & 63) + 128) .
|
||||
chr(($num & 63) + 128);
|
||||
} elseif ($num <= 0x1FFFFF) {
|
||||
return chr(($num >> 18) + 240) .
|
||||
chr((($num >> 12) & 63) + 128) .
|
||||
chr((($num >> 6) & 63) + 128) .
|
||||
chr(($num & 63) + 128);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiled line terminators cache
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $lineTerminatorsCache;
|
||||
|
||||
/**
|
||||
* Returns line terminators array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function getLineTerminators()
|
||||
{
|
||||
if (!self::$lineTerminatorsCache) {
|
||||
self::$lineTerminatorsCache = array();
|
||||
foreach (Scanner::$lineTerminatorsChars as $char) {
|
||||
self::$lineTerminatorsCache[] = is_int($char) ?
|
||||
self::unicodeToUtf8($char) :
|
||||
$char;
|
||||
}
|
||||
}
|
||||
return self::$lineTerminatorsCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a surrogate pair of Unicode code points to UTF-8
|
||||
*
|
||||
* @param string $first First Unicode code point
|
||||
* @param string $second Second Unicode code point
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
static public function surrogatePairToUtf8($first, $second)
|
||||
{
|
||||
//From: https://stackoverflow.com/questions/39226593/how-to-convert-utf16-surrogate-pairs-to-equivalent-hex-codepoint-in-php
|
||||
$value = ((hexdec($first) & 0x3ff) << 10) | (hexdec($second) & 0x3ff);
|
||||
return self::unicodeToUtf8($value + 0x10000);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function takes a string as it appears in the source code and returns
|
||||
* an unquoted version of it
|
||||
*
|
||||
* @param string $str The string to unquote
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function unquoteLiteralString($str)
|
||||
{
|
||||
//Remove quotes
|
||||
$str = substr($str, 1, -1);
|
||||
|
||||
//Return immediately if the escape character is missing
|
||||
if (strpos($str, "\\") === false) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
$lineTerminators = self::getLineTerminators();
|
||||
|
||||
//Surrogate pairs regex
|
||||
$surrogatePairsReg = sprintf(
|
||||
'u(?:%1$s|\{%1$s\})\\\\u(?:%2$s|\{%2$s\})',
|
||||
"[dD][89abAB][0-9a-fA-F]{2}", "[dD][c-fC-F][0-9a-fA-F]{2}"
|
||||
);
|
||||
|
||||
//Handle escapes
|
||||
$patterns = array(
|
||||
$surrogatePairsReg,
|
||||
"u\{[a-fA-F0-9]+\}",
|
||||
"u[a-fA-F0-9]{4}",
|
||||
"x[a-fA-F0-9]{2}",
|
||||
"0[0-7]{2}",
|
||||
"[1-7][0-7]",
|
||||
"."
|
||||
);
|
||||
$reg = "/\\\\(" . implode("|", $patterns) . ")/s";
|
||||
$simpleSequence = array(
|
||||
"n" => "\n",
|
||||
"f" => "\f",
|
||||
"r" => "\r",
|
||||
"t" => "\t",
|
||||
"v" => "\v",
|
||||
"b" => "\x8"
|
||||
);
|
||||
$replacement = function ($m) use ($simpleSequence, $lineTerminators) {
|
||||
$type = $m[1][0];
|
||||
if (isset($simpleSequence[$type])) {
|
||||
// \n, \r, \t ...
|
||||
return $simpleSequence[$type];
|
||||
} elseif ($type === "u" || $type === "x") {
|
||||
//Invalid unicode or hexadecimal sequences
|
||||
if (strlen($m[1]) === 1) {
|
||||
return "\\$type";
|
||||
}
|
||||
// Surrogate pair
|
||||
if ($type === "u" && strpos($m[1], "\\") !== false) {
|
||||
$points = explode("\\", $m[1]);
|
||||
return Utils::surrogatePairToUtf8(
|
||||
str_replace(array("{", "}", "u"), "", $points[0]),
|
||||
str_replace(array("{", "}", "u"), "", $points[1])
|
||||
);
|
||||
}
|
||||
// \uFFFF, \u{FFFF}, \xFF
|
||||
$code = substr($m[1], 1);
|
||||
$code = str_replace(array("{", "}"), "", $code);
|
||||
return Utils::unicodeToUtf8(hexdec($code));
|
||||
} elseif ($type >= "0" && $type <= "7") {
|
||||
//Invalid octal sequences
|
||||
if (strlen($m[1]) === 1) {
|
||||
return "\\$type";
|
||||
}
|
||||
// \123
|
||||
return Utils::unicodeToUtf8(octdec($m[1]));
|
||||
} elseif (in_array($m[1], $lineTerminators)) {
|
||||
// Escaped line terminators
|
||||
return "";
|
||||
} else {
|
||||
// Escaped characters
|
||||
return $m[1];
|
||||
}
|
||||
};
|
||||
return preg_replace_callback($reg, $replacement, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function converts a string to a quoted javascript string
|
||||
*
|
||||
* @param string $str String to quote
|
||||
* @param string $quote Quote character
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function quoteLiteralString($str, $quote)
|
||||
{
|
||||
$escape = self::getLineTerminators();
|
||||
$escape[] = $quote;
|
||||
$escape[] = "\\\\";
|
||||
$reg = "/(" . implode("|", $escape) . ")/";
|
||||
$str = preg_replace($reg, "\\\\$1", $str);
|
||||
return $quote . $str . $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the properties map for the given node
|
||||
*
|
||||
* @param mixed $node Node or class to consider
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static protected function getPropertiesMap($node)
|
||||
{
|
||||
static $cache = array();
|
||||
|
||||
if ($node instanceof \ReflectionClass) {
|
||||
$className = $node->getName();
|
||||
} else {
|
||||
$className = get_class($node);
|
||||
}
|
||||
|
||||
if (!isset($cache[$className])) {
|
||||
$class = new \ReflectionClass($className);
|
||||
$parent = $class->getParentClass();
|
||||
$props = $parent ? self::getPropertiesMap($parent) : array();
|
||||
$defaults = $class->getDefaultProperties();
|
||||
if (isset($defaults["propertiesMap"])) {
|
||||
$props = array_merge($props, $defaults["propertiesMap"]);
|
||||
}
|
||||
$cache[$className] = $props;
|
||||
}
|
||||
return $cache[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the properties list for the given node
|
||||
*
|
||||
* @param Node\Node $node Node to consider
|
||||
* @param bool $traversable If true it returns only traversable properties
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function getNodeProperties(Node\Node $node, $traversable = false)
|
||||
{
|
||||
$props = self::getPropertiesMap($node);
|
||||
return array_map(
|
||||
function ($prop) {
|
||||
$ucProp = ucfirst($prop);
|
||||
return array(
|
||||
"name" => $prop,
|
||||
"getter" => "get$ucProp",
|
||||
"setter" => "set$ucProp"
|
||||
);
|
||||
},
|
||||
array_keys($traversable ? array_filter($props) : $props)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an expanded version of the traversable node properties.
|
||||
* The return of the function is an array of node properties
|
||||
* values with arrays flattened
|
||||
*
|
||||
* @param Node\Node $node Node
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function getExpandedNodeProperties(Node\Node $node)
|
||||
{
|
||||
$ret = array();
|
||||
$props = self::getNodeProperties($node, true);
|
||||
foreach ($props as $prop) {
|
||||
$val = $node->{$prop["getter"]}();
|
||||
if (is_array($val)) {
|
||||
$ret = array_merge($ret, $val);
|
||||
} else {
|
||||
$ret[] = $val;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an array element by value
|
||||
*
|
||||
* @param array $array Array
|
||||
* @param mixed $val Value to remove
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static public function removeArrayValue(&$array, $val)
|
||||
{
|
||||
array_splice($array, array_search($val, $array), 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user