代码初始化
This commit is contained in:
2
addons/epay/library/hyperf/utils/.gitattributes
vendored
Normal file
2
addons/epay/library/hyperf/utils/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/tests export-ignore
|
||||
/.github export-ignore
|
||||
22
addons/epay/library/hyperf/utils/LICENSE
Normal file
22
addons/epay/library/hyperf/utils/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
Copyright (c) Hyperf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
58
addons/epay/library/hyperf/utils/composer.json
Normal file
58
addons/epay/library/hyperf/utils/composer.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "hyperf/utils",
|
||||
"description": "A tools package that could help developer solved the problem quickly.",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"php",
|
||||
"swoole",
|
||||
"hyperf",
|
||||
"utils"
|
||||
],
|
||||
"homepage": "https://hyperf.io",
|
||||
"support": {
|
||||
"docs": "https://hyperf.wiki",
|
||||
"issues": "https://github.com/hyperf/hyperf/issues",
|
||||
"pull-request": "https://github.com/hyperf/hyperf/pulls",
|
||||
"source": "https://github.com/hyperf/hyperf"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"doctrine/inflector": "^2.0",
|
||||
"hyperf/context": "~2.2.0",
|
||||
"hyperf/contract": "~2.2.0",
|
||||
"hyperf/engine": "^1.1",
|
||||
"hyperf/macroable": "~2.2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-swoole": "Required to use methods related to swoole (>=4.5).",
|
||||
"symfony/var-dumper": "Required to use the dd function (^5.0).",
|
||||
"symfony/serializer": "Required to use SymfonyNormalizer (^5.0)",
|
||||
"symfony/property-access": "Required to use SymfonyNormalizer (^5.0)",
|
||||
"hyperf/di": "Required to use ExceptionNormalizer",
|
||||
"nikic/php-parser": "Required to use PhpParser. (^4.0)"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Hyperf\\Utils\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"HyperfTest\\Utils\\": "tests/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"hyperf": {
|
||||
"config": "Hyperf\\Utils\\ConfigProvider"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
41
addons/epay/library/hyperf/utils/src/ApplicationContext.php
Normal file
41
addons/epay/library/hyperf/utils/src/ApplicationContext.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class ApplicationContext
|
||||
{
|
||||
/**
|
||||
* @var null|ContainerInterface
|
||||
*/
|
||||
private static $container;
|
||||
|
||||
/**
|
||||
* @throws \TypeError
|
||||
*/
|
||||
public static function getContainer(): ContainerInterface
|
||||
{
|
||||
return self::$container;
|
||||
}
|
||||
|
||||
public static function hasContainer(): bool
|
||||
{
|
||||
return isset(self::$container);
|
||||
}
|
||||
|
||||
public static function setContainer(ContainerInterface $container): ContainerInterface
|
||||
{
|
||||
self::$container = $container;
|
||||
return $container;
|
||||
}
|
||||
}
|
||||
558
addons/epay/library/hyperf/utils/src/Arr.php
Normal file
558
addons/epay/library/hyperf/utils/src/Arr.php
Normal file
@@ -0,0 +1,558 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use ArrayAccess;
|
||||
use Hyperf\Macroable\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Most of the methods in this file come from illuminate/support,
|
||||
* thanks Laravel Team provide such a useful class.
|
||||
*/
|
||||
class Arr
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* Determine whether the given value is array accessible.
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function accessible($value): bool
|
||||
{
|
||||
return is_array($value) || $value instanceof ArrayAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to an array using "dot" notation if it doesn't exist.
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function add(array $array, string $key, $value): array
|
||||
{
|
||||
if (is_null(static::get($array, $key))) {
|
||||
static::set($array, $key, $value);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse an array of arrays into a single array.
|
||||
*/
|
||||
public static function collapse(array $array): array
|
||||
{
|
||||
$results = [];
|
||||
foreach ($array as $values) {
|
||||
if ($values instanceof Collection) {
|
||||
$values = $values->all();
|
||||
} elseif (! is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
$results[] = $values;
|
||||
}
|
||||
return array_merge([], ...$results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross join the given arrays, returning all possible permutations.
|
||||
*
|
||||
* @param array ...$arrays
|
||||
*/
|
||||
public static function crossJoin(...$arrays): array
|
||||
{
|
||||
$results = [[]];
|
||||
foreach ($arrays as $index => $array) {
|
||||
$append = [];
|
||||
foreach ($results as $product) {
|
||||
foreach ($array as $item) {
|
||||
$product[$index] = $item;
|
||||
$append[] = $product;
|
||||
}
|
||||
}
|
||||
$results = $append;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide an array into two arrays. One with keys and the other with values.
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function divide($array)
|
||||
{
|
||||
return [array_keys($array), array_values($array)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional associative array with dots.
|
||||
*/
|
||||
public static function dot(array $array, string $prepend = ''): array
|
||||
{
|
||||
$results = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value) && ! empty($value)) {
|
||||
$results = array_merge($results, static::dot($value, $prepend . $key . '.'));
|
||||
} else {
|
||||
$results[$prepend . $key] = $value;
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the given array except for a specified array of keys.
|
||||
*
|
||||
* @param array|string $keys
|
||||
*/
|
||||
public static function except(array $array, $keys): array
|
||||
{
|
||||
static::forget($array, $keys);
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key exists in the provided array.
|
||||
*
|
||||
* @param array|\ArrayAccess $array
|
||||
* @param int|string $key
|
||||
*/
|
||||
public static function exists($array, $key): bool
|
||||
{
|
||||
if ($array instanceof ArrayAccess) {
|
||||
return $array->offsetExists($key);
|
||||
}
|
||||
return array_key_exists($key, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element in an array passing a given truth test.
|
||||
*
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
public static function first(array $array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
if (empty($array)) {
|
||||
return value($default);
|
||||
}
|
||||
foreach ($array as $item) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
foreach ($array as $key => $value) {
|
||||
if (call_user_func($callback, $value, $key)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last element in an array passing a given truth test.
|
||||
*
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
public static function last(array $array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return empty($array) ? value($default) : end($array);
|
||||
}
|
||||
return static::first(array_reverse($array, true), $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional array into a single level.
|
||||
* @param float|int $depth
|
||||
*/
|
||||
public static function flatten(array $array, $depth = INF): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($array as $item) {
|
||||
$item = $item instanceof Collection ? $item->all() : $item;
|
||||
if (! is_array($item)) {
|
||||
$result[] = $item;
|
||||
} elseif ($depth === 1) {
|
||||
$result = array_merge($result, array_values($item));
|
||||
} else {
|
||||
$result = array_merge($result, static::flatten($item, $depth - 1));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove one or many array items from a given array using "dot" notation.
|
||||
*
|
||||
* @param array|string $keys
|
||||
*/
|
||||
public static function forget(array &$array, $keys): void
|
||||
{
|
||||
$original = &$array;
|
||||
$keys = (array) $keys;
|
||||
if (count($keys) === 0) {
|
||||
return;
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
// if the exact key exists in the top-level, remove it
|
||||
if (static::exists($array, $key)) {
|
||||
unset($array[$key]);
|
||||
continue;
|
||||
}
|
||||
$parts = explode('.', (string) $key);
|
||||
// clean up before each pass
|
||||
$array = &$original;
|
||||
while (count($parts) > 1) {
|
||||
$part = array_shift($parts);
|
||||
if (isset($array[$part]) && is_array($array[$part])) {
|
||||
$array = &$array[$part];
|
||||
} else {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
unset($array[array_shift($parts)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "dot" notation.
|
||||
*
|
||||
* @param array|\ArrayAccess $array
|
||||
* @param null|int|string $key
|
||||
* @param mixed $default
|
||||
*/
|
||||
public static function get($array, $key = null, $default = null)
|
||||
{
|
||||
if (! static::accessible($array)) {
|
||||
return value($default);
|
||||
}
|
||||
if (is_null($key)) {
|
||||
return $array;
|
||||
}
|
||||
if (static::exists($array, $key)) {
|
||||
return $array[$key];
|
||||
}
|
||||
if (! is_string($key) || strpos($key, '.') === false) {
|
||||
return $array[$key] ?? value($default);
|
||||
}
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($array) && static::exists($array, $segment)) {
|
||||
$array = $array[$segment];
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item or items exist in an array using "dot" notation.
|
||||
*
|
||||
* @param array|\ArrayAccess $array
|
||||
* @param null|array|string $keys
|
||||
*/
|
||||
public static function has($array, $keys): bool
|
||||
{
|
||||
if (is_null($keys)) {
|
||||
return false;
|
||||
}
|
||||
$keys = (array) $keys;
|
||||
if (! $array) {
|
||||
return false;
|
||||
}
|
||||
if ($keys === []) {
|
||||
return false;
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
$subKeyArray = $array;
|
||||
if (static::exists($array, $key)) {
|
||||
continue;
|
||||
}
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
|
||||
$subKeyArray = $subKeyArray[$segment];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an array is associative.
|
||||
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
|
||||
*/
|
||||
public static function isAssoc(array $array): bool
|
||||
{
|
||||
$keys = array_keys($array);
|
||||
return array_keys($keys) !== $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a subset of the items from the given array.
|
||||
*
|
||||
* @param array|string $keys
|
||||
*/
|
||||
public static function only(array $array, $keys): array
|
||||
{
|
||||
return array_intersect_key($array, array_flip((array) $keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluck an array of values from an array.
|
||||
*
|
||||
* @param array|string $value
|
||||
* @param null|array|string $key
|
||||
*/
|
||||
public static function pluck(array $array, $value, $key = null): array
|
||||
{
|
||||
$results = [];
|
||||
[$value, $key] = static::explodePluckParameters($value, $key);
|
||||
foreach ($array as $item) {
|
||||
$itemValue = data_get($item, $value);
|
||||
// If the key is "null", we will just append the value to the array and keep
|
||||
// looping. Otherwise we will key the array using the value of the key we
|
||||
// received from the developer. Then we'll return the final array form.
|
||||
if (is_null($key)) {
|
||||
$results[] = $itemValue;
|
||||
} else {
|
||||
$itemKey = data_get($item, $key);
|
||||
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
|
||||
$itemKey = (string) $itemKey;
|
||||
}
|
||||
$results[$itemKey] = $itemValue;
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an item onto the beginning of an array.
|
||||
*
|
||||
* @template TKey of array-key
|
||||
* @template TValue
|
||||
*
|
||||
* @param array<TKey, TValue> $array
|
||||
* @param null|TKey $key
|
||||
* @param TValue $value
|
||||
* @return array<TKey, TValue>
|
||||
*/
|
||||
public static function prepend(array $array, $value, $key = null): array
|
||||
{
|
||||
if (is_null($key)) {
|
||||
array_unshift($array, $value);
|
||||
} else {
|
||||
$array = [$key => $value] + $array;
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the array, and remove it.
|
||||
*
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
public static function pull(array &$array, string $key, $default = null)
|
||||
{
|
||||
$value = static::get($array, $key, $default);
|
||||
static::forget($array, $key);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or a specified number of random values from an array.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function random(array $array, int $number = null)
|
||||
{
|
||||
$requested = is_null($number) ? 1 : $number;
|
||||
$count = count($array);
|
||||
if ($requested > $count) {
|
||||
throw new InvalidArgumentException("You requested {$requested} items, but there are only {$count} items available.");
|
||||
}
|
||||
if (is_null($number)) {
|
||||
return $array[array_rand($array)];
|
||||
}
|
||||
if ((int) $number === 0) {
|
||||
return [];
|
||||
}
|
||||
$keys = array_rand($array, $number);
|
||||
$results = [];
|
||||
foreach ((array) $keys as $key) {
|
||||
$results[] = $array[$key];
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array item to a given value using "dot" notation.
|
||||
* If no key is given to the method, the entire array will be replaced.
|
||||
*
|
||||
* @param null|int|string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function set(array &$array, $key, $value): array
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $array = $value;
|
||||
}
|
||||
if (! is_string($key)) {
|
||||
$array[$key] = $value;
|
||||
return $array;
|
||||
}
|
||||
$keys = explode('.', $key);
|
||||
while (count($keys) > 1) {
|
||||
$key = array_shift($keys);
|
||||
// If the key doesn't exist at this depth, we will just create an empty array
|
||||
// to hold the next value, allowing us to create the arrays to hold final
|
||||
// values at the correct depth. Then we'll keep digging into the array.
|
||||
if (! isset($array[$key]) || ! is_array($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
$array[array_shift($keys)] = $value;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the given array and return the result.
|
||||
*/
|
||||
public static function shuffle(array $array, int $seed = null): array
|
||||
{
|
||||
if (is_null($seed)) {
|
||||
shuffle($array);
|
||||
} else {
|
||||
srand($seed);
|
||||
usort($array, function () {
|
||||
return rand(-1, 1);
|
||||
});
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the array using the given callback or "dot" notation.
|
||||
*
|
||||
* @param null|callable|string $callback
|
||||
*/
|
||||
public static function sort(array $array, $callback = null): array
|
||||
{
|
||||
return Collection::make($array)->sortBy($callback)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sort an array by keys and values.
|
||||
*/
|
||||
public static function sortRecursive(array $array): array
|
||||
{
|
||||
foreach ($array as &$value) {
|
||||
if (is_array($value)) {
|
||||
$value = static::sortRecursive($value);
|
||||
}
|
||||
}
|
||||
if (static::isAssoc($array)) {
|
||||
ksort($array);
|
||||
} else {
|
||||
sort($array);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the array into a query string.
|
||||
*/
|
||||
public static function query(array $array): string
|
||||
{
|
||||
return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the array using the given callback.
|
||||
*/
|
||||
public static function where(array $array, callable $callback): array
|
||||
{
|
||||
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given value is not an array and not null, wrap it in one.
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function wrap($value): array
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return [];
|
||||
}
|
||||
return ! is_array($value) ? [$value] : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make array elements unique.
|
||||
*/
|
||||
public static function unique(array $array): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($array ?? [] as $key => $item) {
|
||||
if (is_array($item)) {
|
||||
$result[$key] = self::unique($item);
|
||||
} else {
|
||||
$result[$key] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if (! self::isAssoc($result)) {
|
||||
return array_unique($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function merge(array $array1, array $array2, bool $unique = true): array
|
||||
{
|
||||
$isAssoc = static::isAssoc($array1 ?: $array2);
|
||||
if ($isAssoc) {
|
||||
foreach ($array2 as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$array1[$key] = static::merge($array1[$key] ?? [], $value, $unique);
|
||||
} else {
|
||||
$array1[$key] = $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($array2 as $key => $value) {
|
||||
if ($unique && in_array($value, $array1, true)) {
|
||||
continue;
|
||||
}
|
||||
$array1[] = $value;
|
||||
}
|
||||
|
||||
$array1 = array_values($array1);
|
||||
}
|
||||
return $array1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the "value" and "key" arguments passed to "pluck".
|
||||
*
|
||||
* @param array|string $value
|
||||
* @param null|array|string $key
|
||||
*/
|
||||
protected static function explodePluckParameters($value, $key): array
|
||||
{
|
||||
$value = is_string($value) ? explode('.', $value) : $value;
|
||||
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
|
||||
return [$value, $key];
|
||||
}
|
||||
}
|
||||
84
addons/epay/library/hyperf/utils/src/Backoff.php
Normal file
84
addons/epay/library/hyperf/utils/src/Backoff.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
class Backoff
|
||||
{
|
||||
/**
|
||||
* Max backoff.
|
||||
*/
|
||||
private const CAP = 60 * 1000; // 1 minute
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $firstMs;
|
||||
|
||||
/**
|
||||
* Backoff interval.
|
||||
* @var int
|
||||
*/
|
||||
private $currentMs;
|
||||
|
||||
/**
|
||||
* @param int the first backoff in milliseconds
|
||||
*/
|
||||
public function __construct(int $firstMs = 0)
|
||||
{
|
||||
if ($firstMs < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
'first backoff interval must be greater or equal than 0'
|
||||
);
|
||||
}
|
||||
|
||||
if ($firstMs > Backoff::CAP) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'first backoff interval must be less or equal than %d milliseconds',
|
||||
self::CAP
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->firstMs = $firstMs;
|
||||
$this->currentMs = $firstMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep until the next execution.
|
||||
*/
|
||||
public function sleep(): void
|
||||
{
|
||||
if ($this->currentMs === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
usleep($this->currentMs * 1000);
|
||||
|
||||
// update backoff using Decorrelated Jitter
|
||||
// see: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
||||
$this->currentMs = rand($this->firstMs, $this->currentMs * 3);
|
||||
|
||||
if ($this->currentMs > self::CAP) {
|
||||
$this->currentMs = self::CAP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next backoff for logging, etc.
|
||||
* @return int next backoff
|
||||
*/
|
||||
public function nextBackoff(): int
|
||||
{
|
||||
return $this->currentMs;
|
||||
}
|
||||
}
|
||||
79
addons/epay/library/hyperf/utils/src/Channel/Caller.php
Normal file
79
addons/epay/library/hyperf/utils/src/Channel/Caller.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Channel;
|
||||
|
||||
use Closure;
|
||||
use Hyperf\Engine\Channel;
|
||||
use Hyperf\Utils\Exception\ChannelClosedException;
|
||||
use Hyperf\Utils\Exception\WaitTimeoutException;
|
||||
|
||||
class Caller
|
||||
{
|
||||
/**
|
||||
* @var null|Channel
|
||||
*/
|
||||
protected $channel;
|
||||
|
||||
/**
|
||||
* @var float wait seconds
|
||||
*/
|
||||
protected $waitTimeout;
|
||||
|
||||
/**
|
||||
* @var null|Closure
|
||||
*/
|
||||
protected $closure;
|
||||
|
||||
public function __construct(Closure $closure, float $waitTimeout = 10)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
$this->waitTimeout = $waitTimeout;
|
||||
$this->initInstance();
|
||||
}
|
||||
|
||||
public function call(Closure $closure)
|
||||
{
|
||||
$release = true;
|
||||
$channel = $this->channel;
|
||||
try {
|
||||
$instance = $channel->pop($this->waitTimeout);
|
||||
if ($instance === false) {
|
||||
if ($channel->isClosing()) {
|
||||
throw new ChannelClosedException('The channel was closed.');
|
||||
}
|
||||
|
||||
if ($channel->isTimeout()) {
|
||||
throw new WaitTimeoutException('The instance pop from channel timeout.');
|
||||
}
|
||||
}
|
||||
|
||||
$result = $closure($instance);
|
||||
} catch (ChannelClosedException|WaitTimeoutException $exception) {
|
||||
$release = false;
|
||||
throw $exception;
|
||||
} finally {
|
||||
$release && $channel->push($instance ?? null);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function initInstance(): void
|
||||
{
|
||||
if ($this->channel) {
|
||||
$this->channel->close();
|
||||
}
|
||||
|
||||
$this->channel = new Channel(1);
|
||||
$this->channel->push($this->closure->__invoke());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Channel;
|
||||
|
||||
use Hyperf\Engine\Channel;
|
||||
|
||||
class ChannelManager
|
||||
{
|
||||
/**
|
||||
* @var Channel[]
|
||||
*/
|
||||
protected $channels = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $size = 1;
|
||||
|
||||
public function __construct(int $size = 1)
|
||||
{
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
public function get(int $id, bool $initialize = false): ?Channel
|
||||
{
|
||||
if (isset($this->channels[$id])) {
|
||||
return $this->channels[$id];
|
||||
}
|
||||
|
||||
if ($initialize) {
|
||||
return $this->channels[$id] = $this->make($this->size);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function make(int $limit): Channel
|
||||
{
|
||||
return new Channel($limit);
|
||||
}
|
||||
|
||||
public function close(int $id): void
|
||||
{
|
||||
if ($channel = $this->channels[$id] ?? null) {
|
||||
$channel->close();
|
||||
}
|
||||
|
||||
unset($this->channels[$id]);
|
||||
}
|
||||
|
||||
public function getChannels(): array
|
||||
{
|
||||
return $this->channels;
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
$channels = $this->getChannels();
|
||||
foreach ($channels as $id => $channel) {
|
||||
$this->close($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
addons/epay/library/hyperf/utils/src/ChannelPool.php
Normal file
38
addons/epay/library/hyperf/utils/src/ChannelPool.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Swoole\Coroutine\Channel;
|
||||
|
||||
class ChannelPool extends \SplQueue
|
||||
{
|
||||
/**
|
||||
* @var ChannelPool
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
public static function getInstance(): self
|
||||
{
|
||||
return static::$instance ?? (static::$instance = new self());
|
||||
}
|
||||
|
||||
public function get(): Channel
|
||||
{
|
||||
return $this->isEmpty() ? new Channel(1) : $this->pop();
|
||||
}
|
||||
|
||||
public function release(Channel $channel)
|
||||
{
|
||||
$channel->errCode = 0;
|
||||
$this->push($channel);
|
||||
}
|
||||
}
|
||||
62
addons/epay/library/hyperf/utils/src/ClearStatCache.php
Normal file
62
addons/epay/library/hyperf/utils/src/ClearStatCache.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
class ClearStatCache
|
||||
{
|
||||
/**
|
||||
* Interval at which to clear fileystem stat cache. Values below 1 indicate
|
||||
* the stat cache should ALWAYS be cleared. Otherwise, the value is the number
|
||||
* of seconds between clear operations.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $interval = 1;
|
||||
|
||||
/**
|
||||
* When the filesystem stat cache was last cleared.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $lastCleared;
|
||||
|
||||
public static function clear(?string $filename = null): void
|
||||
{
|
||||
$now = time();
|
||||
if (1 > self::$interval
|
||||
|| self::$lastCleared
|
||||
|| (self::$lastCleared + self::$interval < $now)
|
||||
) {
|
||||
self::forceClear($filename);
|
||||
self::$lastCleared = $now;
|
||||
}
|
||||
}
|
||||
|
||||
public static function forceClear(?string $filename = null): void
|
||||
{
|
||||
if ($filename !== null) {
|
||||
clearstatcache(true, $filename);
|
||||
} else {
|
||||
clearstatcache();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getInterval(): int
|
||||
{
|
||||
return self::$interval;
|
||||
}
|
||||
|
||||
public static function setInterval(int $interval)
|
||||
{
|
||||
self::$interval = $interval;
|
||||
}
|
||||
}
|
||||
26
addons/epay/library/hyperf/utils/src/CodeGen/Package.php
Normal file
26
addons/epay/library/hyperf/utils/src/CodeGen/Package.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\CodeGen;
|
||||
|
||||
use Jean85\PrettyVersions;
|
||||
|
||||
class Package
|
||||
{
|
||||
public static function getPrettyVersion(string $package): string
|
||||
{
|
||||
try {
|
||||
return (string) PrettyVersions::getVersion($package);
|
||||
} catch (\Throwable $exception) {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
247
addons/epay/library/hyperf/utils/src/CodeGen/PhpDocReader.php
Normal file
247
addons/epay/library/hyperf/utils/src/CodeGen/PhpDocReader.php
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\CodeGen;
|
||||
|
||||
use PhpDocReader\AnnotationException;
|
||||
use PhpDocReader\PhpParser\UseStatementParser;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
use ReflectionProperty;
|
||||
use Reflector;
|
||||
|
||||
/**
|
||||
* @see https://github.com/PHP-DI/PhpDocReader
|
||||
*/
|
||||
class PhpDocReader
|
||||
{
|
||||
private const PRIMITIVE_TYPES = [
|
||||
'bool' => 'bool',
|
||||
'boolean' => 'bool',
|
||||
'string' => 'string',
|
||||
'int' => 'int',
|
||||
'integer' => 'int',
|
||||
'float' => 'float',
|
||||
'double' => 'float',
|
||||
'array' => 'array',
|
||||
'object' => 'object',
|
||||
'callable' => 'callable',
|
||||
'resource' => 'resource',
|
||||
'mixed' => 'mixed',
|
||||
'iterable' => 'iterable',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var null|PhpDocReader
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/** @var UseStatementParser */
|
||||
private $parser;
|
||||
|
||||
/** @var bool */
|
||||
private $ignorePhpDocErrors;
|
||||
|
||||
/**
|
||||
* @param bool $ignorePhpDocErrors enable or disable throwing errors when PhpDoc errors occur (when parsing annotations)
|
||||
*/
|
||||
public function __construct(bool $ignorePhpDocErrors = false)
|
||||
{
|
||||
$this->parser = new UseStatementParser();
|
||||
$this->ignorePhpDocErrors = $ignorePhpDocErrors;
|
||||
}
|
||||
|
||||
public static function getInstance(): PhpDocReader
|
||||
{
|
||||
if (static::$instance) {
|
||||
return static::$instance;
|
||||
}
|
||||
return static::$instance = new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the docblock of the property to get the type (class or primitive type) of the param annotation.
|
||||
*
|
||||
* @throws AnnotationException
|
||||
*/
|
||||
public function getReturnType(ReflectionMethod $method, bool $withoutNamespace = false): array
|
||||
{
|
||||
return $this->readReturnClass($method, true, $withoutNamespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the docblock of the property to get the class of the param annotation.
|
||||
*
|
||||
* @throws AnnotationException
|
||||
*/
|
||||
public function getReturnClass(ReflectionMethod $method, bool $withoutNamespace = false): array
|
||||
{
|
||||
return $this->readReturnClass($method, false, $withoutNamespace);
|
||||
}
|
||||
|
||||
protected function readReturnClass(ReflectionMethod $method, bool $allowPrimitiveTypes, bool $withoutNamespace = false): array
|
||||
{
|
||||
// Use reflection
|
||||
$returnType = $method->getReturnType();
|
||||
if ($returnType instanceof \ReflectionNamedType) {
|
||||
if (! $returnType->isBuiltin() || $allowPrimitiveTypes) {
|
||||
return [($returnType->allowsNull() ? '?' : '') . $returnType->getName()];
|
||||
}
|
||||
}
|
||||
|
||||
$docComment = $method->getDocComment();
|
||||
if (! $docComment) {
|
||||
return ['mixed'];
|
||||
}
|
||||
if (preg_match('/@return\s+([^\s]+)\s+/', $docComment, $matches)) {
|
||||
[, $type] = $matches;
|
||||
} else {
|
||||
return ['mixed'];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$class = $method->getDeclaringClass();
|
||||
$types = explode('|', $type);
|
||||
foreach ($types as $type) {
|
||||
// Ignore primitive types
|
||||
if (isset(self::PRIMITIVE_TYPES[$type])) {
|
||||
if ($allowPrimitiveTypes) {
|
||||
$result[] = self::PRIMITIVE_TYPES[$type];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore types containing special characters ([], <> ...)
|
||||
if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the class name is not fully qualified (i.e. doesn't start with a \)
|
||||
if ($type[0] !== '\\' && ! $withoutNamespace) {
|
||||
// Try to resolve the FQN using the class context
|
||||
$resolvedType = $this->tryResolveFqn($type, $class, $method);
|
||||
|
||||
if (! $resolvedType && ! $this->ignorePhpDocErrors) {
|
||||
throw new AnnotationException(sprintf(
|
||||
'The @return annotation for parameter "%s" of %s::%s contains a non existent class "%s". '
|
||||
. 'Did you maybe forget to add a "use" statement for this annotation?',
|
||||
$method,
|
||||
$class->name,
|
||||
$method->name,
|
||||
$type
|
||||
));
|
||||
}
|
||||
|
||||
$type = $resolvedType;
|
||||
}
|
||||
|
||||
if (! $this->ignorePhpDocErrors && ! $withoutNamespace && ! $this->classExists($type)) {
|
||||
throw new AnnotationException(sprintf(
|
||||
'The @return annotation for parameter "%s" of %s::%s contains a non existent class "%s"',
|
||||
$method,
|
||||
$class->name,
|
||||
$method->name,
|
||||
$type
|
||||
));
|
||||
}
|
||||
|
||||
// Remove the leading \ (FQN shouldn't contain it)
|
||||
$result[] = is_string($type) ? ltrim($type, '\\') : null;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the FQN of the provided $type based on the $class and $member context.
|
||||
*
|
||||
* @return null|string Fully qualified name of the type, or null if it could not be resolved
|
||||
*/
|
||||
protected function tryResolveFqn(string $type, ReflectionClass $class, Reflector $member): ?string
|
||||
{
|
||||
$alias = ($pos = strpos($type, '\\')) === false ? $type : substr($type, 0, $pos);
|
||||
$loweredAlias = strtolower($alias);
|
||||
|
||||
// Retrieve "use" statements
|
||||
$uses = $this->parser->parseUseStatements($class);
|
||||
|
||||
if (isset($uses[$loweredAlias])) {
|
||||
// Imported classes
|
||||
if ($pos !== false) {
|
||||
return $uses[$loweredAlias] . substr($type, $pos);
|
||||
}
|
||||
return $uses[$loweredAlias];
|
||||
}
|
||||
|
||||
if ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
|
||||
return $class->getNamespaceName() . '\\' . $type;
|
||||
}
|
||||
|
||||
if (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
|
||||
// Class namespace
|
||||
return $uses['__NAMESPACE__'] . '\\' . $type;
|
||||
}
|
||||
|
||||
if ($this->classExists($type)) {
|
||||
// No namespace
|
||||
return $type;
|
||||
}
|
||||
|
||||
// If all fail, try resolving through related traits
|
||||
return $this->tryResolveFqnInTraits($type, $class, $member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the FQN of the provided $type based on the $class and $member context, specifically searching
|
||||
* through the traits that are used by the provided $class.
|
||||
*
|
||||
* @return null|string Fully qualified name of the type, or null if it could not be resolved
|
||||
*/
|
||||
protected function tryResolveFqnInTraits(string $type, ReflectionClass $class, Reflector $member): ?string
|
||||
{
|
||||
/** @var ReflectionClass[] $traits */
|
||||
$traits = [];
|
||||
|
||||
// Get traits for the class and its parents
|
||||
while ($class) {
|
||||
$traits = array_merge($traits, $class->getTraits());
|
||||
$class = $class->getParentClass();
|
||||
}
|
||||
|
||||
foreach ($traits as $trait) {
|
||||
// Eliminate traits that don't have the property/method/parameter
|
||||
if ($member instanceof ReflectionProperty && ! $trait->hasProperty($member->name)) {
|
||||
continue;
|
||||
}
|
||||
if ($member instanceof ReflectionMethod && ! $trait->hasMethod($member->name)) {
|
||||
continue;
|
||||
}
|
||||
if ($member instanceof ReflectionParameter && ! $trait->hasMethod($member->getDeclaringFunction()->name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Run the resolver again with the ReflectionClass instance for the trait
|
||||
$resolvedType = $this->tryResolveFqn($type, $trait, $member);
|
||||
|
||||
if ($resolvedType) {
|
||||
return $resolvedType;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function classExists(string $class): bool
|
||||
{
|
||||
return class_exists($class) || interface_exists($class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\CodeGen;
|
||||
|
||||
use PhpDocReader\PhpDocReader;
|
||||
|
||||
class PhpDocReaderManager
|
||||
{
|
||||
/**
|
||||
* @var null|PhpDocReader
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
public static function getInstance(): PhpDocReader
|
||||
{
|
||||
if (static::$instance) {
|
||||
return static::$instance;
|
||||
}
|
||||
return static::$instance = new PhpDocReader();
|
||||
}
|
||||
}
|
||||
156
addons/epay/library/hyperf/utils/src/CodeGen/PhpParser.php
Normal file
156
addons/epay/library/hyperf/utils/src/CodeGen/PhpParser.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\CodeGen;
|
||||
|
||||
use Hyperf\Utils\Exception\InvalidArgumentException;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Parser;
|
||||
use PhpParser\ParserFactory;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
|
||||
class PhpParser
|
||||
{
|
||||
public const TYPES = [
|
||||
'int',
|
||||
'float',
|
||||
'string',
|
||||
'bool',
|
||||
'array',
|
||||
'object',
|
||||
'resource',
|
||||
'mixed',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var null|PhpParser
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* @var Parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$parserFactory = new ParserFactory();
|
||||
$this->parser = $parserFactory->create(ParserFactory::ONLY_PHP7);
|
||||
}
|
||||
|
||||
public static function getInstance(): PhpParser
|
||||
{
|
||||
if (static::$instance) {
|
||||
return static::$instance;
|
||||
}
|
||||
return static::$instance = new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Node\Stmt[]
|
||||
*/
|
||||
public function getNodesFromReflectionClass(ReflectionClass $reflectionClass): ?array
|
||||
{
|
||||
$code = file_get_contents($reflectionClass->getFileName());
|
||||
return $this->parser->parse($code);
|
||||
}
|
||||
|
||||
public function getNodeFromReflectionParameter(ReflectionParameter $parameter): Node\Param
|
||||
{
|
||||
$result = new Node\Param(
|
||||
new Node\Expr\Variable($parameter->getName())
|
||||
);
|
||||
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
$result->default = $this->getExprFromValue($parameter->getDefaultValue());
|
||||
}
|
||||
|
||||
if ($parameter->hasType()) {
|
||||
/** @var \ReflectionNamedType|\ReflectionUnionType $reflection */
|
||||
$reflection = $parameter->getType();
|
||||
if ($reflection instanceof \ReflectionUnionType) {
|
||||
$unionType = [];
|
||||
foreach ($reflection->getTypes() as $objType) {
|
||||
$type = $objType->getName();
|
||||
if (! in_array($type, static::TYPES)) {
|
||||
$unionType[] = new Node\Name('\\' . $type);
|
||||
} else {
|
||||
$unionType[] = new Node\Identifier($type);
|
||||
}
|
||||
}
|
||||
$result->type = new Node\UnionType($unionType);
|
||||
} else {
|
||||
$type = $reflection->getName();
|
||||
if (! in_array($type, static::TYPES)) {
|
||||
$result->type = new Node\Name('\\' . $type);
|
||||
} else {
|
||||
$result->type = new Node\Identifier($type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($parameter->isPassedByReference()) {
|
||||
$result->byRef = true;
|
||||
}
|
||||
|
||||
if ($parameter->isVariadic()) {
|
||||
$result->variadic = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getExprFromValue($value): Node\Expr
|
||||
{
|
||||
switch (gettype($value)) {
|
||||
case 'array':
|
||||
return new Node\Expr\Array_($value);
|
||||
case 'string':
|
||||
return new Node\Scalar\String_($value);
|
||||
case 'integer':
|
||||
return new Node\Scalar\LNumber($value);
|
||||
case 'double':
|
||||
return new Node\Scalar\DNumber($value);
|
||||
case 'NULL':
|
||||
return new Node\Expr\ConstFetch(new Node\Name('null'));
|
||||
case 'boolean':
|
||||
return new Node\Expr\ConstFetch(new Node\Name($value ? 'true' : 'false'));
|
||||
default:
|
||||
throw new InvalidArgumentException($value . ' is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node\Stmt\ClassMethod[]
|
||||
*/
|
||||
public function getAllMethodsFromStmts(array $stmts): array
|
||||
{
|
||||
$methods = [];
|
||||
foreach ($stmts as $namespace) {
|
||||
if (! $namespace instanceof Node\Stmt\Namespace_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($namespace->stmts as $class) {
|
||||
if (! $class instanceof Node\Stmt\Class_ && ! $class instanceof Node\Stmt\Interface_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($class->getMethods() as $method) {
|
||||
$methods[] = $method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
}
|
||||
69
addons/epay/library/hyperf/utils/src/CodeGen/Project.php
Normal file
69
addons/epay/library/hyperf/utils/src/CodeGen/Project.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\CodeGen;
|
||||
|
||||
use Hyperf\Utils\Composer;
|
||||
use Hyperf\Utils\Str;
|
||||
|
||||
/**
|
||||
* Read composer.json autoload psr-4 rules to figure out the namespace or path.
|
||||
*/
|
||||
class Project
|
||||
{
|
||||
public function namespace(string $path): string
|
||||
{
|
||||
$ext = pathinfo($path, PATHINFO_EXTENSION);
|
||||
|
||||
if ($ext !== '') {
|
||||
$path = substr($path, 0, -(strlen($ext) + 1));
|
||||
} else {
|
||||
$path = trim($path, '/') . '/';
|
||||
}
|
||||
|
||||
foreach ($this->getAutoloadRules() as $prefix => $prefixPath) {
|
||||
if ($this->isRootNamespace($prefix) || strpos($path, $prefixPath) === 0) {
|
||||
return $prefix . str_replace('/', '\\', substr($path, strlen($prefixPath)));
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException("Invalid project path: {$path}");
|
||||
}
|
||||
|
||||
public function className(string $path): string
|
||||
{
|
||||
return $this->namespace($path);
|
||||
}
|
||||
|
||||
public function path(string $name, $extension = '.php'): string
|
||||
{
|
||||
if (Str::endsWith($name, '\\')) {
|
||||
$extension = '';
|
||||
}
|
||||
|
||||
foreach ($this->getAutoloadRules() as $prefix => $prefixPath) {
|
||||
if ($this->isRootNamespace($prefix) || strpos($name, $prefix) === 0) {
|
||||
return $prefixPath . str_replace('\\', '/', substr($name, strlen($prefix))) . $extension;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \RuntimeException("Invalid class name: {$name}");
|
||||
}
|
||||
|
||||
protected function isRootNamespace(string $namespace): bool
|
||||
{
|
||||
return $namespace === '';
|
||||
}
|
||||
|
||||
protected function getAutoloadRules(): array
|
||||
{
|
||||
return data_get(Composer::getJsonContent(), 'autoload.psr-4', []);
|
||||
}
|
||||
}
|
||||
39
addons/epay/library/hyperf/utils/src/Codec/Base62.php
Normal file
39
addons/epay/library/hyperf/utils/src/Codec/Base62.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Codec;
|
||||
|
||||
class Base62
|
||||
{
|
||||
public const CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
public const BASE = 62;
|
||||
|
||||
public static function encode(int $number): string
|
||||
{
|
||||
$chars = [];
|
||||
while ($number > 0) {
|
||||
$remain = $number % self::BASE;
|
||||
$chars[] = self::CHARS[$remain];
|
||||
$number = ($number - $remain) / self::BASE;
|
||||
}
|
||||
return implode('', array_reverse($chars));
|
||||
}
|
||||
|
||||
public static function decode(string $data): int
|
||||
{
|
||||
return array_reduce(array_map(function ($character) {
|
||||
return strpos(self::CHARS, $character);
|
||||
}, str_split($data)), function ($result, $remain) {
|
||||
return $result * self::BASE + $remain;
|
||||
});
|
||||
}
|
||||
}
|
||||
56
addons/epay/library/hyperf/utils/src/Codec/Json.php
Normal file
56
addons/epay/library/hyperf/utils/src/Codec/Json.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Codec;
|
||||
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Jsonable;
|
||||
use Hyperf\Utils\Exception\InvalidArgumentException;
|
||||
|
||||
class Json
|
||||
{
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function encode($data, int $flags = JSON_UNESCAPED_UNICODE, int $depth = 512): string
|
||||
{
|
||||
if ($data instanceof Jsonable) {
|
||||
return (string) $data;
|
||||
}
|
||||
|
||||
if ($data instanceof Arrayable) {
|
||||
$data = $data->toArray();
|
||||
}
|
||||
|
||||
try {
|
||||
$json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth);
|
||||
} catch (\Throwable $exception) {
|
||||
throw new InvalidArgumentException($exception->getMessage(), $exception->getCode());
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function decode(string $json, bool $assoc = true, int $depth = 512, int $flags = 0)
|
||||
{
|
||||
try {
|
||||
$decode = json_decode($json, $assoc, $depth, $flags | JSON_THROW_ON_ERROR);
|
||||
} catch (\Throwable $exception) {
|
||||
throw new InvalidArgumentException($exception->getMessage(), $exception->getCode());
|
||||
}
|
||||
|
||||
return $decode;
|
||||
}
|
||||
}
|
||||
70
addons/epay/library/hyperf/utils/src/Codec/Xml.php
Normal file
70
addons/epay/library/hyperf/utils/src/Codec/Xml.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Codec;
|
||||
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Xmlable;
|
||||
use Hyperf\Utils\Exception\InvalidArgumentException;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class Xml
|
||||
{
|
||||
public static function toXml($data, $parentNode = null, $root = 'root')
|
||||
{
|
||||
if ($data instanceof Xmlable) {
|
||||
return (string) $data;
|
||||
}
|
||||
if ($data instanceof Arrayable) {
|
||||
$data = $data->toArray();
|
||||
} else {
|
||||
$data = (array) $data;
|
||||
}
|
||||
if ($parentNode === null) {
|
||||
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?>' . "<{$root}></{$root}>");
|
||||
} else {
|
||||
$xml = $parentNode;
|
||||
}
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
self::toXml($value, $xml->addChild($key));
|
||||
} else {
|
||||
if (is_numeric($key)) {
|
||||
$xml->addChild('item' . $key, (string) $value);
|
||||
} else {
|
||||
$xml->addChild($key, (string) $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return trim($xml->asXML());
|
||||
}
|
||||
|
||||
public static function toArray($xml)
|
||||
{
|
||||
// For PHP 8.0, libxml_disable_entity_loader() has been deprecated.
|
||||
// As libxml 2.9.0 is now required, external entity loading is guaranteed to be disabled by default.
|
||||
// And this function is no longer needed to protect against XXE attacks, unless the (still vulnerable). LIBXML_NOENT is used.
|
||||
// In that case, it is recommended to refactor the code using libxml_set_external_entity_loader() to suppress loading of external entities.
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
$disableLibxmlEntityLoader = libxml_disable_entity_loader(true);
|
||||
$respObject = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOERROR);
|
||||
libxml_disable_entity_loader($disableLibxmlEntityLoader);
|
||||
} else {
|
||||
$respObject = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOERROR);
|
||||
}
|
||||
|
||||
if ($respObject === false) {
|
||||
throw new InvalidArgumentException('Syntax error.');
|
||||
}
|
||||
|
||||
return json_decode(json_encode($respObject), true);
|
||||
}
|
||||
}
|
||||
1835
addons/epay/library/hyperf/utils/src/Collection.php
Normal file
1835
addons/epay/library/hyperf/utils/src/Collection.php
Normal file
File diff suppressed because it is too large
Load Diff
159
addons/epay/library/hyperf/utils/src/Composer.php
Normal file
159
addons/epay/library/hyperf/utils/src/Composer.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
class Composer
|
||||
{
|
||||
/**
|
||||
* @var null|Collection
|
||||
*/
|
||||
private static $content;
|
||||
|
||||
/**
|
||||
* @var null|Collection
|
||||
*/
|
||||
private static $json;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $extra = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $scripts = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $versions = [];
|
||||
|
||||
/**
|
||||
* @var null|ClassLoader
|
||||
*/
|
||||
private static $classLoader;
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException When composer.lock does not exist.
|
||||
*/
|
||||
public static function getLockContent(): Collection
|
||||
{
|
||||
if (! self::$content) {
|
||||
$path = self::discoverLockFile();
|
||||
if (! $path) {
|
||||
throw new \RuntimeException('composer.lock not found.');
|
||||
}
|
||||
self::$content = collect(json_decode(file_get_contents($path), true));
|
||||
$packages = self::$content->offsetGet('packages') ?? [];
|
||||
$packagesDev = self::$content->offsetGet('packages-dev') ?? [];
|
||||
foreach (array_merge($packages, $packagesDev) as $package) {
|
||||
$packageName = '';
|
||||
foreach ($package ?? [] as $key => $value) {
|
||||
if ($key === 'name') {
|
||||
$packageName = $value;
|
||||
continue;
|
||||
}
|
||||
switch ($key) {
|
||||
case 'extra':
|
||||
$packageName && self::$extra[$packageName] = $value;
|
||||
break;
|
||||
case 'scripts':
|
||||
$packageName && self::$scripts[$packageName] = $value;
|
||||
break;
|
||||
case 'version':
|
||||
$packageName && self::$versions[$packageName] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$content;
|
||||
}
|
||||
|
||||
public static function getJsonContent(): Collection
|
||||
{
|
||||
if (! self::$json) {
|
||||
$path = BASE_PATH . '/composer.json';
|
||||
if (! is_readable($path)) {
|
||||
throw new \RuntimeException('composer.json is not readable.');
|
||||
}
|
||||
self::$json = collect(json_decode(file_get_contents($path), true));
|
||||
}
|
||||
return self::$json;
|
||||
}
|
||||
|
||||
public static function discoverLockFile(): string
|
||||
{
|
||||
$path = '';
|
||||
if (is_readable(BASE_PATH . '/composer.lock')) {
|
||||
$path = BASE_PATH . '/composer.lock';
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
public static function getMergedExtra(string $key = null)
|
||||
{
|
||||
if (! self::$extra) {
|
||||
self::getLockContent();
|
||||
}
|
||||
if ($key === null) {
|
||||
return self::$extra;
|
||||
}
|
||||
$extra = [];
|
||||
foreach (self::$extra ?? [] as $project => $config) {
|
||||
foreach ($config ?? [] as $configKey => $item) {
|
||||
if ($key === $configKey && $item) {
|
||||
foreach ($item ?? [] as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$extra[$k] = array_merge($extra[$k] ?? [], $v);
|
||||
} else {
|
||||
$extra[$k][] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $extra;
|
||||
}
|
||||
|
||||
public static function getLoader(): ClassLoader
|
||||
{
|
||||
if (! self::$classLoader) {
|
||||
self::$classLoader = self::findLoader();
|
||||
}
|
||||
return self::$classLoader;
|
||||
}
|
||||
|
||||
public static function setLoader(ClassLoader $classLoader): ClassLoader
|
||||
{
|
||||
self::$classLoader = $classLoader;
|
||||
return $classLoader;
|
||||
}
|
||||
|
||||
private static function findLoader(): ClassLoader
|
||||
{
|
||||
$composerClass = '';
|
||||
foreach (get_declared_classes() as $declaredClass) {
|
||||
if (strpos($declaredClass, 'ComposerAutoloaderInit') === 0 && method_exists($declaredClass, 'getLoader')) {
|
||||
$composerClass = $declaredClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! $composerClass) {
|
||||
throw new \RuntimeException('Composer loader not found.');
|
||||
}
|
||||
return $composerClass::getLoader();
|
||||
}
|
||||
}
|
||||
37
addons/epay/library/hyperf/utils/src/ConfigProvider.php
Normal file
37
addons/epay/library/hyperf/utils/src/ConfigProvider.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Hyperf\Contract\NormalizerInterface;
|
||||
use Hyperf\Utils\Serializer\SerializerFactory;
|
||||
use Hyperf\Utils\Serializer\SimpleNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
return [
|
||||
'dependencies' => [
|
||||
Serializer::class => SerializerFactory::class,
|
||||
NormalizerInterface::class => SimpleNormalizer::class,
|
||||
],
|
||||
'annotations' => [
|
||||
'scan' => [
|
||||
'paths' => [
|
||||
__DIR__,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
107
addons/epay/library/hyperf/utils/src/Context.php
Normal file
107
addons/epay/library/hyperf/utils/src/Context.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Hyperf\Engine\Coroutine as Co;
|
||||
|
||||
/**
|
||||
* @deprecated v3.0 please use `hyperf/context` instead.
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
protected static $nonCoContext = [];
|
||||
|
||||
public static function set(string $id, $value)
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
Co::getContextFor()[$id] = $value;
|
||||
} else {
|
||||
static::$nonCoContext[$id] = $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function get(string $id, $default = null, $coroutineId = null)
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
return Co::getContextFor($coroutineId)[$id] ?? $default;
|
||||
}
|
||||
|
||||
return static::$nonCoContext[$id] ?? $default;
|
||||
}
|
||||
|
||||
public static function has(string $id, $coroutineId = null)
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
return isset(Co::getContextFor($coroutineId)[$id]);
|
||||
}
|
||||
|
||||
return isset(static::$nonCoContext[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the context when you are not in coroutine environment.
|
||||
*/
|
||||
public static function destroy(string $id)
|
||||
{
|
||||
unset(static::$nonCoContext[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the context from a coroutine to current coroutine.
|
||||
*/
|
||||
public static function copy(int $fromCoroutineId, array $keys = []): void
|
||||
{
|
||||
$from = Co::getContextFor($fromCoroutineId);
|
||||
if ($from === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current = Co::getContextFor();
|
||||
$current->exchangeArray($keys ? Arr::only($from->getArrayCopy(), $keys) : $from->getArrayCopy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value and override it by closure.
|
||||
*/
|
||||
public static function override(string $id, \Closure $closure)
|
||||
{
|
||||
$value = null;
|
||||
if (self::has($id)) {
|
||||
$value = self::get($id);
|
||||
}
|
||||
$value = $closure($value);
|
||||
self::set($id, $value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value and store it if not exists.
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function getOrSet(string $id, $value)
|
||||
{
|
||||
if (! self::has($id)) {
|
||||
return self::set($id, value($value));
|
||||
}
|
||||
return self::get($id);
|
||||
}
|
||||
|
||||
public static function getContainer()
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
return Co::getContextFor();
|
||||
}
|
||||
|
||||
return static::$nonCoContext;
|
||||
}
|
||||
}
|
||||
24
addons/epay/library/hyperf/utils/src/Contracts/Arrayable.php
Normal file
24
addons/epay/library/hyperf/utils/src/Contracts/Arrayable.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
/**
|
||||
* @template TKey of array-key
|
||||
* @template TValue
|
||||
*/
|
||||
interface Arrayable
|
||||
{
|
||||
/**
|
||||
* @return array<TKey, TValue>
|
||||
*/
|
||||
public function toArray(): array;
|
||||
}
|
||||
17
addons/epay/library/hyperf/utils/src/Contracts/Jsonable.php
Normal file
17
addons/epay/library/hyperf/utils/src/Contracts/Jsonable.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
interface Jsonable
|
||||
{
|
||||
public function __toString(): string;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
interface MessageBag
|
||||
{
|
||||
/**
|
||||
* Get the keys present in the message bag.
|
||||
*/
|
||||
public function keys(): array;
|
||||
|
||||
/**
|
||||
* Add a message to the bag.
|
||||
*/
|
||||
public function add(string $key, string $message): MessageBag;
|
||||
|
||||
/**
|
||||
* Merge a new array of messages into the bag.
|
||||
*
|
||||
* @param array|MessageProvider $messages
|
||||
* @return $this
|
||||
*/
|
||||
public function merge($messages);
|
||||
|
||||
/**
|
||||
* Determine if messages exist for a given key.
|
||||
*
|
||||
* @param array|string $key
|
||||
*/
|
||||
public function has($key): bool;
|
||||
|
||||
/**
|
||||
* Get the first message from the bag for a given key.
|
||||
*/
|
||||
public function first(?string $key = null, ?string $format = null): string;
|
||||
|
||||
/**
|
||||
* Get all of the messages from the bag for a given key.
|
||||
*/
|
||||
public function get(string $key, ?string $format = null): array;
|
||||
|
||||
/**
|
||||
* Get all of the messages for every key in the bag.
|
||||
*/
|
||||
public function all(?string $format = null): array;
|
||||
|
||||
/**
|
||||
* Get the raw messages in the container.
|
||||
*/
|
||||
public function getMessages(): array;
|
||||
|
||||
/**
|
||||
* Get the default message format.
|
||||
*/
|
||||
public function getFormat(): string;
|
||||
|
||||
/**
|
||||
* Set the default message format.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormat(string $format = ':message');
|
||||
|
||||
/**
|
||||
* Determine if the message bag has any messages.
|
||||
*/
|
||||
public function isEmpty(): bool;
|
||||
|
||||
/**
|
||||
* Determine if the message bag has any messages.
|
||||
*/
|
||||
public function isNotEmpty(): bool;
|
||||
|
||||
/**
|
||||
* Get the number of messages in the container.
|
||||
*/
|
||||
public function count(): int;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
interface MessageProvider
|
||||
{
|
||||
/**
|
||||
* Get the messages for the instance.
|
||||
*/
|
||||
public function getMessageBag(): MessageBag;
|
||||
}
|
||||
17
addons/epay/library/hyperf/utils/src/Contracts/Xmlable.php
Normal file
17
addons/epay/library/hyperf/utils/src/Contracts/Xmlable.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
interface Xmlable
|
||||
{
|
||||
public function __toString(): string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Coordinator;
|
||||
|
||||
class Constants
|
||||
{
|
||||
/**
|
||||
* Swoole onWorkerStart event.
|
||||
*/
|
||||
public const WORKER_START = 'workerStart';
|
||||
|
||||
/**
|
||||
* Swoole onWorkerExit event.
|
||||
*/
|
||||
public const WORKER_EXIT = 'workerExit';
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Coordinator;
|
||||
|
||||
use Hyperf\Engine\Channel;
|
||||
|
||||
class Coordinator
|
||||
{
|
||||
/**
|
||||
* @var Channel
|
||||
*/
|
||||
private $channel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->channel = new Channel(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Yield the current coroutine for a given timeout,
|
||||
* unless the coordinator is woke up from outside.
|
||||
*
|
||||
* @param float|int $timeout
|
||||
* @return bool returns true if the coordinator has been woken up
|
||||
*/
|
||||
public function yield($timeout = -1): bool
|
||||
{
|
||||
$this->channel->pop((float) $timeout);
|
||||
return $this->channel->isClosing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakeup all coroutines yielding for this coordinator.
|
||||
*/
|
||||
public function resume(): void
|
||||
{
|
||||
$this->channel->close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Coordinator;
|
||||
|
||||
class CoordinatorManager
|
||||
{
|
||||
/**
|
||||
* A container that is used for storing coordinator.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $container = [];
|
||||
|
||||
/**
|
||||
* You should initialize a Coordinator with the identifier before use it.
|
||||
*/
|
||||
public static function initialize(string $identifier): void
|
||||
{
|
||||
static::$container[$identifier] = new Coordinator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Coordinator from container by the identifier.
|
||||
*
|
||||
* @throws \RuntimeException when the Coordinator with the identifier has not initialization
|
||||
*/
|
||||
public static function until(string $identifier): Coordinator
|
||||
{
|
||||
if (! isset(static::$container[$identifier])) {
|
||||
static::$container[$identifier] = new Coordinator();
|
||||
}
|
||||
|
||||
return static::$container[$identifier];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the Coordinator by the identifier from container after used,
|
||||
* otherwise memory leaks will occur.
|
||||
*/
|
||||
public static function clear(string $identifier): void
|
||||
{
|
||||
unset(static::$container[$identifier]);
|
||||
}
|
||||
}
|
||||
92
addons/epay/library/hyperf/utils/src/Coroutine.php
Normal file
92
addons/epay/library/hyperf/utils/src/Coroutine.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Engine\Coroutine as Co;
|
||||
use Hyperf\Engine\Exception\CoroutineDestroyedException;
|
||||
use Hyperf\Engine\Exception\RunningInNonCoroutineException;
|
||||
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
|
||||
class Coroutine
|
||||
{
|
||||
/**
|
||||
* Returns the current coroutine ID.
|
||||
* Returns -1 when running in non-coroutine context.
|
||||
*/
|
||||
public static function id(): int
|
||||
{
|
||||
return Co::id();
|
||||
}
|
||||
|
||||
public static function defer(callable $callable)
|
||||
{
|
||||
Co::defer($callable);
|
||||
}
|
||||
|
||||
public static function sleep(float $seconds)
|
||||
{
|
||||
usleep(intval($seconds * 1000 * 1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent coroutine ID.
|
||||
* Returns 0 when running in the top level coroutine.
|
||||
* @throws RunningInNonCoroutineException when running in non-coroutine context
|
||||
* @throws CoroutineDestroyedException when the coroutine has been destroyed
|
||||
*/
|
||||
public static function parentId(?int $coroutineId = null): int
|
||||
{
|
||||
return Co::pid($coroutineId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Returns the coroutine ID of the coroutine just created.
|
||||
* Returns -1 when coroutine create failed.
|
||||
*/
|
||||
public static function create(callable $callable): int
|
||||
{
|
||||
$coroutine = Co::create(function () use ($callable) {
|
||||
try {
|
||||
call($callable);
|
||||
} catch (Throwable $throwable) {
|
||||
if (ApplicationContext::hasContainer()) {
|
||||
$container = ApplicationContext::getContainer();
|
||||
if ($container->has(StdoutLoggerInterface::class)) {
|
||||
/* @var LoggerInterface $logger */
|
||||
$logger = $container->get(StdoutLoggerInterface::class);
|
||||
/* @var FormatterInterface $formatter */
|
||||
if ($container->has(FormatterInterface::class)) {
|
||||
$formatter = $container->get(FormatterInterface::class);
|
||||
$logger->warning($formatter->format($throwable));
|
||||
} else {
|
||||
$logger->warning(sprintf('Uncaptured exception[%s] detected in %s::%d.', get_class($throwable), $throwable->getFile(), $throwable->getLine()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return $coroutine->getId();
|
||||
} catch (\Throwable $exception) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static function inCoroutine(): bool
|
||||
{
|
||||
return Co::id() > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Coroutine;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Engine\Channel;
|
||||
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Coroutine;
|
||||
|
||||
/**
|
||||
* @method bool isFull()
|
||||
* @method bool isEmpty()
|
||||
*/
|
||||
class Concurrent
|
||||
{
|
||||
/**
|
||||
* @var Channel
|
||||
*/
|
||||
protected $channel;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $limit;
|
||||
|
||||
public function __construct(int $limit)
|
||||
{
|
||||
$this->limit = $limit;
|
||||
$this->channel = new Channel($limit);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if (in_array($name, ['isFull', 'isEmpty'])) {
|
||||
return $this->channel->{$name}(...$arguments);
|
||||
}
|
||||
}
|
||||
|
||||
public function getLimit(): int
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
public function length(): int
|
||||
{
|
||||
return $this->channel->getLength();
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return $this->channel->getLength();
|
||||
}
|
||||
|
||||
public function getRunningCoroutineCount(): int
|
||||
{
|
||||
return $this->getLength();
|
||||
}
|
||||
|
||||
public function getChannel(): Channel
|
||||
{
|
||||
return $this->channel;
|
||||
}
|
||||
|
||||
public function create(callable $callable): void
|
||||
{
|
||||
$this->channel->push(true);
|
||||
|
||||
Coroutine::create(function () use ($callable) {
|
||||
try {
|
||||
$callable();
|
||||
} catch (\Throwable $exception) {
|
||||
if (ApplicationContext::hasContainer()) {
|
||||
$container = ApplicationContext::getContainer();
|
||||
if ($container->has(StdoutLoggerInterface::class) && $container->has(FormatterInterface::class)) {
|
||||
$logger = $container->get(StdoutLoggerInterface::class);
|
||||
$formatter = $container->get(FormatterInterface::class);
|
||||
$logger->error($formatter->format($exception));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$this->channel->pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
60
addons/epay/library/hyperf/utils/src/Coroutine/Locker.php
Normal file
60
addons/epay/library/hyperf/utils/src/Coroutine/Locker.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Coroutine;
|
||||
|
||||
use Hyperf\Utils\Coroutine;
|
||||
use Hyperf\Utils\Traits\Container;
|
||||
use Swoole\Coroutine as SwooleCoroutine;
|
||||
|
||||
class Locker
|
||||
{
|
||||
use Container;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $container = [];
|
||||
|
||||
public static function add($key, $id): void
|
||||
{
|
||||
self::$container[$key][] = $id;
|
||||
}
|
||||
|
||||
public static function clear($key): void
|
||||
{
|
||||
unset(self::$container[$key]);
|
||||
}
|
||||
|
||||
public static function lock($key): bool
|
||||
{
|
||||
if (! self::has($key)) {
|
||||
self::add($key, 0);
|
||||
return true;
|
||||
}
|
||||
self::add($key, Coroutine::id());
|
||||
SwooleCoroutine::suspend();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function unlock($key): void
|
||||
{
|
||||
if (self::has($key)) {
|
||||
$ids = self::get($key);
|
||||
foreach ($ids as $id) {
|
||||
if ($id > 0) {
|
||||
SwooleCoroutine::resume($id);
|
||||
}
|
||||
}
|
||||
self::clear($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
class ChannelClosedException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
final class ExceptionThrower
|
||||
{
|
||||
/**
|
||||
* @var Throwable
|
||||
*/
|
||||
private $throwable;
|
||||
|
||||
public function __construct(Throwable $throwable)
|
||||
{
|
||||
$this->throwable = $throwable;
|
||||
}
|
||||
|
||||
public function getThrowable(): Throwable
|
||||
{
|
||||
return $this->throwable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
class ParallelExecutionException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $results;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $throwables;
|
||||
|
||||
public function getResults()
|
||||
{
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
public function setResults(array $results)
|
||||
{
|
||||
$this->results = $results;
|
||||
}
|
||||
|
||||
public function getThrowables()
|
||||
{
|
||||
return $this->throwables;
|
||||
}
|
||||
|
||||
public function setThrowables(array $throwables)
|
||||
{
|
||||
return $this->throwables = $throwables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
class TimeoutException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Exception;
|
||||
|
||||
class WaitTimeoutException extends TimeoutException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Filesystem;
|
||||
|
||||
class FileNotFoundException extends \Exception
|
||||
{
|
||||
}
|
||||
554
addons/epay/library/hyperf/utils/src/Filesystem/Filesystem.php
Normal file
554
addons/epay/library/hyperf/utils/src/Filesystem/Filesystem.php
Normal file
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Filesystem;
|
||||
|
||||
use ErrorException;
|
||||
use FilesystemIterator;
|
||||
use Hyperf\Macroable\Macroable;
|
||||
use Hyperf\Utils\Coroutine;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Most of the methods in this file come from illuminate/filesystem,
|
||||
* thanks Laravel Team provide such a useful class.
|
||||
*/
|
||||
class Filesystem
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* Determine if a file or directory exists.
|
||||
*/
|
||||
public function exists(string $path): bool
|
||||
{
|
||||
return file_exists($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a file.
|
||||
*
|
||||
* @throws \Hyperf\Utils\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get(string $path, bool $lock = false): string
|
||||
{
|
||||
if ($this->isFile($path)) {
|
||||
return $lock ? $this->sharedGet($path) : file_get_contents($path);
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("File does not exist at path {$path}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contents of a file with shared access.
|
||||
*/
|
||||
public function sharedGet(string $path): string
|
||||
{
|
||||
return $this->atomic($path, function ($path) {
|
||||
$contents = '';
|
||||
$handle = fopen($path, 'rb');
|
||||
if ($handle) {
|
||||
$wouldBlock = false;
|
||||
flock($handle, LOCK_SH | LOCK_NB, $wouldBlock);
|
||||
while ($wouldBlock) {
|
||||
usleep(1000);
|
||||
flock($handle, LOCK_SH | LOCK_NB, $wouldBlock);
|
||||
}
|
||||
try {
|
||||
clearstatcache(true, $path);
|
||||
$contents = fread($handle, $this->size($path) ?: 1);
|
||||
} finally {
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
return $contents;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the returned value of a file.
|
||||
*
|
||||
* @throws \Hyperf\Utils\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function getRequire(string $path)
|
||||
{
|
||||
if ($this->isFile($path)) {
|
||||
return require $path;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("File does not exist at path {$path}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the given file once.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function requireOnce(string $file)
|
||||
{
|
||||
require_once $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MD5 hash of the file at the given path.
|
||||
*/
|
||||
public function hash(string $path): string
|
||||
{
|
||||
return md5_file($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears file status cache.
|
||||
*/
|
||||
public function clearStatCache(string $path): void
|
||||
{
|
||||
clearstatcache(true, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of a file.
|
||||
*
|
||||
* @param resource|string $contents
|
||||
* @return bool|int
|
||||
*/
|
||||
public function put(string $path, $contents, bool $lock = false)
|
||||
{
|
||||
if ($lock) {
|
||||
return $this->atomic($path, function ($path) use ($contents) {
|
||||
$handle = fopen($path, 'w+');
|
||||
if ($handle) {
|
||||
$wouldBlock = false;
|
||||
flock($handle, LOCK_EX | LOCK_NB, $wouldBlock);
|
||||
while ($wouldBlock) {
|
||||
usleep(1000);
|
||||
flock($handle, LOCK_EX | LOCK_NB, $wouldBlock);
|
||||
}
|
||||
try {
|
||||
fwrite($handle, $contents);
|
||||
} finally {
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return file_put_contents($path, $contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of a file, replacing it atomically if it already exists.
|
||||
*/
|
||||
public function replace(string $path, string $content)
|
||||
{
|
||||
// If the path already exists and is a symlink, get the real path...
|
||||
clearstatcache(true, $path);
|
||||
|
||||
$path = realpath($path) ?: $path;
|
||||
|
||||
$tempPath = tempnam(dirname($path), basename($path));
|
||||
|
||||
// Fix permissions of tempPath because `tempnam()` creates it with permissions set to 0600...
|
||||
chmod($tempPath, 0777 - umask());
|
||||
|
||||
file_put_contents($tempPath, $content);
|
||||
|
||||
rename($tempPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend to a file.
|
||||
*/
|
||||
public function prepend(string $path, string $data): int
|
||||
{
|
||||
if ($this->exists($path)) {
|
||||
return $this->put($path, $data . $this->get($path));
|
||||
}
|
||||
|
||||
return $this->put($path, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append to a file.
|
||||
*/
|
||||
public function append(string $path, string $data): int
|
||||
{
|
||||
return file_put_contents($path, $data, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set UNIX mode of a file or directory.
|
||||
*/
|
||||
public function chmod(string $path, ?int $mode = null)
|
||||
{
|
||||
if ($mode) {
|
||||
return chmod($path, $mode);
|
||||
}
|
||||
|
||||
return substr(sprintf('%o', fileperms($path)), -4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the file at a given path.
|
||||
*
|
||||
* @param array|string $paths
|
||||
*/
|
||||
public function delete($paths): bool
|
||||
{
|
||||
$paths = is_array($paths) ? $paths : func_get_args();
|
||||
|
||||
$success = true;
|
||||
|
||||
foreach ($paths as $path) {
|
||||
try {
|
||||
if (! @unlink($path)) {
|
||||
$success = false;
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a file to a new location.
|
||||
*/
|
||||
public function move(string $path, string $target): bool
|
||||
{
|
||||
return rename($path, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file to a new location.
|
||||
*/
|
||||
public function copy(string $path, string $target): bool
|
||||
{
|
||||
return copy($path, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a hard link to the target file or directory.
|
||||
*/
|
||||
public function link(string $target, string $link)
|
||||
{
|
||||
if (! $this->windowsOs()) {
|
||||
return symlink($target, $link);
|
||||
}
|
||||
|
||||
$mode = $this->isDirectory($target) ? 'J' : 'H';
|
||||
|
||||
exec("mklink /{$mode} \"{$link}\" \"{$target}\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the file name from a file path.
|
||||
*/
|
||||
public function name(string $path): string
|
||||
{
|
||||
return pathinfo($path, PATHINFO_FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the trailing name component from a file path.
|
||||
*/
|
||||
public function basename(string $path): string
|
||||
{
|
||||
return pathinfo($path, PATHINFO_BASENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the parent directory from a file path.
|
||||
*/
|
||||
public function dirname(string $path): string
|
||||
{
|
||||
return pathinfo($path, PATHINFO_DIRNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the file extension from a file path.
|
||||
*/
|
||||
public function extension(string $path): string
|
||||
{
|
||||
return pathinfo($path, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file type of a given file.
|
||||
*/
|
||||
public function type(string $path): string
|
||||
{
|
||||
return filetype($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mime-type of a given file.
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function mimeType(string $path)
|
||||
{
|
||||
return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file size of a given file.
|
||||
*/
|
||||
public function size(string $path): int
|
||||
{
|
||||
return filesize($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file's last modification time.
|
||||
*/
|
||||
public function lastModified(string $path): int
|
||||
{
|
||||
return filemtime($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path is a directory.
|
||||
*/
|
||||
public function isDirectory(string $directory): bool
|
||||
{
|
||||
return is_dir($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path is readable.
|
||||
*/
|
||||
public function isReadable(string $path): bool
|
||||
{
|
||||
return is_readable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path is writable.
|
||||
*/
|
||||
public function isWritable(string $path): bool
|
||||
{
|
||||
return is_writable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path is a file.
|
||||
*/
|
||||
public function isFile(string $file): bool
|
||||
{
|
||||
return is_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find path names matching a given pattern.
|
||||
*/
|
||||
public function glob(string $pattern, int $flags = 0): array
|
||||
{
|
||||
return glob($pattern, $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all files in a directory.
|
||||
*
|
||||
* @return \Symfony\Component\Finder\SplFileInfo[]
|
||||
*/
|
||||
public function files(string $directory, bool $hidden = false): array
|
||||
{
|
||||
return iterator_to_array(
|
||||
Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->depth(0)->sortByName(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the files from the given directory (recursive).
|
||||
* @return \Symfony\Component\Finder\SplFileInfo[]
|
||||
*/
|
||||
public function allFiles(string $directory, bool $hidden = false): array
|
||||
{
|
||||
return iterator_to_array(
|
||||
Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->sortByName(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the directories within a given directory.
|
||||
*/
|
||||
public function directories(string $directory): array
|
||||
{
|
||||
$directories = [];
|
||||
|
||||
foreach (Finder::create()->in($directory)->directories()->depth(0)->sortByName() as $dir) {
|
||||
$directories[] = $dir->getPathname();
|
||||
}
|
||||
|
||||
return $directories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a directory.
|
||||
*/
|
||||
public function makeDirectory(string $path, int $mode = 0755, bool $recursive = false, bool $force = false): bool
|
||||
{
|
||||
if ($force) {
|
||||
return @mkdir($path, $mode, $recursive);
|
||||
}
|
||||
|
||||
return mkdir($path, $mode, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a directory.
|
||||
*/
|
||||
public function moveDirectory(string $from, string $to, bool $overwrite = false): bool
|
||||
{
|
||||
if ($overwrite && $this->isDirectory($to) && ! $this->deleteDirectory($to)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return @rename($from, $to) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a directory from one location to another.
|
||||
*/
|
||||
public function copyDirectory(string $directory, string $destination, int $options = null): bool
|
||||
{
|
||||
if (! $this->isDirectory($directory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$options = $options ?: FilesystemIterator::SKIP_DOTS;
|
||||
|
||||
// If the destination directory does not actually exist, we will go ahead and
|
||||
// create it recursively, which just gets the destination prepared to copy
|
||||
// the files over. Once we make the directory we'll proceed the copying.
|
||||
if (! $this->isDirectory($destination)) {
|
||||
$this->makeDirectory($destination, 0777, true);
|
||||
}
|
||||
|
||||
$items = new FilesystemIterator($directory, $options);
|
||||
|
||||
foreach ($items as $item) {
|
||||
// As we spin through items, we will check to see if the current file is actually
|
||||
// a directory or a file. When it is actually a directory we will need to call
|
||||
// back into this function recursively to keep copying these nested folders.
|
||||
$target = $destination . DIRECTORY_SEPARATOR . $item->getBasename();
|
||||
|
||||
if ($item->isDir()) {
|
||||
$path = $item->getPathname();
|
||||
|
||||
if (! $this->copyDirectory($path, $target, $options)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the current items is just a regular file, we will just copy this to the new
|
||||
// location and keep looping. If for some reason the copy fails we'll bail out
|
||||
// and return false, so the developer is aware that the copy process failed.
|
||||
else {
|
||||
if (! $this->copy($item->getPathname(), $target)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively delete a directory.
|
||||
*
|
||||
* The directory itself may be optionally preserved.
|
||||
*/
|
||||
public function deleteDirectory(string $directory, bool $preserve = false): bool
|
||||
{
|
||||
if (! $this->isDirectory($directory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$items = new FilesystemIterator($directory);
|
||||
|
||||
foreach ($items as $item) {
|
||||
// If the item is a directory, we can just recurse into the function and
|
||||
// delete that sub-directory otherwise we'll just delete the file and
|
||||
// keep iterating through each file until the directory is cleaned.
|
||||
if ($item->isDir() && ! $item->isLink()) {
|
||||
$this->deleteDirectory($item->getPathname());
|
||||
}
|
||||
|
||||
// If the item is just a file, we can go ahead and delete it since we're
|
||||
// just looping through and waxing all of the files in this directory
|
||||
// and calling directories recursively, so we delete the real path.
|
||||
else {
|
||||
$this->delete($item->getPathname());
|
||||
}
|
||||
}
|
||||
|
||||
if (! $preserve) {
|
||||
@rmdir($directory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all of the directories within a given directory.
|
||||
*/
|
||||
public function deleteDirectories(string $directory): bool
|
||||
{
|
||||
$allDirectories = $this->directories($directory);
|
||||
|
||||
if (! empty($allDirectories)) {
|
||||
foreach ($allDirectories as $directoryName) {
|
||||
$this->deleteDirectory($directoryName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the specified directory of all files and folders.
|
||||
*/
|
||||
public function cleanDirectory(string $directory): bool
|
||||
{
|
||||
return $this->deleteDirectory($directory, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect whether it's Windows.
|
||||
*/
|
||||
public function windowsOs(): bool
|
||||
{
|
||||
return stripos(PHP_OS, 'win') === 0;
|
||||
}
|
||||
|
||||
protected function atomic($path, $callback)
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
try {
|
||||
while (! Coroutine\Locker::lock($path)) {
|
||||
usleep(1000);
|
||||
}
|
||||
return $callback($path);
|
||||
} finally {
|
||||
Coroutine\Locker::unlock($path);
|
||||
}
|
||||
} else {
|
||||
return $callback($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
200
addons/epay/library/hyperf/utils/src/Fluent.php
Normal file
200
addons/epay/library/hyperf/utils/src/Fluent.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use ArrayAccess;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Jsonable;
|
||||
use JsonSerializable;
|
||||
|
||||
/**
|
||||
* Most of the methods in this file come from illuminate/support,
|
||||
* thanks Laravel Team provide such a useful class.
|
||||
*/
|
||||
class Fluent implements ArrayAccess, Arrayable, Jsonable, JsonSerializable
|
||||
{
|
||||
/**
|
||||
* All of the attributes set on the fluent instance.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = [];
|
||||
|
||||
/**
|
||||
* Create a new fluent instance.
|
||||
*
|
||||
* @param array|object $attributes
|
||||
*/
|
||||
public function __construct($attributes = [])
|
||||
{
|
||||
foreach ($attributes as $key => $value) {
|
||||
$this->attributes[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic calls to the fluent instance to set attributes.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
$this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically retrieve the value of an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically set the value of an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically check if an attribute is set.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->offsetExists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically unset an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
$this->offsetUnset($key);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an attribute from the fluent instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (array_key_exists($key, $this->attributes)) {
|
||||
return $this->attributes[$key];
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attributes from the fluent instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the fluent instance to an array.
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object into something JSON serializable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the fluent instance to JSON.
|
||||
*
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
public function toJson($options = 0)
|
||||
{
|
||||
return json_encode($this->jsonSerialize(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->attributes[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for a given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->attributes[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->attributes[$offset]);
|
||||
}
|
||||
}
|
||||
486
addons/epay/library/hyperf/utils/src/Functions.php
Normal file
486
addons/epay/library/hyperf/utils/src/Functions.php
Normal file
@@ -0,0 +1,486 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Arr;
|
||||
use Hyperf\Utils\Backoff;
|
||||
use Hyperf\Utils\Collection;
|
||||
use Hyperf\Utils\Coroutine;
|
||||
use Hyperf\Utils\HigherOrderTapProxy;
|
||||
use Hyperf\Utils\Optional;
|
||||
use Hyperf\Utils\Parallel;
|
||||
use Hyperf\Utils\Str;
|
||||
use Hyperf\Utils\Waiter;
|
||||
|
||||
if (! function_exists('value')) {
|
||||
/**
|
||||
* Return the default value of the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
function value($value, ...$args)
|
||||
{
|
||||
return $value instanceof Closure ? $value(...$args) : $value;
|
||||
}
|
||||
}
|
||||
if (! function_exists('env')) {
|
||||
/**
|
||||
* Gets the value of an environment variable.
|
||||
*
|
||||
* @param string $key
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
function env($key, $default = null)
|
||||
{
|
||||
$value = getenv($key);
|
||||
if ($value === false) {
|
||||
return value($default);
|
||||
}
|
||||
switch (strtolower($value)) {
|
||||
case 'true':
|
||||
case '(true)':
|
||||
return true;
|
||||
case 'false':
|
||||
case '(false)':
|
||||
return false;
|
||||
case 'empty':
|
||||
case '(empty)':
|
||||
return '';
|
||||
case 'null':
|
||||
case '(null)':
|
||||
return;
|
||||
}
|
||||
if (($valueLength = strlen($value)) > 1 && $value[0] === '"' && $value[$valueLength - 1] === '"') {
|
||||
return substr($value, 1, -1);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
if (! function_exists('retry')) {
|
||||
/**
|
||||
* Retry an operation a given number of times.
|
||||
*
|
||||
* @param float|int $times
|
||||
* @param int $sleep millisecond
|
||||
* @throws \Throwable
|
||||
*/
|
||||
function retry($times, callable $callback, int $sleep = 0)
|
||||
{
|
||||
$attempts = 0;
|
||||
$backoff = new Backoff($sleep);
|
||||
|
||||
beginning:
|
||||
try {
|
||||
return $callback(++$attempts);
|
||||
} catch (\Throwable $e) {
|
||||
if (--$times < 0) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$backoff->sleep();
|
||||
goto beginning;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! function_exists('with')) {
|
||||
/**
|
||||
* Return the given value, optionally passed through the given callback.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
function with($value, callable $callback = null)
|
||||
{
|
||||
return is_null($callback) ? $value : $callback($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('collect')) {
|
||||
/**
|
||||
* Create a collection from the given value.
|
||||
*
|
||||
* @param null|mixed $value
|
||||
* @return Collection
|
||||
*/
|
||||
function collect($value = null)
|
||||
{
|
||||
return new Collection($value);
|
||||
}
|
||||
}
|
||||
if (! function_exists('data_fill')) {
|
||||
/**
|
||||
* Fill in data where it's missing.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param array|string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
function data_fill(&$target, $key, $value)
|
||||
{
|
||||
return data_set($target, $key, $value, false);
|
||||
}
|
||||
}
|
||||
if (! function_exists('data_get')) {
|
||||
/**
|
||||
* Get an item from an array or object using "dot" notation.
|
||||
*
|
||||
* @param null|array|int|string $key
|
||||
* @param null|mixed $default
|
||||
* @param mixed $target
|
||||
*/
|
||||
function data_get($target, $key, $default = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$key = is_array($key) ? $key : explode('.', is_int($key) ? (string) $key : $key);
|
||||
while (! is_null($segment = array_shift($key))) {
|
||||
if ($segment === '*') {
|
||||
if ($target instanceof Collection) {
|
||||
$target = $target->all();
|
||||
} elseif (! is_array($target)) {
|
||||
return value($default);
|
||||
}
|
||||
$result = [];
|
||||
foreach ($target as $item) {
|
||||
$result[] = data_get($item, $key);
|
||||
}
|
||||
return in_array('*', $key) ? Arr::collapse($result) : $result;
|
||||
}
|
||||
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
|
||||
$target = $target[$segment];
|
||||
} elseif (is_object($target) && isset($target->{$segment})) {
|
||||
$target = $target->{$segment};
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
if (! function_exists('data_set')) {
|
||||
/**
|
||||
* Set an item on an array or object using dot notation.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param array|string $key
|
||||
* @param bool $overwrite
|
||||
* @param mixed $value
|
||||
*/
|
||||
function data_set(&$target, $key, $value, $overwrite = true)
|
||||
{
|
||||
$segments = is_array($key) ? $key : explode('.', $key);
|
||||
if (($segment = array_shift($segments)) === '*') {
|
||||
if (! Arr::accessible($target)) {
|
||||
$target = [];
|
||||
}
|
||||
if ($segments) {
|
||||
foreach ($target as &$inner) {
|
||||
data_set($inner, $segments, $value, $overwrite);
|
||||
}
|
||||
} elseif ($overwrite) {
|
||||
foreach ($target as &$inner) {
|
||||
$inner = $value;
|
||||
}
|
||||
}
|
||||
} elseif (Arr::accessible($target)) {
|
||||
if ($segments) {
|
||||
if (! Arr::exists($target, $segment)) {
|
||||
$target[$segment] = [];
|
||||
}
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || ! Arr::exists($target, $segment)) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
} elseif (is_object($target)) {
|
||||
if ($segments) {
|
||||
if (! isset($target->{$segment})) {
|
||||
$target->{$segment} = [];
|
||||
}
|
||||
data_set($target->{$segment}, $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || ! isset($target->{$segment})) {
|
||||
$target->{$segment} = $value;
|
||||
}
|
||||
} else {
|
||||
$target = [];
|
||||
if ($segments) {
|
||||
$target[$segment] = [];
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
}
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
if (! function_exists('head')) {
|
||||
/**
|
||||
* Get the first element of an array. Useful for method chaining.
|
||||
*
|
||||
* @param array $array
|
||||
*/
|
||||
function head($array)
|
||||
{
|
||||
return reset($array);
|
||||
}
|
||||
}
|
||||
if (! function_exists('last')) {
|
||||
/**
|
||||
* Get the last element from an array.
|
||||
*
|
||||
* @param array $array
|
||||
*/
|
||||
function last($array)
|
||||
{
|
||||
return end($array);
|
||||
}
|
||||
}
|
||||
if (! function_exists('tap')) {
|
||||
/**
|
||||
* Call the given Closure with the given value then return the value.
|
||||
*
|
||||
* @param null|callable $callback
|
||||
* @param mixed $value
|
||||
*/
|
||||
function tap($value, $callback = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return new HigherOrderTapProxy($value);
|
||||
}
|
||||
$callback($value);
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('call')) {
|
||||
/**
|
||||
* Call a callback with the arguments.
|
||||
*
|
||||
* @param mixed $callback
|
||||
* @return null|mixed
|
||||
*/
|
||||
function call($callback, array $args = [])
|
||||
{
|
||||
$result = null;
|
||||
if ($callback instanceof \Closure) {
|
||||
$result = $callback(...$args);
|
||||
} elseif (is_object($callback) || (is_string($callback) && function_exists($callback))) {
|
||||
$result = $callback(...$args);
|
||||
} elseif (is_array($callback)) {
|
||||
[$object, $method] = $callback;
|
||||
$result = is_object($object) ? $object->{$method}(...$args) : $object::$method(...$args);
|
||||
} else {
|
||||
$result = call_user_func_array($callback, $args);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('go')) {
|
||||
/**
|
||||
* @return bool|int
|
||||
*/
|
||||
function go(callable $callable)
|
||||
{
|
||||
$id = Coroutine::create($callable);
|
||||
return $id > 0 ? $id : false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('co')) {
|
||||
/**
|
||||
* @return bool|int
|
||||
*/
|
||||
function co(callable $callable)
|
||||
{
|
||||
$id = Coroutine::create($callable);
|
||||
return $id > 0 ? $id : false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('defer')) {
|
||||
function defer(callable $callable): void
|
||||
{
|
||||
Coroutine::defer($callable);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('class_basename')) {
|
||||
/**
|
||||
* Get the class "basename" of the given object / class.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return string
|
||||
*/
|
||||
function class_basename($class)
|
||||
{
|
||||
$class = is_object($class) ? get_class($class) : $class;
|
||||
|
||||
return basename(str_replace('\\', '/', $class));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('trait_uses_recursive')) {
|
||||
/**
|
||||
* Returns all traits used by a trait and its traits.
|
||||
*
|
||||
* @param string $trait
|
||||
* @return array
|
||||
*/
|
||||
function trait_uses_recursive($trait)
|
||||
{
|
||||
$traits = class_uses($trait);
|
||||
|
||||
foreach ($traits as $trait) {
|
||||
$traits += trait_uses_recursive($trait);
|
||||
}
|
||||
|
||||
return $traits;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('class_uses_recursive')) {
|
||||
/**
|
||||
* Returns all traits used by a class, its parent classes and trait of their traits.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return array
|
||||
*/
|
||||
function class_uses_recursive($class)
|
||||
{
|
||||
if (is_object($class)) {
|
||||
$class = get_class($class);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
/* @phpstan-ignore-next-line */
|
||||
foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) {
|
||||
$results += trait_uses_recursive($class);
|
||||
}
|
||||
|
||||
return array_unique($results);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('setter')) {
|
||||
/**
|
||||
* Create a setter string.
|
||||
*/
|
||||
function setter(string $property): string
|
||||
{
|
||||
return 'set' . Str::studly($property);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('getter')) {
|
||||
/**
|
||||
* Create a getter string.
|
||||
*/
|
||||
function getter(string $property): string
|
||||
{
|
||||
return 'get' . Str::studly($property);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('parallel')) {
|
||||
/**
|
||||
* @param callable[] $callables
|
||||
* @param int $concurrent if $concurrent is equal to 0, that means unlimit
|
||||
*/
|
||||
function parallel(array $callables, int $concurrent = 0)
|
||||
{
|
||||
$parallel = new Parallel($concurrent);
|
||||
foreach ($callables as $key => $callable) {
|
||||
$parallel->add($callable, $key);
|
||||
}
|
||||
return $parallel->wait();
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('make')) {
|
||||
/**
|
||||
* Create an object instance, if the DI container exist in ApplicationContext,
|
||||
* then the object will be created by DI container via `make()` method, if not,
|
||||
* the object will create by `new` keyword.
|
||||
*/
|
||||
function make(string $name, array $parameters = [])
|
||||
{
|
||||
if (ApplicationContext::hasContainer()) {
|
||||
$container = ApplicationContext::getContainer();
|
||||
if (method_exists($container, 'make')) {
|
||||
return $container->make($name, $parameters);
|
||||
}
|
||||
}
|
||||
$parameters = array_values($parameters);
|
||||
return new $name(...$parameters);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('run')) {
|
||||
/**
|
||||
* Run callable in non-coroutine environment, all hook functions by Swoole only available in the callable.
|
||||
*
|
||||
* @param array|callable $callbacks
|
||||
*/
|
||||
function run($callbacks, int $flags = SWOOLE_HOOK_ALL): bool
|
||||
{
|
||||
if (Coroutine::inCoroutine()) {
|
||||
throw new RuntimeException('Function \'run\' only execute in non-coroutine environment.');
|
||||
}
|
||||
|
||||
\Swoole\Runtime::enableCoroutine($flags);
|
||||
|
||||
$result = \Swoole\Coroutine\Run(...(array) $callbacks);
|
||||
|
||||
\Swoole\Runtime::enableCoroutine(false);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('swoole_hook_flags')) {
|
||||
/**
|
||||
* Return the default swoole hook flags, you can rewrite it by defining `SWOOLE_HOOK_FLAGS`.
|
||||
*/
|
||||
function swoole_hook_flags(): int
|
||||
{
|
||||
return defined('SWOOLE_HOOK_FLAGS') ? SWOOLE_HOOK_FLAGS : SWOOLE_HOOK_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('optional')) {
|
||||
/**
|
||||
* Provide access to optional objects.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
function optional($value = null, callable $callback = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return new Optional($value);
|
||||
}
|
||||
if (! is_null($value)) {
|
||||
return $callback($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('wait')) {
|
||||
function wait(Closure $closure, ?float $timeout = null)
|
||||
{
|
||||
if (ApplicationContext::hasContainer()) {
|
||||
$waiter = ApplicationContext::getContainer()->get(Waiter::class);
|
||||
return $waiter->wait($closure, $timeout);
|
||||
}
|
||||
return (new Waiter())->wait($closure, $timeout);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
/**
|
||||
* @mixin Collection
|
||||
* Most of the methods in this file come from illuminate/support,
|
||||
* thanks Laravel Team provide such a useful class.
|
||||
*/
|
||||
class HigherOrderCollectionProxy
|
||||
{
|
||||
/**
|
||||
* The collection being operated on.
|
||||
*
|
||||
* @var Collection
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* The method being proxied.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method;
|
||||
|
||||
/**
|
||||
* Create a new proxy instance.
|
||||
*/
|
||||
public function __construct(Collection $collection, string $method)
|
||||
{
|
||||
$this->method = $method;
|
||||
$this->collection = $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy accessing an attribute onto the collection items.
|
||||
*/
|
||||
public function __get(string $key)
|
||||
{
|
||||
return $this->collection->{$this->method}(function ($value) use ($key) {
|
||||
return is_array($value) ? $value[$key] : $value->{$key};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy a method call onto the collection items.
|
||||
*/
|
||||
public function __call(string $method, array $parameters)
|
||||
{
|
||||
return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
|
||||
return $value->{$method}(...$parameters);
|
||||
});
|
||||
}
|
||||
}
|
||||
46
addons/epay/library/hyperf/utils/src/HigherOrderTapProxy.php
Normal file
46
addons/epay/library/hyperf/utils/src/HigherOrderTapProxy.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
class HigherOrderTapProxy
|
||||
{
|
||||
/**
|
||||
* The target being tapped.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* Create a new tap proxy instance.
|
||||
*
|
||||
* @param mixed $target
|
||||
*/
|
||||
public function __construct($target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass method calls to the target.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
$this->target->{$method}(...$parameters);
|
||||
|
||||
return $this->target;
|
||||
}
|
||||
}
|
||||
70
addons/epay/library/hyperf/utils/src/InteractsWithTime.php
Normal file
70
addons/epay/library/hyperf/utils/src/InteractsWithTime.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
|
||||
trait InteractsWithTime
|
||||
{
|
||||
/**
|
||||
* Get the number of seconds until the given DateTime.
|
||||
*
|
||||
* @param \DateInterval|\DateTimeInterface|int $delay
|
||||
*/
|
||||
protected function secondsUntil($delay): int
|
||||
{
|
||||
$delay = $this->parseDateInterval($delay);
|
||||
|
||||
return $delay instanceof DateTimeInterface
|
||||
? max(0, $delay->getTimestamp() - $this->currentTime())
|
||||
: (int) $delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "available at" UNIX timestamp.
|
||||
*
|
||||
* @param \DateInterval|\DateTimeInterface|int $delay
|
||||
*/
|
||||
protected function availableAt($delay = 0): int
|
||||
{
|
||||
$delay = $this->parseDateInterval($delay);
|
||||
|
||||
return $delay instanceof DateTimeInterface
|
||||
? $delay->getTimestamp()
|
||||
: Carbon::now()->addSeconds($delay)->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given value is an interval, convert it to a DateTime instance.
|
||||
*
|
||||
* @param \DateInterval|\DateTimeInterface|int $delay
|
||||
* @return \DateTimeInterface|int
|
||||
*/
|
||||
protected function parseDateInterval($delay)
|
||||
{
|
||||
if ($delay instanceof DateInterval) {
|
||||
$delay = Carbon::now()->add($delay);
|
||||
}
|
||||
|
||||
return $delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current system time as a UNIX timestamp.
|
||||
*/
|
||||
protected function currentTime(): int
|
||||
{
|
||||
return Carbon::now()->getTimestamp();
|
||||
}
|
||||
}
|
||||
351
addons/epay/library/hyperf/utils/src/MessageBag.php
Normal file
351
addons/epay/library/hyperf/utils/src/MessageBag.php
Normal file
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Countable;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Jsonable;
|
||||
use Hyperf\Utils\Contracts\MessageBag as MessageBagContract;
|
||||
use Hyperf\Utils\Contracts\MessageProvider;
|
||||
use JsonSerializable;
|
||||
|
||||
class MessageBag implements Arrayable, Countable, Jsonable, JsonSerializable, MessageBagContract, MessageProvider
|
||||
{
|
||||
/**
|
||||
* All of the registered messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $messages = [];
|
||||
|
||||
/**
|
||||
* Default format for message output.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $format = ':message';
|
||||
|
||||
/**
|
||||
* Create a new message bag instance.
|
||||
*/
|
||||
public function __construct(array $messages = [])
|
||||
{
|
||||
foreach ($messages as $key => $value) {
|
||||
$value = $value instanceof Arrayable ? $value->toArray() : (array) $value;
|
||||
|
||||
$this->messages[$key] = array_unique($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the message bag to its string representation.
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys present in the message bag.
|
||||
*/
|
||||
public function keys(): array
|
||||
{
|
||||
return array_keys($this->messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a message to the message bag.
|
||||
*/
|
||||
public function add(string $key, string $message): MessageBagContract
|
||||
{
|
||||
if ($this->isUnique($key, $message)) {
|
||||
$this->messages[$key][] = $message;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a new array of messages into the message bag.
|
||||
*
|
||||
* @param array|MessageProvider $messages
|
||||
* @return $this
|
||||
*/
|
||||
public function merge($messages)
|
||||
{
|
||||
if ($messages instanceof MessageProvider) {
|
||||
$messages = $messages->getMessageBag()->getMessages();
|
||||
}
|
||||
|
||||
$this->messages = array_merge_recursive($this->messages, $messages);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if messages exist for all of the given keys.
|
||||
*
|
||||
* @param null|array|string $key
|
||||
*/
|
||||
public function has($key): bool
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($key)) {
|
||||
return $this->any();
|
||||
}
|
||||
|
||||
$keys = is_array($key) ? $key : func_get_args();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($this->first($key) === '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if messages exist for any of the given keys.
|
||||
*
|
||||
* @param array|string $keys
|
||||
*/
|
||||
public function hasAny($keys = []): bool
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$keys = is_array($keys) ? $keys : func_get_args();
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($this->has($key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first message from the message bag for a given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $format
|
||||
*/
|
||||
public function first($key = null, $format = null): string
|
||||
{
|
||||
$messages = is_null($key) ? $this->all($format) : $this->get($key, $format);
|
||||
|
||||
$firstMessage = Arr::first($messages, null, '');
|
||||
|
||||
return is_array($firstMessage) ? Arr::first($firstMessage) : $firstMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the messages from the message bag for a given key.
|
||||
*/
|
||||
public function get(string $key, ?string $format = null): array
|
||||
{
|
||||
// If the message exists in the message bag, we will transform it and return
|
||||
// the message. Otherwise, we will check if the key is implicit & collect
|
||||
// all the messages that match the given key and output it as an array.
|
||||
if (array_key_exists($key, $this->messages)) {
|
||||
return $this->transform(
|
||||
$this->messages[$key],
|
||||
$this->checkFormat($format),
|
||||
$key
|
||||
);
|
||||
}
|
||||
|
||||
if (Str::contains($key, '*')) {
|
||||
return $this->getMessagesForWildcardKey($key, $format);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the messages for every key in the message bag.
|
||||
*/
|
||||
public function all(?string $format = null): array
|
||||
{
|
||||
$format = $this->checkFormat($format);
|
||||
|
||||
$all = [];
|
||||
|
||||
foreach ($this->messages as $key => $messages) {
|
||||
$all = array_merge($all, $this->transform($messages, $format, $key));
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the unique messages for every key in the message bag.
|
||||
*/
|
||||
public function unique(?string $format = null): array
|
||||
{
|
||||
return array_unique($this->all($format));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw messages in the message bag.
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw messages in the message bag.
|
||||
*/
|
||||
public function getMessages(): array
|
||||
{
|
||||
return $this->messages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the messages for the instance.
|
||||
*/
|
||||
public function getMessageBag(): MessageBagContract
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default message format.
|
||||
*/
|
||||
public function getFormat(): string
|
||||
{
|
||||
return $this->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default message format.
|
||||
*/
|
||||
public function setFormat(string $format = ':message'): self
|
||||
{
|
||||
$this->format = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the message bag has any messages.
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return ! $this->any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the message bag has any messages.
|
||||
*/
|
||||
public function isNotEmpty(): bool
|
||||
{
|
||||
return $this->any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the message bag has any messages.
|
||||
*/
|
||||
public function any(): bool
|
||||
{
|
||||
return $this->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of messages in the message bag.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->messages, COUNT_RECURSIVE) - count($this->messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instance as an array.
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->getMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object into something JSON serializable.
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object to its JSON representation.
|
||||
*/
|
||||
public function toJson(int $options = 0): string
|
||||
{
|
||||
return json_encode($this->jsonSerialize(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a key and message combination already exists.
|
||||
*/
|
||||
protected function isUnique(string $key, string $message): bool
|
||||
{
|
||||
$messages = (array) $this->messages;
|
||||
|
||||
return ! isset($messages[$key]) || ! in_array($message, $messages[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the messages for a wildcard key.
|
||||
*/
|
||||
protected function getMessagesForWildcardKey(string $key, ?string $format): array
|
||||
{
|
||||
return collect($this->messages)
|
||||
->filter(function ($messages, $messageKey) use ($key) {
|
||||
return Str::is($key, $messageKey);
|
||||
})
|
||||
->map(function ($messages, $messageKey) use ($format) {
|
||||
return $this->transform(
|
||||
$messages,
|
||||
$this->checkFormat($format),
|
||||
$messageKey
|
||||
);
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an array of messages.
|
||||
*/
|
||||
protected function transform(array $messages, string $format, string $messageKey): array
|
||||
{
|
||||
return collect($messages)
|
||||
->map(function ($message) use ($format, $messageKey) {
|
||||
// We will simply spin through the given messages and transform each one
|
||||
// replacing the :message place holder with the real message allowing
|
||||
// the messages to be easily formatted to each developer's desires.
|
||||
return str_replace([':message', ':key'], [$message, $messageKey], $format);
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate format based on the given format.
|
||||
*/
|
||||
protected function checkFormat(?string $format): string
|
||||
{
|
||||
return $format ?: $this->format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,814 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
class MimeTypeExtensionGuesser
|
||||
{
|
||||
/**
|
||||
* A map of mime types and their default extensions.
|
||||
*
|
||||
* @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
|
||||
*/
|
||||
protected $defaultExtensions = [
|
||||
'application/andrew-inset' => 'ez',
|
||||
'application/applixware' => 'aw',
|
||||
'application/atom+xml' => 'atom',
|
||||
'application/atomcat+xml' => 'atomcat',
|
||||
'application/atomsvc+xml' => 'atomsvc',
|
||||
'application/ccxml+xml' => 'ccxml',
|
||||
'application/cdmi-capability' => 'cdmia',
|
||||
'application/cdmi-container' => 'cdmic',
|
||||
'application/cdmi-domain' => 'cdmid',
|
||||
'application/cdmi-object' => 'cdmio',
|
||||
'application/cdmi-queue' => 'cdmiq',
|
||||
'application/cu-seeme' => 'cu',
|
||||
'application/davmount+xml' => 'davmount',
|
||||
'application/docbook+xml' => 'dbk',
|
||||
'application/dssc+der' => 'dssc',
|
||||
'application/dssc+xml' => 'xdssc',
|
||||
'application/ecmascript' => 'ecma',
|
||||
'application/emma+xml' => 'emma',
|
||||
'application/epub+zip' => 'epub',
|
||||
'application/exi' => 'exi',
|
||||
'application/font-tdpfr' => 'pfr',
|
||||
'application/gml+xml' => 'gml',
|
||||
'application/gpx+xml' => 'gpx',
|
||||
'application/gxf' => 'gxf',
|
||||
'application/hyperstudio' => 'stk',
|
||||
'application/inkml+xml' => 'ink',
|
||||
'application/ipfix' => 'ipfix',
|
||||
'application/java-archive' => 'jar',
|
||||
'application/java-serialized-object' => 'ser',
|
||||
'application/java-vm' => 'class',
|
||||
'application/javascript' => 'js',
|
||||
'application/json' => 'json',
|
||||
'application/jsonml+json' => 'jsonml',
|
||||
'application/lost+xml' => 'lostxml',
|
||||
'application/mac-binhex40' => 'hqx',
|
||||
'application/mac-compactpro' => 'cpt',
|
||||
'application/mads+xml' => 'mads',
|
||||
'application/marc' => 'mrc',
|
||||
'application/marcxml+xml' => 'mrcx',
|
||||
'application/mathematica' => 'ma',
|
||||
'application/mathml+xml' => 'mathml',
|
||||
'application/mbox' => 'mbox',
|
||||
'application/mediaservercontrol+xml' => 'mscml',
|
||||
'application/metalink+xml' => 'metalink',
|
||||
'application/metalink4+xml' => 'meta4',
|
||||
'application/mets+xml' => 'mets',
|
||||
'application/mods+xml' => 'mods',
|
||||
'application/mp21' => 'm21',
|
||||
'application/mp4' => 'mp4s',
|
||||
'application/msword' => 'doc',
|
||||
'application/mxf' => 'mxf',
|
||||
'application/octet-stream' => 'bin',
|
||||
'application/oda' => 'oda',
|
||||
'application/oebps-package+xml' => 'opf',
|
||||
'application/ogg' => 'ogx',
|
||||
'application/omdoc+xml' => 'omdoc',
|
||||
'application/onenote' => 'onetoc',
|
||||
'application/oxps' => 'oxps',
|
||||
'application/patch-ops-error+xml' => 'xer',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/pgp-encrypted' => 'pgp',
|
||||
'application/pgp-signature' => 'asc',
|
||||
'application/pics-rules' => 'prf',
|
||||
'application/pkcs10' => 'p10',
|
||||
'application/pkcs7-mime' => 'p7m',
|
||||
'application/pkcs7-signature' => 'p7s',
|
||||
'application/pkcs8' => 'p8',
|
||||
'application/pkix-attr-cert' => 'ac',
|
||||
'application/pkix-cert' => 'cer',
|
||||
'application/pkix-crl' => 'crl',
|
||||
'application/pkix-pkipath' => 'pkipath',
|
||||
'application/pkixcmp' => 'pki',
|
||||
'application/pls+xml' => 'pls',
|
||||
'application/postscript' => 'ai',
|
||||
'application/prs.cww' => 'cww',
|
||||
'application/pskc+xml' => 'pskcxml',
|
||||
'application/rdf+xml' => 'rdf',
|
||||
'application/reginfo+xml' => 'rif',
|
||||
'application/relax-ng-compact-syntax' => 'rnc',
|
||||
'application/resource-lists+xml' => 'rl',
|
||||
'application/resource-lists-diff+xml' => 'rld',
|
||||
'application/rls-services+xml' => 'rs',
|
||||
'application/rpki-ghostbusters' => 'gbr',
|
||||
'application/rpki-manifest' => 'mft',
|
||||
'application/rpki-roa' => 'roa',
|
||||
'application/rsd+xml' => 'rsd',
|
||||
'application/rss+xml' => 'rss',
|
||||
'application/rtf' => 'rtf',
|
||||
'application/sbml+xml' => 'sbml',
|
||||
'application/scvp-cv-request' => 'scq',
|
||||
'application/scvp-cv-response' => 'scs',
|
||||
'application/scvp-vp-request' => 'spq',
|
||||
'application/scvp-vp-response' => 'spp',
|
||||
'application/sdp' => 'sdp',
|
||||
'application/set-payment-initiation' => 'setpay',
|
||||
'application/set-registration-initiation' => 'setreg',
|
||||
'application/shf+xml' => 'shf',
|
||||
'application/smil+xml' => 'smi',
|
||||
'application/sparql-query' => 'rq',
|
||||
'application/sparql-results+xml' => 'srx',
|
||||
'application/srgs' => 'gram',
|
||||
'application/srgs+xml' => 'grxml',
|
||||
'application/sru+xml' => 'sru',
|
||||
'application/ssdl+xml' => 'ssdl',
|
||||
'application/ssml+xml' => 'ssml',
|
||||
'application/tei+xml' => 'tei',
|
||||
'application/thraud+xml' => 'tfi',
|
||||
'application/timestamped-data' => 'tsd',
|
||||
'application/vnd.3gpp.pic-bw-large' => 'plb',
|
||||
'application/vnd.3gpp.pic-bw-small' => 'psb',
|
||||
'application/vnd.3gpp.pic-bw-var' => 'pvb',
|
||||
'application/vnd.3gpp2.tcap' => 'tcap',
|
||||
'application/vnd.3m.post-it-notes' => 'pwn',
|
||||
'application/vnd.accpac.simply.aso' => 'aso',
|
||||
'application/vnd.accpac.simply.imp' => 'imp',
|
||||
'application/vnd.acucobol' => 'acu',
|
||||
'application/vnd.acucorp' => 'atc',
|
||||
'application/vnd.adobe.air-application-installer-package+zip' => 'air',
|
||||
'application/vnd.adobe.formscentral.fcdt' => 'fcdt',
|
||||
'application/vnd.adobe.fxp' => 'fxp',
|
||||
'application/vnd.adobe.xdp+xml' => 'xdp',
|
||||
'application/vnd.adobe.xfdf' => 'xfdf',
|
||||
'application/vnd.ahead.space' => 'ahead',
|
||||
'application/vnd.airzip.filesecure.azf' => 'azf',
|
||||
'application/vnd.airzip.filesecure.azs' => 'azs',
|
||||
'application/vnd.amazon.ebook' => 'azw',
|
||||
'application/vnd.americandynamics.acc' => 'acc',
|
||||
'application/vnd.amiga.ami' => 'ami',
|
||||
'application/vnd.android.package-archive' => 'apk',
|
||||
'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
|
||||
'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
|
||||
'application/vnd.antix.game-component' => 'atx',
|
||||
'application/vnd.apple.installer+xml' => 'mpkg',
|
||||
'application/vnd.apple.mpegurl' => 'm3u8',
|
||||
'application/vnd.aristanetworks.swi' => 'swi',
|
||||
'application/vnd.astraea-software.iota' => 'iota',
|
||||
'application/vnd.audiograph' => 'aep',
|
||||
'application/vnd.blueice.multipass' => 'mpm',
|
||||
'application/vnd.bmi' => 'bmi',
|
||||
'application/vnd.businessobjects' => 'rep',
|
||||
'application/vnd.chemdraw+xml' => 'cdxml',
|
||||
'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
|
||||
'application/vnd.cinderella' => 'cdy',
|
||||
'application/vnd.claymore' => 'cla',
|
||||
'application/vnd.cloanto.rp9' => 'rp9',
|
||||
'application/vnd.clonk.c4group' => 'c4g',
|
||||
'application/vnd.cluetrust.cartomobile-config' => 'c11amc',
|
||||
'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz',
|
||||
'application/vnd.commonspace' => 'csp',
|
||||
'application/vnd.contact.cmsg' => 'cdbcmsg',
|
||||
'application/vnd.cosmocaller' => 'cmc',
|
||||
'application/vnd.crick.clicker' => 'clkx',
|
||||
'application/vnd.crick.clicker.keyboard' => 'clkk',
|
||||
'application/vnd.crick.clicker.palette' => 'clkp',
|
||||
'application/vnd.crick.clicker.template' => 'clkt',
|
||||
'application/vnd.crick.clicker.wordbank' => 'clkw',
|
||||
'application/vnd.criticaltools.wbs+xml' => 'wbs',
|
||||
'application/vnd.ctc-posml' => 'pml',
|
||||
'application/vnd.cups-ppd' => 'ppd',
|
||||
'application/vnd.curl.car' => 'car',
|
||||
'application/vnd.curl.pcurl' => 'pcurl',
|
||||
'application/vnd.dart' => 'dart',
|
||||
'application/vnd.data-vision.rdz' => 'rdz',
|
||||
'application/vnd.dece.data' => 'uvf',
|
||||
'application/vnd.dece.ttml+xml' => 'uvt',
|
||||
'application/vnd.dece.unspecified' => 'uvx',
|
||||
'application/vnd.dece.zip' => 'uvz',
|
||||
'application/vnd.denovo.fcselayout-link' => 'fe_launch',
|
||||
'application/vnd.dna' => 'dna',
|
||||
'application/vnd.dolby.mlp' => 'mlp',
|
||||
'application/vnd.dpgraph' => 'dpg',
|
||||
'application/vnd.dreamfactory' => 'dfac',
|
||||
'application/vnd.ds-keypoint' => 'kpxx',
|
||||
'application/vnd.dvb.ait' => 'ait',
|
||||
'application/vnd.dvb.service' => 'svc',
|
||||
'application/vnd.dynageo' => 'geo',
|
||||
'application/vnd.ecowin.chart' => 'mag',
|
||||
'application/vnd.enliven' => 'nml',
|
||||
'application/vnd.epson.esf' => 'esf',
|
||||
'application/vnd.epson.msf' => 'msf',
|
||||
'application/vnd.epson.quickanime' => 'qam',
|
||||
'application/vnd.epson.salt' => 'slt',
|
||||
'application/vnd.epson.ssf' => 'ssf',
|
||||
'application/vnd.eszigno3+xml' => 'es3',
|
||||
'application/vnd.ezpix-album' => 'ez2',
|
||||
'application/vnd.ezpix-package' => 'ez3',
|
||||
'application/vnd.fdf' => 'fdf',
|
||||
'application/vnd.fdsn.mseed' => 'mseed',
|
||||
'application/vnd.fdsn.seed' => 'seed',
|
||||
'application/vnd.flographit' => 'gph',
|
||||
'application/vnd.fluxtime.clip' => 'ftc',
|
||||
'application/vnd.framemaker' => 'fm',
|
||||
'application/vnd.frogans.fnc' => 'fnc',
|
||||
'application/vnd.frogans.ltf' => 'ltf',
|
||||
'application/vnd.fsc.weblaunch' => 'fsc',
|
||||
'application/vnd.fujitsu.oasys' => 'oas',
|
||||
'application/vnd.fujitsu.oasys2' => 'oa2',
|
||||
'application/vnd.fujitsu.oasys3' => 'oa3',
|
||||
'application/vnd.fujitsu.oasysgp' => 'fg5',
|
||||
'application/vnd.fujitsu.oasysprs' => 'bh2',
|
||||
'application/vnd.fujixerox.ddd' => 'ddd',
|
||||
'application/vnd.fujixerox.docuworks' => 'xdw',
|
||||
'application/vnd.fujixerox.docuworks.binder' => 'xbd',
|
||||
'application/vnd.fuzzysheet' => 'fzs',
|
||||
'application/vnd.genomatix.tuxedo' => 'txd',
|
||||
'application/vnd.geogebra.file' => 'ggb',
|
||||
'application/vnd.geogebra.tool' => 'ggt',
|
||||
'application/vnd.geometry-explorer' => 'gex',
|
||||
'application/vnd.geonext' => 'gxt',
|
||||
'application/vnd.geoplan' => 'g2w',
|
||||
'application/vnd.geospace' => 'g3w',
|
||||
'application/vnd.gmx' => 'gmx',
|
||||
'application/vnd.google-earth.kml+xml' => 'kml',
|
||||
'application/vnd.google-earth.kmz' => 'kmz',
|
||||
'application/vnd.grafeq' => 'gqf',
|
||||
'application/vnd.groove-account' => 'gac',
|
||||
'application/vnd.groove-help' => 'ghf',
|
||||
'application/vnd.groove-identity-message' => 'gim',
|
||||
'application/vnd.groove-injector' => 'grv',
|
||||
'application/vnd.groove-tool-message' => 'gtm',
|
||||
'application/vnd.groove-tool-template' => 'tpl',
|
||||
'application/vnd.groove-vcard' => 'vcg',
|
||||
'application/vnd.hal+xml' => 'hal',
|
||||
'application/vnd.handheld-entertainment+xml' => 'zmm',
|
||||
'application/vnd.hbci' => 'hbci',
|
||||
'application/vnd.hhe.lesson-player' => 'les',
|
||||
'application/vnd.hp-hpgl' => 'hpgl',
|
||||
'application/vnd.hp-hpid' => 'hpid',
|
||||
'application/vnd.hp-hps' => 'hps',
|
||||
'application/vnd.hp-jlyt' => 'jlt',
|
||||
'application/vnd.hp-pcl' => 'pcl',
|
||||
'application/vnd.hp-pclxl' => 'pclxl',
|
||||
'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
|
||||
'application/vnd.ibm.minipay' => 'mpy',
|
||||
'application/vnd.ibm.modcap' => 'afp',
|
||||
'application/vnd.ibm.rights-management' => 'irm',
|
||||
'application/vnd.ibm.secure-container' => 'sc',
|
||||
'application/vnd.iccprofile' => 'icc',
|
||||
'application/vnd.igloader' => 'igl',
|
||||
'application/vnd.immervision-ivp' => 'ivp',
|
||||
'application/vnd.immervision-ivu' => 'ivu',
|
||||
'application/vnd.insors.igm' => 'igm',
|
||||
'application/vnd.intercon.formnet' => 'xpw',
|
||||
'application/vnd.intergeo' => 'i2g',
|
||||
'application/vnd.intu.qbo' => 'qbo',
|
||||
'application/vnd.intu.qfx' => 'qfx',
|
||||
'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
|
||||
'application/vnd.irepository.package+xml' => 'irp',
|
||||
'application/vnd.is-xpr' => 'xpr',
|
||||
'application/vnd.isac.fcs' => 'fcs',
|
||||
'application/vnd.jam' => 'jam',
|
||||
'application/vnd.jcp.javame.midlet-rms' => 'rms',
|
||||
'application/vnd.jisp' => 'jisp',
|
||||
'application/vnd.joost.joda-archive' => 'joda',
|
||||
'application/vnd.kahootz' => 'ktz',
|
||||
'application/vnd.kde.karbon' => 'karbon',
|
||||
'application/vnd.kde.kchart' => 'chrt',
|
||||
'application/vnd.kde.kformula' => 'kfo',
|
||||
'application/vnd.kde.kivio' => 'flw',
|
||||
'application/vnd.kde.kontour' => 'kon',
|
||||
'application/vnd.kde.kpresenter' => 'kpr',
|
||||
'application/vnd.kde.kspread' => 'ksp',
|
||||
'application/vnd.kde.kword' => 'kwd',
|
||||
'application/vnd.kenameaapp' => 'htke',
|
||||
'application/vnd.kidspiration' => 'kia',
|
||||
'application/vnd.kinar' => 'kne',
|
||||
'application/vnd.koan' => 'skp',
|
||||
'application/vnd.kodak-descriptor' => 'sse',
|
||||
'application/vnd.las.las+xml' => 'lasxml',
|
||||
'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
|
||||
'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
|
||||
'application/vnd.lotus-1-2-3' => '123',
|
||||
'application/vnd.lotus-approach' => 'apr',
|
||||
'application/vnd.lotus-freelance' => 'pre',
|
||||
'application/vnd.lotus-notes' => 'nsf',
|
||||
'application/vnd.lotus-organizer' => 'org',
|
||||
'application/vnd.lotus-screencam' => 'scm',
|
||||
'application/vnd.lotus-wordpro' => 'lwp',
|
||||
'application/vnd.macports.portpkg' => 'portpkg',
|
||||
'application/vnd.mcd' => 'mcd',
|
||||
'application/vnd.medcalcdata' => 'mc1',
|
||||
'application/vnd.mediastation.cdkey' => 'cdkey',
|
||||
'application/vnd.mfer' => 'mwf',
|
||||
'application/vnd.mfmp' => 'mfm',
|
||||
'application/vnd.micrografx.flo' => 'flo',
|
||||
'application/vnd.micrografx.igx' => 'igx',
|
||||
'application/vnd.mif' => 'mif',
|
||||
'application/vnd.mobius.daf' => 'daf',
|
||||
'application/vnd.mobius.dis' => 'dis',
|
||||
'application/vnd.mobius.mbk' => 'mbk',
|
||||
'application/vnd.mobius.mqy' => 'mqy',
|
||||
'application/vnd.mobius.msl' => 'msl',
|
||||
'application/vnd.mobius.plc' => 'plc',
|
||||
'application/vnd.mobius.txf' => 'txf',
|
||||
'application/vnd.mophun.application' => 'mpn',
|
||||
'application/vnd.mophun.certificate' => 'mpc',
|
||||
'application/vnd.mozilla.xul+xml' => 'xul',
|
||||
'application/vnd.ms-artgalry' => 'cil',
|
||||
'application/vnd.ms-cab-compressed' => 'cab',
|
||||
'application/vnd.ms-excel' => 'xls',
|
||||
'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
|
||||
'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
|
||||
'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
|
||||
'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
|
||||
'application/vnd.ms-fontobject' => 'eot',
|
||||
'application/vnd.ms-htmlhelp' => 'chm',
|
||||
'application/vnd.ms-ims' => 'ims',
|
||||
'application/vnd.ms-lrm' => 'lrm',
|
||||
'application/vnd.ms-officetheme' => 'thmx',
|
||||
'application/vnd.ms-pki.seccat' => 'cat',
|
||||
'application/vnd.ms-pki.stl' => 'stl',
|
||||
'application/vnd.ms-powerpoint' => 'ppt',
|
||||
'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
|
||||
'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
|
||||
'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
|
||||
'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
|
||||
'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
|
||||
'application/vnd.ms-project' => 'mpp',
|
||||
'application/vnd.ms-word.document.macroenabled.12' => 'docm',
|
||||
'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
|
||||
'application/vnd.ms-works' => 'wps',
|
||||
'application/vnd.ms-wpl' => 'wpl',
|
||||
'application/vnd.ms-xpsdocument' => 'xps',
|
||||
'application/vnd.mseq' => 'mseq',
|
||||
'application/vnd.musician' => 'mus',
|
||||
'application/vnd.muvee.style' => 'msty',
|
||||
'application/vnd.mynfc' => 'taglet',
|
||||
'application/vnd.neurolanguage.nlu' => 'nlu',
|
||||
'application/vnd.nitf' => 'ntf',
|
||||
'application/vnd.noblenet-directory' => 'nnd',
|
||||
'application/vnd.noblenet-sealer' => 'nns',
|
||||
'application/vnd.noblenet-web' => 'nnw',
|
||||
'application/vnd.nokia.n-gage.data' => 'ngdat',
|
||||
'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
|
||||
'application/vnd.nokia.radio-preset' => 'rpst',
|
||||
'application/vnd.nokia.radio-presets' => 'rpss',
|
||||
'application/vnd.novadigm.edm' => 'edm',
|
||||
'application/vnd.novadigm.edx' => 'edx',
|
||||
'application/vnd.novadigm.ext' => 'ext',
|
||||
'application/vnd.oasis.opendocument.chart' => 'odc',
|
||||
'application/vnd.oasis.opendocument.chart-template' => 'otc',
|
||||
'application/vnd.oasis.opendocument.database' => 'odb',
|
||||
'application/vnd.oasis.opendocument.formula' => 'odf',
|
||||
'application/vnd.oasis.opendocument.formula-template' => 'odft',
|
||||
'application/vnd.oasis.opendocument.graphics' => 'odg',
|
||||
'application/vnd.oasis.opendocument.graphics-template' => 'otg',
|
||||
'application/vnd.oasis.opendocument.image' => 'odi',
|
||||
'application/vnd.oasis.opendocument.image-template' => 'oti',
|
||||
'application/vnd.oasis.opendocument.presentation' => 'odp',
|
||||
'application/vnd.oasis.opendocument.presentation-template' => 'otp',
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
|
||||
'application/vnd.oasis.opendocument.text' => 'odt',
|
||||
'application/vnd.oasis.opendocument.text-master' => 'odm',
|
||||
'application/vnd.oasis.opendocument.text-template' => 'ott',
|
||||
'application/vnd.oasis.opendocument.text-web' => 'oth',
|
||||
'application/vnd.olpc-sugar' => 'xo',
|
||||
'application/vnd.oma.dd2+xml' => 'dd2',
|
||||
'application/vnd.openofficeorg.extension' => 'oxt',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
|
||||
'application/vnd.osgeo.mapguide.package' => 'mgp',
|
||||
'application/vnd.osgi.dp' => 'dp',
|
||||
'application/vnd.osgi.subsystem' => 'esa',
|
||||
'application/vnd.palm' => 'pdb',
|
||||
'application/vnd.pawaafile' => 'paw',
|
||||
'application/vnd.pg.format' => 'str',
|
||||
'application/vnd.pg.osasli' => 'ei6',
|
||||
'application/vnd.picsel' => 'efif',
|
||||
'application/vnd.pmi.widget' => 'wg',
|
||||
'application/vnd.pocketlearn' => 'plf',
|
||||
'application/vnd.powerbuilder6' => 'pbd',
|
||||
'application/vnd.previewsystems.box' => 'box',
|
||||
'application/vnd.proteus.magazine' => 'mgz',
|
||||
'application/vnd.publishare-delta-tree' => 'qps',
|
||||
'application/vnd.pvi.ptid1' => 'ptid',
|
||||
'application/vnd.quark.quarkxpress' => 'qxd',
|
||||
'application/vnd.realvnc.bed' => 'bed',
|
||||
'application/vnd.recordare.musicxml' => 'mxl',
|
||||
'application/vnd.recordare.musicxml+xml' => 'musicxml',
|
||||
'application/vnd.rig.cryptonote' => 'cryptonote',
|
||||
'application/vnd.rim.cod' => 'cod',
|
||||
'application/vnd.rn-realmedia' => 'rm',
|
||||
'application/vnd.rn-realmedia-vbr' => 'rmvb',
|
||||
'application/vnd.route66.link66+xml' => 'link66',
|
||||
'application/vnd.sailingtracker.track' => 'st',
|
||||
'application/vnd.seemail' => 'see',
|
||||
'application/vnd.sema' => 'sema',
|
||||
'application/vnd.semd' => 'semd',
|
||||
'application/vnd.semf' => 'semf',
|
||||
'application/vnd.shana.informed.formdata' => 'ifm',
|
||||
'application/vnd.shana.informed.formtemplate' => 'itp',
|
||||
'application/vnd.shana.informed.interchange' => 'iif',
|
||||
'application/vnd.shana.informed.package' => 'ipk',
|
||||
'application/vnd.simtech-mindmapper' => 'twd',
|
||||
'application/vnd.smaf' => 'mmf',
|
||||
'application/vnd.smart.teacher' => 'teacher',
|
||||
'application/vnd.solent.sdkm+xml' => 'sdkm',
|
||||
'application/vnd.spotfire.dxp' => 'dxp',
|
||||
'application/vnd.spotfire.sfs' => 'sfs',
|
||||
'application/vnd.stardivision.calc' => 'sdc',
|
||||
'application/vnd.stardivision.draw' => 'sda',
|
||||
'application/vnd.stardivision.impress' => 'sdd',
|
||||
'application/vnd.stardivision.math' => 'smf',
|
||||
'application/vnd.stardivision.writer' => 'sdw',
|
||||
'application/vnd.stardivision.writer-global' => 'sgl',
|
||||
'application/vnd.stepmania.package' => 'smzip',
|
||||
'application/vnd.stepmania.stepchart' => 'sm',
|
||||
'application/vnd.sun.xml.calc' => 'sxc',
|
||||
'application/vnd.sun.xml.calc.template' => 'stc',
|
||||
'application/vnd.sun.xml.draw' => 'sxd',
|
||||
'application/vnd.sun.xml.draw.template' => 'std',
|
||||
'application/vnd.sun.xml.impress' => 'sxi',
|
||||
'application/vnd.sun.xml.impress.template' => 'sti',
|
||||
'application/vnd.sun.xml.math' => 'sxm',
|
||||
'application/vnd.sun.xml.writer' => 'sxw',
|
||||
'application/vnd.sun.xml.writer.global' => 'sxg',
|
||||
'application/vnd.sun.xml.writer.template' => 'stw',
|
||||
'application/vnd.sus-calendar' => 'sus',
|
||||
'application/vnd.svd' => 'svd',
|
||||
'application/vnd.symbian.install' => 'sis',
|
||||
'application/vnd.syncml+xml' => 'xsm',
|
||||
'application/vnd.syncml.dm+wbxml' => 'bdm',
|
||||
'application/vnd.syncml.dm+xml' => 'xdm',
|
||||
'application/vnd.tao.intent-module-archive' => 'tao',
|
||||
'application/vnd.tcpdump.pcap' => 'pcap',
|
||||
'application/vnd.tmobile-livetv' => 'tmo',
|
||||
'application/vnd.trid.tpt' => 'tpt',
|
||||
'application/vnd.triscape.mxs' => 'mxs',
|
||||
'application/vnd.trueapp' => 'tra',
|
||||
'application/vnd.ufdl' => 'ufd',
|
||||
'application/vnd.uiq.theme' => 'utz',
|
||||
'application/vnd.umajin' => 'umj',
|
||||
'application/vnd.unity' => 'unityweb',
|
||||
'application/vnd.uoml+xml' => 'uoml',
|
||||
'application/vnd.vcx' => 'vcx',
|
||||
'application/vnd.visio' => 'vsd',
|
||||
'application/vnd.visionary' => 'vis',
|
||||
'application/vnd.vsf' => 'vsf',
|
||||
'application/vnd.wap.wbxml' => 'wbxml',
|
||||
'application/vnd.wap.wmlc' => 'wmlc',
|
||||
'application/vnd.wap.wmlscriptc' => 'wmlsc',
|
||||
'application/vnd.webturbo' => 'wtb',
|
||||
'application/vnd.wolfram.player' => 'nbp',
|
||||
'application/vnd.wordperfect' => 'wpd',
|
||||
'application/vnd.wqd' => 'wqd',
|
||||
'application/vnd.wt.stf' => 'stf',
|
||||
'application/vnd.xara' => 'xar',
|
||||
'application/vnd.xfdl' => 'xfdl',
|
||||
'application/vnd.yamaha.hv-dic' => 'hvd',
|
||||
'application/vnd.yamaha.hv-script' => 'hvs',
|
||||
'application/vnd.yamaha.hv-voice' => 'hvp',
|
||||
'application/vnd.yamaha.openscoreformat' => 'osf',
|
||||
'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
|
||||
'application/vnd.yamaha.smaf-audio' => 'saf',
|
||||
'application/vnd.yamaha.smaf-phrase' => 'spf',
|
||||
'application/vnd.yellowriver-custom-menu' => 'cmp',
|
||||
'application/vnd.zul' => 'zir',
|
||||
'application/vnd.zzazz.deck+xml' => 'zaz',
|
||||
'application/voicexml+xml' => 'vxml',
|
||||
'application/widget' => 'wgt',
|
||||
'application/winhlp' => 'hlp',
|
||||
'application/wsdl+xml' => 'wsdl',
|
||||
'application/wspolicy+xml' => 'wspolicy',
|
||||
'application/x-7z-compressed' => '7z',
|
||||
'application/x-abiword' => 'abw',
|
||||
'application/x-ace-compressed' => 'ace',
|
||||
'application/x-apple-diskimage' => 'dmg',
|
||||
'application/x-authorware-bin' => 'aab',
|
||||
'application/x-authorware-map' => 'aam',
|
||||
'application/x-authorware-seg' => 'aas',
|
||||
'application/x-bcpio' => 'bcpio',
|
||||
'application/x-bittorrent' => 'torrent',
|
||||
'application/x-blorb' => 'blb',
|
||||
'application/x-bzip' => 'bz',
|
||||
'application/x-bzip2' => 'bz2',
|
||||
'application/x-cbr' => 'cbr',
|
||||
'application/x-cdlink' => 'vcd',
|
||||
'application/x-cfs-compressed' => 'cfs',
|
||||
'application/x-chat' => 'chat',
|
||||
'application/x-chess-pgn' => 'pgn',
|
||||
'application/x-conference' => 'nsc',
|
||||
'application/x-cpio' => 'cpio',
|
||||
'application/x-csh' => 'csh',
|
||||
'application/x-debian-package' => 'deb',
|
||||
'application/x-dgc-compressed' => 'dgc',
|
||||
'application/x-director' => 'dir',
|
||||
'application/x-doom' => 'wad',
|
||||
'application/x-dtbncx+xml' => 'ncx',
|
||||
'application/x-dtbook+xml' => 'dtb',
|
||||
'application/x-dtbresource+xml' => 'res',
|
||||
'application/x-dvi' => 'dvi',
|
||||
'application/x-envoy' => 'evy',
|
||||
'application/x-eva' => 'eva',
|
||||
'application/x-font-bdf' => 'bdf',
|
||||
'application/x-font-ghostscript' => 'gsf',
|
||||
'application/x-font-linux-psf' => 'psf',
|
||||
'application/x-font-otf' => 'otf',
|
||||
'application/x-font-pcf' => 'pcf',
|
||||
'application/x-font-snf' => 'snf',
|
||||
'application/x-font-ttf' => 'ttf',
|
||||
'application/x-font-type1' => 'pfa',
|
||||
'application/x-font-woff' => 'woff',
|
||||
'application/x-freearc' => 'arc',
|
||||
'application/x-futuresplash' => 'spl',
|
||||
'application/x-gca-compressed' => 'gca',
|
||||
'application/x-glulx' => 'ulx',
|
||||
'application/x-gnumeric' => 'gnumeric',
|
||||
'application/x-gramps-xml' => 'gramps',
|
||||
'application/x-gtar' => 'gtar',
|
||||
'application/x-hdf' => 'hdf',
|
||||
'application/x-install-instructions' => 'install',
|
||||
'application/x-iso9660-image' => 'iso',
|
||||
'application/x-java-jnlp-file' => 'jnlp',
|
||||
'application/x-latex' => 'latex',
|
||||
'application/x-lzh-compressed' => 'lzh',
|
||||
'application/x-mie' => 'mie',
|
||||
'application/x-mobipocket-ebook' => 'prc',
|
||||
'application/x-ms-application' => 'application',
|
||||
'application/x-ms-shortcut' => 'lnk',
|
||||
'application/x-ms-wmd' => 'wmd',
|
||||
'application/x-ms-wmz' => 'wmz',
|
||||
'application/x-ms-xbap' => 'xbap',
|
||||
'application/x-msaccess' => 'mdb',
|
||||
'application/x-msbinder' => 'obd',
|
||||
'application/x-mscardfile' => 'crd',
|
||||
'application/x-msclip' => 'clp',
|
||||
'application/x-msdownload' => 'exe',
|
||||
'application/x-msmediaview' => 'mvb',
|
||||
'application/x-msmetafile' => 'wmf',
|
||||
'application/x-msmoney' => 'mny',
|
||||
'application/x-mspublisher' => 'pub',
|
||||
'application/x-msschedule' => 'scd',
|
||||
'application/x-msterminal' => 'trm',
|
||||
'application/x-mswrite' => 'wri',
|
||||
'application/x-netcdf' => 'nc',
|
||||
'application/x-nzb' => 'nzb',
|
||||
'application/x-pkcs12' => 'p12',
|
||||
'application/x-pkcs7-certificates' => 'p7b',
|
||||
'application/x-pkcs7-certreqresp' => 'p7r',
|
||||
'application/x-rar-compressed' => 'rar',
|
||||
'application/x-rar' => 'rar',
|
||||
'application/x-research-info-systems' => 'ris',
|
||||
'application/x-sh' => 'sh',
|
||||
'application/x-shar' => 'shar',
|
||||
'application/x-shockwave-flash' => 'swf',
|
||||
'application/x-silverlight-app' => 'xap',
|
||||
'application/x-sql' => 'sql',
|
||||
'application/x-stuffit' => 'sit',
|
||||
'application/x-stuffitx' => 'sitx',
|
||||
'application/x-subrip' => 'srt',
|
||||
'application/x-sv4cpio' => 'sv4cpio',
|
||||
'application/x-sv4crc' => 'sv4crc',
|
||||
'application/x-t3vm-image' => 't3',
|
||||
'application/x-tads' => 'gam',
|
||||
'application/x-tar' => 'tar',
|
||||
'application/x-tcl' => 'tcl',
|
||||
'application/x-tex' => 'tex',
|
||||
'application/x-tex-tfm' => 'tfm',
|
||||
'application/x-texinfo' => 'texinfo',
|
||||
'application/x-tgif' => 'obj',
|
||||
'application/x-ustar' => 'ustar',
|
||||
'application/x-wais-source' => 'src',
|
||||
'application/x-x509-ca-cert' => 'der',
|
||||
'application/x-xfig' => 'fig',
|
||||
'application/x-xliff+xml' => 'xlf',
|
||||
'application/x-xpinstall' => 'xpi',
|
||||
'application/x-xz' => 'xz',
|
||||
'application/x-zip-compressed' => 'zip',
|
||||
'application/x-zmachine' => 'z1',
|
||||
'application/xaml+xml' => 'xaml',
|
||||
'application/xcap-diff+xml' => 'xdf',
|
||||
'application/xenc+xml' => 'xenc',
|
||||
'application/xhtml+xml' => 'xhtml',
|
||||
'application/xml' => 'xml',
|
||||
'application/xml-dtd' => 'dtd',
|
||||
'application/xop+xml' => 'xop',
|
||||
'application/xproc+xml' => 'xpl',
|
||||
'application/xslt+xml' => 'xslt',
|
||||
'application/xspf+xml' => 'xspf',
|
||||
'application/xv+xml' => 'mxml',
|
||||
'application/yang' => 'yang',
|
||||
'application/yin+xml' => 'yin',
|
||||
'application/zip' => 'zip',
|
||||
'audio/adpcm' => 'adp',
|
||||
'audio/basic' => 'au',
|
||||
'audio/midi' => 'mid',
|
||||
'audio/mp4' => 'mp4a',
|
||||
'audio/mpeg' => 'mpga',
|
||||
'audio/ogg' => 'oga',
|
||||
'audio/s3m' => 's3m',
|
||||
'audio/silk' => 'sil',
|
||||
'audio/vnd.dece.audio' => 'uva',
|
||||
'audio/vnd.digital-winds' => 'eol',
|
||||
'audio/vnd.dra' => 'dra',
|
||||
'audio/vnd.dts' => 'dts',
|
||||
'audio/vnd.dts.hd' => 'dtshd',
|
||||
'audio/vnd.lucent.voice' => 'lvp',
|
||||
'audio/vnd.ms-playready.media.pya' => 'pya',
|
||||
'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
|
||||
'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
|
||||
'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
|
||||
'audio/vnd.rip' => 'rip',
|
||||
'audio/webm' => 'weba',
|
||||
'audio/x-aac' => 'aac',
|
||||
'audio/x-aiff' => 'aif',
|
||||
'audio/x-caf' => 'caf',
|
||||
'audio/x-flac' => 'flac',
|
||||
'audio/x-matroska' => 'mka',
|
||||
'audio/x-mpegurl' => 'm3u',
|
||||
'audio/x-ms-wax' => 'wax',
|
||||
'audio/x-ms-wma' => 'wma',
|
||||
'audio/x-pn-realaudio' => 'ram',
|
||||
'audio/x-pn-realaudio-plugin' => 'rmp',
|
||||
'audio/x-wav' => 'wav',
|
||||
'audio/xm' => 'xm',
|
||||
'chemical/x-cdx' => 'cdx',
|
||||
'chemical/x-cif' => 'cif',
|
||||
'chemical/x-cmdf' => 'cmdf',
|
||||
'chemical/x-cml' => 'cml',
|
||||
'chemical/x-csml' => 'csml',
|
||||
'chemical/x-xyz' => 'xyz',
|
||||
'image/bmp' => 'bmp',
|
||||
'image/x-ms-bmp' => 'bmp',
|
||||
'image/cgm' => 'cgm',
|
||||
'image/g3fax' => 'g3',
|
||||
'image/gif' => 'gif',
|
||||
'image/ief' => 'ief',
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/pjpeg' => 'jpeg',
|
||||
'image/ktx' => 'ktx',
|
||||
'image/png' => 'png',
|
||||
'image/prs.btif' => 'btif',
|
||||
'image/sgi' => 'sgi',
|
||||
'image/svg+xml' => 'svg',
|
||||
'image/tiff' => 'tiff',
|
||||
'image/vnd.adobe.photoshop' => 'psd',
|
||||
'image/vnd.dece.graphic' => 'uvi',
|
||||
'image/vnd.dvb.subtitle' => 'sub',
|
||||
'image/vnd.djvu' => 'djvu',
|
||||
'image/vnd.dwg' => 'dwg',
|
||||
'image/vnd.dxf' => 'dxf',
|
||||
'image/vnd.fastbidsheet' => 'fbs',
|
||||
'image/vnd.fpx' => 'fpx',
|
||||
'image/vnd.fst' => 'fst',
|
||||
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
|
||||
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
|
||||
'image/vnd.ms-modi' => 'mdi',
|
||||
'image/vnd.ms-photo' => 'wdp',
|
||||
'image/vnd.net-fpx' => 'npx',
|
||||
'image/vnd.wap.wbmp' => 'wbmp',
|
||||
'image/vnd.xiff' => 'xif',
|
||||
'image/webp' => 'webp',
|
||||
'image/x-3ds' => '3ds',
|
||||
'image/x-cmu-raster' => 'ras',
|
||||
'image/x-cmx' => 'cmx',
|
||||
'image/x-freehand' => 'fh',
|
||||
'image/x-icon' => 'ico',
|
||||
'image/x-mrsid-image' => 'sid',
|
||||
'image/x-pcx' => 'pcx',
|
||||
'image/x-pict' => 'pic',
|
||||
'image/x-portable-anymap' => 'pnm',
|
||||
'image/x-portable-bitmap' => 'pbm',
|
||||
'image/x-portable-graymap' => 'pgm',
|
||||
'image/x-portable-pixmap' => 'ppm',
|
||||
'image/x-rgb' => 'rgb',
|
||||
'image/x-tga' => 'tga',
|
||||
'image/x-xbitmap' => 'xbm',
|
||||
'image/x-xpixmap' => 'xpm',
|
||||
'image/x-xwindowdump' => 'xwd',
|
||||
'message/rfc822' => 'eml',
|
||||
'model/iges' => 'igs',
|
||||
'model/mesh' => 'msh',
|
||||
'model/vnd.collada+xml' => 'dae',
|
||||
'model/vnd.dwf' => 'dwf',
|
||||
'model/vnd.gdl' => 'gdl',
|
||||
'model/vnd.gtw' => 'gtw',
|
||||
'model/vnd.mts' => 'mts',
|
||||
'model/vnd.vtu' => 'vtu',
|
||||
'model/vrml' => 'wrl',
|
||||
'model/x3d+binary' => 'x3db',
|
||||
'model/x3d+vrml' => 'x3dv',
|
||||
'model/x3d+xml' => 'x3d',
|
||||
'text/cache-manifest' => 'appcache',
|
||||
'text/calendar' => 'ics',
|
||||
'text/css' => 'css',
|
||||
'text/csv' => 'csv',
|
||||
'text/html' => 'html',
|
||||
'text/n3' => 'n3',
|
||||
'text/plain' => 'txt',
|
||||
'text/prs.lines.tag' => 'dsc',
|
||||
'text/richtext' => 'rtx',
|
||||
'text/rtf' => 'rtf',
|
||||
'text/sgml' => 'sgml',
|
||||
'text/tab-separated-values' => 'tsv',
|
||||
'text/troff' => 't',
|
||||
'text/turtle' => 'ttl',
|
||||
'text/uri-list' => 'uri',
|
||||
'text/vcard' => 'vcard',
|
||||
'text/vnd.curl' => 'curl',
|
||||
'text/vnd.curl.dcurl' => 'dcurl',
|
||||
'text/vnd.curl.scurl' => 'scurl',
|
||||
'text/vnd.curl.mcurl' => 'mcurl',
|
||||
'text/vnd.dvb.subtitle' => 'sub',
|
||||
'text/vnd.fly' => 'fly',
|
||||
'text/vnd.fmi.flexstor' => 'flx',
|
||||
'text/vnd.graphviz' => 'gv',
|
||||
'text/vnd.in3d.3dml' => '3dml',
|
||||
'text/vnd.in3d.spot' => 'spot',
|
||||
'text/vnd.sun.j2me.app-descriptor' => 'jad',
|
||||
'text/vnd.wap.wml' => 'wml',
|
||||
'text/vnd.wap.wmlscript' => 'wmls',
|
||||
'text/vtt' => 'vtt',
|
||||
'text/x-asm' => 's',
|
||||
'text/x-c' => 'c',
|
||||
'text/x-fortran' => 'f',
|
||||
'text/x-pascal' => 'p',
|
||||
'text/x-java-source' => 'java',
|
||||
'text/x-opml' => 'opml',
|
||||
'text/x-nfo' => 'nfo',
|
||||
'text/x-setext' => 'etx',
|
||||
'text/x-sfv' => 'sfv',
|
||||
'text/x-uuencode' => 'uu',
|
||||
'text/x-vcalendar' => 'vcs',
|
||||
'text/x-vcard' => 'vcf',
|
||||
'video/3gpp' => '3gp',
|
||||
'video/3gpp2' => '3g2',
|
||||
'video/h261' => 'h261',
|
||||
'video/h263' => 'h263',
|
||||
'video/h264' => 'h264',
|
||||
'video/jpeg' => 'jpgv',
|
||||
'video/jpm' => 'jpm',
|
||||
'video/mj2' => 'mj2',
|
||||
'video/mp4' => 'mp4',
|
||||
'video/mpeg' => 'mpeg',
|
||||
'video/ogg' => 'ogv',
|
||||
'video/quicktime' => 'qt',
|
||||
'video/vnd.dece.hd' => 'uvh',
|
||||
'video/vnd.dece.mobile' => 'uvm',
|
||||
'video/vnd.dece.pd' => 'uvp',
|
||||
'video/vnd.dece.sd' => 'uvs',
|
||||
'video/vnd.dece.video' => 'uvv',
|
||||
'video/vnd.dvb.file' => 'dvb',
|
||||
'video/vnd.fvt' => 'fvt',
|
||||
'video/vnd.mpegurl' => 'mxu',
|
||||
'video/vnd.ms-playready.media.pyv' => 'pyv',
|
||||
'video/vnd.uvvu.mp4' => 'uvu',
|
||||
'video/vnd.vivo' => 'viv',
|
||||
'video/webm' => 'webm',
|
||||
'video/x-f4v' => 'f4v',
|
||||
'video/x-fli' => 'fli',
|
||||
'video/x-flv' => 'flv',
|
||||
'video/x-m4v' => 'm4v',
|
||||
'video/x-matroska' => 'mkv',
|
||||
'video/x-mng' => 'mng',
|
||||
'video/x-ms-asf' => 'asf',
|
||||
'video/x-ms-vob' => 'vob',
|
||||
'video/x-ms-wm' => 'wm',
|
||||
'video/x-ms-wmv' => 'wmv',
|
||||
'video/x-ms-wmx' => 'wmx',
|
||||
'video/x-ms-wvx' => 'wvx',
|
||||
'video/x-msvideo' => 'avi',
|
||||
'video/x-sgi-movie' => 'movie',
|
||||
'video/x-smv' => 'smv',
|
||||
'x-conference/x-cooltalk' => 'ice',
|
||||
];
|
||||
|
||||
/**
|
||||
* Reversed from $defaultExtensions property in constructor.
|
||||
*/
|
||||
private $defaultMineTypes = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->defaultMineTypes = array_flip($this->defaultExtensions);
|
||||
}
|
||||
|
||||
public function guessExtension(string $mimeType): ?string
|
||||
{
|
||||
return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null;
|
||||
}
|
||||
|
||||
public function guessMimeType(string $extension): ?string
|
||||
{
|
||||
return isset($this->defaultMineTypes[$extension]) ? $this->defaultMineTypes[$extension] : null;
|
||||
}
|
||||
}
|
||||
46
addons/epay/library/hyperf/utils/src/Network.php
Normal file
46
addons/epay/library/hyperf/utils/src/Network.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class Network
|
||||
{
|
||||
public static function ip(): string
|
||||
{
|
||||
$ips = [];
|
||||
if (function_exists('swoole_get_local_ip')) {
|
||||
$ips = swoole_get_local_ip();
|
||||
}
|
||||
if (empty($ips) && function_exists('net_get_interfaces')) {
|
||||
foreach (net_get_interfaces() ?: [] as $name => $value) {
|
||||
foreach ($value['unicast'] as $item) {
|
||||
if (! isset($item['address'])) {
|
||||
continue;
|
||||
}
|
||||
if (! Str::contains($item['address'], '::') && $item['address'] !== '127.0.0.1') {
|
||||
$ips[$name] = $item['address'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_array($ips) && ! empty($ips)) {
|
||||
return current($ips);
|
||||
}
|
||||
/** @var mixed|string $ip */
|
||||
$ip = gethostbyname(gethostname());
|
||||
if (is_string($ip)) {
|
||||
return $ip;
|
||||
}
|
||||
throw new RuntimeException('Can not get the internal IP.');
|
||||
}
|
||||
}
|
||||
134
addons/epay/library/hyperf/utils/src/Optional.php
Normal file
134
addons/epay/library/hyperf/utils/src/Optional.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use ArrayAccess;
|
||||
use Hyperf\Macroable\Macroable;
|
||||
|
||||
class Optional implements ArrayAccess
|
||||
{
|
||||
use Macroable {
|
||||
__call as macroCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* The underlying object.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create a new optional instance.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically access a property on the underlying object.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
if (is_object($this->value)) {
|
||||
return $this->value->{$key} ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically check a property exists on the underlying object.
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
if (is_object($this->value)) {
|
||||
return isset($this->value->{$name});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass a method to the underlying object.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (static::hasMacro($method)) {
|
||||
return $this->macroCall($method, $parameters);
|
||||
}
|
||||
|
||||
if (is_object($this->value)) {
|
||||
return $this->value->{$method}(...$parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item exists at an offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return Arr::accessible($this->value) && Arr::exists($this->value, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item at a given offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return Arr::get($this->value, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the item at a given offset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
if (Arr::accessible($this->value)) {
|
||||
$this->value[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the item at a given offset.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
if (Arr::accessible($this->value)) {
|
||||
unset($this->value[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
addons/epay/library/hyperf/utils/src/Packer/JsonPacker.php
Normal file
27
addons/epay/library/hyperf/utils/src/Packer/JsonPacker.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Packer;
|
||||
|
||||
use Hyperf\Contract\PackerInterface;
|
||||
|
||||
class JsonPacker implements PackerInterface
|
||||
{
|
||||
public function pack($data): string
|
||||
{
|
||||
return json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
public function unpack(string $data)
|
||||
{
|
||||
return json_decode($data, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Packer;
|
||||
|
||||
use Hyperf\Contract\PackerInterface;
|
||||
|
||||
class PhpSerializerPacker implements PackerInterface
|
||||
{
|
||||
public function pack($data): string
|
||||
{
|
||||
return serialize($data);
|
||||
}
|
||||
|
||||
public function unpack(string $data)
|
||||
{
|
||||
return unserialize($data);
|
||||
}
|
||||
}
|
||||
111
addons/epay/library/hyperf/utils/src/Parallel.php
Normal file
111
addons/epay/library/hyperf/utils/src/Parallel.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Hyperf\Utils\Exception\ParallelExecutionException;
|
||||
use Swoole\Coroutine\Channel;
|
||||
|
||||
class Parallel
|
||||
{
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
private $callbacks = [];
|
||||
|
||||
/**
|
||||
* @var null|Channel
|
||||
*/
|
||||
private $concurrentChannel;
|
||||
|
||||
private $results = [];
|
||||
|
||||
/**
|
||||
* @var \Throwable[]
|
||||
*/
|
||||
private $throwables = [];
|
||||
|
||||
/**
|
||||
* @param int $concurrent if $concurrent is equal to 0, that means unlimit
|
||||
*/
|
||||
public function __construct(int $concurrent = 0)
|
||||
{
|
||||
if ($concurrent > 0) {
|
||||
$this->concurrentChannel = new Channel($concurrent);
|
||||
}
|
||||
}
|
||||
|
||||
public function add(callable $callable, $key = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
$this->callbacks[] = $callable;
|
||||
} else {
|
||||
$this->callbacks[$key] = $callable;
|
||||
}
|
||||
}
|
||||
|
||||
public function wait(bool $throw = true): array
|
||||
{
|
||||
$wg = new WaitGroup();
|
||||
$wg->add(count($this->callbacks));
|
||||
foreach ($this->callbacks as $key => $callback) {
|
||||
$this->concurrentChannel && $this->concurrentChannel->push(true);
|
||||
$this->results[$key] = null;
|
||||
Coroutine::create(function () use ($callback, $key, $wg) {
|
||||
try {
|
||||
$this->results[$key] = $callback();
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->throwables[$key] = $throwable;
|
||||
unset($this->results[$key]);
|
||||
} finally {
|
||||
$this->concurrentChannel && $this->concurrentChannel->pop();
|
||||
$wg->done();
|
||||
}
|
||||
});
|
||||
}
|
||||
$wg->wait();
|
||||
if ($throw && ($throwableCount = count($this->throwables)) > 0) {
|
||||
$message = 'Detecting ' . $throwableCount . ' throwable occurred during parallel execution:' . PHP_EOL . $this->formatThrowables($this->throwables);
|
||||
$executionException = new ParallelExecutionException($message);
|
||||
$executionException->setResults($this->results);
|
||||
$executionException->setThrowables($this->throwables);
|
||||
unset($this->results, $this->throwables);
|
||||
throw $executionException;
|
||||
}
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->callbacks);
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
$this->callbacks = [];
|
||||
$this->results = [];
|
||||
$this->throwables = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format throwables into a nice list.
|
||||
*
|
||||
* @param \Throwable[] $throwables
|
||||
*/
|
||||
private function formatThrowables(array $throwables): string
|
||||
{
|
||||
$output = '';
|
||||
foreach ($throwables as $key => $value) {
|
||||
$output .= \sprintf('(%s) %s: %s' . PHP_EOL . '%s' . PHP_EOL, $key, get_class($value), $value->getMessage(), $value->getTraceAsString());
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
171
addons/epay/library/hyperf/utils/src/Pipeline.php
Normal file
171
addons/epay/library/hyperf/utils/src/Pipeline.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Closure;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* This file mostly code come from illuminate/pipe,
|
||||
* thanks Laravel Team provide such a useful class.
|
||||
*/
|
||||
class Pipeline
|
||||
{
|
||||
/**
|
||||
* The container implementation.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The object being passed through the pipeline.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $passable;
|
||||
|
||||
/**
|
||||
* The array of class pipes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pipes = [];
|
||||
|
||||
/**
|
||||
* The method to call on each pipe.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method = 'handle';
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object being sent through the pipeline.
|
||||
* @param mixed $passable
|
||||
*/
|
||||
public function send($passable): self
|
||||
{
|
||||
$this->passable = $passable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the array of pipes.
|
||||
*
|
||||
* @param array|mixed $pipes
|
||||
*/
|
||||
public function through($pipes): self
|
||||
{
|
||||
$this->pipes = is_array($pipes) ? $pipes : func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the method to call on the pipes.
|
||||
*/
|
||||
public function via(string $method): self
|
||||
{
|
||||
$this->method = $method;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the pipeline with a final destination callback.
|
||||
*/
|
||||
public function then(Closure $destination)
|
||||
{
|
||||
$pipeline = array_reduce(array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination));
|
||||
|
||||
return $pipeline($this->passable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the final piece of the Closure onion.
|
||||
*/
|
||||
protected function prepareDestination(Closure $destination): Closure
|
||||
{
|
||||
return static function ($passable) use ($destination) {
|
||||
return $destination($passable);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Closure that represents a slice of the application onion.
|
||||
*/
|
||||
protected function carry(): Closure
|
||||
{
|
||||
return function ($stack, $pipe) {
|
||||
return function ($passable) use ($stack, $pipe) {
|
||||
if (is_callable($pipe)) {
|
||||
// If the pipe is an instance of a Closure, we will just call it directly but
|
||||
// otherwise we'll resolve the pipes out of the container and call it with
|
||||
// the appropriate method and arguments, returning the results back out.
|
||||
return $pipe($passable, $stack);
|
||||
}
|
||||
if (! is_object($pipe)) {
|
||||
[$name, $parameters] = $this->parsePipeString($pipe);
|
||||
|
||||
// If the pipe is a string we will parse the string and resolve the class out
|
||||
// of the dependency injection container. We can then build a callable and
|
||||
// execute the pipe function giving in the parameters that are required.
|
||||
$pipe = $this->container->get($name);
|
||||
|
||||
$parameters = array_merge([$passable, $stack], $parameters);
|
||||
} else {
|
||||
// If the pipe is already an object we'll just make a callable and pass it to
|
||||
// the pipe as-is. There is no need to do any extra parsing and formatting
|
||||
// since the object we're given was already a fully instantiated object.
|
||||
$parameters = [$passable, $stack];
|
||||
}
|
||||
|
||||
$carry = method_exists($pipe, $this->method) ? $pipe->{$this->method}(...$parameters) : $pipe(...$parameters);
|
||||
|
||||
return $this->handleCarry($carry);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse full pipe string to get name and parameters.
|
||||
*
|
||||
* @param string $pipe
|
||||
* @return array
|
||||
*/
|
||||
protected function parsePipeString($pipe)
|
||||
{
|
||||
[$name, $parameters] = array_pad(explode(':', $pipe, 2), 2, []);
|
||||
|
||||
if (is_string($parameters)) {
|
||||
$parameters = explode(',', $parameters);
|
||||
}
|
||||
|
||||
return [$name, $parameters];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the value returned from each pipe before passing it to the next.
|
||||
*
|
||||
* @param mixed $carry
|
||||
* @return mixed
|
||||
*/
|
||||
protected function handleCarry($carry)
|
||||
{
|
||||
return $carry;
|
||||
}
|
||||
}
|
||||
161
addons/epay/library/hyperf/utils/src/Pluralizer.php
Normal file
161
addons/epay/library/hyperf/utils/src/Pluralizer.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Doctrine\Inflector\CachedWordInflector;
|
||||
use Doctrine\Inflector\Inflector;
|
||||
use Doctrine\Inflector\Rules\English;
|
||||
use Doctrine\Inflector\RulesetInflector;
|
||||
|
||||
class Pluralizer
|
||||
{
|
||||
/**
|
||||
* Uncountable word forms.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $uncountable
|
||||
= [
|
||||
'audio',
|
||||
'bison',
|
||||
'cattle',
|
||||
'chassis',
|
||||
'compensation',
|
||||
'coreopsis',
|
||||
'data',
|
||||
'deer',
|
||||
'education',
|
||||
'emoji',
|
||||
'equipment',
|
||||
'evidence',
|
||||
'feedback',
|
||||
'firmware',
|
||||
'fish',
|
||||
'furniture',
|
||||
'gold',
|
||||
'hardware',
|
||||
'information',
|
||||
'jedi',
|
||||
'kin',
|
||||
'knowledge',
|
||||
'love',
|
||||
'metadata',
|
||||
'money',
|
||||
'moose',
|
||||
'news',
|
||||
'nutrition',
|
||||
'offspring',
|
||||
'plankton',
|
||||
'pokemon',
|
||||
'police',
|
||||
'rain',
|
||||
'rice',
|
||||
'series',
|
||||
'sheep',
|
||||
'software',
|
||||
'species',
|
||||
'swine',
|
||||
'traffic',
|
||||
'wheat',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var null|Inflector
|
||||
*/
|
||||
protected static $inflector;
|
||||
|
||||
/**
|
||||
* Get the plural form of an English word.
|
||||
*
|
||||
* @param string $value
|
||||
* @param int $count
|
||||
* @return string
|
||||
*/
|
||||
public static function plural($value, $count = 2)
|
||||
{
|
||||
if ((int) abs($count) === 1 || static::uncountable($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$plural = static::getInflector()->pluralize($value);
|
||||
|
||||
return static::matchCase($plural, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singular form of an English word.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function singular($value)
|
||||
{
|
||||
$singular = static::getInflector()->singularize($value);
|
||||
|
||||
return static::matchCase($singular, $value);
|
||||
}
|
||||
|
||||
public static function setInflector(?Inflector $inflector): void
|
||||
{
|
||||
static::$inflector = $inflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inflector instance.
|
||||
*/
|
||||
public static function getInflector(): Inflector
|
||||
{
|
||||
if (is_null(static::$inflector)) {
|
||||
static::$inflector = new Inflector(
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
English\Rules::getSingularRuleset()
|
||||
)),
|
||||
new CachedWordInflector(new RulesetInflector(
|
||||
English\Rules::getPluralRuleset()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
return static::$inflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given value is uncountable.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected static function uncountable($value)
|
||||
{
|
||||
return in_array(strtolower($value), static::$uncountable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to match the case on two strings.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $comparison
|
||||
* @return string
|
||||
*/
|
||||
protected static function matchCase($value, $comparison)
|
||||
{
|
||||
$functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords'];
|
||||
|
||||
foreach ($functions as $function) {
|
||||
if (call_user_func($function, $comparison) === $comparison) {
|
||||
return call_user_func($function, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Reflection;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
class ClassInvoker
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
*/
|
||||
protected $instance;
|
||||
|
||||
/**
|
||||
* @var ReflectionClass
|
||||
*/
|
||||
protected $reflection;
|
||||
|
||||
public function __construct(object $instance)
|
||||
{
|
||||
$this->instance = $instance;
|
||||
$this->reflection = new ReflectionClass($instance);
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
$property = $this->reflection->getProperty($name);
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
return $property->getValue($this->instance);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$method = $this->reflection->getMethod($name);
|
||||
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method->invokeArgs($this->instance, $arguments);
|
||||
}
|
||||
}
|
||||
37
addons/epay/library/hyperf/utils/src/Resource.php
Normal file
37
addons/epay/library/hyperf/utils/src/Resource.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
/**
|
||||
* @deprecated v2.3, please use ResourceGenerator instead.
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
/**
|
||||
* TODO: Swoole file hook does not support `php://temp` and `php://memory`.
|
||||
*/
|
||||
public static function from(string $body, string $filename = 'php://temp')
|
||||
{
|
||||
$resource = fopen($filename, 'r+');
|
||||
if ($body !== '') {
|
||||
fwrite($resource, $body);
|
||||
fseek($resource, 0);
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
public static function fromMemory(string $body)
|
||||
{
|
||||
return static::from($body, 'php://memory');
|
||||
}
|
||||
}
|
||||
34
addons/epay/library/hyperf/utils/src/ResourceGenerator.php
Normal file
34
addons/epay/library/hyperf/utils/src/ResourceGenerator.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
class ResourceGenerator
|
||||
{
|
||||
/**
|
||||
* TODO: Swoole file hook does not support `php://temp` and `php://memory`.
|
||||
*/
|
||||
public static function from(string $body, string $filename = 'php://temp')
|
||||
{
|
||||
$resource = fopen($filename, 'r+');
|
||||
if ($body !== '') {
|
||||
fwrite($resource, $body);
|
||||
fseek($resource, 0);
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
public static function fromMemory(string $body)
|
||||
{
|
||||
return static::from($body, 'php://memory');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Doctrine\Instantiator\Instantiator;
|
||||
use Hyperf\Di\ReflectionManager;
|
||||
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class ExceptionNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
/**
|
||||
* @var null|Instantiator
|
||||
*/
|
||||
protected $instantiator;
|
||||
|
||||
public function denormalize($data, string $class, string $format = null, array $context = [])
|
||||
{
|
||||
if (is_string($data)) {
|
||||
$ex = unserialize($data);
|
||||
if ($ex instanceof \Throwable) {
|
||||
return $ex;
|
||||
}
|
||||
|
||||
// Retry handle it if the exception not instanceof \Throwable.
|
||||
$data = $ex;
|
||||
}
|
||||
if (is_array($data) && isset($data['message'], $data['code'])) {
|
||||
try {
|
||||
$exception = $this->getInstantiator()->instantiate($class);
|
||||
foreach (['code', 'message', 'file', 'line'] as $attribute) {
|
||||
if (isset($data[$attribute])) {
|
||||
$property = ReflectionManager::reflectProperty($class, $attribute);
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($exception, $data[$attribute]);
|
||||
}
|
||||
}
|
||||
return $exception;
|
||||
} catch (\ReflectionException $e) {
|
||||
return new \RuntimeException(sprintf(
|
||||
'Bad data %s: %s',
|
||||
$data['class'],
|
||||
$data['message']
|
||||
), $data['code']);
|
||||
} catch (\TypeError $e) {
|
||||
return new \RuntimeException(sprintf(
|
||||
'Uncaught data %s: %s',
|
||||
$data['class'],
|
||||
$data['message']
|
||||
), $data['code']);
|
||||
}
|
||||
}
|
||||
|
||||
return new \RuntimeException('Bad data data: ' . json_encode($data));
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, $type, $format = null)
|
||||
{
|
||||
return class_exists($type) && is_a($type, \Throwable::class, true);
|
||||
}
|
||||
|
||||
public function normalize($object, string $format = null, array $context = [])
|
||||
{
|
||||
if ($object instanceof \Serializable) {
|
||||
return serialize($object);
|
||||
}
|
||||
/* @var \Throwable $object */
|
||||
return [
|
||||
'message' => $object->getMessage(),
|
||||
'code' => $object->getCode(),
|
||||
'file' => $object->getFile(),
|
||||
'line' => $object->getLine(),
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null)
|
||||
{
|
||||
return $data instanceof \Throwable;
|
||||
}
|
||||
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return \get_class($this) === __CLASS__;
|
||||
}
|
||||
|
||||
protected function getInstantiator(): Instantiator
|
||||
{
|
||||
if ($this->instantiator instanceof Instantiator) {
|
||||
return $this->instantiator;
|
||||
}
|
||||
|
||||
return $this->instantiator = new Instantiator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use function get_class;
|
||||
use function is_scalar;
|
||||
|
||||
class ScalarNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
|
||||
{
|
||||
public function hasCacheableSupportsMethod(): bool
|
||||
{
|
||||
return get_class($this) === __CLASS__;
|
||||
}
|
||||
|
||||
public function denormalize($data, string $class, string $format = null, array $context = [])
|
||||
{
|
||||
switch ($class) {
|
||||
case 'int':
|
||||
return (int) $data;
|
||||
case 'string':
|
||||
return (string) $data;
|
||||
case 'float':
|
||||
return (float) $data;
|
||||
case 'bool':
|
||||
return (bool) $data;
|
||||
default:
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, $type, string $format = null)
|
||||
{
|
||||
return in_array($type, [
|
||||
'int',
|
||||
'string',
|
||||
'float',
|
||||
'bool',
|
||||
'mixed',
|
||||
'array', // TODO: Symfony\Component\Serializer\Normalizer\ArrayDenormalizer not support array, so it denormalized in ScalarNormalizer.
|
||||
]);
|
||||
}
|
||||
|
||||
public function normalize($object, string $format = null, array $context = [])
|
||||
{
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null)
|
||||
{
|
||||
return is_scalar($data);
|
||||
}
|
||||
}
|
||||
312
addons/epay/library/hyperf/utils/src/Serializer/Serializer.php
Normal file
312
addons/epay/library/hyperf/utils/src/Serializer/Serializer.php
Normal file
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Hyperf\Contract\NormalizerInterface as Normalizer;
|
||||
use Symfony\Component\Serializer\Encoder;
|
||||
use Symfony\Component\Serializer\Encoder\ChainDecoder;
|
||||
use Symfony\Component\Serializer\Encoder\ChainEncoder;
|
||||
use Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface;
|
||||
use Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface;
|
||||
use Symfony\Component\Serializer\Encoder\DecoderInterface;
|
||||
use Symfony\Component\Serializer\Encoder\EncoderInterface;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Serializer serializes and deserializes data.
|
||||
*
|
||||
* objects are turned into arrays by normalizers.
|
||||
* arrays are turned into various output formats by encoders.
|
||||
*
|
||||
* $serializer->serialize($obj, 'xml')
|
||||
* $serializer->decode($data, 'xml')
|
||||
* $serializer->denormalize($data, 'Class', 'xml')
|
||||
*/
|
||||
class Serializer implements Normalizer, SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface
|
||||
{
|
||||
private const SCALAR_TYPES = [
|
||||
'int' => true,
|
||||
'bool' => true,
|
||||
'float' => true,
|
||||
'string' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var Encoder\ChainEncoder
|
||||
*/
|
||||
protected $encoder;
|
||||
|
||||
/**
|
||||
* @var Encoder\ChainDecoder
|
||||
*/
|
||||
protected $decoder;
|
||||
|
||||
private $normalizers = [];
|
||||
|
||||
private $denormalizerCache = [];
|
||||
|
||||
private $normalizerCache = [];
|
||||
|
||||
/**
|
||||
* @param (NormalizerInterface|DenormalizerInterface|mixed)[] $normalizers
|
||||
* @param (EncoderInterface|DecoderInterface|mixed)[] $encoders
|
||||
*/
|
||||
public function __construct(array $normalizers = [], array $encoders = [])
|
||||
{
|
||||
foreach ($normalizers as $normalizer) {
|
||||
if ($normalizer instanceof SerializerAwareInterface) {
|
||||
$normalizer->setSerializer($this);
|
||||
}
|
||||
|
||||
if ($normalizer instanceof DenormalizerAwareInterface) {
|
||||
$normalizer->setDenormalizer($this);
|
||||
}
|
||||
|
||||
if ($normalizer instanceof NormalizerAwareInterface) {
|
||||
$normalizer->setNormalizer($this);
|
||||
}
|
||||
|
||||
if (! ($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) {
|
||||
throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($normalizer), NormalizerInterface::class, DenormalizerInterface::class));
|
||||
}
|
||||
}
|
||||
$this->normalizers = $normalizers;
|
||||
|
||||
$decoders = [];
|
||||
$realEncoders = [];
|
||||
foreach ($encoders as $encoder) {
|
||||
if ($encoder instanceof SerializerAwareInterface) {
|
||||
$encoder->setSerializer($this);
|
||||
}
|
||||
if ($encoder instanceof DecoderInterface) {
|
||||
$decoders[] = $encoder;
|
||||
}
|
||||
if ($encoder instanceof EncoderInterface) {
|
||||
$realEncoders[] = $encoder;
|
||||
}
|
||||
|
||||
if (! ($encoder instanceof EncoderInterface || $encoder instanceof DecoderInterface)) {
|
||||
throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($encoder), EncoderInterface::class, DecoderInterface::class));
|
||||
}
|
||||
}
|
||||
$this->encoder = new ChainEncoder($realEncoders);
|
||||
$this->decoder = new ChainDecoder($decoders);
|
||||
}
|
||||
|
||||
final public function serialize($data, string $format, array $context = []): string
|
||||
{
|
||||
if (! $this->supportsEncoding($format, $context)) {
|
||||
throw new NotEncodableValueException(sprintf('Serialization for the format "%s" is not supported.', $format));
|
||||
}
|
||||
|
||||
if ($this->encoder->needsNormalization($format, $context)) {
|
||||
$data = $this->normalize($data, $format, $context);
|
||||
}
|
||||
|
||||
return $this->encode($data, $format, $context);
|
||||
}
|
||||
|
||||
final public function deserialize($data, string $type, string $format, array $context = [])
|
||||
{
|
||||
if (! $this->supportsDecoding($format, $context)) {
|
||||
throw new NotEncodableValueException(sprintf('Deserialization for the format "%s" is not supported.', $format));
|
||||
}
|
||||
|
||||
$data = $this->decode($data, $format, $context);
|
||||
|
||||
return $this->denormalize($data, $type, $format, $context);
|
||||
}
|
||||
|
||||
public function normalize($data, string $format = null, array $context = [])
|
||||
{
|
||||
// If a normalizer supports the given data, use it
|
||||
if ($normalizer = $this->getNormalizer($data, $format, $context)) {
|
||||
return $normalizer->normalize($data, $format, $context);
|
||||
}
|
||||
|
||||
if ($data === null || is_scalar($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (\is_array($data) || $data instanceof \Traversable) {
|
||||
if ($data instanceof \Countable && $data->count() === 0) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$normalized = [];
|
||||
foreach ($data as $key => $val) {
|
||||
$normalized[$key] = $this->normalize($val, $format, $context);
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
if (\is_object($data)) {
|
||||
if (! $this->normalizers) {
|
||||
throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
|
||||
}
|
||||
|
||||
throw new NotNormalizableValueException(sprintf('Could not normalize object of type "%s", no supporting normalizer found.', get_debug_type($data)));
|
||||
}
|
||||
|
||||
throw new NotNormalizableValueException('An unexpected value could not be normalized: ' . (! \is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @throws NotNormalizableValueException
|
||||
*/
|
||||
public function denormalize($data, string $type, string $format = null, array $context = [])
|
||||
{
|
||||
if (isset(self::SCALAR_TYPES[$type])) {
|
||||
if (is_scalar($data)) {
|
||||
switch ($type) {
|
||||
case 'int':
|
||||
return (int) $data;
|
||||
case 'bool':
|
||||
return (bool) $data;
|
||||
case 'float':
|
||||
return (float) $data;
|
||||
case 'string':
|
||||
return (string) $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->normalizers) {
|
||||
throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
|
||||
}
|
||||
|
||||
if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) {
|
||||
return $normalizer->denormalize($data, $type, $format, $context);
|
||||
}
|
||||
|
||||
throw new NotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type));
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null, array $context = [])
|
||||
{
|
||||
return $this->getNormalizer($data, $format, $context) !== null;
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, string $type, string $format = null, array $context = [])
|
||||
{
|
||||
return isset(self::SCALAR_TYPES[$type]) || $this->getDenormalizer($data, $type, $format, $context) !== null;
|
||||
}
|
||||
|
||||
final public function encode($data, string $format, array $context = [])
|
||||
{
|
||||
return $this->encoder->encode($data, $format, $context);
|
||||
}
|
||||
|
||||
final public function decode(string $data, string $format, array $context = [])
|
||||
{
|
||||
return $this->decoder->decode($data, $format, $context);
|
||||
}
|
||||
|
||||
public function supportsEncoding(string $format, array $context = [])
|
||||
{
|
||||
return $this->encoder->supportsEncoding($format, $context);
|
||||
}
|
||||
|
||||
public function supportsDecoding(string $format, array $context = [])
|
||||
{
|
||||
return $this->decoder->supportsDecoding($format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matching normalizer.
|
||||
*
|
||||
* @param mixed $data Data to get the serializer for
|
||||
* @param string $format Format name, present to give the option to normalizers to act differently based on formats
|
||||
* @param array $context Options available to the normalizer
|
||||
*/
|
||||
private function getNormalizer($data, ?string $format, array $context): ?NormalizerInterface
|
||||
{
|
||||
$type = \is_object($data) ? \get_class($data) : 'native-' . \gettype($data);
|
||||
|
||||
if (! isset($this->normalizerCache[$format][$type])) {
|
||||
$this->normalizerCache[$format][$type] = [];
|
||||
|
||||
foreach ($this->normalizers as $k => $normalizer) {
|
||||
if (! $normalizer instanceof NormalizerInterface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) {
|
||||
$this->normalizerCache[$format][$type][$k] = false;
|
||||
} elseif ($normalizer->supportsNormalization($data, $format)) {
|
||||
$this->normalizerCache[$format][$type][$k] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->normalizerCache[$format][$type] as $k => $cached) {
|
||||
$normalizer = $this->normalizers[$k];
|
||||
if ($cached || $normalizer->supportsNormalization($data, $format, $context)) {
|
||||
return $normalizer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matching denormalizer.
|
||||
*
|
||||
* @param mixed $data Data to restore
|
||||
* @param string $class The expected class to instantiate
|
||||
* @param string $format Format name, present to give the option to normalizers to act differently based on formats
|
||||
* @param array $context Options available to the denormalizer
|
||||
*/
|
||||
private function getDenormalizer($data, string $class, ?string $format, array $context): ?DenormalizerInterface
|
||||
{
|
||||
if (! isset($this->denormalizerCache[$format][$class])) {
|
||||
$this->denormalizerCache[$format][$class] = [];
|
||||
|
||||
foreach ($this->normalizers as $k => $normalizer) {
|
||||
if (! $normalizer instanceof DenormalizerInterface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) {
|
||||
$this->denormalizerCache[$format][$class][$k] = false;
|
||||
} elseif ($normalizer->supportsDenormalization(null, $class, $format)) {
|
||||
$this->denormalizerCache[$format][$class][$k] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->denormalizerCache[$format][$class] as $k => $cached) {
|
||||
$normalizer = $this->normalizers[$k];
|
||||
if ($cached || $normalizer->supportsDenormalization($data, $class, $format, $context)) {
|
||||
return $normalizer;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
class SerializerFactory
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
public function __construct(string $serializer = Serializer::class)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
public function __invoke()
|
||||
{
|
||||
return new $this->serializer([
|
||||
new ExceptionNormalizer(),
|
||||
new ObjectNormalizer(),
|
||||
new ArrayDenormalizer(),
|
||||
new ScalarNormalizer(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Hyperf\Contract\NormalizerInterface;
|
||||
|
||||
class SimpleNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function normalize($object)
|
||||
{
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function denormalize($data, string $class)
|
||||
{
|
||||
switch ($class) {
|
||||
case 'int':
|
||||
return (int) $data;
|
||||
case 'string':
|
||||
return (string) $data;
|
||||
case 'float':
|
||||
return (float) $data;
|
||||
case 'array':
|
||||
return (array) $data;
|
||||
case 'bool':
|
||||
return (bool) $data;
|
||||
default:
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Serializer;
|
||||
|
||||
use Hyperf\Contract\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
class SymfonyNormalizer implements NormalizerInterface
|
||||
{
|
||||
/**
|
||||
* @var Serializer
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
public function __construct(Serializer $serializer)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
public function normalize($object)
|
||||
{
|
||||
return $this->serializer->normalize($object);
|
||||
}
|
||||
|
||||
public function denormalize($data, string $class)
|
||||
{
|
||||
return $this->serializer->denormalize($data, $class);
|
||||
}
|
||||
}
|
||||
1320
addons/epay/library/hyperf/utils/src/Str.php
Normal file
1320
addons/epay/library/hyperf/utils/src/Str.php
Normal file
File diff suppressed because it is too large
Load Diff
803
addons/epay/library/hyperf/utils/src/Stringable.php
Normal file
803
addons/epay/library/hyperf/utils/src/Stringable.php
Normal file
@@ -0,0 +1,803 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Closure;
|
||||
use Hyperf\Macroable\Macroable;
|
||||
use JsonSerializable;
|
||||
|
||||
class Stringable implements JsonSerializable
|
||||
{
|
||||
use Traits\Conditionable;
|
||||
use Macroable;
|
||||
use Traits\Tappable;
|
||||
|
||||
/**
|
||||
* The underlying string value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create a new instance of the class.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct($value = '')
|
||||
{
|
||||
$this->value = (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy dynamic properties onto methods.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->{$key}();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw string value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remainder of a string after the first occurrence of a given value.
|
||||
*
|
||||
* @param string $search
|
||||
* @return static
|
||||
*/
|
||||
public function after($search)
|
||||
{
|
||||
return new static(Str::after($this->value, $search));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remainder of a string after the last occurrence of a given value.
|
||||
*
|
||||
* @param string $search
|
||||
* @return static
|
||||
*/
|
||||
public function afterLast($search)
|
||||
{
|
||||
return new static(Str::afterLast($this->value, $search));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given values to the string.
|
||||
*
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function append(...$values)
|
||||
{
|
||||
return new static($this->value . implode('', $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transliterate a UTF-8 value to ASCII.
|
||||
*
|
||||
* @param string $language
|
||||
* @return static
|
||||
*/
|
||||
public function ascii($language = 'en')
|
||||
{
|
||||
return new static(Str::ascii($this->value, $language));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trailing name component of the path.
|
||||
*
|
||||
* @param string $suffix
|
||||
* @return static
|
||||
*/
|
||||
public function basename($suffix = '')
|
||||
{
|
||||
return new static(basename($this->value, $suffix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the basename of the class path.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function classBasename()
|
||||
{
|
||||
return new static(class_basename($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the portion of a string before the first occurrence of a given value.
|
||||
*
|
||||
* @param string $search
|
||||
* @return static
|
||||
*/
|
||||
public function before($search)
|
||||
{
|
||||
return new static(Str::before($this->value, $search));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the portion of a string before the last occurrence of a given value.
|
||||
*
|
||||
* @param string $search
|
||||
* @return static
|
||||
*/
|
||||
public function beforeLast($search)
|
||||
{
|
||||
return new static(Str::beforeLast($this->value, $search));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the portion of a string between two given values.
|
||||
*
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
* @return static
|
||||
*/
|
||||
public function between($from, $to)
|
||||
{
|
||||
return new static(Str::between($this->value, $from, $to));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value to camel case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function camel()
|
||||
{
|
||||
return new static(Str::camel($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string contains a given substring.
|
||||
*
|
||||
* @param array|string $needles
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($needles)
|
||||
{
|
||||
return Str::contains($this->value, $needles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string contains all array values.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function containsAll(array $needles)
|
||||
{
|
||||
return Str::containsAll($this->value, $needles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent directory's path.
|
||||
*
|
||||
* @param int $levels
|
||||
* @return static
|
||||
*/
|
||||
public function dirname($levels = 1)
|
||||
{
|
||||
return new static(dirname($this->value, $levels));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string ends with a given substring.
|
||||
*
|
||||
* @param array|string $needles
|
||||
* @return bool
|
||||
*/
|
||||
public function endsWith($needles)
|
||||
{
|
||||
return Str::endsWith($this->value, $needles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string is an exact match with the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public function exactly($value)
|
||||
{
|
||||
return $this->value === $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the string into an array.
|
||||
*
|
||||
* @param string $delimiter
|
||||
* @param int $limit
|
||||
* @return \Hyperf\Utils\Collection
|
||||
*/
|
||||
public function explode($delimiter, $limit = PHP_INT_MAX)
|
||||
{
|
||||
return collect(explode($delimiter, $this->value, $limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a string using a regular expression or by length.
|
||||
*
|
||||
* @param int|string $pattern
|
||||
* @param int $limit
|
||||
* @param int $flags
|
||||
* @return \Hyperf\Utils\Collection
|
||||
*/
|
||||
public function split($pattern, $limit = -1, $flags = 0)
|
||||
{
|
||||
if (filter_var($pattern, FILTER_VALIDATE_INT) !== false) {
|
||||
return collect(mb_str_split($this->value, $pattern));
|
||||
}
|
||||
|
||||
$segments = preg_split($pattern, $this->value, $limit, $flags);
|
||||
|
||||
return ! empty($segments) ? collect($segments) : collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cap a string with a single instance of a given value.
|
||||
*
|
||||
* @param string $cap
|
||||
* @return static
|
||||
*/
|
||||
public function finish($cap)
|
||||
{
|
||||
return new static(Str::finish($this->value, $cap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string matches a given pattern.
|
||||
*
|
||||
* @param array|string $pattern
|
||||
* @return bool
|
||||
*/
|
||||
public function is($pattern)
|
||||
{
|
||||
return Str::is($pattern, $this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given string is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->value === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given string is not empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotEmpty()
|
||||
{
|
||||
return ! $this->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to kebab case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function kebab()
|
||||
{
|
||||
return new static(Str::kebab($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the given string.
|
||||
*
|
||||
* @param string $encoding
|
||||
* @return int
|
||||
*/
|
||||
public function length($encoding = null)
|
||||
{
|
||||
return Str::length($this->value, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of characters in a string.
|
||||
*
|
||||
* @param int $limit
|
||||
* @param string $end
|
||||
* @return static
|
||||
*/
|
||||
public function limit($limit = 100, $end = '...')
|
||||
{
|
||||
return new static(Str::limit($this->value, $limit, $end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given string to lower-case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function lower()
|
||||
{
|
||||
return new static(Str::lower($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string matching the given pattern.
|
||||
*
|
||||
* @param string $pattern
|
||||
* @return static
|
||||
*/
|
||||
public function match($pattern)
|
||||
{
|
||||
preg_match($pattern, $this->value, $matches);
|
||||
|
||||
if (! $matches) {
|
||||
return new static();
|
||||
}
|
||||
|
||||
return new static($matches[1] ?? $matches[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string matching the given pattern.
|
||||
*
|
||||
* @param string $pattern
|
||||
* @return \Hyperf\Utils\Collection
|
||||
*/
|
||||
public function matchAll($pattern)
|
||||
{
|
||||
preg_match_all($pattern, $this->value, $matches);
|
||||
|
||||
if (empty($matches[0])) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return collect($matches[1] ?? $matches[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string matches the given pattern.
|
||||
*
|
||||
* @param string $pattern
|
||||
* @return bool
|
||||
*/
|
||||
public function test($pattern)
|
||||
{
|
||||
return $this->match($pattern)->isNotEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad both sides of the string with another.
|
||||
*
|
||||
* @param int $length
|
||||
* @param string $pad
|
||||
* @return static
|
||||
*/
|
||||
public function padBoth($length, $pad = ' ')
|
||||
{
|
||||
return new static(Str::padBoth($this->value, $length, $pad));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad the left side of the string with another.
|
||||
*
|
||||
* @param int $length
|
||||
* @param string $pad
|
||||
* @return static
|
||||
*/
|
||||
public function padLeft($length, $pad = ' ')
|
||||
{
|
||||
return new static(Str::padLeft($this->value, $length, $pad));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad the right side of the string with another.
|
||||
*
|
||||
* @param int $length
|
||||
* @param string $pad
|
||||
* @return static
|
||||
*/
|
||||
public function padRight($length, $pad = ' ')
|
||||
{
|
||||
return new static(Str::padRight($this->value, $length, $pad));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a Class@method style callback into class and method.
|
||||
*
|
||||
* @param null|string $default
|
||||
* @return array
|
||||
*/
|
||||
public function parseCallback($default = null)
|
||||
{
|
||||
return Str::parseCallback($this->value, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given callback and return a new string.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function pipe(callable $callback)
|
||||
{
|
||||
return new static(call_user_func($callback, $this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plural form of an English word.
|
||||
*
|
||||
* @param int $count
|
||||
* @return static
|
||||
*/
|
||||
public function plural($count = 2)
|
||||
{
|
||||
return new static(Str::plural($this->value, $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluralize the last word of an English, studly caps case string.
|
||||
*
|
||||
* @param int $count
|
||||
* @return static
|
||||
*/
|
||||
public function pluralStudly($count = 2)
|
||||
{
|
||||
return new static(Str::pluralStudly($this->value, $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend the given values to the string.
|
||||
*
|
||||
* @param array $values
|
||||
* @return static
|
||||
*/
|
||||
public function prepend(...$values)
|
||||
{
|
||||
return new static(implode('', $values) . $this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any occurrence of the given string in the subject.
|
||||
*
|
||||
* @param array<string>|string $search
|
||||
* @param bool $caseSensitive
|
||||
* @return static
|
||||
*/
|
||||
public function remove($search, $caseSensitive = true)
|
||||
{
|
||||
return new static(Str::remove($search, $this->value, $caseSensitive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the string.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function repeat(int $times)
|
||||
{
|
||||
return new static(Str::repeat($this->value, $times));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the given value in the given string.
|
||||
*
|
||||
* @param string|string[] $search
|
||||
* @param string|string[] $replace
|
||||
* @return static
|
||||
*/
|
||||
public function replace($search, $replace)
|
||||
{
|
||||
return new static(Str::replace($search, $replace, $this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a given value in the string sequentially with an array.
|
||||
*
|
||||
* @param string $search
|
||||
* @return static
|
||||
*/
|
||||
public function replaceArray($search, array $replace)
|
||||
{
|
||||
return new static(Str::replaceArray($search, $replace, $this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first occurrence of a given value in the string.
|
||||
*
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @return static
|
||||
*/
|
||||
public function replaceFirst($search, $replace)
|
||||
{
|
||||
return new static(Str::replaceFirst($search, $replace, $this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the last occurrence of a given value in the string.
|
||||
*
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @return static
|
||||
*/
|
||||
public function replaceLast($search, $replace)
|
||||
{
|
||||
return new static(Str::replaceLast($search, $replace, $this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the patterns matching the given regular expression.
|
||||
*
|
||||
* @param string $pattern
|
||||
* @param \Closure|string $replace
|
||||
* @param int $limit
|
||||
* @return static
|
||||
*/
|
||||
public function replaceMatches($pattern, $replace, $limit = -1)
|
||||
{
|
||||
if ($replace instanceof Closure) {
|
||||
return new static(preg_replace_callback($pattern, $replace, $this->value, $limit));
|
||||
}
|
||||
|
||||
return new static(preg_replace($pattern, $replace, $this->value, $limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a string with a single instance of a given value.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return static
|
||||
*/
|
||||
public function start($prefix)
|
||||
{
|
||||
return new static(Str::start($this->value, $prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip HTML and PHP tags from the given string.
|
||||
*
|
||||
* @param null|string|string[] $allowedTags
|
||||
* @return static
|
||||
*/
|
||||
public function stripTags($allowedTags = null)
|
||||
{
|
||||
return new static(strip_tags($this->value, $allowedTags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given string to upper-case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function upper()
|
||||
{
|
||||
return new static(Str::upper($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given string to title case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function title()
|
||||
{
|
||||
return new static(Str::title($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singular form of an English word.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function singular()
|
||||
{
|
||||
return new static(Str::singular($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a URL friendly "slug" from a given string.
|
||||
*
|
||||
* @param string $separator
|
||||
* @param null|string $language
|
||||
* @return static
|
||||
*/
|
||||
public function slug($separator = '-', $language = 'en')
|
||||
{
|
||||
return new static(Str::slug($this->value, $separator, $language));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to snake case.
|
||||
*
|
||||
* @param string $delimiter
|
||||
* @return static
|
||||
*/
|
||||
public function snake($delimiter = '_')
|
||||
{
|
||||
return new static(Str::snake($this->value, $delimiter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given string starts with a given substring.
|
||||
*
|
||||
* @param array|string $needles
|
||||
* @return bool
|
||||
*/
|
||||
public function startsWith($needles)
|
||||
{
|
||||
return Str::startsWith($this->value, $needles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value to studly caps case.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function studly()
|
||||
{
|
||||
return new static(Str::studly($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the portion of the string specified by the start and length parameters.
|
||||
*
|
||||
* @param int $start
|
||||
* @param null|int $length
|
||||
* @return static
|
||||
*/
|
||||
public function substr($start, $length = null)
|
||||
{
|
||||
return new static(Str::substr($this->value, $start, $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of substring occurrences.
|
||||
*
|
||||
* @param string $needle
|
||||
* @param null|int $offset
|
||||
* @param null|int $length
|
||||
* @return int
|
||||
*/
|
||||
public function substrCount($needle, $offset = null, $length = null)
|
||||
{
|
||||
return Str::substrCount($this->value, $needle, $offset ?? 0, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the string of the given characters.
|
||||
*
|
||||
* @param string $characters
|
||||
* @return static
|
||||
*/
|
||||
public function trim($characters = null)
|
||||
{
|
||||
return new static(trim(...array_merge([$this->value], func_get_args())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Left trim the string of the given characters.
|
||||
*
|
||||
* @param string $characters
|
||||
* @return static
|
||||
*/
|
||||
public function ltrim($characters = null)
|
||||
{
|
||||
return new static(ltrim(...array_merge([$this->value], func_get_args())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Right trim the string of the given characters.
|
||||
*
|
||||
* @param string $characters
|
||||
* @return static
|
||||
*/
|
||||
public function rtrim($characters = null)
|
||||
{
|
||||
return new static(rtrim(...array_merge([$this->value], func_get_args())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a string's first character uppercase.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function ucfirst()
|
||||
{
|
||||
return new static(Str::ucfirst($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the first or the last ones chars from a string by a given char.
|
||||
*
|
||||
* @param int $offset if is negative it starts from the end
|
||||
* @param string $replacement default is *
|
||||
* @return static
|
||||
*/
|
||||
public function mask(int $offset = 0, int $length = 0, string $replacement = '*')
|
||||
{
|
||||
return new static(Str::mask($this->value, $offset, $length, $replacement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given callback if the string is empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function whenEmpty($callback)
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
$result = $callback($this);
|
||||
|
||||
return is_null($result) ? $this : $result;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given callback if the string is not empty.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public function whenNotEmpty($callback)
|
||||
{
|
||||
if ($this->isNotEmpty()) {
|
||||
$result = $callback($this);
|
||||
|
||||
return is_null($result) ? $this : $result;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of words in a string.
|
||||
*
|
||||
* @param int $words
|
||||
* @param string $end
|
||||
* @return static
|
||||
*/
|
||||
public function words($words = 100, $end = '...')
|
||||
{
|
||||
return new static(Str::words($this->value, $words, $end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of words a string contains.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function wordCount()
|
||||
{
|
||||
return str_word_count($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object to a string when JSON encoded.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
trait Conditionable
|
||||
{
|
||||
/**
|
||||
* Apply the callback if the given "value" is truthy.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param null|callable $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function when($value, $callback, $default = null)
|
||||
{
|
||||
if ($value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
}
|
||||
if ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback if the given "value" is falsy.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param null|callable $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function unless($value, $callback, $default = null)
|
||||
{
|
||||
if (! $value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
}
|
||||
if ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
64
addons/epay/library/hyperf/utils/src/Traits/Container.php
Normal file
64
addons/epay/library/hyperf/utils/src/Traits/Container.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
trait Container
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $container = [];
|
||||
|
||||
/**
|
||||
* Add a value to container by identifier.
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function set(string $id, $value)
|
||||
{
|
||||
static::$container[$id] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an entry of the container by its identifier and returns it,
|
||||
* Retunrs $default when does not exists in the container.
|
||||
* @param null|mixed $default
|
||||
*/
|
||||
public static function get(string $id, $default = null)
|
||||
{
|
||||
return static::$container[$id] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the container can return an entry for the given identifier.
|
||||
* Returns false otherwise.
|
||||
*/
|
||||
public static function has(string $id): bool
|
||||
{
|
||||
return isset(static::$container[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the container.
|
||||
*/
|
||||
public static function list(): array
|
||||
{
|
||||
return static::$container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the container.
|
||||
*/
|
||||
public static function clear(): void
|
||||
{
|
||||
static::$container = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
use Hyperf\Utils\Context;
|
||||
|
||||
trait CoroutineProxy
|
||||
{
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$target = $this->getTargetObject();
|
||||
return $target->{$name}(...$arguments);
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
$target = $this->getTargetObject();
|
||||
return $target->{$name};
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$target = $this->getTargetObject();
|
||||
return $target->{$name} = $value;
|
||||
}
|
||||
|
||||
protected function getTargetObject()
|
||||
{
|
||||
if (! isset($this->proxyKey)) {
|
||||
throw new \RuntimeException('$proxyKey property of class missing.');
|
||||
}
|
||||
return Context::get($this->proxyKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Error;
|
||||
use function get_class;
|
||||
|
||||
trait ForwardsCalls
|
||||
{
|
||||
/**
|
||||
* Forward a method call to the given object.
|
||||
*
|
||||
* @param mixed $object
|
||||
* @throws Error
|
||||
*/
|
||||
protected function forwardCallTo($object, string $method, array $parameters)
|
||||
{
|
||||
try {
|
||||
return $object->{$method}(...$parameters);
|
||||
} catch (Error|BadMethodCallException $e) {
|
||||
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
|
||||
|
||||
if (! preg_match($pattern, $e->getMessage(), $matches)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($matches['class'] !== get_class($object) || $matches['method'] !== $method) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
static::throwBadMethodCallException($method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a bad method call exception for the given method.
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
protected static function throwBadMethodCallException(string $method): void
|
||||
{
|
||||
throw new BadMethodCallException(sprintf('Call to undefined method %s::%s()', static::class, $method));
|
||||
}
|
||||
}
|
||||
20
addons/epay/library/hyperf/utils/src/Traits/Macroable.php
Normal file
20
addons/epay/library/hyperf/utils/src/Traits/Macroable.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
/**
|
||||
* @deprecated please use `Hyperf\Macroable\Macroable` instead
|
||||
*/
|
||||
trait Macroable
|
||||
{
|
||||
use \Hyperf\Macroable\Macroable;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
use Hyperf\Utils\Context;
|
||||
|
||||
trait StaticInstance
|
||||
{
|
||||
protected $instanceKey;
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param bool $refresh
|
||||
* @return static
|
||||
*/
|
||||
public static function instance($params = [], $refresh = false)
|
||||
{
|
||||
$key = get_called_class();
|
||||
$instance = null;
|
||||
if (Context::has($key)) {
|
||||
$instance = Context::get($key);
|
||||
}
|
||||
|
||||
if ($refresh || is_null($instance) || ! $instance instanceof static) {
|
||||
$instance = new static(...$params);
|
||||
Context::set($key, $instance);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
26
addons/epay/library/hyperf/utils/src/Traits/Tappable.php
Normal file
26
addons/epay/library/hyperf/utils/src/Traits/Tappable.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils\Traits;
|
||||
|
||||
trait Tappable
|
||||
{
|
||||
/**
|
||||
* Call the given Closure with this instance then return the instance.
|
||||
*
|
||||
* @param null|callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function tap($callback = null)
|
||||
{
|
||||
return tap($this, $callback);
|
||||
}
|
||||
}
|
||||
18
addons/epay/library/hyperf/utils/src/WaitGroup.php
Normal file
18
addons/epay/library/hyperf/utils/src/WaitGroup.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Swoole\Coroutine\WaitGroup as SwooleWaitGroup;
|
||||
|
||||
class WaitGroup extends SwooleWaitGroup
|
||||
{
|
||||
}
|
||||
67
addons/epay/library/hyperf/utils/src/Waiter.php
Normal file
67
addons/epay/library/hyperf/utils/src/Waiter.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use Closure;
|
||||
use Hyperf\Engine\Channel;
|
||||
use Hyperf\Utils\Exception\ExceptionThrower;
|
||||
use Hyperf\Utils\Exception\WaitTimeoutException;
|
||||
use Throwable;
|
||||
|
||||
class Waiter
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $pushTimeout = 10.0;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $popTimeout = 10.0;
|
||||
|
||||
public function __construct(float $timeout = 10.0)
|
||||
{
|
||||
$this->popTimeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|float $timeout seconds
|
||||
*/
|
||||
public function wait(Closure $closure, ?float $timeout = null)
|
||||
{
|
||||
if ($timeout === null) {
|
||||
$timeout = $this->popTimeout;
|
||||
}
|
||||
|
||||
$channel = new Channel(1);
|
||||
Coroutine::create(function () use ($channel, $closure) {
|
||||
try {
|
||||
$result = $closure();
|
||||
} catch (Throwable $exception) {
|
||||
$result = new ExceptionThrower($exception);
|
||||
} finally {
|
||||
$channel->push($result ?? null, $this->pushTimeout);
|
||||
}
|
||||
});
|
||||
|
||||
$result = $channel->pop($timeout);
|
||||
if ($result === false && $channel->isTimeout()) {
|
||||
throw new WaitTimeoutException(sprintf('Channel wait failed, reason: Timed out for %s s', $timeout));
|
||||
}
|
||||
if ($result instanceof ExceptionThrower) {
|
||||
throw $result->getThrowable();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user