diff --git a/Server/application/common/controller/Api.php b/Server/application/common/controller/Api.php index 1c4196a1..ba350669 100644 --- a/Server/application/common/controller/Api.php +++ b/Server/application/common/controller/Api.php @@ -73,7 +73,6 @@ class Api extends Controller header('Access-Control-Max-Age: 1728000'); header('Access-Control-Allow-Credentials: true'); - // 对OPTIONS请求直接返回 if ($this->requestType === 'OPTIONS') { Response::create()->send(); diff --git a/Server/application/common/model/DeviceUser.php b/Server/application/common/model/DeviceUser.php index 74dd9771..27697b1b 100644 --- a/Server/application/common/model/DeviceUser.php +++ b/Server/application/common/model/DeviceUser.php @@ -141,7 +141,7 @@ class DeviceUser extends Model * @param int $deviceId 设备ID * @return bool 是否删除成功 */ - public static function removeRelation($companyId, $userId, $deviceId) + public static function removeDeviceUserRelation($companyId, $userId, $deviceId) { return self::where([ 'companyId' => $companyId, diff --git a/Server/application/devices/controller/Device.php b/Server/application/devices/controller/Device.php index e4b2c50c..bcd2bd22 100644 --- a/Server/application/devices/controller/Device.php +++ b/Server/application/devices/controller/Device.php @@ -35,14 +35,20 @@ class Device extends Controller public function count() { try { + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + // 获取查询条件 $where = []; - // 租户ID - $tenantId = Request::param('tenant_id'); - if (is_numeric($tenantId)) { - $where['tenantId'] = $tenantId; - } + // 租户ID / 公司ID + $where['companyId'] = $userInfo['companyId']; // 设备在线状态 $alive = Request::param('alive'); @@ -50,8 +56,31 @@ class Device extends Controller $where['alive'] = $alive; } - // 获取设备总数 - $count = DeviceModel::getDeviceCount($where); + // 根据用户管理员状态调整查询条件 + if ($userInfo['isAdmin'] == 1) { + // 管理员直接查询所有设备 + $count = DeviceModel::getDeviceCount($where); + } else { + // 非管理员需要查询关联表 + $deviceIds = \app\common\model\DeviceUser::getUserDeviceIds( + $userInfo['id'], + $userInfo['companyId'] + ); + + if (empty($deviceIds)) { + return json([ + 'code' => 403, + 'msg' => '请联系管理员绑定设备', + 'data' => [ + 'count' => 0 + ] + ]); + } + + // 添加设备ID过滤条件 + $where['id'] = ['in', $deviceIds]; + $count = DeviceModel::getDeviceCount($where); + } return json([ 'code' => 200, @@ -75,6 +104,15 @@ class Device extends Controller public function index() { try { + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + // 获取查询条件 $where = []; @@ -104,8 +142,31 @@ class Device extends Controller $sort = Request::param('sort', 'id'); $order = Request::param('order', 'desc'); - // 获取设备列表 - $list = DeviceModel::getDeviceList($where, "{$sort} {$order}", $page, $limit); + // 添加公司ID过滤条件 + $where['companyId'] = $userInfo['companyId']; + + // 根据用户管理员状态调整查询条件 + if ($userInfo['isAdmin'] == 1) { + // 管理员直接查询所有设备 + $list = DeviceModel::getDeviceList($where, "{$sort} {$order}", $page, $limit); + } else { + // 非管理员需要查询关联表 + $deviceIds = \app\common\model\DeviceUser::getUserDeviceIds( + $userInfo['id'], + $userInfo['companyId'] + ); + + if (empty($deviceIds)) { + return json([ + 'code' => 403, + 'msg' => '请联系管理员绑定设备' + ]); + } + + // 添加设备ID过滤条件 + $where['id'] = ['in', $deviceIds]; + $list = DeviceModel::getDeviceList($where, "{$sort} {$order}", $page, $limit); + } return json([ 'code' => 200, @@ -130,6 +191,15 @@ class Device extends Controller public function read() { try { + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + // 获取设备ID $id = Request::param('id/d'); if (empty($id)) { @@ -139,6 +209,23 @@ class Device extends Controller ]); } + // 检查用户权限 + if ($userInfo['isAdmin'] != 1) { + // 非管理员需要检查是否有权限访问该设备 + $hasPermission = \app\common\model\DeviceUser::checkUserDevicePermission( + $userInfo['id'], + $id, + $userInfo['companyId'] + ); + + if (!$hasPermission) { + return json([ + 'code' => 403, + 'msg' => '您没有权限查看该设备' + ]); + } + } + // 获取设备详情 $info = DeviceModel::getDeviceInfo($id); if (empty($info)) { @@ -148,6 +235,14 @@ class Device extends Controller ]); } + // 检查设备是否属于用户所在公司 + if ($info['companyId'] != $userInfo['companyId']) { + return json([ + 'code' => 403, + 'msg' => '您没有权限查看该设备' + ]); + } + return json([ 'code' => 200, 'msg' => '获取成功', @@ -168,7 +263,18 @@ class Device extends Controller public function refresh() { try { - + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + + // 执行刷新逻辑 + // TODO: 实现实际刷新设备状态的功能 + return json([ 'code' => 200, 'msg' => '刷新成功', @@ -189,6 +295,23 @@ class Device extends Controller public function save() { try { + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + + // 检查用户权限,只有管理员可以添加设备 + if ($userInfo['isAdmin'] != 1) { + return json([ + 'code' => 403, + 'msg' => '您没有权限添加设备' + ]); + } + // 获取设备数据 $data = Request::post(); @@ -209,6 +332,9 @@ class Device extends Controller ]); } + // 设置设备公司ID + $data['companyId'] = $userInfo['companyId']; + // 添加设备 $id = DeviceModel::addDevice($data); @@ -234,6 +360,23 @@ class Device extends Controller public function delete() { try { + // 获取登录用户信息 + $userInfo = request()->userInfo; + if (empty($userInfo)) { + return json([ + 'code' => 401, + 'msg' => '未登录或登录已过期' + ]); + } + + // 检查用户权限,只有管理员可以删除设备 + if ($userInfo['isAdmin'] != 1) { + return json([ + 'code' => 403, + 'msg' => '您没有权限删除设备' + ]); + } + // 获取设备ID $id = Request::param('id/d'); if (empty($id)) { @@ -244,11 +387,15 @@ class Device extends Controller } // 验证设备是否存在 - $exists = DeviceModel::where('id', $id)->where('isDeleted', 0)->find(); + $exists = DeviceModel::where('id', $id) + ->where('isDeleted', 0) + ->where('companyId', $userInfo['companyId']) + ->find(); + if (!$exists) { return json([ 'code' => 404, - 'msg' => '设备不存在' + 'msg' => '设备不存在或无权限操作' ]); } diff --git a/composer.json b/composer.json index ee002b8e..61c93b31 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "require": { - "topthink/think-queue": "2.0.*" + "topthink/think-queue": "2.0.*", + "symfony/var-dumper": "^5.4" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 78458b89..fb7cf5db 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,257 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "df449f5841f2028f66d27fbae732c9ec", + "content-hash": "c5312c17aaa7d134ec90cbb20c791f62", "packages": [ + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-08T15:21:10+00:00" + }, { "name": "topthink/framework", "version": "v5.1.42", @@ -235,5 +484,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/vendor/bin/var-dump-server b/vendor/bin/var-dump-server new file mode 100644 index 00000000..18db1c1e --- /dev/null +++ b/vendor/bin/var-dump-server @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server'); + } +} + +return include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server'; diff --git a/vendor/bin/var-dump-server.bat b/vendor/bin/var-dump-server.bat new file mode 100644 index 00000000..94333da5 --- /dev/null +++ b/vendor/bin/var-dump-server.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/var-dump-server +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 0fb0a2c1..5490b88d 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,5 +6,10 @@ $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 12c890b3..615365c1 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,6 +6,9 @@ $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php', + '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', 'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6dd0ba50..1691cd75 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -8,4 +8,7 @@ $baseDir = dirname($vendorDir); return array( 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), 'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-queue/src'), + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), ); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 445c1e60..22614c66 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -7,7 +7,10 @@ namespace Composer\Autoload; class ComposerStaticInitdf449f5841f2028f66d27fbae732c9ec { public static $files = array ( + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', + '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', 'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php', ); @@ -17,6 +20,12 @@ class ComposerStaticInitdf449f5841f2028f66d27fbae732c9ec 'think\\composer\\' => 15, 'think\\' => 6, ), + 'S' => + array ( + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Component\\VarDumper\\' => 28, + ), ); public static $prefixDirsPsr4 = array ( @@ -29,10 +38,27 @@ class ComposerStaticInitdf449f5841f2028f66d27fbae732c9ec 0 => __DIR__ . '/..' . '/topthink/think-helper/src', 1 => __DIR__ . '/..' . '/topthink/think-queue/src', ), + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Mbstring\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', + ), + 'Symfony\\Component\\VarDumper\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/var-dumper', + ), ); public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 2ab5fda6..331ca943 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,5 +1,263 @@ { "packages": [ + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "version_normalized": "1.31.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2024-09-09T11:45:10+00:00", + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-mbstring" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "version_normalized": "1.31.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "time": "2024-09-09T11:45:10+00:00", + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "name": "symfony/var-dumper", + "version": "v5.4.48", + "version_normalized": "5.4.48.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "time": "2024-11-08T15:21:10+00:00", + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/var-dumper" + }, { "name": "topthink/framework", "version": "v5.1.42", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 9ac4bf7a..986224c0 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => 'f0fa19f89f042e746b487a6d79e7019b657db2ce', + 'reference' => 'c55cc5c64417fbcf69d9fa1bb68f749800bd3b08', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,12 +13,39 @@ '__root__' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => 'f0fa19f89f042e746b487a6d79e7019b657db2ce', + 'reference' => 'c55cc5c64417fbcf69d9fa1bb68f749800bd3b08', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/polyfill-mbstring' => array( + 'pretty_version' => 'v1.31.0', + 'version' => '1.31.0.0', + 'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.31.0', + 'version' => '1.31.0.0', + 'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/var-dumper' => array( + 'pretty_version' => 'v5.4.48', + 'version' => '5.4.48.0', + 'reference' => '42f18f170aa86d612c3559cfb3bd11a375df32c8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/var-dumper', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'topthink/framework' => array( 'pretty_version' => 'v5.1.42', 'version' => '5.1.42.0', diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index 6d3407db..a8b98d5c 100644 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 70100)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.0". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 70205)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE new file mode 100644 index 00000000..6e3afce6 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-present Fabien Potencier + +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. diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php new file mode 100644 index 00000000..3d45c9d9 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -0,0 +1,1045 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Mbstring; + +/** + * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. + * + * Implemented: + * - mb_chr - Returns a specific character from its Unicode code point + * - mb_convert_encoding - Convert character encoding + * - mb_convert_variables - Convert character code in variable(s) + * - mb_decode_mimeheader - Decode string in MIME header field + * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED + * - mb_decode_numericentity - Decode HTML numeric string reference to character + * - mb_encode_numericentity - Encode character to HTML numeric string reference + * - mb_convert_case - Perform case folding on a string + * - mb_detect_encoding - Detect character encoding + * - mb_get_info - Get internal settings of mbstring + * - mb_http_input - Detect HTTP input character encoding + * - mb_http_output - Set/Get HTTP output character encoding + * - mb_internal_encoding - Set/Get internal character encoding + * - mb_list_encodings - Returns an array of all supported encodings + * - mb_ord - Returns the Unicode code point of a character + * - mb_output_handler - Callback function converts character encoding in output buffer + * - mb_scrub - Replaces ill-formed byte sequences with substitute characters + * - mb_strlen - Get string length + * - mb_strpos - Find position of first occurrence of string in a string + * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array + * - mb_strtolower - Make a string lowercase + * - mb_strtoupper - Make a string uppercase + * - mb_substitute_character - Set/Get substitution character + * - mb_substr - Get part of string + * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive + * - mb_stristr - Finds first occurrence of a string within another, case insensitive + * - mb_strrchr - Finds the last occurrence of a character in a string within another + * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive + * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive + * - mb_strstr - Finds first occurrence of a string within another + * - mb_strwidth - Return width of string + * - mb_substr_count - Count the number of substring occurrences + * - mb_ucfirst - Make a string's first character uppercase + * - mb_lcfirst - Make a string's first character lowercase + * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string + * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string + * - mb_rtrim - Strip whitespace (or other characters) from the end of a string + * + * Not implemented: + * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) + * - mb_ereg_* - Regular expression with multibyte support + * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable + * - mb_preferred_mime_name - Get MIME charset string + * - mb_regex_encoding - Returns current encoding for multibyte regex as string + * - mb_regex_set_options - Set/Get the default options for mbregex functions + * - mb_send_mail - Send encoded mail + * - mb_split - Split multibyte string using regular expression + * - mb_strcut - Get part of string + * - mb_strimwidth - Get truncated string with specified width + * + * @author Nicolas Grekas + * + * @internal + */ +final class Mbstring +{ + public const MB_CASE_FOLD = \PHP_INT_MAX; + + private const SIMPLE_CASE_FOLD = [ + ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], + ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], + ]; + + private static $encodingList = ['ASCII', 'UTF-8']; + private static $language = 'neutral'; + private static $internalEncoding = 'UTF-8'; + + public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) + { + if (\is_array($s)) { + $r = []; + foreach ($s as $str) { + $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding); + } + + return $r; + } + + if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { + $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); + } else { + $fromEncoding = self::getEncoding($fromEncoding); + } + + $toEncoding = self::getEncoding($toEncoding); + + if ('BASE64' === $fromEncoding) { + $s = base64_decode($s); + $fromEncoding = $toEncoding; + } + + if ('BASE64' === $toEncoding) { + return base64_encode($s); + } + + if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { + if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { + $fromEncoding = 'Windows-1252'; + } + if ('UTF-8' !== $fromEncoding) { + $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + } + + return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); + } + + if ('HTML-ENTITIES' === $fromEncoding) { + $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); + $fromEncoding = 'UTF-8'; + } + + return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + } + + public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) + { + $ok = true; + array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { + if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { + $ok = false; + } + }); + + return $ok ? $fromEncoding : false; + } + + public static function mb_decode_mimeheader($s) + { + return iconv_mime_decode($s, 2, self::$internalEncoding); + } + + public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) + { + trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); + } + + public static function mb_decode_numericentity($s, $convmap, $encoding = null) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return ''; // Instead of null (cf. mb_encode_numericentity). + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $cnt = floor(\count($convmap) / 4) * 4; + + for ($i = 0; $i < $cnt; $i += 4) { + // collector_decode_htmlnumericentity ignores $convmap[$i + 3] + $convmap[$i] += $convmap[$i + 2]; + $convmap[$i + 1] += $convmap[$i + 2]; + } + + $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { + $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; + for ($i = 0; $i < $cnt; $i += 4) { + if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { + return self::mb_chr($c - $convmap[$i + 2]); + } + } + + return $m[0]; + }, $s); + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); + + return null; // Instead of '' (cf. mb_decode_numericentity). + } + + if (null !== $is_hex && !\is_scalar($is_hex)) { + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); + + return null; + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + + $cnt = floor(\count($convmap) / 4) * 4; + $i = 0; + $len = \strlen($s); + $result = ''; + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + $c = self::mb_ord($uchr); + + for ($j = 0; $j < $cnt; $j += 4) { + if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { + $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; + $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; + continue 2; + } + } + $result .= $uchr; + } + + if (null === $encoding) { + return $result; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $result); + } + + public static function mb_convert_case($s, $mode, $encoding = null) + { + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + if (\MB_CASE_TITLE == $mode) { + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); + } else { + if (\MB_CASE_UPPER == $mode) { + static $upper = null; + if (null === $upper) { + $upper = self::getData('upperCase'); + } + $map = $upper; + } else { + if (self::MB_CASE_FOLD === $mode) { + static $caseFolding = null; + if (null === $caseFolding) { + $caseFolding = self::getData('caseFolding'); + } + $s = strtr($s, $caseFolding); + } + + static $lower = null; + if (null === $lower) { + $lower = self::getData('lowerCase'); + } + $map = $lower; + } + + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if (isset($map[$uchr])) { + $uchr = $map[$uchr]; + $nlen = \strlen($uchr); + + if ($nlen == $ulen) { + $nlen = $i; + do { + $s[--$nlen] = $uchr[--$ulen]; + } while ($ulen); + } else { + $s = substr_replace($s, $uchr, $i - $ulen, $ulen); + $len += $nlen - $ulen; + $i += $nlen - $ulen; + } + } + } + } + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_internal_encoding($encoding = null) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + $normalizedEncoding = self::getEncoding($encoding); + + if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { + self::$internalEncoding = $normalizedEncoding; + + return true; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); + } + + public static function mb_language($lang = null) + { + if (null === $lang) { + return self::$language; + } + + switch ($normalizedLang = strtolower($lang)) { + case 'uni': + case 'neutral': + self::$language = $normalizedLang; + + return true; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); + } + + public static function mb_list_encodings() + { + return ['UTF-8']; + } + + public static function mb_encoding_aliases($encoding) + { + switch (strtoupper($encoding)) { + case 'UTF8': + case 'UTF-8': + return ['utf8']; + } + + return false; + } + + public static function mb_check_encoding($var = null, $encoding = null) + { + if (null === $encoding) { + if (null === $var) { + return false; + } + $encoding = self::$internalEncoding; + } + + if (!\is_array($var)) { + return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); + } + + foreach ($var as $key => $value) { + if (!self::mb_check_encoding($key, $encoding)) { + return false; + } + if (!self::mb_check_encoding($value, $encoding)) { + return false; + } + } + + return true; + } + + public static function mb_detect_encoding($str, $encodingList = null, $strict = false) + { + if (null === $encodingList) { + $encodingList = self::$encodingList; + } else { + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + } + + foreach ($encodingList as $enc) { + switch ($enc) { + case 'ASCII': + if (!preg_match('/[\x80-\xFF]/', $str)) { + return $enc; + } + break; + + case 'UTF8': + case 'UTF-8': + if (preg_match('//u', $str)) { + return 'UTF-8'; + } + break; + + default: + if (0 === strncmp($enc, 'ISO-8859-', 9)) { + return $enc; + } + } + } + + return false; + } + + public static function mb_detect_order($encodingList = null) + { + if (null === $encodingList) { + return self::$encodingList; + } + + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + + foreach ($encodingList as $enc) { + switch ($enc) { + default: + if (strncmp($enc, 'ISO-8859-', 9)) { + return false; + } + // no break + case 'ASCII': + case 'UTF8': + case 'UTF-8': + } + } + + self::$encodingList = $encodingList; + + return true; + } + + public static function mb_strlen($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return \strlen($s); + } + + return @iconv_strlen($s, $encoding); + } + + public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strpos($haystack, $needle, $offset); + } + + $needle = (string) $needle; + if ('' === $needle) { + if (80000 > \PHP_VERSION_ID) { + trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); + + return false; + } + + return 0; + } + + return iconv_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrpos($haystack, $needle, $offset); + } + + if ($offset != (int) $offset) { + $offset = 0; + } elseif ($offset = (int) $offset) { + if ($offset < 0) { + if (0 > $offset += self::mb_strlen($needle)) { + $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + } + $offset = 0; + } else { + $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); + } + } + + $pos = '' !== $needle || 80000 > \PHP_VERSION_ID + ? iconv_strrpos($haystack, $needle, $encoding) + : self::mb_strlen($haystack, $encoding); + + return false !== $pos ? $offset + $pos : false; + } + + public static function mb_str_split($string, $split_length = 1, $encoding = null) + { + if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); + + return null; + } + + if (1 > $split_length = (int) $split_length) { + if (80000 > \PHP_VERSION_ID) { + trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); + + return false; + } + + throw new \ValueError('Argument #2 ($length) must be greater than 0'); + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + if ('UTF-8' === $encoding = self::getEncoding($encoding)) { + $rx = '/('; + while (65535 < $split_length) { + $rx .= '.{65535}'; + $split_length -= 65535; + } + $rx .= '.{'.$split_length.'})/us'; + + return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + } + + $result = []; + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + + public static function mb_strtolower($s, $encoding = null) + { + return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); + } + + public static function mb_strtoupper($s, $encoding = null) + { + return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); + } + + public static function mb_substitute_character($c = null) + { + if (null === $c) { + return 'none'; + } + if (0 === strcasecmp($c, 'none')) { + return true; + } + if (80000 > \PHP_VERSION_ID) { + return false; + } + if (\is_int($c) || 'long' === $c || 'entity' === $c) { + return false; + } + + throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); + } + + public static function mb_substr($s, $start, $length = null, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return (string) substr($s, $start, null === $length ? 2147483647 : $length); + } + + if ($start < 0) { + $start = iconv_strlen($s, $encoding) + $start; + if ($start < 0) { + $start = 0; + } + } + + if (null === $length) { + $length = 2147483647; + } elseif ($length < 0) { + $length = iconv_strlen($s, $encoding) + $length - $start; + if ($length < 0) { + return ''; + } + } + + return (string) iconv_substr($s, $start, $length, $encoding); + } + + public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) + { + [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ + self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), + self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), + ]); + + return self::mb_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) + { + $pos = self::mb_stripos($haystack, $needle, 0, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + $pos = strrpos($haystack, $needle); + } else { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = iconv_strrpos($haystack, $needle, $encoding); + } + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) + { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = self::mb_strripos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); + $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); + + $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); + $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); + + return self::mb_strrpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) + { + $pos = strpos($haystack, $needle); + if (false === $pos) { + return false; + } + if ($part) { + return substr($haystack, 0, $pos); + } + + return substr($haystack, $pos); + } + + public static function mb_get_info($type = 'all') + { + $info = [ + 'internal_encoding' => self::$internalEncoding, + 'http_output' => 'pass', + 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', + 'func_overload' => 0, + 'func_overload_list' => 'no overload', + 'mail_charset' => 'UTF-8', + 'mail_header_encoding' => 'BASE64', + 'mail_body_encoding' => 'BASE64', + 'illegal_chars' => 0, + 'encoding_translation' => 'Off', + 'language' => self::$language, + 'detect_order' => self::$encodingList, + 'substitute_character' => 'none', + 'strict_detection' => 'Off', + ]; + + if ('all' === $type) { + return $info; + } + if (isset($info[$type])) { + return $info[$type]; + } + + return false; + } + + public static function mb_http_input($type = '') + { + return false; + } + + public static function mb_http_output($encoding = null) + { + return null !== $encoding ? 'pass' === $encoding : 'pass'; + } + + public static function mb_strwidth($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + + if ('UTF-8' !== $encoding) { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); + + return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + } + + public static function mb_substr_count($haystack, $needle, $encoding = null) + { + return substr_count($haystack, $needle); + } + + public static function mb_output_handler($contents, $status) + { + return $contents; + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } + + public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string + { + if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { + throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); + } + + if (null === $encoding) { + $encoding = self::mb_internal_encoding(); + } else { + self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); + } + + if (self::mb_strlen($pad_string, $encoding) <= 0) { + throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); + } + + $paddingRequired = $length - self::mb_strlen($string, $encoding); + + if ($paddingRequired < 1) { + return $string; + } + + switch ($pad_type) { + case \STR_PAD_LEFT: + return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; + case \STR_PAD_RIGHT: + return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); + default: + $leftPaddingLength = floor($paddingRequired / 2); + $rightPaddingLength = $paddingRequired - $leftPaddingLength; + + return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); + } + } + + public static function mb_ucfirst(string $string, ?string $encoding = null): string + { + if (null === $encoding) { + $encoding = self::mb_internal_encoding(); + } else { + self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); + } + + $firstChar = mb_substr($string, 0, 1, $encoding); + $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding); + + return $firstChar.mb_substr($string, 1, null, $encoding); + } + + public static function mb_lcfirst(string $string, ?string $encoding = null): string + { + if (null === $encoding) { + $encoding = self::mb_internal_encoding(); + } else { + self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); + } + + $firstChar = mb_substr($string, 0, 1, $encoding); + $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding); + + return $firstChar.mb_substr($string, 1, null, $encoding); + } + + private static function getSubpart($pos, $part, $haystack, $encoding) + { + if (false === $pos) { + return false; + } + if ($part) { + return self::mb_substr($haystack, 0, $pos, $encoding); + } + + return self::mb_substr($haystack, $pos, null, $encoding); + } + + private static function html_encoding_callback(array $m) + { + $i = 1; + $entities = ''; + $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); + + while (isset($m[$i])) { + if (0x80 > $m[$i]) { + $entities .= \chr($m[$i++]); + continue; + } + if (0xF0 <= $m[$i]) { + $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } elseif (0xE0 <= $m[$i]) { + $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } else { + $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; + } + + $entities .= '&#'.$c.';'; + } + + return $entities; + } + + private static function title_case(array $s) + { + return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } + + private static function getEncoding($encoding) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + if ('UTF-8' === $encoding) { + return 'UTF-8'; + } + + $encoding = strtoupper($encoding); + + if ('8BIT' === $encoding || 'BINARY' === $encoding) { + return 'CP850'; + } + + if ('UTF8' === $encoding) { + return 'UTF-8'; + } + + return $encoding; + } + + public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string + { + return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__); + } + + public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string + { + return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__); + } + + public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string + { + return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__); + } + + private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string + { + if (null === $encoding) { + $encoding = self::mb_internal_encoding(); + } else { + self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given'); + } + + if ('' === $characters) { + return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding); + } + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $string)) { + $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string); + } + if (null !== $characters && !preg_match('//u', $characters)) { + $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters); + } + } else { + $string = iconv($encoding, 'UTF-8//IGNORE', $string); + + if (null !== $characters) { + $characters = iconv($encoding, 'UTF-8//IGNORE', $characters); + } + } + + if (null === $characters) { + $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}"; + } else { + $characters = preg_quote($characters); + } + + $string = preg_replace(sprintf($regex, $characters), '', $string); + + if (null === $encoding) { + return $string; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $string); + } + + private static function assertEncoding(string $encoding, string $errorFormat): void + { + try { + $validEncoding = @self::mb_check_encoding('', $encoding); + } catch (\ValueError $e) { + throw new \ValueError(sprintf($errorFormat, $encoding)); + } + + // BC for PHP 7.3 and lower + if (!$validEncoding) { + throw new \ValueError(sprintf($errorFormat, $encoding)); + } + } +} diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md new file mode 100644 index 00000000..478b40da --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/README.md @@ -0,0 +1,13 @@ +Symfony Polyfill / Mbstring +=========================== + +This component provides a partial, native PHP implementation for the +[Mbstring](https://php.net/mbstring) extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php new file mode 100644 index 00000000..512bba0b --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php @@ -0,0 +1,119 @@ + 'i̇', + 'µ' => 'μ', + 'ſ' => 's', + 'ͅ' => 'ι', + 'ς' => 'σ', + 'ϐ' => 'β', + 'ϑ' => 'θ', + 'ϕ' => 'φ', + 'ϖ' => 'π', + 'ϰ' => 'κ', + 'ϱ' => 'ρ', + 'ϵ' => 'ε', + 'ẛ' => 'ṡ', + 'ι' => 'ι', + 'ß' => 'ss', + 'ʼn' => 'ʼn', + 'ǰ' => 'ǰ', + 'ΐ' => 'ΐ', + 'ΰ' => 'ΰ', + 'և' => 'եւ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẚ' => 'aʾ', + 'ẞ' => 'ss', + 'ὐ' => 'ὐ', + 'ὒ' => 'ὒ', + 'ὔ' => 'ὔ', + 'ὖ' => 'ὖ', + 'ᾀ' => 'ἀι', + 'ᾁ' => 'ἁι', + 'ᾂ' => 'ἂι', + 'ᾃ' => 'ἃι', + 'ᾄ' => 'ἄι', + 'ᾅ' => 'ἅι', + 'ᾆ' => 'ἆι', + 'ᾇ' => 'ἇι', + 'ᾈ' => 'ἀι', + 'ᾉ' => 'ἁι', + 'ᾊ' => 'ἂι', + 'ᾋ' => 'ἃι', + 'ᾌ' => 'ἄι', + 'ᾍ' => 'ἅι', + 'ᾎ' => 'ἆι', + 'ᾏ' => 'ἇι', + 'ᾐ' => 'ἠι', + 'ᾑ' => 'ἡι', + 'ᾒ' => 'ἢι', + 'ᾓ' => 'ἣι', + 'ᾔ' => 'ἤι', + 'ᾕ' => 'ἥι', + 'ᾖ' => 'ἦι', + 'ᾗ' => 'ἧι', + 'ᾘ' => 'ἠι', + 'ᾙ' => 'ἡι', + 'ᾚ' => 'ἢι', + 'ᾛ' => 'ἣι', + 'ᾜ' => 'ἤι', + 'ᾝ' => 'ἥι', + 'ᾞ' => 'ἦι', + 'ᾟ' => 'ἧι', + 'ᾠ' => 'ὠι', + 'ᾡ' => 'ὡι', + 'ᾢ' => 'ὢι', + 'ᾣ' => 'ὣι', + 'ᾤ' => 'ὤι', + 'ᾥ' => 'ὥι', + 'ᾦ' => 'ὦι', + 'ᾧ' => 'ὧι', + 'ᾨ' => 'ὠι', + 'ᾩ' => 'ὡι', + 'ᾪ' => 'ὢι', + 'ᾫ' => 'ὣι', + 'ᾬ' => 'ὤι', + 'ᾭ' => 'ὥι', + 'ᾮ' => 'ὦι', + 'ᾯ' => 'ὧι', + 'ᾲ' => 'ὰι', + 'ᾳ' => 'αι', + 'ᾴ' => 'άι', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾶι', + 'ᾼ' => 'αι', + 'ῂ' => 'ὴι', + 'ῃ' => 'ηι', + 'ῄ' => 'ήι', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῆι', + 'ῌ' => 'ηι', + 'ῒ' => 'ῒ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'ῢ' => 'ῢ', + 'ῤ' => 'ῤ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'ῲ' => 'ὼι', + 'ῳ' => 'ωι', + 'ῴ' => 'ώι', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῶι', + 'ῼ' => 'ωι', + 'ff' => 'ff', + 'fi' => 'fi', + 'fl' => 'fl', + 'ffi' => 'ffi', + 'ffl' => 'ffl', + 'ſt' => 'st', + 'st' => 'st', + 'ﬓ' => 'մն', + 'ﬔ' => 'մե', + 'ﬕ' => 'մի', + 'ﬖ' => 'վն', + 'ﬗ' => 'մխ', +]; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php new file mode 100644 index 00000000..fac60b08 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -0,0 +1,1397 @@ + 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + 'À' => 'à', + 'Á' => 'á', + 'Â' => 'â', + 'Ã' => 'ã', + 'Ä' => 'ä', + 'Å' => 'å', + 'Æ' => 'æ', + 'Ç' => 'ç', + 'È' => 'è', + 'É' => 'é', + 'Ê' => 'ê', + 'Ë' => 'ë', + 'Ì' => 'ì', + 'Í' => 'í', + 'Î' => 'î', + 'Ï' => 'ï', + 'Ð' => 'ð', + 'Ñ' => 'ñ', + 'Ò' => 'ò', + 'Ó' => 'ó', + 'Ô' => 'ô', + 'Õ' => 'õ', + 'Ö' => 'ö', + 'Ø' => 'ø', + 'Ù' => 'ù', + 'Ú' => 'ú', + 'Û' => 'û', + 'Ü' => 'ü', + 'Ý' => 'ý', + 'Þ' => 'þ', + 'Ā' => 'ā', + 'Ă' => 'ă', + 'Ą' => 'ą', + 'Ć' => 'ć', + 'Ĉ' => 'ĉ', + 'Ċ' => 'ċ', + 'Č' => 'č', + 'Ď' => 'ď', + 'Đ' => 'đ', + 'Ē' => 'ē', + 'Ĕ' => 'ĕ', + 'Ė' => 'ė', + 'Ę' => 'ę', + 'Ě' => 'ě', + 'Ĝ' => 'ĝ', + 'Ğ' => 'ğ', + 'Ġ' => 'ġ', + 'Ģ' => 'ģ', + 'Ĥ' => 'ĥ', + 'Ħ' => 'ħ', + 'Ĩ' => 'ĩ', + 'Ī' => 'ī', + 'Ĭ' => 'ĭ', + 'Į' => 'į', + 'İ' => 'i̇', + 'IJ' => 'ij', + 'Ĵ' => 'ĵ', + 'Ķ' => 'ķ', + 'Ĺ' => 'ĺ', + 'Ļ' => 'ļ', + 'Ľ' => 'ľ', + 'Ŀ' => 'ŀ', + 'Ł' => 'ł', + 'Ń' => 'ń', + 'Ņ' => 'ņ', + 'Ň' => 'ň', + 'Ŋ' => 'ŋ', + 'Ō' => 'ō', + 'Ŏ' => 'ŏ', + 'Ő' => 'ő', + 'Œ' => 'œ', + 'Ŕ' => 'ŕ', + 'Ŗ' => 'ŗ', + 'Ř' => 'ř', + 'Ś' => 'ś', + 'Ŝ' => 'ŝ', + 'Ş' => 'ş', + 'Š' => 'š', + 'Ţ' => 'ţ', + 'Ť' => 'ť', + 'Ŧ' => 'ŧ', + 'Ũ' => 'ũ', + 'Ū' => 'ū', + 'Ŭ' => 'ŭ', + 'Ů' => 'ů', + 'Ű' => 'ű', + 'Ų' => 'ų', + 'Ŵ' => 'ŵ', + 'Ŷ' => 'ŷ', + 'Ÿ' => 'ÿ', + 'Ź' => 'ź', + 'Ż' => 'ż', + 'Ž' => 'ž', + 'Ɓ' => 'ɓ', + 'Ƃ' => 'ƃ', + 'Ƅ' => 'ƅ', + 'Ɔ' => 'ɔ', + 'Ƈ' => 'ƈ', + 'Ɖ' => 'ɖ', + 'Ɗ' => 'ɗ', + 'Ƌ' => 'ƌ', + 'Ǝ' => 'ǝ', + 'Ə' => 'ə', + 'Ɛ' => 'ɛ', + 'Ƒ' => 'ƒ', + 'Ɠ' => 'ɠ', + 'Ɣ' => 'ɣ', + 'Ɩ' => 'ɩ', + 'Ɨ' => 'ɨ', + 'Ƙ' => 'ƙ', + 'Ɯ' => 'ɯ', + 'Ɲ' => 'ɲ', + 'Ɵ' => 'ɵ', + 'Ơ' => 'ơ', + 'Ƣ' => 'ƣ', + 'Ƥ' => 'ƥ', + 'Ʀ' => 'ʀ', + 'Ƨ' => 'ƨ', + 'Ʃ' => 'ʃ', + 'Ƭ' => 'ƭ', + 'Ʈ' => 'ʈ', + 'Ư' => 'ư', + 'Ʊ' => 'ʊ', + 'Ʋ' => 'ʋ', + 'Ƴ' => 'ƴ', + 'Ƶ' => 'ƶ', + 'Ʒ' => 'ʒ', + 'Ƹ' => 'ƹ', + 'Ƽ' => 'ƽ', + 'DŽ' => 'dž', + 'Dž' => 'dž', + 'LJ' => 'lj', + 'Lj' => 'lj', + 'NJ' => 'nj', + 'Nj' => 'nj', + 'Ǎ' => 'ǎ', + 'Ǐ' => 'ǐ', + 'Ǒ' => 'ǒ', + 'Ǔ' => 'ǔ', + 'Ǖ' => 'ǖ', + 'Ǘ' => 'ǘ', + 'Ǚ' => 'ǚ', + 'Ǜ' => 'ǜ', + 'Ǟ' => 'ǟ', + 'Ǡ' => 'ǡ', + 'Ǣ' => 'ǣ', + 'Ǥ' => 'ǥ', + 'Ǧ' => 'ǧ', + 'Ǩ' => 'ǩ', + 'Ǫ' => 'ǫ', + 'Ǭ' => 'ǭ', + 'Ǯ' => 'ǯ', + 'DZ' => 'dz', + 'Dz' => 'dz', + 'Ǵ' => 'ǵ', + 'Ƕ' => 'ƕ', + 'Ƿ' => 'ƿ', + 'Ǹ' => 'ǹ', + 'Ǻ' => 'ǻ', + 'Ǽ' => 'ǽ', + 'Ǿ' => 'ǿ', + 'Ȁ' => 'ȁ', + 'Ȃ' => 'ȃ', + 'Ȅ' => 'ȅ', + 'Ȇ' => 'ȇ', + 'Ȉ' => 'ȉ', + 'Ȋ' => 'ȋ', + 'Ȍ' => 'ȍ', + 'Ȏ' => 'ȏ', + 'Ȑ' => 'ȑ', + 'Ȓ' => 'ȓ', + 'Ȕ' => 'ȕ', + 'Ȗ' => 'ȗ', + 'Ș' => 'ș', + 'Ț' => 'ț', + 'Ȝ' => 'ȝ', + 'Ȟ' => 'ȟ', + 'Ƞ' => 'ƞ', + 'Ȣ' => 'ȣ', + 'Ȥ' => 'ȥ', + 'Ȧ' => 'ȧ', + 'Ȩ' => 'ȩ', + 'Ȫ' => 'ȫ', + 'Ȭ' => 'ȭ', + 'Ȯ' => 'ȯ', + 'Ȱ' => 'ȱ', + 'Ȳ' => 'ȳ', + 'Ⱥ' => 'ⱥ', + 'Ȼ' => 'ȼ', + 'Ƚ' => 'ƚ', + 'Ⱦ' => 'ⱦ', + 'Ɂ' => 'ɂ', + 'Ƀ' => 'ƀ', + 'Ʉ' => 'ʉ', + 'Ʌ' => 'ʌ', + 'Ɇ' => 'ɇ', + 'Ɉ' => 'ɉ', + 'Ɋ' => 'ɋ', + 'Ɍ' => 'ɍ', + 'Ɏ' => 'ɏ', + 'Ͱ' => 'ͱ', + 'Ͳ' => 'ͳ', + 'Ͷ' => 'ͷ', + 'Ϳ' => 'ϳ', + 'Ά' => 'ά', + 'Έ' => 'έ', + 'Ή' => 'ή', + 'Ί' => 'ί', + 'Ό' => 'ό', + 'Ύ' => 'ύ', + 'Ώ' => 'ώ', + 'Α' => 'α', + 'Β' => 'β', + 'Γ' => 'γ', + 'Δ' => 'δ', + 'Ε' => 'ε', + 'Ζ' => 'ζ', + 'Η' => 'η', + 'Θ' => 'θ', + 'Ι' => 'ι', + 'Κ' => 'κ', + 'Λ' => 'λ', + 'Μ' => 'μ', + 'Ν' => 'ν', + 'Ξ' => 'ξ', + 'Ο' => 'ο', + 'Π' => 'π', + 'Ρ' => 'ρ', + 'Σ' => 'σ', + 'Τ' => 'τ', + 'Υ' => 'υ', + 'Φ' => 'φ', + 'Χ' => 'χ', + 'Ψ' => 'ψ', + 'Ω' => 'ω', + 'Ϊ' => 'ϊ', + 'Ϋ' => 'ϋ', + 'Ϗ' => 'ϗ', + 'Ϙ' => 'ϙ', + 'Ϛ' => 'ϛ', + 'Ϝ' => 'ϝ', + 'Ϟ' => 'ϟ', + 'Ϡ' => 'ϡ', + 'Ϣ' => 'ϣ', + 'Ϥ' => 'ϥ', + 'Ϧ' => 'ϧ', + 'Ϩ' => 'ϩ', + 'Ϫ' => 'ϫ', + 'Ϭ' => 'ϭ', + 'Ϯ' => 'ϯ', + 'ϴ' => 'θ', + 'Ϸ' => 'ϸ', + 'Ϲ' => 'ϲ', + 'Ϻ' => 'ϻ', + 'Ͻ' => 'ͻ', + 'Ͼ' => 'ͼ', + 'Ͽ' => 'ͽ', + 'Ѐ' => 'ѐ', + 'Ё' => 'ё', + 'Ђ' => 'ђ', + 'Ѓ' => 'ѓ', + 'Є' => 'є', + 'Ѕ' => 'ѕ', + 'І' => 'і', + 'Ї' => 'ї', + 'Ј' => 'ј', + 'Љ' => 'љ', + 'Њ' => 'њ', + 'Ћ' => 'ћ', + 'Ќ' => 'ќ', + 'Ѝ' => 'ѝ', + 'Ў' => 'ў', + 'Џ' => 'џ', + 'А' => 'а', + 'Б' => 'б', + 'В' => 'в', + 'Г' => 'г', + 'Д' => 'д', + 'Е' => 'е', + 'Ж' => 'ж', + 'З' => 'з', + 'И' => 'и', + 'Й' => 'й', + 'К' => 'к', + 'Л' => 'л', + 'М' => 'м', + 'Н' => 'н', + 'О' => 'о', + 'П' => 'п', + 'Р' => 'р', + 'С' => 'с', + 'Т' => 'т', + 'У' => 'у', + 'Ф' => 'ф', + 'Х' => 'х', + 'Ц' => 'ц', + 'Ч' => 'ч', + 'Ш' => 'ш', + 'Щ' => 'щ', + 'Ъ' => 'ъ', + 'Ы' => 'ы', + 'Ь' => 'ь', + 'Э' => 'э', + 'Ю' => 'ю', + 'Я' => 'я', + 'Ѡ' => 'ѡ', + 'Ѣ' => 'ѣ', + 'Ѥ' => 'ѥ', + 'Ѧ' => 'ѧ', + 'Ѩ' => 'ѩ', + 'Ѫ' => 'ѫ', + 'Ѭ' => 'ѭ', + 'Ѯ' => 'ѯ', + 'Ѱ' => 'ѱ', + 'Ѳ' => 'ѳ', + 'Ѵ' => 'ѵ', + 'Ѷ' => 'ѷ', + 'Ѹ' => 'ѹ', + 'Ѻ' => 'ѻ', + 'Ѽ' => 'ѽ', + 'Ѿ' => 'ѿ', + 'Ҁ' => 'ҁ', + 'Ҋ' => 'ҋ', + 'Ҍ' => 'ҍ', + 'Ҏ' => 'ҏ', + 'Ґ' => 'ґ', + 'Ғ' => 'ғ', + 'Ҕ' => 'ҕ', + 'Җ' => 'җ', + 'Ҙ' => 'ҙ', + 'Қ' => 'қ', + 'Ҝ' => 'ҝ', + 'Ҟ' => 'ҟ', + 'Ҡ' => 'ҡ', + 'Ң' => 'ң', + 'Ҥ' => 'ҥ', + 'Ҧ' => 'ҧ', + 'Ҩ' => 'ҩ', + 'Ҫ' => 'ҫ', + 'Ҭ' => 'ҭ', + 'Ү' => 'ү', + 'Ұ' => 'ұ', + 'Ҳ' => 'ҳ', + 'Ҵ' => 'ҵ', + 'Ҷ' => 'ҷ', + 'Ҹ' => 'ҹ', + 'Һ' => 'һ', + 'Ҽ' => 'ҽ', + 'Ҿ' => 'ҿ', + 'Ӏ' => 'ӏ', + 'Ӂ' => 'ӂ', + 'Ӄ' => 'ӄ', + 'Ӆ' => 'ӆ', + 'Ӈ' => 'ӈ', + 'Ӊ' => 'ӊ', + 'Ӌ' => 'ӌ', + 'Ӎ' => 'ӎ', + 'Ӑ' => 'ӑ', + 'Ӓ' => 'ӓ', + 'Ӕ' => 'ӕ', + 'Ӗ' => 'ӗ', + 'Ә' => 'ә', + 'Ӛ' => 'ӛ', + 'Ӝ' => 'ӝ', + 'Ӟ' => 'ӟ', + 'Ӡ' => 'ӡ', + 'Ӣ' => 'ӣ', + 'Ӥ' => 'ӥ', + 'Ӧ' => 'ӧ', + 'Ө' => 'ө', + 'Ӫ' => 'ӫ', + 'Ӭ' => 'ӭ', + 'Ӯ' => 'ӯ', + 'Ӱ' => 'ӱ', + 'Ӳ' => 'ӳ', + 'Ӵ' => 'ӵ', + 'Ӷ' => 'ӷ', + 'Ӹ' => 'ӹ', + 'Ӻ' => 'ӻ', + 'Ӽ' => 'ӽ', + 'Ӿ' => 'ӿ', + 'Ԁ' => 'ԁ', + 'Ԃ' => 'ԃ', + 'Ԅ' => 'ԅ', + 'Ԇ' => 'ԇ', + 'Ԉ' => 'ԉ', + 'Ԋ' => 'ԋ', + 'Ԍ' => 'ԍ', + 'Ԏ' => 'ԏ', + 'Ԑ' => 'ԑ', + 'Ԓ' => 'ԓ', + 'Ԕ' => 'ԕ', + 'Ԗ' => 'ԗ', + 'Ԙ' => 'ԙ', + 'Ԛ' => 'ԛ', + 'Ԝ' => 'ԝ', + 'Ԟ' => 'ԟ', + 'Ԡ' => 'ԡ', + 'Ԣ' => 'ԣ', + 'Ԥ' => 'ԥ', + 'Ԧ' => 'ԧ', + 'Ԩ' => 'ԩ', + 'Ԫ' => 'ԫ', + 'Ԭ' => 'ԭ', + 'Ԯ' => 'ԯ', + 'Ա' => 'ա', + 'Բ' => 'բ', + 'Գ' => 'գ', + 'Դ' => 'դ', + 'Ե' => 'ե', + 'Զ' => 'զ', + 'Է' => 'է', + 'Ը' => 'ը', + 'Թ' => 'թ', + 'Ժ' => 'ժ', + 'Ի' => 'ի', + 'Լ' => 'լ', + 'Խ' => 'խ', + 'Ծ' => 'ծ', + 'Կ' => 'կ', + 'Հ' => 'հ', + 'Ձ' => 'ձ', + 'Ղ' => 'ղ', + 'Ճ' => 'ճ', + 'Մ' => 'մ', + 'Յ' => 'յ', + 'Ն' => 'ն', + 'Շ' => 'շ', + 'Ո' => 'ո', + 'Չ' => 'չ', + 'Պ' => 'պ', + 'Ջ' => 'ջ', + 'Ռ' => 'ռ', + 'Ս' => 'ս', + 'Վ' => 'վ', + 'Տ' => 'տ', + 'Ր' => 'ր', + 'Ց' => 'ց', + 'Ւ' => 'ւ', + 'Փ' => 'փ', + 'Ք' => 'ք', + 'Օ' => 'օ', + 'Ֆ' => 'ֆ', + 'Ⴀ' => 'ⴀ', + 'Ⴁ' => 'ⴁ', + 'Ⴂ' => 'ⴂ', + 'Ⴃ' => 'ⴃ', + 'Ⴄ' => 'ⴄ', + 'Ⴅ' => 'ⴅ', + 'Ⴆ' => 'ⴆ', + 'Ⴇ' => 'ⴇ', + 'Ⴈ' => 'ⴈ', + 'Ⴉ' => 'ⴉ', + 'Ⴊ' => 'ⴊ', + 'Ⴋ' => 'ⴋ', + 'Ⴌ' => 'ⴌ', + 'Ⴍ' => 'ⴍ', + 'Ⴎ' => 'ⴎ', + 'Ⴏ' => 'ⴏ', + 'Ⴐ' => 'ⴐ', + 'Ⴑ' => 'ⴑ', + 'Ⴒ' => 'ⴒ', + 'Ⴓ' => 'ⴓ', + 'Ⴔ' => 'ⴔ', + 'Ⴕ' => 'ⴕ', + 'Ⴖ' => 'ⴖ', + 'Ⴗ' => 'ⴗ', + 'Ⴘ' => 'ⴘ', + 'Ⴙ' => 'ⴙ', + 'Ⴚ' => 'ⴚ', + 'Ⴛ' => 'ⴛ', + 'Ⴜ' => 'ⴜ', + 'Ⴝ' => 'ⴝ', + 'Ⴞ' => 'ⴞ', + 'Ⴟ' => 'ⴟ', + 'Ⴠ' => 'ⴠ', + 'Ⴡ' => 'ⴡ', + 'Ⴢ' => 'ⴢ', + 'Ⴣ' => 'ⴣ', + 'Ⴤ' => 'ⴤ', + 'Ⴥ' => 'ⴥ', + 'Ⴧ' => 'ⴧ', + 'Ⴭ' => 'ⴭ', + 'Ꭰ' => 'ꭰ', + 'Ꭱ' => 'ꭱ', + 'Ꭲ' => 'ꭲ', + 'Ꭳ' => 'ꭳ', + 'Ꭴ' => 'ꭴ', + 'Ꭵ' => 'ꭵ', + 'Ꭶ' => 'ꭶ', + 'Ꭷ' => 'ꭷ', + 'Ꭸ' => 'ꭸ', + 'Ꭹ' => 'ꭹ', + 'Ꭺ' => 'ꭺ', + 'Ꭻ' => 'ꭻ', + 'Ꭼ' => 'ꭼ', + 'Ꭽ' => 'ꭽ', + 'Ꭾ' => 'ꭾ', + 'Ꭿ' => 'ꭿ', + 'Ꮀ' => 'ꮀ', + 'Ꮁ' => 'ꮁ', + 'Ꮂ' => 'ꮂ', + 'Ꮃ' => 'ꮃ', + 'Ꮄ' => 'ꮄ', + 'Ꮅ' => 'ꮅ', + 'Ꮆ' => 'ꮆ', + 'Ꮇ' => 'ꮇ', + 'Ꮈ' => 'ꮈ', + 'Ꮉ' => 'ꮉ', + 'Ꮊ' => 'ꮊ', + 'Ꮋ' => 'ꮋ', + 'Ꮌ' => 'ꮌ', + 'Ꮍ' => 'ꮍ', + 'Ꮎ' => 'ꮎ', + 'Ꮏ' => 'ꮏ', + 'Ꮐ' => 'ꮐ', + 'Ꮑ' => 'ꮑ', + 'Ꮒ' => 'ꮒ', + 'Ꮓ' => 'ꮓ', + 'Ꮔ' => 'ꮔ', + 'Ꮕ' => 'ꮕ', + 'Ꮖ' => 'ꮖ', + 'Ꮗ' => 'ꮗ', + 'Ꮘ' => 'ꮘ', + 'Ꮙ' => 'ꮙ', + 'Ꮚ' => 'ꮚ', + 'Ꮛ' => 'ꮛ', + 'Ꮜ' => 'ꮜ', + 'Ꮝ' => 'ꮝ', + 'Ꮞ' => 'ꮞ', + 'Ꮟ' => 'ꮟ', + 'Ꮠ' => 'ꮠ', + 'Ꮡ' => 'ꮡ', + 'Ꮢ' => 'ꮢ', + 'Ꮣ' => 'ꮣ', + 'Ꮤ' => 'ꮤ', + 'Ꮥ' => 'ꮥ', + 'Ꮦ' => 'ꮦ', + 'Ꮧ' => 'ꮧ', + 'Ꮨ' => 'ꮨ', + 'Ꮩ' => 'ꮩ', + 'Ꮪ' => 'ꮪ', + 'Ꮫ' => 'ꮫ', + 'Ꮬ' => 'ꮬ', + 'Ꮭ' => 'ꮭ', + 'Ꮮ' => 'ꮮ', + 'Ꮯ' => 'ꮯ', + 'Ꮰ' => 'ꮰ', + 'Ꮱ' => 'ꮱ', + 'Ꮲ' => 'ꮲ', + 'Ꮳ' => 'ꮳ', + 'Ꮴ' => 'ꮴ', + 'Ꮵ' => 'ꮵ', + 'Ꮶ' => 'ꮶ', + 'Ꮷ' => 'ꮷ', + 'Ꮸ' => 'ꮸ', + 'Ꮹ' => 'ꮹ', + 'Ꮺ' => 'ꮺ', + 'Ꮻ' => 'ꮻ', + 'Ꮼ' => 'ꮼ', + 'Ꮽ' => 'ꮽ', + 'Ꮾ' => 'ꮾ', + 'Ꮿ' => 'ꮿ', + 'Ᏸ' => 'ᏸ', + 'Ᏹ' => 'ᏹ', + 'Ᏺ' => 'ᏺ', + 'Ᏻ' => 'ᏻ', + 'Ᏼ' => 'ᏼ', + 'Ᏽ' => 'ᏽ', + 'Ა' => 'ა', + 'Ბ' => 'ბ', + 'Გ' => 'გ', + 'Დ' => 'დ', + 'Ე' => 'ე', + 'Ვ' => 'ვ', + 'Ზ' => 'ზ', + 'Თ' => 'თ', + 'Ი' => 'ი', + 'Კ' => 'კ', + 'Ლ' => 'ლ', + 'Მ' => 'მ', + 'Ნ' => 'ნ', + 'Ო' => 'ო', + 'Პ' => 'პ', + 'Ჟ' => 'ჟ', + 'Რ' => 'რ', + 'Ს' => 'ს', + 'Ტ' => 'ტ', + 'Უ' => 'უ', + 'Ფ' => 'ფ', + 'Ქ' => 'ქ', + 'Ღ' => 'ღ', + 'Ყ' => 'ყ', + 'Შ' => 'შ', + 'Ჩ' => 'ჩ', + 'Ც' => 'ც', + 'Ძ' => 'ძ', + 'Წ' => 'წ', + 'Ჭ' => 'ჭ', + 'Ხ' => 'ხ', + 'Ჯ' => 'ჯ', + 'Ჰ' => 'ჰ', + 'Ჱ' => 'ჱ', + 'Ჲ' => 'ჲ', + 'Ჳ' => 'ჳ', + 'Ჴ' => 'ჴ', + 'Ჵ' => 'ჵ', + 'Ჶ' => 'ჶ', + 'Ჷ' => 'ჷ', + 'Ჸ' => 'ჸ', + 'Ჹ' => 'ჹ', + 'Ჺ' => 'ჺ', + 'Ჽ' => 'ჽ', + 'Ჾ' => 'ჾ', + 'Ჿ' => 'ჿ', + 'Ḁ' => 'ḁ', + 'Ḃ' => 'ḃ', + 'Ḅ' => 'ḅ', + 'Ḇ' => 'ḇ', + 'Ḉ' => 'ḉ', + 'Ḋ' => 'ḋ', + 'Ḍ' => 'ḍ', + 'Ḏ' => 'ḏ', + 'Ḑ' => 'ḑ', + 'Ḓ' => 'ḓ', + 'Ḕ' => 'ḕ', + 'Ḗ' => 'ḗ', + 'Ḙ' => 'ḙ', + 'Ḛ' => 'ḛ', + 'Ḝ' => 'ḝ', + 'Ḟ' => 'ḟ', + 'Ḡ' => 'ḡ', + 'Ḣ' => 'ḣ', + 'Ḥ' => 'ḥ', + 'Ḧ' => 'ḧ', + 'Ḩ' => 'ḩ', + 'Ḫ' => 'ḫ', + 'Ḭ' => 'ḭ', + 'Ḯ' => 'ḯ', + 'Ḱ' => 'ḱ', + 'Ḳ' => 'ḳ', + 'Ḵ' => 'ḵ', + 'Ḷ' => 'ḷ', + 'Ḹ' => 'ḹ', + 'Ḻ' => 'ḻ', + 'Ḽ' => 'ḽ', + 'Ḿ' => 'ḿ', + 'Ṁ' => 'ṁ', + 'Ṃ' => 'ṃ', + 'Ṅ' => 'ṅ', + 'Ṇ' => 'ṇ', + 'Ṉ' => 'ṉ', + 'Ṋ' => 'ṋ', + 'Ṍ' => 'ṍ', + 'Ṏ' => 'ṏ', + 'Ṑ' => 'ṑ', + 'Ṓ' => 'ṓ', + 'Ṕ' => 'ṕ', + 'Ṗ' => 'ṗ', + 'Ṙ' => 'ṙ', + 'Ṛ' => 'ṛ', + 'Ṝ' => 'ṝ', + 'Ṟ' => 'ṟ', + 'Ṡ' => 'ṡ', + 'Ṣ' => 'ṣ', + 'Ṥ' => 'ṥ', + 'Ṧ' => 'ṧ', + 'Ṩ' => 'ṩ', + 'Ṫ' => 'ṫ', + 'Ṭ' => 'ṭ', + 'Ṯ' => 'ṯ', + 'Ṱ' => 'ṱ', + 'Ṳ' => 'ṳ', + 'Ṵ' => 'ṵ', + 'Ṷ' => 'ṷ', + 'Ṹ' => 'ṹ', + 'Ṻ' => 'ṻ', + 'Ṽ' => 'ṽ', + 'Ṿ' => 'ṿ', + 'Ẁ' => 'ẁ', + 'Ẃ' => 'ẃ', + 'Ẅ' => 'ẅ', + 'Ẇ' => 'ẇ', + 'Ẉ' => 'ẉ', + 'Ẋ' => 'ẋ', + 'Ẍ' => 'ẍ', + 'Ẏ' => 'ẏ', + 'Ẑ' => 'ẑ', + 'Ẓ' => 'ẓ', + 'Ẕ' => 'ẕ', + 'ẞ' => 'ß', + 'Ạ' => 'ạ', + 'Ả' => 'ả', + 'Ấ' => 'ấ', + 'Ầ' => 'ầ', + 'Ẩ' => 'ẩ', + 'Ẫ' => 'ẫ', + 'Ậ' => 'ậ', + 'Ắ' => 'ắ', + 'Ằ' => 'ằ', + 'Ẳ' => 'ẳ', + 'Ẵ' => 'ẵ', + 'Ặ' => 'ặ', + 'Ẹ' => 'ẹ', + 'Ẻ' => 'ẻ', + 'Ẽ' => 'ẽ', + 'Ế' => 'ế', + 'Ề' => 'ề', + 'Ể' => 'ể', + 'Ễ' => 'ễ', + 'Ệ' => 'ệ', + 'Ỉ' => 'ỉ', + 'Ị' => 'ị', + 'Ọ' => 'ọ', + 'Ỏ' => 'ỏ', + 'Ố' => 'ố', + 'Ồ' => 'ồ', + 'Ổ' => 'ổ', + 'Ỗ' => 'ỗ', + 'Ộ' => 'ộ', + 'Ớ' => 'ớ', + 'Ờ' => 'ờ', + 'Ở' => 'ở', + 'Ỡ' => 'ỡ', + 'Ợ' => 'ợ', + 'Ụ' => 'ụ', + 'Ủ' => 'ủ', + 'Ứ' => 'ứ', + 'Ừ' => 'ừ', + 'Ử' => 'ử', + 'Ữ' => 'ữ', + 'Ự' => 'ự', + 'Ỳ' => 'ỳ', + 'Ỵ' => 'ỵ', + 'Ỷ' => 'ỷ', + 'Ỹ' => 'ỹ', + 'Ỻ' => 'ỻ', + 'Ỽ' => 'ỽ', + 'Ỿ' => 'ỿ', + 'Ἀ' => 'ἀ', + 'Ἁ' => 'ἁ', + 'Ἂ' => 'ἂ', + 'Ἃ' => 'ἃ', + 'Ἄ' => 'ἄ', + 'Ἅ' => 'ἅ', + 'Ἆ' => 'ἆ', + 'Ἇ' => 'ἇ', + 'Ἐ' => 'ἐ', + 'Ἑ' => 'ἑ', + 'Ἒ' => 'ἒ', + 'Ἓ' => 'ἓ', + 'Ἔ' => 'ἔ', + 'Ἕ' => 'ἕ', + 'Ἠ' => 'ἠ', + 'Ἡ' => 'ἡ', + 'Ἢ' => 'ἢ', + 'Ἣ' => 'ἣ', + 'Ἤ' => 'ἤ', + 'Ἥ' => 'ἥ', + 'Ἦ' => 'ἦ', + 'Ἧ' => 'ἧ', + 'Ἰ' => 'ἰ', + 'Ἱ' => 'ἱ', + 'Ἲ' => 'ἲ', + 'Ἳ' => 'ἳ', + 'Ἴ' => 'ἴ', + 'Ἵ' => 'ἵ', + 'Ἶ' => 'ἶ', + 'Ἷ' => 'ἷ', + 'Ὀ' => 'ὀ', + 'Ὁ' => 'ὁ', + 'Ὂ' => 'ὂ', + 'Ὃ' => 'ὃ', + 'Ὄ' => 'ὄ', + 'Ὅ' => 'ὅ', + 'Ὑ' => 'ὑ', + 'Ὓ' => 'ὓ', + 'Ὕ' => 'ὕ', + 'Ὗ' => 'ὗ', + 'Ὠ' => 'ὠ', + 'Ὡ' => 'ὡ', + 'Ὢ' => 'ὢ', + 'Ὣ' => 'ὣ', + 'Ὤ' => 'ὤ', + 'Ὥ' => 'ὥ', + 'Ὦ' => 'ὦ', + 'Ὧ' => 'ὧ', + 'ᾈ' => 'ᾀ', + 'ᾉ' => 'ᾁ', + 'ᾊ' => 'ᾂ', + 'ᾋ' => 'ᾃ', + 'ᾌ' => 'ᾄ', + 'ᾍ' => 'ᾅ', + 'ᾎ' => 'ᾆ', + 'ᾏ' => 'ᾇ', + 'ᾘ' => 'ᾐ', + 'ᾙ' => 'ᾑ', + 'ᾚ' => 'ᾒ', + 'ᾛ' => 'ᾓ', + 'ᾜ' => 'ᾔ', + 'ᾝ' => 'ᾕ', + 'ᾞ' => 'ᾖ', + 'ᾟ' => 'ᾗ', + 'ᾨ' => 'ᾠ', + 'ᾩ' => 'ᾡ', + 'ᾪ' => 'ᾢ', + 'ᾫ' => 'ᾣ', + 'ᾬ' => 'ᾤ', + 'ᾭ' => 'ᾥ', + 'ᾮ' => 'ᾦ', + 'ᾯ' => 'ᾧ', + 'Ᾰ' => 'ᾰ', + 'Ᾱ' => 'ᾱ', + 'Ὰ' => 'ὰ', + 'Ά' => 'ά', + 'ᾼ' => 'ᾳ', + 'Ὲ' => 'ὲ', + 'Έ' => 'έ', + 'Ὴ' => 'ὴ', + 'Ή' => 'ή', + 'ῌ' => 'ῃ', + 'Ῐ' => 'ῐ', + 'Ῑ' => 'ῑ', + 'Ὶ' => 'ὶ', + 'Ί' => 'ί', + 'Ῠ' => 'ῠ', + 'Ῡ' => 'ῡ', + 'Ὺ' => 'ὺ', + 'Ύ' => 'ύ', + 'Ῥ' => 'ῥ', + 'Ὸ' => 'ὸ', + 'Ό' => 'ό', + 'Ὼ' => 'ὼ', + 'Ώ' => 'ώ', + 'ῼ' => 'ῳ', + 'Ω' => 'ω', + 'K' => 'k', + 'Å' => 'å', + 'Ⅎ' => 'ⅎ', + 'Ⅰ' => 'ⅰ', + 'Ⅱ' => 'ⅱ', + 'Ⅲ' => 'ⅲ', + 'Ⅳ' => 'ⅳ', + 'Ⅴ' => 'ⅴ', + 'Ⅵ' => 'ⅵ', + 'Ⅶ' => 'ⅶ', + 'Ⅷ' => 'ⅷ', + 'Ⅸ' => 'ⅸ', + 'Ⅹ' => 'ⅹ', + 'Ⅺ' => 'ⅺ', + 'Ⅻ' => 'ⅻ', + 'Ⅼ' => 'ⅼ', + 'Ⅽ' => 'ⅽ', + 'Ⅾ' => 'ⅾ', + 'Ⅿ' => 'ⅿ', + 'Ↄ' => 'ↄ', + 'Ⓐ' => 'ⓐ', + 'Ⓑ' => 'ⓑ', + 'Ⓒ' => 'ⓒ', + 'Ⓓ' => 'ⓓ', + 'Ⓔ' => 'ⓔ', + 'Ⓕ' => 'ⓕ', + 'Ⓖ' => 'ⓖ', + 'Ⓗ' => 'ⓗ', + 'Ⓘ' => 'ⓘ', + 'Ⓙ' => 'ⓙ', + 'Ⓚ' => 'ⓚ', + 'Ⓛ' => 'ⓛ', + 'Ⓜ' => 'ⓜ', + 'Ⓝ' => 'ⓝ', + 'Ⓞ' => 'ⓞ', + 'Ⓟ' => 'ⓟ', + 'Ⓠ' => 'ⓠ', + 'Ⓡ' => 'ⓡ', + 'Ⓢ' => 'ⓢ', + 'Ⓣ' => 'ⓣ', + 'Ⓤ' => 'ⓤ', + 'Ⓥ' => 'ⓥ', + 'Ⓦ' => 'ⓦ', + 'Ⓧ' => 'ⓧ', + 'Ⓨ' => 'ⓨ', + 'Ⓩ' => 'ⓩ', + 'Ⰰ' => 'ⰰ', + 'Ⰱ' => 'ⰱ', + 'Ⰲ' => 'ⰲ', + 'Ⰳ' => 'ⰳ', + 'Ⰴ' => 'ⰴ', + 'Ⰵ' => 'ⰵ', + 'Ⰶ' => 'ⰶ', + 'Ⰷ' => 'ⰷ', + 'Ⰸ' => 'ⰸ', + 'Ⰹ' => 'ⰹ', + 'Ⰺ' => 'ⰺ', + 'Ⰻ' => 'ⰻ', + 'Ⰼ' => 'ⰼ', + 'Ⰽ' => 'ⰽ', + 'Ⰾ' => 'ⰾ', + 'Ⰿ' => 'ⰿ', + 'Ⱀ' => 'ⱀ', + 'Ⱁ' => 'ⱁ', + 'Ⱂ' => 'ⱂ', + 'Ⱃ' => 'ⱃ', + 'Ⱄ' => 'ⱄ', + 'Ⱅ' => 'ⱅ', + 'Ⱆ' => 'ⱆ', + 'Ⱇ' => 'ⱇ', + 'Ⱈ' => 'ⱈ', + 'Ⱉ' => 'ⱉ', + 'Ⱊ' => 'ⱊ', + 'Ⱋ' => 'ⱋ', + 'Ⱌ' => 'ⱌ', + 'Ⱍ' => 'ⱍ', + 'Ⱎ' => 'ⱎ', + 'Ⱏ' => 'ⱏ', + 'Ⱐ' => 'ⱐ', + 'Ⱑ' => 'ⱑ', + 'Ⱒ' => 'ⱒ', + 'Ⱓ' => 'ⱓ', + 'Ⱔ' => 'ⱔ', + 'Ⱕ' => 'ⱕ', + 'Ⱖ' => 'ⱖ', + 'Ⱗ' => 'ⱗ', + 'Ⱘ' => 'ⱘ', + 'Ⱙ' => 'ⱙ', + 'Ⱚ' => 'ⱚ', + 'Ⱛ' => 'ⱛ', + 'Ⱜ' => 'ⱜ', + 'Ⱝ' => 'ⱝ', + 'Ⱞ' => 'ⱞ', + 'Ⱡ' => 'ⱡ', + 'Ɫ' => 'ɫ', + 'Ᵽ' => 'ᵽ', + 'Ɽ' => 'ɽ', + 'Ⱨ' => 'ⱨ', + 'Ⱪ' => 'ⱪ', + 'Ⱬ' => 'ⱬ', + 'Ɑ' => 'ɑ', + 'Ɱ' => 'ɱ', + 'Ɐ' => 'ɐ', + 'Ɒ' => 'ɒ', + 'Ⱳ' => 'ⱳ', + 'Ⱶ' => 'ⱶ', + 'Ȿ' => 'ȿ', + 'Ɀ' => 'ɀ', + 'Ⲁ' => 'ⲁ', + 'Ⲃ' => 'ⲃ', + 'Ⲅ' => 'ⲅ', + 'Ⲇ' => 'ⲇ', + 'Ⲉ' => 'ⲉ', + 'Ⲋ' => 'ⲋ', + 'Ⲍ' => 'ⲍ', + 'Ⲏ' => 'ⲏ', + 'Ⲑ' => 'ⲑ', + 'Ⲓ' => 'ⲓ', + 'Ⲕ' => 'ⲕ', + 'Ⲗ' => 'ⲗ', + 'Ⲙ' => 'ⲙ', + 'Ⲛ' => 'ⲛ', + 'Ⲝ' => 'ⲝ', + 'Ⲟ' => 'ⲟ', + 'Ⲡ' => 'ⲡ', + 'Ⲣ' => 'ⲣ', + 'Ⲥ' => 'ⲥ', + 'Ⲧ' => 'ⲧ', + 'Ⲩ' => 'ⲩ', + 'Ⲫ' => 'ⲫ', + 'Ⲭ' => 'ⲭ', + 'Ⲯ' => 'ⲯ', + 'Ⲱ' => 'ⲱ', + 'Ⲳ' => 'ⲳ', + 'Ⲵ' => 'ⲵ', + 'Ⲷ' => 'ⲷ', + 'Ⲹ' => 'ⲹ', + 'Ⲻ' => 'ⲻ', + 'Ⲽ' => 'ⲽ', + 'Ⲿ' => 'ⲿ', + 'Ⳁ' => 'ⳁ', + 'Ⳃ' => 'ⳃ', + 'Ⳅ' => 'ⳅ', + 'Ⳇ' => 'ⳇ', + 'Ⳉ' => 'ⳉ', + 'Ⳋ' => 'ⳋ', + 'Ⳍ' => 'ⳍ', + 'Ⳏ' => 'ⳏ', + 'Ⳑ' => 'ⳑ', + 'Ⳓ' => 'ⳓ', + 'Ⳕ' => 'ⳕ', + 'Ⳗ' => 'ⳗ', + 'Ⳙ' => 'ⳙ', + 'Ⳛ' => 'ⳛ', + 'Ⳝ' => 'ⳝ', + 'Ⳟ' => 'ⳟ', + 'Ⳡ' => 'ⳡ', + 'Ⳣ' => 'ⳣ', + 'Ⳬ' => 'ⳬ', + 'Ⳮ' => 'ⳮ', + 'Ⳳ' => 'ⳳ', + 'Ꙁ' => 'ꙁ', + 'Ꙃ' => 'ꙃ', + 'Ꙅ' => 'ꙅ', + 'Ꙇ' => 'ꙇ', + 'Ꙉ' => 'ꙉ', + 'Ꙋ' => 'ꙋ', + 'Ꙍ' => 'ꙍ', + 'Ꙏ' => 'ꙏ', + 'Ꙑ' => 'ꙑ', + 'Ꙓ' => 'ꙓ', + 'Ꙕ' => 'ꙕ', + 'Ꙗ' => 'ꙗ', + 'Ꙙ' => 'ꙙ', + 'Ꙛ' => 'ꙛ', + 'Ꙝ' => 'ꙝ', + 'Ꙟ' => 'ꙟ', + 'Ꙡ' => 'ꙡ', + 'Ꙣ' => 'ꙣ', + 'Ꙥ' => 'ꙥ', + 'Ꙧ' => 'ꙧ', + 'Ꙩ' => 'ꙩ', + 'Ꙫ' => 'ꙫ', + 'Ꙭ' => 'ꙭ', + 'Ꚁ' => 'ꚁ', + 'Ꚃ' => 'ꚃ', + 'Ꚅ' => 'ꚅ', + 'Ꚇ' => 'ꚇ', + 'Ꚉ' => 'ꚉ', + 'Ꚋ' => 'ꚋ', + 'Ꚍ' => 'ꚍ', + 'Ꚏ' => 'ꚏ', + 'Ꚑ' => 'ꚑ', + 'Ꚓ' => 'ꚓ', + 'Ꚕ' => 'ꚕ', + 'Ꚗ' => 'ꚗ', + 'Ꚙ' => 'ꚙ', + 'Ꚛ' => 'ꚛ', + 'Ꜣ' => 'ꜣ', + 'Ꜥ' => 'ꜥ', + 'Ꜧ' => 'ꜧ', + 'Ꜩ' => 'ꜩ', + 'Ꜫ' => 'ꜫ', + 'Ꜭ' => 'ꜭ', + 'Ꜯ' => 'ꜯ', + 'Ꜳ' => 'ꜳ', + 'Ꜵ' => 'ꜵ', + 'Ꜷ' => 'ꜷ', + 'Ꜹ' => 'ꜹ', + 'Ꜻ' => 'ꜻ', + 'Ꜽ' => 'ꜽ', + 'Ꜿ' => 'ꜿ', + 'Ꝁ' => 'ꝁ', + 'Ꝃ' => 'ꝃ', + 'Ꝅ' => 'ꝅ', + 'Ꝇ' => 'ꝇ', + 'Ꝉ' => 'ꝉ', + 'Ꝋ' => 'ꝋ', + 'Ꝍ' => 'ꝍ', + 'Ꝏ' => 'ꝏ', + 'Ꝑ' => 'ꝑ', + 'Ꝓ' => 'ꝓ', + 'Ꝕ' => 'ꝕ', + 'Ꝗ' => 'ꝗ', + 'Ꝙ' => 'ꝙ', + 'Ꝛ' => 'ꝛ', + 'Ꝝ' => 'ꝝ', + 'Ꝟ' => 'ꝟ', + 'Ꝡ' => 'ꝡ', + 'Ꝣ' => 'ꝣ', + 'Ꝥ' => 'ꝥ', + 'Ꝧ' => 'ꝧ', + 'Ꝩ' => 'ꝩ', + 'Ꝫ' => 'ꝫ', + 'Ꝭ' => 'ꝭ', + 'Ꝯ' => 'ꝯ', + 'Ꝺ' => 'ꝺ', + 'Ꝼ' => 'ꝼ', + 'Ᵹ' => 'ᵹ', + 'Ꝿ' => 'ꝿ', + 'Ꞁ' => 'ꞁ', + 'Ꞃ' => 'ꞃ', + 'Ꞅ' => 'ꞅ', + 'Ꞇ' => 'ꞇ', + 'Ꞌ' => 'ꞌ', + 'Ɥ' => 'ɥ', + 'Ꞑ' => 'ꞑ', + 'Ꞓ' => 'ꞓ', + 'Ꞗ' => 'ꞗ', + 'Ꞙ' => 'ꞙ', + 'Ꞛ' => 'ꞛ', + 'Ꞝ' => 'ꞝ', + 'Ꞟ' => 'ꞟ', + 'Ꞡ' => 'ꞡ', + 'Ꞣ' => 'ꞣ', + 'Ꞥ' => 'ꞥ', + 'Ꞧ' => 'ꞧ', + 'Ꞩ' => 'ꞩ', + 'Ɦ' => 'ɦ', + 'Ɜ' => 'ɜ', + 'Ɡ' => 'ɡ', + 'Ɬ' => 'ɬ', + 'Ɪ' => 'ɪ', + 'Ʞ' => 'ʞ', + 'Ʇ' => 'ʇ', + 'Ʝ' => 'ʝ', + 'Ꭓ' => 'ꭓ', + 'Ꞵ' => 'ꞵ', + 'Ꞷ' => 'ꞷ', + 'Ꞹ' => 'ꞹ', + 'Ꞻ' => 'ꞻ', + 'Ꞽ' => 'ꞽ', + 'Ꞿ' => 'ꞿ', + 'Ꟃ' => 'ꟃ', + 'Ꞔ' => 'ꞔ', + 'Ʂ' => 'ʂ', + 'Ᶎ' => 'ᶎ', + 'Ꟈ' => 'ꟈ', + 'Ꟊ' => 'ꟊ', + 'Ꟶ' => 'ꟶ', + 'A' => 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + '𐐀' => '𐐨', + '𐐁' => '𐐩', + '𐐂' => '𐐪', + '𐐃' => '𐐫', + '𐐄' => '𐐬', + '𐐅' => '𐐭', + '𐐆' => '𐐮', + '𐐇' => '𐐯', + '𐐈' => '𐐰', + '𐐉' => '𐐱', + '𐐊' => '𐐲', + '𐐋' => '𐐳', + '𐐌' => '𐐴', + '𐐍' => '𐐵', + '𐐎' => '𐐶', + '𐐏' => '𐐷', + '𐐐' => '𐐸', + '𐐑' => '𐐹', + '𐐒' => '𐐺', + '𐐓' => '𐐻', + '𐐔' => '𐐼', + '𐐕' => '𐐽', + '𐐖' => '𐐾', + '𐐗' => '𐐿', + '𐐘' => '𐑀', + '𐐙' => '𐑁', + '𐐚' => '𐑂', + '𐐛' => '𐑃', + '𐐜' => '𐑄', + '𐐝' => '𐑅', + '𐐞' => '𐑆', + '𐐟' => '𐑇', + '𐐠' => '𐑈', + '𐐡' => '𐑉', + '𐐢' => '𐑊', + '𐐣' => '𐑋', + '𐐤' => '𐑌', + '𐐥' => '𐑍', + '𐐦' => '𐑎', + '𐐧' => '𐑏', + '𐒰' => '𐓘', + '𐒱' => '𐓙', + '𐒲' => '𐓚', + '𐒳' => '𐓛', + '𐒴' => '𐓜', + '𐒵' => '𐓝', + '𐒶' => '𐓞', + '𐒷' => '𐓟', + '𐒸' => '𐓠', + '𐒹' => '𐓡', + '𐒺' => '𐓢', + '𐒻' => '𐓣', + '𐒼' => '𐓤', + '𐒽' => '𐓥', + '𐒾' => '𐓦', + '𐒿' => '𐓧', + '𐓀' => '𐓨', + '𐓁' => '𐓩', + '𐓂' => '𐓪', + '𐓃' => '𐓫', + '𐓄' => '𐓬', + '𐓅' => '𐓭', + '𐓆' => '𐓮', + '𐓇' => '𐓯', + '𐓈' => '𐓰', + '𐓉' => '𐓱', + '𐓊' => '𐓲', + '𐓋' => '𐓳', + '𐓌' => '𐓴', + '𐓍' => '𐓵', + '𐓎' => '𐓶', + '𐓏' => '𐓷', + '𐓐' => '𐓸', + '𐓑' => '𐓹', + '𐓒' => '𐓺', + '𐓓' => '𐓻', + '𐲀' => '𐳀', + '𐲁' => '𐳁', + '𐲂' => '𐳂', + '𐲃' => '𐳃', + '𐲄' => '𐳄', + '𐲅' => '𐳅', + '𐲆' => '𐳆', + '𐲇' => '𐳇', + '𐲈' => '𐳈', + '𐲉' => '𐳉', + '𐲊' => '𐳊', + '𐲋' => '𐳋', + '𐲌' => '𐳌', + '𐲍' => '𐳍', + '𐲎' => '𐳎', + '𐲏' => '𐳏', + '𐲐' => '𐳐', + '𐲑' => '𐳑', + '𐲒' => '𐳒', + '𐲓' => '𐳓', + '𐲔' => '𐳔', + '𐲕' => '𐳕', + '𐲖' => '𐳖', + '𐲗' => '𐳗', + '𐲘' => '𐳘', + '𐲙' => '𐳙', + '𐲚' => '𐳚', + '𐲛' => '𐳛', + '𐲜' => '𐳜', + '𐲝' => '𐳝', + '𐲞' => '𐳞', + '𐲟' => '𐳟', + '𐲠' => '𐳠', + '𐲡' => '𐳡', + '𐲢' => '𐳢', + '𐲣' => '𐳣', + '𐲤' => '𐳤', + '𐲥' => '𐳥', + '𐲦' => '𐳦', + '𐲧' => '𐳧', + '𐲨' => '𐳨', + '𐲩' => '𐳩', + '𐲪' => '𐳪', + '𐲫' => '𐳫', + '𐲬' => '𐳬', + '𐲭' => '𐳭', + '𐲮' => '𐳮', + '𐲯' => '𐳯', + '𐲰' => '𐳰', + '𐲱' => '𐳱', + '𐲲' => '𐳲', + '𑢠' => '𑣀', + '𑢡' => '𑣁', + '𑢢' => '𑣂', + '𑢣' => '𑣃', + '𑢤' => '𑣄', + '𑢥' => '𑣅', + '𑢦' => '𑣆', + '𑢧' => '𑣇', + '𑢨' => '𑣈', + '𑢩' => '𑣉', + '𑢪' => '𑣊', + '𑢫' => '𑣋', + '𑢬' => '𑣌', + '𑢭' => '𑣍', + '𑢮' => '𑣎', + '𑢯' => '𑣏', + '𑢰' => '𑣐', + '𑢱' => '𑣑', + '𑢲' => '𑣒', + '𑢳' => '𑣓', + '𑢴' => '𑣔', + '𑢵' => '𑣕', + '𑢶' => '𑣖', + '𑢷' => '𑣗', + '𑢸' => '𑣘', + '𑢹' => '𑣙', + '𑢺' => '𑣚', + '𑢻' => '𑣛', + '𑢼' => '𑣜', + '𑢽' => '𑣝', + '𑢾' => '𑣞', + '𑢿' => '𑣟', + '𖹀' => '𖹠', + '𖹁' => '𖹡', + '𖹂' => '𖹢', + '𖹃' => '𖹣', + '𖹄' => '𖹤', + '𖹅' => '𖹥', + '𖹆' => '𖹦', + '𖹇' => '𖹧', + '𖹈' => '𖹨', + '𖹉' => '𖹩', + '𖹊' => '𖹪', + '𖹋' => '𖹫', + '𖹌' => '𖹬', + '𖹍' => '𖹭', + '𖹎' => '𖹮', + '𖹏' => '𖹯', + '𖹐' => '𖹰', + '𖹑' => '𖹱', + '𖹒' => '𖹲', + '𖹓' => '𖹳', + '𖹔' => '𖹴', + '𖹕' => '𖹵', + '𖹖' => '𖹶', + '𖹗' => '𖹷', + '𖹘' => '𖹸', + '𖹙' => '𖹹', + '𖹚' => '𖹺', + '𖹛' => '𖹻', + '𖹜' => '𖹼', + '𖹝' => '𖹽', + '𖹞' => '𖹾', + '𖹟' => '𖹿', + '𞤀' => '𞤢', + '𞤁' => '𞤣', + '𞤂' => '𞤤', + '𞤃' => '𞤥', + '𞤄' => '𞤦', + '𞤅' => '𞤧', + '𞤆' => '𞤨', + '𞤇' => '𞤩', + '𞤈' => '𞤪', + '𞤉' => '𞤫', + '𞤊' => '𞤬', + '𞤋' => '𞤭', + '𞤌' => '𞤮', + '𞤍' => '𞤯', + '𞤎' => '𞤰', + '𞤏' => '𞤱', + '𞤐' => '𞤲', + '𞤑' => '𞤳', + '𞤒' => '𞤴', + '𞤓' => '𞤵', + '𞤔' => '𞤶', + '𞤕' => '𞤷', + '𞤖' => '𞤸', + '𞤗' => '𞤹', + '𞤘' => '𞤺', + '𞤙' => '𞤻', + '𞤚' => '𞤼', + '𞤛' => '𞤽', + '𞤜' => '𞤾', + '𞤝' => '𞤿', + '𞤞' => '𞥀', + '𞤟' => '𞥁', + '𞤠' => '𞥂', + '𞤡' => '𞥃', +); diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 00000000..2a8f6e73 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ + 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + 'µ' => 'Μ', + 'à' => 'À', + 'á' => 'Á', + 'â' => 'Â', + 'ã' => 'Ã', + 'ä' => 'Ä', + 'å' => 'Å', + 'æ' => 'Æ', + 'ç' => 'Ç', + 'è' => 'È', + 'é' => 'É', + 'ê' => 'Ê', + 'ë' => 'Ë', + 'ì' => 'Ì', + 'í' => 'Í', + 'î' => 'Î', + 'ï' => 'Ï', + 'ð' => 'Ð', + 'ñ' => 'Ñ', + 'ò' => 'Ò', + 'ó' => 'Ó', + 'ô' => 'Ô', + 'õ' => 'Õ', + 'ö' => 'Ö', + 'ø' => 'Ø', + 'ù' => 'Ù', + 'ú' => 'Ú', + 'û' => 'Û', + 'ü' => 'Ü', + 'ý' => 'Ý', + 'þ' => 'Þ', + 'ÿ' => 'Ÿ', + 'ā' => 'Ā', + 'ă' => 'Ă', + 'ą' => 'Ą', + 'ć' => 'Ć', + 'ĉ' => 'Ĉ', + 'ċ' => 'Ċ', + 'č' => 'Č', + 'ď' => 'Ď', + 'đ' => 'Đ', + 'ē' => 'Ē', + 'ĕ' => 'Ĕ', + 'ė' => 'Ė', + 'ę' => 'Ę', + 'ě' => 'Ě', + 'ĝ' => 'Ĝ', + 'ğ' => 'Ğ', + 'ġ' => 'Ġ', + 'ģ' => 'Ģ', + 'ĥ' => 'Ĥ', + 'ħ' => 'Ħ', + 'ĩ' => 'Ĩ', + 'ī' => 'Ī', + 'ĭ' => 'Ĭ', + 'į' => 'Į', + 'ı' => 'I', + 'ij' => 'IJ', + 'ĵ' => 'Ĵ', + 'ķ' => 'Ķ', + 'ĺ' => 'Ĺ', + 'ļ' => 'Ļ', + 'ľ' => 'Ľ', + 'ŀ' => 'Ŀ', + 'ł' => 'Ł', + 'ń' => 'Ń', + 'ņ' => 'Ņ', + 'ň' => 'Ň', + 'ŋ' => 'Ŋ', + 'ō' => 'Ō', + 'ŏ' => 'Ŏ', + 'ő' => 'Ő', + 'œ' => 'Œ', + 'ŕ' => 'Ŕ', + 'ŗ' => 'Ŗ', + 'ř' => 'Ř', + 'ś' => 'Ś', + 'ŝ' => 'Ŝ', + 'ş' => 'Ş', + 'š' => 'Š', + 'ţ' => 'Ţ', + 'ť' => 'Ť', + 'ŧ' => 'Ŧ', + 'ũ' => 'Ũ', + 'ū' => 'Ū', + 'ŭ' => 'Ŭ', + 'ů' => 'Ů', + 'ű' => 'Ű', + 'ų' => 'Ų', + 'ŵ' => 'Ŵ', + 'ŷ' => 'Ŷ', + 'ź' => 'Ź', + 'ż' => 'Ż', + 'ž' => 'Ž', + 'ſ' => 'S', + 'ƀ' => 'Ƀ', + 'ƃ' => 'Ƃ', + 'ƅ' => 'Ƅ', + 'ƈ' => 'Ƈ', + 'ƌ' => 'Ƌ', + 'ƒ' => 'Ƒ', + 'ƕ' => 'Ƕ', + 'ƙ' => 'Ƙ', + 'ƚ' => 'Ƚ', + 'ƞ' => 'Ƞ', + 'ơ' => 'Ơ', + 'ƣ' => 'Ƣ', + 'ƥ' => 'Ƥ', + 'ƨ' => 'Ƨ', + 'ƭ' => 'Ƭ', + 'ư' => 'Ư', + 'ƴ' => 'Ƴ', + 'ƶ' => 'Ƶ', + 'ƹ' => 'Ƹ', + 'ƽ' => 'Ƽ', + 'ƿ' => 'Ƿ', + 'Dž' => 'DŽ', + 'dž' => 'DŽ', + 'Lj' => 'LJ', + 'lj' => 'LJ', + 'Nj' => 'NJ', + 'nj' => 'NJ', + 'ǎ' => 'Ǎ', + 'ǐ' => 'Ǐ', + 'ǒ' => 'Ǒ', + 'ǔ' => 'Ǔ', + 'ǖ' => 'Ǖ', + 'ǘ' => 'Ǘ', + 'ǚ' => 'Ǚ', + 'ǜ' => 'Ǜ', + 'ǝ' => 'Ǝ', + 'ǟ' => 'Ǟ', + 'ǡ' => 'Ǡ', + 'ǣ' => 'Ǣ', + 'ǥ' => 'Ǥ', + 'ǧ' => 'Ǧ', + 'ǩ' => 'Ǩ', + 'ǫ' => 'Ǫ', + 'ǭ' => 'Ǭ', + 'ǯ' => 'Ǯ', + 'Dz' => 'DZ', + 'dz' => 'DZ', + 'ǵ' => 'Ǵ', + 'ǹ' => 'Ǹ', + 'ǻ' => 'Ǻ', + 'ǽ' => 'Ǽ', + 'ǿ' => 'Ǿ', + 'ȁ' => 'Ȁ', + 'ȃ' => 'Ȃ', + 'ȅ' => 'Ȅ', + 'ȇ' => 'Ȇ', + 'ȉ' => 'Ȉ', + 'ȋ' => 'Ȋ', + 'ȍ' => 'Ȍ', + 'ȏ' => 'Ȏ', + 'ȑ' => 'Ȑ', + 'ȓ' => 'Ȓ', + 'ȕ' => 'Ȕ', + 'ȗ' => 'Ȗ', + 'ș' => 'Ș', + 'ț' => 'Ț', + 'ȝ' => 'Ȝ', + 'ȟ' => 'Ȟ', + 'ȣ' => 'Ȣ', + 'ȥ' => 'Ȥ', + 'ȧ' => 'Ȧ', + 'ȩ' => 'Ȩ', + 'ȫ' => 'Ȫ', + 'ȭ' => 'Ȭ', + 'ȯ' => 'Ȯ', + 'ȱ' => 'Ȱ', + 'ȳ' => 'Ȳ', + 'ȼ' => 'Ȼ', + 'ȿ' => 'Ȿ', + 'ɀ' => 'Ɀ', + 'ɂ' => 'Ɂ', + 'ɇ' => 'Ɇ', + 'ɉ' => 'Ɉ', + 'ɋ' => 'Ɋ', + 'ɍ' => 'Ɍ', + 'ɏ' => 'Ɏ', + 'ɐ' => 'Ɐ', + 'ɑ' => 'Ɑ', + 'ɒ' => 'Ɒ', + 'ɓ' => 'Ɓ', + 'ɔ' => 'Ɔ', + 'ɖ' => 'Ɖ', + 'ɗ' => 'Ɗ', + 'ə' => 'Ə', + 'ɛ' => 'Ɛ', + 'ɜ' => 'Ɜ', + 'ɠ' => 'Ɠ', + 'ɡ' => 'Ɡ', + 'ɣ' => 'Ɣ', + 'ɥ' => 'Ɥ', + 'ɦ' => 'Ɦ', + 'ɨ' => 'Ɨ', + 'ɩ' => 'Ɩ', + 'ɪ' => 'Ɪ', + 'ɫ' => 'Ɫ', + 'ɬ' => 'Ɬ', + 'ɯ' => 'Ɯ', + 'ɱ' => 'Ɱ', + 'ɲ' => 'Ɲ', + 'ɵ' => 'Ɵ', + 'ɽ' => 'Ɽ', + 'ʀ' => 'Ʀ', + 'ʂ' => 'Ʂ', + 'ʃ' => 'Ʃ', + 'ʇ' => 'Ʇ', + 'ʈ' => 'Ʈ', + 'ʉ' => 'Ʉ', + 'ʊ' => 'Ʊ', + 'ʋ' => 'Ʋ', + 'ʌ' => 'Ʌ', + 'ʒ' => 'Ʒ', + 'ʝ' => 'Ʝ', + 'ʞ' => 'Ʞ', + 'ͅ' => 'Ι', + 'ͱ' => 'Ͱ', + 'ͳ' => 'Ͳ', + 'ͷ' => 'Ͷ', + 'ͻ' => 'Ͻ', + 'ͼ' => 'Ͼ', + 'ͽ' => 'Ͽ', + 'ά' => 'Ά', + 'έ' => 'Έ', + 'ή' => 'Ή', + 'ί' => 'Ί', + 'α' => 'Α', + 'β' => 'Β', + 'γ' => 'Γ', + 'δ' => 'Δ', + 'ε' => 'Ε', + 'ζ' => 'Ζ', + 'η' => 'Η', + 'θ' => 'Θ', + 'ι' => 'Ι', + 'κ' => 'Κ', + 'λ' => 'Λ', + 'μ' => 'Μ', + 'ν' => 'Ν', + 'ξ' => 'Ξ', + 'ο' => 'Ο', + 'π' => 'Π', + 'ρ' => 'Ρ', + 'ς' => 'Σ', + 'σ' => 'Σ', + 'τ' => 'Τ', + 'υ' => 'Υ', + 'φ' => 'Φ', + 'χ' => 'Χ', + 'ψ' => 'Ψ', + 'ω' => 'Ω', + 'ϊ' => 'Ϊ', + 'ϋ' => 'Ϋ', + 'ό' => 'Ό', + 'ύ' => 'Ύ', + 'ώ' => 'Ώ', + 'ϐ' => 'Β', + 'ϑ' => 'Θ', + 'ϕ' => 'Φ', + 'ϖ' => 'Π', + 'ϗ' => 'Ϗ', + 'ϙ' => 'Ϙ', + 'ϛ' => 'Ϛ', + 'ϝ' => 'Ϝ', + 'ϟ' => 'Ϟ', + 'ϡ' => 'Ϡ', + 'ϣ' => 'Ϣ', + 'ϥ' => 'Ϥ', + 'ϧ' => 'Ϧ', + 'ϩ' => 'Ϩ', + 'ϫ' => 'Ϫ', + 'ϭ' => 'Ϭ', + 'ϯ' => 'Ϯ', + 'ϰ' => 'Κ', + 'ϱ' => 'Ρ', + 'ϲ' => 'Ϲ', + 'ϳ' => 'Ϳ', + 'ϵ' => 'Ε', + 'ϸ' => 'Ϸ', + 'ϻ' => 'Ϻ', + 'а' => 'А', + 'б' => 'Б', + 'в' => 'В', + 'г' => 'Г', + 'д' => 'Д', + 'е' => 'Е', + 'ж' => 'Ж', + 'з' => 'З', + 'и' => 'И', + 'й' => 'Й', + 'к' => 'К', + 'л' => 'Л', + 'м' => 'М', + 'н' => 'Н', + 'о' => 'О', + 'п' => 'П', + 'р' => 'Р', + 'с' => 'С', + 'т' => 'Т', + 'у' => 'У', + 'ф' => 'Ф', + 'х' => 'Х', + 'ц' => 'Ц', + 'ч' => 'Ч', + 'ш' => 'Ш', + 'щ' => 'Щ', + 'ъ' => 'Ъ', + 'ы' => 'Ы', + 'ь' => 'Ь', + 'э' => 'Э', + 'ю' => 'Ю', + 'я' => 'Я', + 'ѐ' => 'Ѐ', + 'ё' => 'Ё', + 'ђ' => 'Ђ', + 'ѓ' => 'Ѓ', + 'є' => 'Є', + 'ѕ' => 'Ѕ', + 'і' => 'І', + 'ї' => 'Ї', + 'ј' => 'Ј', + 'љ' => 'Љ', + 'њ' => 'Њ', + 'ћ' => 'Ћ', + 'ќ' => 'Ќ', + 'ѝ' => 'Ѝ', + 'ў' => 'Ў', + 'џ' => 'Џ', + 'ѡ' => 'Ѡ', + 'ѣ' => 'Ѣ', + 'ѥ' => 'Ѥ', + 'ѧ' => 'Ѧ', + 'ѩ' => 'Ѩ', + 'ѫ' => 'Ѫ', + 'ѭ' => 'Ѭ', + 'ѯ' => 'Ѯ', + 'ѱ' => 'Ѱ', + 'ѳ' => 'Ѳ', + 'ѵ' => 'Ѵ', + 'ѷ' => 'Ѷ', + 'ѹ' => 'Ѹ', + 'ѻ' => 'Ѻ', + 'ѽ' => 'Ѽ', + 'ѿ' => 'Ѿ', + 'ҁ' => 'Ҁ', + 'ҋ' => 'Ҋ', + 'ҍ' => 'Ҍ', + 'ҏ' => 'Ҏ', + 'ґ' => 'Ґ', + 'ғ' => 'Ғ', + 'ҕ' => 'Ҕ', + 'җ' => 'Җ', + 'ҙ' => 'Ҙ', + 'қ' => 'Қ', + 'ҝ' => 'Ҝ', + 'ҟ' => 'Ҟ', + 'ҡ' => 'Ҡ', + 'ң' => 'Ң', + 'ҥ' => 'Ҥ', + 'ҧ' => 'Ҧ', + 'ҩ' => 'Ҩ', + 'ҫ' => 'Ҫ', + 'ҭ' => 'Ҭ', + 'ү' => 'Ү', + 'ұ' => 'Ұ', + 'ҳ' => 'Ҳ', + 'ҵ' => 'Ҵ', + 'ҷ' => 'Ҷ', + 'ҹ' => 'Ҹ', + 'һ' => 'Һ', + 'ҽ' => 'Ҽ', + 'ҿ' => 'Ҿ', + 'ӂ' => 'Ӂ', + 'ӄ' => 'Ӄ', + 'ӆ' => 'Ӆ', + 'ӈ' => 'Ӈ', + 'ӊ' => 'Ӊ', + 'ӌ' => 'Ӌ', + 'ӎ' => 'Ӎ', + 'ӏ' => 'Ӏ', + 'ӑ' => 'Ӑ', + 'ӓ' => 'Ӓ', + 'ӕ' => 'Ӕ', + 'ӗ' => 'Ӗ', + 'ә' => 'Ә', + 'ӛ' => 'Ӛ', + 'ӝ' => 'Ӝ', + 'ӟ' => 'Ӟ', + 'ӡ' => 'Ӡ', + 'ӣ' => 'Ӣ', + 'ӥ' => 'Ӥ', + 'ӧ' => 'Ӧ', + 'ө' => 'Ө', + 'ӫ' => 'Ӫ', + 'ӭ' => 'Ӭ', + 'ӯ' => 'Ӯ', + 'ӱ' => 'Ӱ', + 'ӳ' => 'Ӳ', + 'ӵ' => 'Ӵ', + 'ӷ' => 'Ӷ', + 'ӹ' => 'Ӹ', + 'ӻ' => 'Ӻ', + 'ӽ' => 'Ӽ', + 'ӿ' => 'Ӿ', + 'ԁ' => 'Ԁ', + 'ԃ' => 'Ԃ', + 'ԅ' => 'Ԅ', + 'ԇ' => 'Ԇ', + 'ԉ' => 'Ԉ', + 'ԋ' => 'Ԋ', + 'ԍ' => 'Ԍ', + 'ԏ' => 'Ԏ', + 'ԑ' => 'Ԑ', + 'ԓ' => 'Ԓ', + 'ԕ' => 'Ԕ', + 'ԗ' => 'Ԗ', + 'ԙ' => 'Ԙ', + 'ԛ' => 'Ԛ', + 'ԝ' => 'Ԝ', + 'ԟ' => 'Ԟ', + 'ԡ' => 'Ԡ', + 'ԣ' => 'Ԣ', + 'ԥ' => 'Ԥ', + 'ԧ' => 'Ԧ', + 'ԩ' => 'Ԩ', + 'ԫ' => 'Ԫ', + 'ԭ' => 'Ԭ', + 'ԯ' => 'Ԯ', + 'ա' => 'Ա', + 'բ' => 'Բ', + 'գ' => 'Գ', + 'դ' => 'Դ', + 'ե' => 'Ե', + 'զ' => 'Զ', + 'է' => 'Է', + 'ը' => 'Ը', + 'թ' => 'Թ', + 'ժ' => 'Ժ', + 'ի' => 'Ի', + 'լ' => 'Լ', + 'խ' => 'Խ', + 'ծ' => 'Ծ', + 'կ' => 'Կ', + 'հ' => 'Հ', + 'ձ' => 'Ձ', + 'ղ' => 'Ղ', + 'ճ' => 'Ճ', + 'մ' => 'Մ', + 'յ' => 'Յ', + 'ն' => 'Ն', + 'շ' => 'Շ', + 'ո' => 'Ո', + 'չ' => 'Չ', + 'պ' => 'Պ', + 'ջ' => 'Ջ', + 'ռ' => 'Ռ', + 'ս' => 'Ս', + 'վ' => 'Վ', + 'տ' => 'Տ', + 'ր' => 'Ր', + 'ց' => 'Ց', + 'ւ' => 'Ւ', + 'փ' => 'Փ', + 'ք' => 'Ք', + 'օ' => 'Օ', + 'ֆ' => 'Ֆ', + 'ა' => 'Ა', + 'ბ' => 'Ბ', + 'გ' => 'Გ', + 'დ' => 'Დ', + 'ე' => 'Ე', + 'ვ' => 'Ვ', + 'ზ' => 'Ზ', + 'თ' => 'Თ', + 'ი' => 'Ი', + 'კ' => 'Კ', + 'ლ' => 'Ლ', + 'მ' => 'Მ', + 'ნ' => 'Ნ', + 'ო' => 'Ო', + 'პ' => 'Პ', + 'ჟ' => 'Ჟ', + 'რ' => 'Რ', + 'ს' => 'Ს', + 'ტ' => 'Ტ', + 'უ' => 'Უ', + 'ფ' => 'Ფ', + 'ქ' => 'Ქ', + 'ღ' => 'Ღ', + 'ყ' => 'Ყ', + 'შ' => 'Შ', + 'ჩ' => 'Ჩ', + 'ც' => 'Ც', + 'ძ' => 'Ძ', + 'წ' => 'Წ', + 'ჭ' => 'Ჭ', + 'ხ' => 'Ხ', + 'ჯ' => 'Ჯ', + 'ჰ' => 'Ჰ', + 'ჱ' => 'Ჱ', + 'ჲ' => 'Ჲ', + 'ჳ' => 'Ჳ', + 'ჴ' => 'Ჴ', + 'ჵ' => 'Ჵ', + 'ჶ' => 'Ჶ', + 'ჷ' => 'Ჷ', + 'ჸ' => 'Ჸ', + 'ჹ' => 'Ჹ', + 'ჺ' => 'Ჺ', + 'ჽ' => 'Ჽ', + 'ჾ' => 'Ჾ', + 'ჿ' => 'Ჿ', + 'ᏸ' => 'Ᏸ', + 'ᏹ' => 'Ᏹ', + 'ᏺ' => 'Ᏺ', + 'ᏻ' => 'Ᏻ', + 'ᏼ' => 'Ᏼ', + 'ᏽ' => 'Ᏽ', + 'ᲀ' => 'В', + 'ᲁ' => 'Д', + 'ᲂ' => 'О', + 'ᲃ' => 'С', + 'ᲄ' => 'Т', + 'ᲅ' => 'Т', + 'ᲆ' => 'Ъ', + 'ᲇ' => 'Ѣ', + 'ᲈ' => 'Ꙋ', + 'ᵹ' => 'Ᵹ', + 'ᵽ' => 'Ᵽ', + 'ᶎ' => 'Ᶎ', + 'ḁ' => 'Ḁ', + 'ḃ' => 'Ḃ', + 'ḅ' => 'Ḅ', + 'ḇ' => 'Ḇ', + 'ḉ' => 'Ḉ', + 'ḋ' => 'Ḋ', + 'ḍ' => 'Ḍ', + 'ḏ' => 'Ḏ', + 'ḑ' => 'Ḑ', + 'ḓ' => 'Ḓ', + 'ḕ' => 'Ḕ', + 'ḗ' => 'Ḗ', + 'ḙ' => 'Ḙ', + 'ḛ' => 'Ḛ', + 'ḝ' => 'Ḝ', + 'ḟ' => 'Ḟ', + 'ḡ' => 'Ḡ', + 'ḣ' => 'Ḣ', + 'ḥ' => 'Ḥ', + 'ḧ' => 'Ḧ', + 'ḩ' => 'Ḩ', + 'ḫ' => 'Ḫ', + 'ḭ' => 'Ḭ', + 'ḯ' => 'Ḯ', + 'ḱ' => 'Ḱ', + 'ḳ' => 'Ḳ', + 'ḵ' => 'Ḵ', + 'ḷ' => 'Ḷ', + 'ḹ' => 'Ḹ', + 'ḻ' => 'Ḻ', + 'ḽ' => 'Ḽ', + 'ḿ' => 'Ḿ', + 'ṁ' => 'Ṁ', + 'ṃ' => 'Ṃ', + 'ṅ' => 'Ṅ', + 'ṇ' => 'Ṇ', + 'ṉ' => 'Ṉ', + 'ṋ' => 'Ṋ', + 'ṍ' => 'Ṍ', + 'ṏ' => 'Ṏ', + 'ṑ' => 'Ṑ', + 'ṓ' => 'Ṓ', + 'ṕ' => 'Ṕ', + 'ṗ' => 'Ṗ', + 'ṙ' => 'Ṙ', + 'ṛ' => 'Ṛ', + 'ṝ' => 'Ṝ', + 'ṟ' => 'Ṟ', + 'ṡ' => 'Ṡ', + 'ṣ' => 'Ṣ', + 'ṥ' => 'Ṥ', + 'ṧ' => 'Ṧ', + 'ṩ' => 'Ṩ', + 'ṫ' => 'Ṫ', + 'ṭ' => 'Ṭ', + 'ṯ' => 'Ṯ', + 'ṱ' => 'Ṱ', + 'ṳ' => 'Ṳ', + 'ṵ' => 'Ṵ', + 'ṷ' => 'Ṷ', + 'ṹ' => 'Ṹ', + 'ṻ' => 'Ṻ', + 'ṽ' => 'Ṽ', + 'ṿ' => 'Ṿ', + 'ẁ' => 'Ẁ', + 'ẃ' => 'Ẃ', + 'ẅ' => 'Ẅ', + 'ẇ' => 'Ẇ', + 'ẉ' => 'Ẉ', + 'ẋ' => 'Ẋ', + 'ẍ' => 'Ẍ', + 'ẏ' => 'Ẏ', + 'ẑ' => 'Ẑ', + 'ẓ' => 'Ẓ', + 'ẕ' => 'Ẕ', + 'ẛ' => 'Ṡ', + 'ạ' => 'Ạ', + 'ả' => 'Ả', + 'ấ' => 'Ấ', + 'ầ' => 'Ầ', + 'ẩ' => 'Ẩ', + 'ẫ' => 'Ẫ', + 'ậ' => 'Ậ', + 'ắ' => 'Ắ', + 'ằ' => 'Ằ', + 'ẳ' => 'Ẳ', + 'ẵ' => 'Ẵ', + 'ặ' => 'Ặ', + 'ẹ' => 'Ẹ', + 'ẻ' => 'Ẻ', + 'ẽ' => 'Ẽ', + 'ế' => 'Ế', + 'ề' => 'Ề', + 'ể' => 'Ể', + 'ễ' => 'Ễ', + 'ệ' => 'Ệ', + 'ỉ' => 'Ỉ', + 'ị' => 'Ị', + 'ọ' => 'Ọ', + 'ỏ' => 'Ỏ', + 'ố' => 'Ố', + 'ồ' => 'Ồ', + 'ổ' => 'Ổ', + 'ỗ' => 'Ỗ', + 'ộ' => 'Ộ', + 'ớ' => 'Ớ', + 'ờ' => 'Ờ', + 'ở' => 'Ở', + 'ỡ' => 'Ỡ', + 'ợ' => 'Ợ', + 'ụ' => 'Ụ', + 'ủ' => 'Ủ', + 'ứ' => 'Ứ', + 'ừ' => 'Ừ', + 'ử' => 'Ử', + 'ữ' => 'Ữ', + 'ự' => 'Ự', + 'ỳ' => 'Ỳ', + 'ỵ' => 'Ỵ', + 'ỷ' => 'Ỷ', + 'ỹ' => 'Ỹ', + 'ỻ' => 'Ỻ', + 'ỽ' => 'Ỽ', + 'ỿ' => 'Ỿ', + 'ἀ' => 'Ἀ', + 'ἁ' => 'Ἁ', + 'ἂ' => 'Ἂ', + 'ἃ' => 'Ἃ', + 'ἄ' => 'Ἄ', + 'ἅ' => 'Ἅ', + 'ἆ' => 'Ἆ', + 'ἇ' => 'Ἇ', + 'ἐ' => 'Ἐ', + 'ἑ' => 'Ἑ', + 'ἒ' => 'Ἒ', + 'ἓ' => 'Ἓ', + 'ἔ' => 'Ἔ', + 'ἕ' => 'Ἕ', + 'ἠ' => 'Ἠ', + 'ἡ' => 'Ἡ', + 'ἢ' => 'Ἢ', + 'ἣ' => 'Ἣ', + 'ἤ' => 'Ἤ', + 'ἥ' => 'Ἥ', + 'ἦ' => 'Ἦ', + 'ἧ' => 'Ἧ', + 'ἰ' => 'Ἰ', + 'ἱ' => 'Ἱ', + 'ἲ' => 'Ἲ', + 'ἳ' => 'Ἳ', + 'ἴ' => 'Ἴ', + 'ἵ' => 'Ἵ', + 'ἶ' => 'Ἶ', + 'ἷ' => 'Ἷ', + 'ὀ' => 'Ὀ', + 'ὁ' => 'Ὁ', + 'ὂ' => 'Ὂ', + 'ὃ' => 'Ὃ', + 'ὄ' => 'Ὄ', + 'ὅ' => 'Ὅ', + 'ὑ' => 'Ὑ', + 'ὓ' => 'Ὓ', + 'ὕ' => 'Ὕ', + 'ὗ' => 'Ὗ', + 'ὠ' => 'Ὠ', + 'ὡ' => 'Ὡ', + 'ὢ' => 'Ὢ', + 'ὣ' => 'Ὣ', + 'ὤ' => 'Ὤ', + 'ὥ' => 'Ὥ', + 'ὦ' => 'Ὦ', + 'ὧ' => 'Ὧ', + 'ὰ' => 'Ὰ', + 'ά' => 'Ά', + 'ὲ' => 'Ὲ', + 'έ' => 'Έ', + 'ὴ' => 'Ὴ', + 'ή' => 'Ή', + 'ὶ' => 'Ὶ', + 'ί' => 'Ί', + 'ὸ' => 'Ὸ', + 'ό' => 'Ό', + 'ὺ' => 'Ὺ', + 'ύ' => 'Ύ', + 'ὼ' => 'Ὼ', + 'ώ' => 'Ώ', + 'ᾀ' => 'ἈΙ', + 'ᾁ' => 'ἉΙ', + 'ᾂ' => 'ἊΙ', + 'ᾃ' => 'ἋΙ', + 'ᾄ' => 'ἌΙ', + 'ᾅ' => 'ἍΙ', + 'ᾆ' => 'ἎΙ', + 'ᾇ' => 'ἏΙ', + 'ᾐ' => 'ἨΙ', + 'ᾑ' => 'ἩΙ', + 'ᾒ' => 'ἪΙ', + 'ᾓ' => 'ἫΙ', + 'ᾔ' => 'ἬΙ', + 'ᾕ' => 'ἭΙ', + 'ᾖ' => 'ἮΙ', + 'ᾗ' => 'ἯΙ', + 'ᾠ' => 'ὨΙ', + 'ᾡ' => 'ὩΙ', + 'ᾢ' => 'ὪΙ', + 'ᾣ' => 'ὫΙ', + 'ᾤ' => 'ὬΙ', + 'ᾥ' => 'ὭΙ', + 'ᾦ' => 'ὮΙ', + 'ᾧ' => 'ὯΙ', + 'ᾰ' => 'Ᾰ', + 'ᾱ' => 'Ᾱ', + 'ᾳ' => 'ΑΙ', + 'ι' => 'Ι', + 'ῃ' => 'ΗΙ', + 'ῐ' => 'Ῐ', + 'ῑ' => 'Ῑ', + 'ῠ' => 'Ῠ', + 'ῡ' => 'Ῡ', + 'ῥ' => 'Ῥ', + 'ῳ' => 'ΩΙ', + 'ⅎ' => 'Ⅎ', + 'ⅰ' => 'Ⅰ', + 'ⅱ' => 'Ⅱ', + 'ⅲ' => 'Ⅲ', + 'ⅳ' => 'Ⅳ', + 'ⅴ' => 'Ⅴ', + 'ⅵ' => 'Ⅵ', + 'ⅶ' => 'Ⅶ', + 'ⅷ' => 'Ⅷ', + 'ⅸ' => 'Ⅸ', + 'ⅹ' => 'Ⅹ', + 'ⅺ' => 'Ⅺ', + 'ⅻ' => 'Ⅻ', + 'ⅼ' => 'Ⅼ', + 'ⅽ' => 'Ⅽ', + 'ⅾ' => 'Ⅾ', + 'ⅿ' => 'Ⅿ', + 'ↄ' => 'Ↄ', + 'ⓐ' => 'Ⓐ', + 'ⓑ' => 'Ⓑ', + 'ⓒ' => 'Ⓒ', + 'ⓓ' => 'Ⓓ', + 'ⓔ' => 'Ⓔ', + 'ⓕ' => 'Ⓕ', + 'ⓖ' => 'Ⓖ', + 'ⓗ' => 'Ⓗ', + 'ⓘ' => 'Ⓘ', + 'ⓙ' => 'Ⓙ', + 'ⓚ' => 'Ⓚ', + 'ⓛ' => 'Ⓛ', + 'ⓜ' => 'Ⓜ', + 'ⓝ' => 'Ⓝ', + 'ⓞ' => 'Ⓞ', + 'ⓟ' => 'Ⓟ', + 'ⓠ' => 'Ⓠ', + 'ⓡ' => 'Ⓡ', + 'ⓢ' => 'Ⓢ', + 'ⓣ' => 'Ⓣ', + 'ⓤ' => 'Ⓤ', + 'ⓥ' => 'Ⓥ', + 'ⓦ' => 'Ⓦ', + 'ⓧ' => 'Ⓧ', + 'ⓨ' => 'Ⓨ', + 'ⓩ' => 'Ⓩ', + 'ⰰ' => 'Ⰰ', + 'ⰱ' => 'Ⰱ', + 'ⰲ' => 'Ⰲ', + 'ⰳ' => 'Ⰳ', + 'ⰴ' => 'Ⰴ', + 'ⰵ' => 'Ⰵ', + 'ⰶ' => 'Ⰶ', + 'ⰷ' => 'Ⰷ', + 'ⰸ' => 'Ⰸ', + 'ⰹ' => 'Ⰹ', + 'ⰺ' => 'Ⰺ', + 'ⰻ' => 'Ⰻ', + 'ⰼ' => 'Ⰼ', + 'ⰽ' => 'Ⰽ', + 'ⰾ' => 'Ⰾ', + 'ⰿ' => 'Ⰿ', + 'ⱀ' => 'Ⱀ', + 'ⱁ' => 'Ⱁ', + 'ⱂ' => 'Ⱂ', + 'ⱃ' => 'Ⱃ', + 'ⱄ' => 'Ⱄ', + 'ⱅ' => 'Ⱅ', + 'ⱆ' => 'Ⱆ', + 'ⱇ' => 'Ⱇ', + 'ⱈ' => 'Ⱈ', + 'ⱉ' => 'Ⱉ', + 'ⱊ' => 'Ⱊ', + 'ⱋ' => 'Ⱋ', + 'ⱌ' => 'Ⱌ', + 'ⱍ' => 'Ⱍ', + 'ⱎ' => 'Ⱎ', + 'ⱏ' => 'Ⱏ', + 'ⱐ' => 'Ⱐ', + 'ⱑ' => 'Ⱑ', + 'ⱒ' => 'Ⱒ', + 'ⱓ' => 'Ⱓ', + 'ⱔ' => 'Ⱔ', + 'ⱕ' => 'Ⱕ', + 'ⱖ' => 'Ⱖ', + 'ⱗ' => 'Ⱗ', + 'ⱘ' => 'Ⱘ', + 'ⱙ' => 'Ⱙ', + 'ⱚ' => 'Ⱚ', + 'ⱛ' => 'Ⱛ', + 'ⱜ' => 'Ⱜ', + 'ⱝ' => 'Ⱝ', + 'ⱞ' => 'Ⱞ', + 'ⱡ' => 'Ⱡ', + 'ⱥ' => 'Ⱥ', + 'ⱦ' => 'Ⱦ', + 'ⱨ' => 'Ⱨ', + 'ⱪ' => 'Ⱪ', + 'ⱬ' => 'Ⱬ', + 'ⱳ' => 'Ⱳ', + 'ⱶ' => 'Ⱶ', + 'ⲁ' => 'Ⲁ', + 'ⲃ' => 'Ⲃ', + 'ⲅ' => 'Ⲅ', + 'ⲇ' => 'Ⲇ', + 'ⲉ' => 'Ⲉ', + 'ⲋ' => 'Ⲋ', + 'ⲍ' => 'Ⲍ', + 'ⲏ' => 'Ⲏ', + 'ⲑ' => 'Ⲑ', + 'ⲓ' => 'Ⲓ', + 'ⲕ' => 'Ⲕ', + 'ⲗ' => 'Ⲗ', + 'ⲙ' => 'Ⲙ', + 'ⲛ' => 'Ⲛ', + 'ⲝ' => 'Ⲝ', + 'ⲟ' => 'Ⲟ', + 'ⲡ' => 'Ⲡ', + 'ⲣ' => 'Ⲣ', + 'ⲥ' => 'Ⲥ', + 'ⲧ' => 'Ⲧ', + 'ⲩ' => 'Ⲩ', + 'ⲫ' => 'Ⲫ', + 'ⲭ' => 'Ⲭ', + 'ⲯ' => 'Ⲯ', + 'ⲱ' => 'Ⲱ', + 'ⲳ' => 'Ⲳ', + 'ⲵ' => 'Ⲵ', + 'ⲷ' => 'Ⲷ', + 'ⲹ' => 'Ⲹ', + 'ⲻ' => 'Ⲻ', + 'ⲽ' => 'Ⲽ', + 'ⲿ' => 'Ⲿ', + 'ⳁ' => 'Ⳁ', + 'ⳃ' => 'Ⳃ', + 'ⳅ' => 'Ⳅ', + 'ⳇ' => 'Ⳇ', + 'ⳉ' => 'Ⳉ', + 'ⳋ' => 'Ⳋ', + 'ⳍ' => 'Ⳍ', + 'ⳏ' => 'Ⳏ', + 'ⳑ' => 'Ⳑ', + 'ⳓ' => 'Ⳓ', + 'ⳕ' => 'Ⳕ', + 'ⳗ' => 'Ⳗ', + 'ⳙ' => 'Ⳙ', + 'ⳛ' => 'Ⳛ', + 'ⳝ' => 'Ⳝ', + 'ⳟ' => 'Ⳟ', + 'ⳡ' => 'Ⳡ', + 'ⳣ' => 'Ⳣ', + 'ⳬ' => 'Ⳬ', + 'ⳮ' => 'Ⳮ', + 'ⳳ' => 'Ⳳ', + 'ⴀ' => 'Ⴀ', + 'ⴁ' => 'Ⴁ', + 'ⴂ' => 'Ⴂ', + 'ⴃ' => 'Ⴃ', + 'ⴄ' => 'Ⴄ', + 'ⴅ' => 'Ⴅ', + 'ⴆ' => 'Ⴆ', + 'ⴇ' => 'Ⴇ', + 'ⴈ' => 'Ⴈ', + 'ⴉ' => 'Ⴉ', + 'ⴊ' => 'Ⴊ', + 'ⴋ' => 'Ⴋ', + 'ⴌ' => 'Ⴌ', + 'ⴍ' => 'Ⴍ', + 'ⴎ' => 'Ⴎ', + 'ⴏ' => 'Ⴏ', + 'ⴐ' => 'Ⴐ', + 'ⴑ' => 'Ⴑ', + 'ⴒ' => 'Ⴒ', + 'ⴓ' => 'Ⴓ', + 'ⴔ' => 'Ⴔ', + 'ⴕ' => 'Ⴕ', + 'ⴖ' => 'Ⴖ', + 'ⴗ' => 'Ⴗ', + 'ⴘ' => 'Ⴘ', + 'ⴙ' => 'Ⴙ', + 'ⴚ' => 'Ⴚ', + 'ⴛ' => 'Ⴛ', + 'ⴜ' => 'Ⴜ', + 'ⴝ' => 'Ⴝ', + 'ⴞ' => 'Ⴞ', + 'ⴟ' => 'Ⴟ', + 'ⴠ' => 'Ⴠ', + 'ⴡ' => 'Ⴡ', + 'ⴢ' => 'Ⴢ', + 'ⴣ' => 'Ⴣ', + 'ⴤ' => 'Ⴤ', + 'ⴥ' => 'Ⴥ', + 'ⴧ' => 'Ⴧ', + 'ⴭ' => 'Ⴭ', + 'ꙁ' => 'Ꙁ', + 'ꙃ' => 'Ꙃ', + 'ꙅ' => 'Ꙅ', + 'ꙇ' => 'Ꙇ', + 'ꙉ' => 'Ꙉ', + 'ꙋ' => 'Ꙋ', + 'ꙍ' => 'Ꙍ', + 'ꙏ' => 'Ꙏ', + 'ꙑ' => 'Ꙑ', + 'ꙓ' => 'Ꙓ', + 'ꙕ' => 'Ꙕ', + 'ꙗ' => 'Ꙗ', + 'ꙙ' => 'Ꙙ', + 'ꙛ' => 'Ꙛ', + 'ꙝ' => 'Ꙝ', + 'ꙟ' => 'Ꙟ', + 'ꙡ' => 'Ꙡ', + 'ꙣ' => 'Ꙣ', + 'ꙥ' => 'Ꙥ', + 'ꙧ' => 'Ꙧ', + 'ꙩ' => 'Ꙩ', + 'ꙫ' => 'Ꙫ', + 'ꙭ' => 'Ꙭ', + 'ꚁ' => 'Ꚁ', + 'ꚃ' => 'Ꚃ', + 'ꚅ' => 'Ꚅ', + 'ꚇ' => 'Ꚇ', + 'ꚉ' => 'Ꚉ', + 'ꚋ' => 'Ꚋ', + 'ꚍ' => 'Ꚍ', + 'ꚏ' => 'Ꚏ', + 'ꚑ' => 'Ꚑ', + 'ꚓ' => 'Ꚓ', + 'ꚕ' => 'Ꚕ', + 'ꚗ' => 'Ꚗ', + 'ꚙ' => 'Ꚙ', + 'ꚛ' => 'Ꚛ', + 'ꜣ' => 'Ꜣ', + 'ꜥ' => 'Ꜥ', + 'ꜧ' => 'Ꜧ', + 'ꜩ' => 'Ꜩ', + 'ꜫ' => 'Ꜫ', + 'ꜭ' => 'Ꜭ', + 'ꜯ' => 'Ꜯ', + 'ꜳ' => 'Ꜳ', + 'ꜵ' => 'Ꜵ', + 'ꜷ' => 'Ꜷ', + 'ꜹ' => 'Ꜹ', + 'ꜻ' => 'Ꜻ', + 'ꜽ' => 'Ꜽ', + 'ꜿ' => 'Ꜿ', + 'ꝁ' => 'Ꝁ', + 'ꝃ' => 'Ꝃ', + 'ꝅ' => 'Ꝅ', + 'ꝇ' => 'Ꝇ', + 'ꝉ' => 'Ꝉ', + 'ꝋ' => 'Ꝋ', + 'ꝍ' => 'Ꝍ', + 'ꝏ' => 'Ꝏ', + 'ꝑ' => 'Ꝑ', + 'ꝓ' => 'Ꝓ', + 'ꝕ' => 'Ꝕ', + 'ꝗ' => 'Ꝗ', + 'ꝙ' => 'Ꝙ', + 'ꝛ' => 'Ꝛ', + 'ꝝ' => 'Ꝝ', + 'ꝟ' => 'Ꝟ', + 'ꝡ' => 'Ꝡ', + 'ꝣ' => 'Ꝣ', + 'ꝥ' => 'Ꝥ', + 'ꝧ' => 'Ꝧ', + 'ꝩ' => 'Ꝩ', + 'ꝫ' => 'Ꝫ', + 'ꝭ' => 'Ꝭ', + 'ꝯ' => 'Ꝯ', + 'ꝺ' => 'Ꝺ', + 'ꝼ' => 'Ꝼ', + 'ꝿ' => 'Ꝿ', + 'ꞁ' => 'Ꞁ', + 'ꞃ' => 'Ꞃ', + 'ꞅ' => 'Ꞅ', + 'ꞇ' => 'Ꞇ', + 'ꞌ' => 'Ꞌ', + 'ꞑ' => 'Ꞑ', + 'ꞓ' => 'Ꞓ', + 'ꞔ' => 'Ꞔ', + 'ꞗ' => 'Ꞗ', + 'ꞙ' => 'Ꞙ', + 'ꞛ' => 'Ꞛ', + 'ꞝ' => 'Ꞝ', + 'ꞟ' => 'Ꞟ', + 'ꞡ' => 'Ꞡ', + 'ꞣ' => 'Ꞣ', + 'ꞥ' => 'Ꞥ', + 'ꞧ' => 'Ꞧ', + 'ꞩ' => 'Ꞩ', + 'ꞵ' => 'Ꞵ', + 'ꞷ' => 'Ꞷ', + 'ꞹ' => 'Ꞹ', + 'ꞻ' => 'Ꞻ', + 'ꞽ' => 'Ꞽ', + 'ꞿ' => 'Ꞿ', + 'ꟃ' => 'Ꟃ', + 'ꟈ' => 'Ꟈ', + 'ꟊ' => 'Ꟊ', + 'ꟶ' => 'Ꟶ', + 'ꭓ' => 'Ꭓ', + 'ꭰ' => 'Ꭰ', + 'ꭱ' => 'Ꭱ', + 'ꭲ' => 'Ꭲ', + 'ꭳ' => 'Ꭳ', + 'ꭴ' => 'Ꭴ', + 'ꭵ' => 'Ꭵ', + 'ꭶ' => 'Ꭶ', + 'ꭷ' => 'Ꭷ', + 'ꭸ' => 'Ꭸ', + 'ꭹ' => 'Ꭹ', + 'ꭺ' => 'Ꭺ', + 'ꭻ' => 'Ꭻ', + 'ꭼ' => 'Ꭼ', + 'ꭽ' => 'Ꭽ', + 'ꭾ' => 'Ꭾ', + 'ꭿ' => 'Ꭿ', + 'ꮀ' => 'Ꮀ', + 'ꮁ' => 'Ꮁ', + 'ꮂ' => 'Ꮂ', + 'ꮃ' => 'Ꮃ', + 'ꮄ' => 'Ꮄ', + 'ꮅ' => 'Ꮅ', + 'ꮆ' => 'Ꮆ', + 'ꮇ' => 'Ꮇ', + 'ꮈ' => 'Ꮈ', + 'ꮉ' => 'Ꮉ', + 'ꮊ' => 'Ꮊ', + 'ꮋ' => 'Ꮋ', + 'ꮌ' => 'Ꮌ', + 'ꮍ' => 'Ꮍ', + 'ꮎ' => 'Ꮎ', + 'ꮏ' => 'Ꮏ', + 'ꮐ' => 'Ꮐ', + 'ꮑ' => 'Ꮑ', + 'ꮒ' => 'Ꮒ', + 'ꮓ' => 'Ꮓ', + 'ꮔ' => 'Ꮔ', + 'ꮕ' => 'Ꮕ', + 'ꮖ' => 'Ꮖ', + 'ꮗ' => 'Ꮗ', + 'ꮘ' => 'Ꮘ', + 'ꮙ' => 'Ꮙ', + 'ꮚ' => 'Ꮚ', + 'ꮛ' => 'Ꮛ', + 'ꮜ' => 'Ꮜ', + 'ꮝ' => 'Ꮝ', + 'ꮞ' => 'Ꮞ', + 'ꮟ' => 'Ꮟ', + 'ꮠ' => 'Ꮠ', + 'ꮡ' => 'Ꮡ', + 'ꮢ' => 'Ꮢ', + 'ꮣ' => 'Ꮣ', + 'ꮤ' => 'Ꮤ', + 'ꮥ' => 'Ꮥ', + 'ꮦ' => 'Ꮦ', + 'ꮧ' => 'Ꮧ', + 'ꮨ' => 'Ꮨ', + 'ꮩ' => 'Ꮩ', + 'ꮪ' => 'Ꮪ', + 'ꮫ' => 'Ꮫ', + 'ꮬ' => 'Ꮬ', + 'ꮭ' => 'Ꮭ', + 'ꮮ' => 'Ꮮ', + 'ꮯ' => 'Ꮯ', + 'ꮰ' => 'Ꮰ', + 'ꮱ' => 'Ꮱ', + 'ꮲ' => 'Ꮲ', + 'ꮳ' => 'Ꮳ', + 'ꮴ' => 'Ꮴ', + 'ꮵ' => 'Ꮵ', + 'ꮶ' => 'Ꮶ', + 'ꮷ' => 'Ꮷ', + 'ꮸ' => 'Ꮸ', + 'ꮹ' => 'Ꮹ', + 'ꮺ' => 'Ꮺ', + 'ꮻ' => 'Ꮻ', + 'ꮼ' => 'Ꮼ', + 'ꮽ' => 'Ꮽ', + 'ꮾ' => 'Ꮾ', + 'ꮿ' => 'Ꮿ', + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + '𐐨' => '𐐀', + '𐐩' => '𐐁', + '𐐪' => '𐐂', + '𐐫' => '𐐃', + '𐐬' => '𐐄', + '𐐭' => '𐐅', + '𐐮' => '𐐆', + '𐐯' => '𐐇', + '𐐰' => '𐐈', + '𐐱' => '𐐉', + '𐐲' => '𐐊', + '𐐳' => '𐐋', + '𐐴' => '𐐌', + '𐐵' => '𐐍', + '𐐶' => '𐐎', + '𐐷' => '𐐏', + '𐐸' => '𐐐', + '𐐹' => '𐐑', + '𐐺' => '𐐒', + '𐐻' => '𐐓', + '𐐼' => '𐐔', + '𐐽' => '𐐕', + '𐐾' => '𐐖', + '𐐿' => '𐐗', + '𐑀' => '𐐘', + '𐑁' => '𐐙', + '𐑂' => '𐐚', + '𐑃' => '𐐛', + '𐑄' => '𐐜', + '𐑅' => '𐐝', + '𐑆' => '𐐞', + '𐑇' => '𐐟', + '𐑈' => '𐐠', + '𐑉' => '𐐡', + '𐑊' => '𐐢', + '𐑋' => '𐐣', + '𐑌' => '𐐤', + '𐑍' => '𐐥', + '𐑎' => '𐐦', + '𐑏' => '𐐧', + '𐓘' => '𐒰', + '𐓙' => '𐒱', + '𐓚' => '𐒲', + '𐓛' => '𐒳', + '𐓜' => '𐒴', + '𐓝' => '𐒵', + '𐓞' => '𐒶', + '𐓟' => '𐒷', + '𐓠' => '𐒸', + '𐓡' => '𐒹', + '𐓢' => '𐒺', + '𐓣' => '𐒻', + '𐓤' => '𐒼', + '𐓥' => '𐒽', + '𐓦' => '𐒾', + '𐓧' => '𐒿', + '𐓨' => '𐓀', + '𐓩' => '𐓁', + '𐓪' => '𐓂', + '𐓫' => '𐓃', + '𐓬' => '𐓄', + '𐓭' => '𐓅', + '𐓮' => '𐓆', + '𐓯' => '𐓇', + '𐓰' => '𐓈', + '𐓱' => '𐓉', + '𐓲' => '𐓊', + '𐓳' => '𐓋', + '𐓴' => '𐓌', + '𐓵' => '𐓍', + '𐓶' => '𐓎', + '𐓷' => '𐓏', + '𐓸' => '𐓐', + '𐓹' => '𐓑', + '𐓺' => '𐓒', + '𐓻' => '𐓓', + '𐳀' => '𐲀', + '𐳁' => '𐲁', + '𐳂' => '𐲂', + '𐳃' => '𐲃', + '𐳄' => '𐲄', + '𐳅' => '𐲅', + '𐳆' => '𐲆', + '𐳇' => '𐲇', + '𐳈' => '𐲈', + '𐳉' => '𐲉', + '𐳊' => '𐲊', + '𐳋' => '𐲋', + '𐳌' => '𐲌', + '𐳍' => '𐲍', + '𐳎' => '𐲎', + '𐳏' => '𐲏', + '𐳐' => '𐲐', + '𐳑' => '𐲑', + '𐳒' => '𐲒', + '𐳓' => '𐲓', + '𐳔' => '𐲔', + '𐳕' => '𐲕', + '𐳖' => '𐲖', + '𐳗' => '𐲗', + '𐳘' => '𐲘', + '𐳙' => '𐲙', + '𐳚' => '𐲚', + '𐳛' => '𐲛', + '𐳜' => '𐲜', + '𐳝' => '𐲝', + '𐳞' => '𐲞', + '𐳟' => '𐲟', + '𐳠' => '𐲠', + '𐳡' => '𐲡', + '𐳢' => '𐲢', + '𐳣' => '𐲣', + '𐳤' => '𐲤', + '𐳥' => '𐲥', + '𐳦' => '𐲦', + '𐳧' => '𐲧', + '𐳨' => '𐲨', + '𐳩' => '𐲩', + '𐳪' => '𐲪', + '𐳫' => '𐲫', + '𐳬' => '𐲬', + '𐳭' => '𐲭', + '𐳮' => '𐲮', + '𐳯' => '𐲯', + '𐳰' => '𐲰', + '𐳱' => '𐲱', + '𐳲' => '𐲲', + '𑣀' => '𑢠', + '𑣁' => '𑢡', + '𑣂' => '𑢢', + '𑣃' => '𑢣', + '𑣄' => '𑢤', + '𑣅' => '𑢥', + '𑣆' => '𑢦', + '𑣇' => '𑢧', + '𑣈' => '𑢨', + '𑣉' => '𑢩', + '𑣊' => '𑢪', + '𑣋' => '𑢫', + '𑣌' => '𑢬', + '𑣍' => '𑢭', + '𑣎' => '𑢮', + '𑣏' => '𑢯', + '𑣐' => '𑢰', + '𑣑' => '𑢱', + '𑣒' => '𑢲', + '𑣓' => '𑢳', + '𑣔' => '𑢴', + '𑣕' => '𑢵', + '𑣖' => '𑢶', + '𑣗' => '𑢷', + '𑣘' => '𑢸', + '𑣙' => '𑢹', + '𑣚' => '𑢺', + '𑣛' => '𑢻', + '𑣜' => '𑢼', + '𑣝' => '𑢽', + '𑣞' => '𑢾', + '𑣟' => '𑢿', + '𖹠' => '𖹀', + '𖹡' => '𖹁', + '𖹢' => '𖹂', + '𖹣' => '𖹃', + '𖹤' => '𖹄', + '𖹥' => '𖹅', + '𖹦' => '𖹆', + '𖹧' => '𖹇', + '𖹨' => '𖹈', + '𖹩' => '𖹉', + '𖹪' => '𖹊', + '𖹫' => '𖹋', + '𖹬' => '𖹌', + '𖹭' => '𖹍', + '𖹮' => '𖹎', + '𖹯' => '𖹏', + '𖹰' => '𖹐', + '𖹱' => '𖹑', + '𖹲' => '𖹒', + '𖹳' => '𖹓', + '𖹴' => '𖹔', + '𖹵' => '𖹕', + '𖹶' => '𖹖', + '𖹷' => '𖹗', + '𖹸' => '𖹘', + '𖹹' => '𖹙', + '𖹺' => '𖹚', + '𖹻' => '𖹛', + '𖹼' => '𖹜', + '𖹽' => '𖹝', + '𖹾' => '𖹞', + '𖹿' => '𖹟', + '𞤢' => '𞤀', + '𞤣' => '𞤁', + '𞤤' => '𞤂', + '𞤥' => '𞤃', + '𞤦' => '𞤄', + '𞤧' => '𞤅', + '𞤨' => '𞤆', + '𞤩' => '𞤇', + '𞤪' => '𞤈', + '𞤫' => '𞤉', + '𞤬' => '𞤊', + '𞤭' => '𞤋', + '𞤮' => '𞤌', + '𞤯' => '𞤍', + '𞤰' => '𞤎', + '𞤱' => '𞤏', + '𞤲' => '𞤐', + '𞤳' => '𞤑', + '𞤴' => '𞤒', + '𞤵' => '𞤓', + '𞤶' => '𞤔', + '𞤷' => '𞤕', + '𞤸' => '𞤖', + '𞤹' => '𞤗', + '𞤺' => '𞤘', + '𞤻' => '𞤙', + '𞤼' => '𞤚', + '𞤽' => '𞤛', + '𞤾' => '𞤜', + '𞤿' => '𞤝', + '𞥀' => '𞤞', + '𞥁' => '𞤟', + '𞥂' => '𞤠', + '𞥃' => '𞤡', + 'ß' => 'SS', + 'ff' => 'FF', + 'fi' => 'FI', + 'fl' => 'FL', + 'ffi' => 'FFI', + 'ffl' => 'FFL', + 'ſt' => 'ST', + 'st' => 'ST', + 'և' => 'ԵՒ', + 'ﬓ' => 'ՄՆ', + 'ﬔ' => 'ՄԵ', + 'ﬕ' => 'ՄԻ', + 'ﬖ' => 'ՎՆ', + 'ﬗ' => 'ՄԽ', + 'ʼn' => 'ʼN', + 'ΐ' => 'Ϊ́', + 'ΰ' => 'Ϋ́', + 'ǰ' => 'J̌', + 'ẖ' => 'H̱', + 'ẗ' => 'T̈', + 'ẘ' => 'W̊', + 'ẙ' => 'Y̊', + 'ẚ' => 'Aʾ', + 'ὐ' => 'Υ̓', + 'ὒ' => 'Υ̓̀', + 'ὔ' => 'Υ̓́', + 'ὖ' => 'Υ̓͂', + 'ᾶ' => 'Α͂', + 'ῆ' => 'Η͂', + 'ῒ' => 'Ϊ̀', + 'ΐ' => 'Ϊ́', + 'ῖ' => 'Ι͂', + 'ῗ' => 'Ϊ͂', + 'ῢ' => 'Ϋ̀', + 'ΰ' => 'Ϋ́', + 'ῤ' => 'Ρ̓', + 'ῦ' => 'Υ͂', + 'ῧ' => 'Ϋ͂', + 'ῶ' => 'Ω͂', + 'ᾈ' => 'ἈΙ', + 'ᾉ' => 'ἉΙ', + 'ᾊ' => 'ἊΙ', + 'ᾋ' => 'ἋΙ', + 'ᾌ' => 'ἌΙ', + 'ᾍ' => 'ἍΙ', + 'ᾎ' => 'ἎΙ', + 'ᾏ' => 'ἏΙ', + 'ᾘ' => 'ἨΙ', + 'ᾙ' => 'ἩΙ', + 'ᾚ' => 'ἪΙ', + 'ᾛ' => 'ἫΙ', + 'ᾜ' => 'ἬΙ', + 'ᾝ' => 'ἭΙ', + 'ᾞ' => 'ἮΙ', + 'ᾟ' => 'ἯΙ', + 'ᾨ' => 'ὨΙ', + 'ᾩ' => 'ὩΙ', + 'ᾪ' => 'ὪΙ', + 'ᾫ' => 'ὫΙ', + 'ᾬ' => 'ὬΙ', + 'ᾭ' => 'ὭΙ', + 'ᾮ' => 'ὮΙ', + 'ᾯ' => 'ὯΙ', + 'ᾼ' => 'ΑΙ', + 'ῌ' => 'ΗΙ', + 'ῼ' => 'ΩΙ', + 'ᾲ' => 'ᾺΙ', + 'ᾴ' => 'ΆΙ', + 'ῂ' => 'ῊΙ', + 'ῄ' => 'ΉΙ', + 'ῲ' => 'ῺΙ', + 'ῴ' => 'ΏΙ', + 'ᾷ' => 'Α͂Ι', + 'ῇ' => 'Η͂Ι', + 'ῷ' => 'Ω͂Ι', +); diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php new file mode 100644 index 00000000..ff51ae07 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language($language = null) { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_get_info')) { + function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } +} + +if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } +} + +if (!function_exists('mb_ucfirst')) { + function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } +} + +if (!function_exists('mb_lcfirst')) { + function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } +} + +if (!function_exists('mb_trim')) { + function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } +} + +if (!function_exists('mb_ltrim')) { + function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } +} + +if (!function_exists('mb_rtrim')) { + function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } +} + + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/vendor/symfony/polyfill-mbstring/bootstrap80.php b/vendor/symfony/polyfill-mbstring/bootstrap80.php new file mode 100644 index 00000000..5be7d201 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/bootstrap80.php @@ -0,0 +1,167 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_get_info')) { + function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } +} + +if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } +} + +if (!function_exists('mb_ucfirst')) { + function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } +} + +if (!function_exists('mb_lcfirst')) { + function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } +} + +if (!function_exists('mb_trim')) { + function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } +} + +if (!function_exists('mb_ltrim')) { + function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } +} + +if (!function_exists('mb_rtrim')) { + function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } +} + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json new file mode 100644 index 00000000..4ed241a3 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/composer.json @@ -0,0 +1,38 @@ +{ + "name": "symfony/polyfill-mbstring", + "type": "library", + "description": "Symfony polyfill for the Mbstring extension", + "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/polyfill-php80/LICENSE b/vendor/symfony/polyfill-php80/LICENSE new file mode 100644 index 00000000..0ed3a246 --- /dev/null +++ b/vendor/symfony/polyfill-php80/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-present Fabien Potencier + +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. diff --git a/vendor/symfony/polyfill-php80/Php80.php b/vendor/symfony/polyfill-php80/Php80.php new file mode 100644 index 00000000..362dd1a9 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Php80.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Ion Bazan + * @author Nico Oelgart + * @author Nicolas Grekas + * + * @internal + */ +final class Php80 +{ + public static function fdiv(float $dividend, float $divisor): float + { + return @($dividend / $divisor); + } + + public static function get_debug_type($value): string + { + switch (true) { + case null === $value: return 'null'; + case \is_bool($value): return 'bool'; + case \is_string($value): return 'string'; + case \is_array($value): return 'array'; + case \is_int($value): return 'int'; + case \is_float($value): return 'float'; + case \is_object($value): break; + case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; + default: + if (null === $type = @get_resource_type($value)) { + return 'unknown'; + } + + if ('Unknown' === $type) { + $type = 'closed'; + } + + return "resource ($type)"; + } + + $class = \get_class($value); + + if (false === strpos($class, '@')) { + return $class; + } + + return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; + } + + public static function get_resource_id($res): int + { + if (!\is_resource($res) && null === @get_resource_type($res)) { + throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + } + + return (int) $res; + } + + public static function preg_last_error_msg(): string + { + switch (preg_last_error()) { + case \PREG_INTERNAL_ERROR: + return 'Internal error'; + case \PREG_BAD_UTF8_ERROR: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + case \PREG_BAD_UTF8_OFFSET_ERROR: + return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; + case \PREG_BACKTRACK_LIMIT_ERROR: + return 'Backtrack limit exhausted'; + case \PREG_RECURSION_LIMIT_ERROR: + return 'Recursion limit exhausted'; + case \PREG_JIT_STACKLIMIT_ERROR: + return 'JIT stack limit exhausted'; + case \PREG_NO_ERROR: + return 'No error'; + default: + return 'Unknown error'; + } + } + + public static function str_contains(string $haystack, string $needle): bool + { + return '' === $needle || false !== strpos($haystack, $needle); + } + + public static function str_starts_with(string $haystack, string $needle): bool + { + return 0 === strncmp($haystack, $needle, \strlen($needle)); + } + + public static function str_ends_with(string $haystack, string $needle): bool + { + if ('' === $needle || $needle === $haystack) { + return true; + } + + if ('' === $haystack) { + return false; + } + + $needleLength = \strlen($needle); + + return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); + } +} diff --git a/vendor/symfony/polyfill-php80/PhpToken.php b/vendor/symfony/polyfill-php80/PhpToken.php new file mode 100644 index 00000000..fe6e6910 --- /dev/null +++ b/vendor/symfony/polyfill-php80/PhpToken.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Fedonyuk Anton + * + * @internal + */ +class PhpToken implements \Stringable +{ + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $text; + + /** + * @var int + */ + public $line; + + /** + * @var int + */ + public $pos; + + public function __construct(int $id, string $text, int $line = -1, int $position = -1) + { + $this->id = $id; + $this->text = $text; + $this->line = $line; + $this->pos = $position; + } + + public function getTokenName(): ?string + { + if ('UNKNOWN' === $name = token_name($this->id)) { + $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; + } + + return $name; + } + + /** + * @param int|string|array $kind + */ + public function is($kind): bool + { + foreach ((array) $kind as $value) { + if (\in_array($value, [$this->id, $this->text], true)) { + return true; + } + } + + return false; + } + + public function isIgnorable(): bool + { + return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); + } + + public function __toString(): string + { + return (string) $this->text; + } + + /** + * @return static[] + */ + public static function tokenize(string $code, int $flags = 0): array + { + $line = 1; + $position = 0; + $tokens = token_get_all($code, $flags); + foreach ($tokens as $index => $token) { + if (\is_string($token)) { + $id = \ord($token); + $text = $token; + } else { + [$id, $text, $line] = $token; + } + $tokens[$index] = new static($id, $text, $line, $position); + $position += \strlen($text); + } + + return $tokens; + } +} diff --git a/vendor/symfony/polyfill-php80/README.md b/vendor/symfony/polyfill-php80/README.md new file mode 100644 index 00000000..3816c559 --- /dev/null +++ b/vendor/symfony/polyfill-php80/README.md @@ -0,0 +1,25 @@ +Symfony Polyfill / Php80 +======================== + +This component provides features added to PHP 8.0 core: + +- [`Stringable`](https://php.net/stringable) interface +- [`fdiv`](https://php.net/fdiv) +- [`ValueError`](https://php.net/valueerror) class +- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class +- `FILTER_VALIDATE_BOOL` constant +- [`get_debug_type`](https://php.net/get_debug_type) +- [`PhpToken`](https://php.net/phptoken) class +- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) +- [`str_contains`](https://php.net/str_contains) +- [`str_starts_with`](https://php.net/str_starts_with) +- [`str_ends_with`](https://php.net/str_ends_with) +- [`get_resource_id`](https://php.net/get_resource_id) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php new file mode 100644 index 00000000..2b955423 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#[Attribute(Attribute::TARGET_CLASS)] +final class Attribute +{ + public const TARGET_CLASS = 1; + public const TARGET_FUNCTION = 2; + public const TARGET_METHOD = 4; + public const TARGET_PROPERTY = 8; + public const TARGET_CLASS_CONSTANT = 16; + public const TARGET_PARAMETER = 32; + public const TARGET_ALL = 63; + public const IS_REPEATABLE = 64; + + /** @var int */ + public $flags; + + public function __construct(int $flags = self::TARGET_ALL) + { + $this->flags = $flags; + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php new file mode 100644 index 00000000..bd1212f6 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { + class PhpToken extends Symfony\Polyfill\Php80\PhpToken + { + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php new file mode 100644 index 00000000..7c62d750 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + interface Stringable + { + /** + * @return string + */ + public function __toString(); + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php new file mode 100644 index 00000000..01c6c6c8 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class UnhandledMatchError extends Error + { + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php new file mode 100644 index 00000000..783dbc28 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class ValueError extends Error + { + } +} diff --git a/vendor/symfony/polyfill-php80/bootstrap.php b/vendor/symfony/polyfill-php80/bootstrap.php new file mode 100644 index 00000000..e5f7dbc1 --- /dev/null +++ b/vendor/symfony/polyfill-php80/bootstrap.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php80 as p; + +if (\PHP_VERSION_ID >= 80000) { + return; +} + +if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { + define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); +} + +if (!function_exists('fdiv')) { + function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } +} +if (!function_exists('preg_last_error_msg')) { + function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } +} +if (!function_exists('str_contains')) { + function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_starts_with')) { + function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_ends_with')) { + function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('get_debug_type')) { + function get_debug_type($value): string { return p\Php80::get_debug_type($value); } +} +if (!function_exists('get_resource_id')) { + function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } +} diff --git a/vendor/symfony/polyfill-php80/composer.json b/vendor/symfony/polyfill-php80/composer.json new file mode 100644 index 00000000..a503b039 --- /dev/null +++ b/vendor/symfony/polyfill-php80/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/polyfill-php80", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/var-dumper/CHANGELOG.md b/vendor/symfony/var-dumper/CHANGELOG.md new file mode 100644 index 00000000..f58ed317 --- /dev/null +++ b/vendor/symfony/var-dumper/CHANGELOG.md @@ -0,0 +1,72 @@ +CHANGELOG +========= + +5.4 +--- + + * Add ability to style integer and double values independently + * Add casters for Symfony's UUIDs and ULIDs + * Add support for `Fiber` + +5.2.0 +----- + + * added support for PHPUnit `--colors` option + * added `VAR_DUMPER_FORMAT=server` env var value support + * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set + +5.1.0 +----- + + * added `RdKafka` support + +4.4.0 +----- + + * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()` + to configure casters & flags to use in tests + * added `ImagineCaster` and infrastructure to dump images + * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data + * added `UuidCaster` + * made all casters final + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added `DsCaster` to support dumping the contents of data structures from the Ds extension + +4.2.0 +----- + + * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli` + +4.1.0 +----- + + * added a `ServerDumper` to send serialized Data clones to a server + * added a `ServerDumpCommand` and `DumpServer` to run a server collecting + and displaying dumps on a single place with multiple formats support + * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support + +4.0.0 +----- + + * support for passing `\ReflectionClass` instances to the `Caster::castObject()` + method has been dropped, pass class names as strings instead + * the `Data::getRawData()` method has been removed + * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0` + argument and moves `$message = ''` argument at 4th position. + * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0` + argument and moves `$message = ''` argument at 4th position. + +3.4.0 +----- + + * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth + * deprecated `MongoCaster` + +2.7.0 +----- + + * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead. diff --git a/vendor/symfony/var-dumper/Caster/AmqpCaster.php b/vendor/symfony/var-dumper/Caster/AmqpCaster.php new file mode 100644 index 00000000..dc3b6219 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/AmqpCaster.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Amqp related classes to array representation. + * + * @author Grégoire Pineau + * + * @final + */ +class AmqpCaster +{ + private const FLAGS = [ + \AMQP_DURABLE => 'AMQP_DURABLE', + \AMQP_PASSIVE => 'AMQP_PASSIVE', + \AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', + \AMQP_AUTODELETE => 'AMQP_AUTODELETE', + \AMQP_INTERNAL => 'AMQP_INTERNAL', + \AMQP_NOLOCAL => 'AMQP_NOLOCAL', + \AMQP_AUTOACK => 'AMQP_AUTOACK', + \AMQP_IFEMPTY => 'AMQP_IFEMPTY', + \AMQP_IFUNUSED => 'AMQP_IFUNUSED', + \AMQP_MANDATORY => 'AMQP_MANDATORY', + \AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', + \AMQP_MULTIPLE => 'AMQP_MULTIPLE', + \AMQP_NOWAIT => 'AMQP_NOWAIT', + \AMQP_REQUEUE => 'AMQP_REQUEUE', + ]; + + private const EXCHANGE_TYPES = [ + \AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', + \AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', + \AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', + \AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS', + ]; + + public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPConnection\x00login"])) { + return $a; + } + + // BC layer in the amqp lib + if (method_exists($c, 'getReadTimeout')) { + $timeout = $c->getReadTimeout(); + } else { + $timeout = $c->getTimeout(); + } + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + $prefix.'login' => $c->getLogin(), + $prefix.'password' => $c->getPassword(), + $prefix.'host' => $c->getHost(), + $prefix.'vhost' => $c->getVhost(), + $prefix.'port' => $c->getPort(), + $prefix.'read_timeout' => $timeout, + ]; + + return $a; + } + + public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + $prefix.'channel_id' => $c->getChannelId(), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPChannel\x00connection"])) { + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'prefetch_size' => $c->getPrefetchSize(), + $prefix.'prefetch_count' => $c->getPrefetchCount(), + ]; + + return $a; + } + + public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'flags' => self::extractFlags($c->getFlags()), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPQueue\x00name"])) { + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'arguments' => $c->getArguments(), + ]; + + return $a; + } + + public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'flags' => self::extractFlags($c->getFlags()), + ]; + + $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType(); + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPExchange\x00name"])) { + $a["\x00AMQPExchange\x00type"] = $type; + + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'type' => $type, + $prefix.'arguments' => $c->getArguments(), + ]; + + return $a; + } + + public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()); + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPEnvelope\x00body"])) { + $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode; + + return $a; + } + + if (!($filter & Caster::EXCLUDE_VERBOSE)) { + $a += [$prefix.'body' => $c->getBody()]; + } + + $a += [ + $prefix.'delivery_tag' => $c->getDeliveryTag(), + $prefix.'is_redelivery' => $c->isRedelivery(), + $prefix.'exchange_name' => $c->getExchangeName(), + $prefix.'routing_key' => $c->getRoutingKey(), + $prefix.'content_type' => $c->getContentType(), + $prefix.'content_encoding' => $c->getContentEncoding(), + $prefix.'headers' => $c->getHeaders(), + $prefix.'delivery_mode' => $deliveryMode, + $prefix.'priority' => $c->getPriority(), + $prefix.'correlation_id' => $c->getCorrelationId(), + $prefix.'reply_to' => $c->getReplyTo(), + $prefix.'expiration' => $c->getExpiration(), + $prefix.'message_id' => $c->getMessageId(), + $prefix.'timestamp' => $c->getTimeStamp(), + $prefix.'type' => $c->getType(), + $prefix.'user_id' => $c->getUserId(), + $prefix.'app_id' => $c->getAppId(), + ]; + + return $a; + } + + private static function extractFlags(int $flags): ConstStub + { + $flagsArray = []; + + foreach (self::FLAGS as $value => $name) { + if ($flags & $value) { + $flagsArray[] = $name; + } + } + + if (!$flagsArray) { + $flagsArray = ['AMQP_NOPARAM']; + } + + return new ConstStub(implode('|', $flagsArray), $flags); + } +} diff --git a/vendor/symfony/var-dumper/Caster/ArgsStub.php b/vendor/symfony/var-dumper/Caster/ArgsStub.php new file mode 100644 index 00000000..b3f7bbee --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ArgsStub.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a list of function arguments. + * + * @author Nicolas Grekas + */ +class ArgsStub extends EnumStub +{ + private static $parameters = []; + + public function __construct(array $args, string $function, ?string $class) + { + [$variadic, $params] = self::getParameters($function, $class); + + $values = []; + foreach ($args as $k => $v) { + $values[$k] = !\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; + } + if (null === $params) { + parent::__construct($values, false); + + return; + } + if (\count($values) < \count($params)) { + $params = \array_slice($params, 0, \count($values)); + } elseif (\count($values) > \count($params)) { + $values[] = new EnumStub(array_splice($values, \count($params)), false); + $params[] = $variadic; + } + if (['...'] === $params) { + $this->dumpKeys = false; + $this->value = $values[0]->value; + } else { + $this->value = array_combine($params, $values); + } + } + + private static function getParameters(string $function, ?string $class): array + { + if (isset(self::$parameters[$k = $class.'::'.$function])) { + return self::$parameters[$k]; + } + + try { + $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function); + } catch (\ReflectionException $e) { + return [null, null]; + } + + $variadic = '...'; + $params = []; + foreach ($r->getParameters() as $v) { + $k = '$'.$v->name; + if ($v->isPassedByReference()) { + $k = '&'.$k; + } + if ($v->isVariadic()) { + $variadic .= $k; + } else { + $params[] = $k; + } + } + + return self::$parameters[$k] = [$variadic, $params]; + } +} diff --git a/vendor/symfony/var-dumper/Caster/Caster.php b/vendor/symfony/var-dumper/Caster/Caster.php new file mode 100644 index 00000000..09238093 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/Caster.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Helper for filtering out properties in casters. + * + * @author Nicolas Grekas + * + * @final + */ +class Caster +{ + public const EXCLUDE_VERBOSE = 1; + public const EXCLUDE_VIRTUAL = 2; + public const EXCLUDE_DYNAMIC = 4; + public const EXCLUDE_PUBLIC = 8; + public const EXCLUDE_PROTECTED = 16; + public const EXCLUDE_PRIVATE = 32; + public const EXCLUDE_NULL = 64; + public const EXCLUDE_EMPTY = 128; + public const EXCLUDE_NOT_IMPORTANT = 256; + public const EXCLUDE_STRICT = 512; + + public const PREFIX_VIRTUAL = "\0~\0"; + public const PREFIX_DYNAMIC = "\0+\0"; + public const PREFIX_PROTECTED = "\0*\0"; + + /** + * Casts objects to arrays and adds the dynamic property prefix. + * + * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not + */ + public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, ?string $debugClass = null): array + { + if ($hasDebugInfo) { + try { + $debugInfo = $obj->__debugInfo(); + } catch (\Throwable $e) { + // ignore failing __debugInfo() + $hasDebugInfo = false; + } + } + + $a = $obj instanceof \Closure ? [] : (array) $obj; + + if ($obj instanceof \__PHP_Incomplete_Class) { + return $a; + } + + if ($a) { + static $publicProperties = []; + $debugClass = $debugClass ?? get_debug_type($obj); + + $i = 0; + $prefixedKeys = []; + foreach ($a as $k => $v) { + if ("\0" !== ($k[0] ?? '')) { + if (!isset($publicProperties[$class])) { + foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { + $publicProperties[$class][$prop->name] = true; + } + } + if (!isset($publicProperties[$class][$k])) { + $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + } + } elseif ($debugClass !== $class && 1 === strpos($k, $class)) { + $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0"); + } + ++$i; + } + if ($prefixedKeys) { + $keys = array_keys($a); + foreach ($prefixedKeys as $i => $k) { + $keys[$i] = $k; + } + $a = array_combine($keys, $a); + } + } + + if ($hasDebugInfo && \is_array($debugInfo)) { + foreach ($debugInfo as $k => $v) { + if (!isset($k[0]) || "\0" !== $k[0]) { + if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) { + continue; + } + $k = self::PREFIX_VIRTUAL.$k; + } + + unset($a[$k]); + $a[$k] = $v; + } + } + + return $a; + } + + /** + * Filters out the specified properties. + * + * By default, a single match in the $filter bit field filters properties out, following an "or" logic. + * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed. + * + * @param array $a The array containing the properties to filter + * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out + * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set + * @param int|null &$count Set to the number of removed properties + */ + public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array + { + $count = 0; + + foreach ($a as $k => $v) { + $type = self::EXCLUDE_STRICT & $filter; + + if (null === $v) { + $type |= self::EXCLUDE_NULL & $filter; + $type |= self::EXCLUDE_EMPTY & $filter; + } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) { + $type |= self::EXCLUDE_EMPTY & $filter; + } + if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) { + $type |= self::EXCLUDE_NOT_IMPORTANT; + } + if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) { + $type |= self::EXCLUDE_VERBOSE; + } + + if (!isset($k[1]) || "\0" !== $k[0]) { + $type |= self::EXCLUDE_PUBLIC & $filter; + } elseif ('~' === $k[1]) { + $type |= self::EXCLUDE_VIRTUAL & $filter; + } elseif ('+' === $k[1]) { + $type |= self::EXCLUDE_DYNAMIC & $filter; + } elseif ('*' === $k[1]) { + $type |= self::EXCLUDE_PROTECTED & $filter; + } else { + $type |= self::EXCLUDE_PRIVATE & $filter; + } + + if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { + unset($a[$k]); + ++$count; + } + } + + return $a; + } + + public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array + { + if (isset($a['__PHP_Incomplete_Class_Name'])) { + $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')'; + unset($a['__PHP_Incomplete_Class_Name']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ClassStub.php b/vendor/symfony/var-dumper/Caster/ClassStub.php new file mode 100644 index 00000000..27c24c9a --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ClassStub.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a PHP class identifier. + * + * @author Nicolas Grekas + */ +class ClassStub extends ConstStub +{ + /** + * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name + * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier + */ + public function __construct(string $identifier, $callable = null) + { + $this->value = $identifier; + + try { + if (null !== $callable) { + if ($callable instanceof \Closure) { + $r = new \ReflectionFunction($callable); + } elseif (\is_object($callable)) { + $r = [$callable, '__invoke']; + } elseif (\is_array($callable)) { + $r = $callable; + } elseif (false !== $i = strpos($callable, '::')) { + $r = [substr($callable, 0, $i), substr($callable, 2 + $i)]; + } else { + $r = new \ReflectionFunction($callable); + } + } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) { + $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)]; + } else { + $r = new \ReflectionClass($identifier); + } + + if (\is_array($r)) { + try { + $r = new \ReflectionMethod($r[0], $r[1]); + } catch (\ReflectionException $e) { + $r = new \ReflectionClass($r[0]); + } + } + + if (str_contains($identifier, "@anonymous\0")) { + $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; + }, $identifier); + } + + if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) { + $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE); + $s = ReflectionCaster::getSignature($s); + + if (str_ends_with($identifier, '()')) { + $this->value = substr_replace($identifier, $s, -2); + } else { + $this->value .= $s; + } + } + } catch (\ReflectionException $e) { + return; + } finally { + if (0 < $i = strrpos($this->value, '\\')) { + $this->attr['ellipsis'] = \strlen($this->value) - $i; + $this->attr['ellipsis-type'] = 'class'; + $this->attr['ellipsis-tail'] = 1; + } + } + + if ($f = $r->getFileName()) { + $this->attr['file'] = $f; + $this->attr['line'] = $r->getStartLine(); + } + } + + public static function wrapCallable($callable) + { + if (\is_object($callable) || !\is_callable($callable)) { + return $callable; + } + + if (!\is_array($callable)) { + $callable = new static($callable, $callable); + } elseif (\is_string($callable[0])) { + $callable[0] = new static($callable[0], $callable); + } else { + $callable[1] = new static($callable[1], $callable); + } + + return $callable; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ConstStub.php b/vendor/symfony/var-dumper/Caster/ConstStub.php new file mode 100644 index 00000000..8b017974 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ConstStub.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a PHP constant and its value. + * + * @author Nicolas Grekas + */ +class ConstStub extends Stub +{ + public function __construct(string $name, $value = null) + { + $this->class = $name; + $this->value = 1 < \func_num_args() ? $value : $name; + } + + /** + * @return string + */ + public function __toString() + { + return (string) $this->value; + } +} diff --git a/vendor/symfony/var-dumper/Caster/CutArrayStub.php b/vendor/symfony/var-dumper/Caster/CutArrayStub.php new file mode 100644 index 00000000..0e4fb363 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/CutArrayStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a cut array. + * + * @author Nicolas Grekas + */ +class CutArrayStub extends CutStub +{ + public $preservedSubset; + + public function __construct(array $value, array $preservedKeys) + { + parent::__construct($value); + + $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys)); + $this->cut -= \count($this->preservedSubset); + } +} diff --git a/vendor/symfony/var-dumper/Caster/CutStub.php b/vendor/symfony/var-dumper/Caster/CutStub.php new file mode 100644 index 00000000..464c6dbd --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/CutStub.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents the main properties of a PHP variable, pre-casted by a caster. + * + * @author Nicolas Grekas + */ +class CutStub extends Stub +{ + public function __construct($value) + { + $this->value = $value; + + switch (\gettype($value)) { + case 'object': + $this->type = self::TYPE_OBJECT; + $this->class = \get_class($value); + + if ($value instanceof \Closure) { + ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE); + } + + $this->cut = -1; + break; + + case 'array': + $this->type = self::TYPE_ARRAY; + $this->class = self::ARRAY_ASSOC; + $this->cut = $this->value = \count($value); + break; + + case 'resource': + case 'unknown type': + case 'resource (closed)': + $this->type = self::TYPE_RESOURCE; + $this->handle = (int) $value; + if ('Unknown' === $this->class = @get_resource_type($value)) { + $this->class = 'Closed'; + } + $this->cut = -1; + break; + + case 'string': + $this->type = self::TYPE_STRING; + $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY; + $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8'); + $this->value = ''; + break; + } + } +} diff --git a/vendor/symfony/var-dumper/Caster/DOMCaster.php b/vendor/symfony/var-dumper/Caster/DOMCaster.php new file mode 100644 index 00000000..5d933cf7 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DOMCaster.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts DOM related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class DOMCaster +{ + private const ERROR_CODES = [ + 0 => 'DOM_PHP_ERR', + \DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', + \DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', + \DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', + \DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', + \DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', + \DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', + \DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', + \DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', + \DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', + \DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', + \DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', + \DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', + \DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', + \DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', + \DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', + \DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR', + ]; + + private const NODE_TYPES = [ + \XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', + \XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', + \XML_TEXT_NODE => 'XML_TEXT_NODE', + \XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', + \XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', + \XML_ENTITY_NODE => 'XML_ENTITY_NODE', + \XML_PI_NODE => 'XML_PI_NODE', + \XML_COMMENT_NODE => 'XML_COMMENT_NODE', + \XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', + \XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', + \XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', + \XML_NOTATION_NODE => 'XML_NOTATION_NODE', + \XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', + \XML_DTD_NODE => 'XML_DTD_NODE', + \XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', + \XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', + \XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', + \XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE', + ]; + + public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested) + { + $k = Caster::PREFIX_PROTECTED.'code'; + if (isset($a[$k], self::ERROR_CODES[$a[$k]])) { + $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]); + } + + return $a; + } + + public static function castLength($dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'length' => $dom->length, + ]; + + return $a; + } + + public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'Core' => '1.0', + Caster::PREFIX_VIRTUAL.'XML' => '2.0', + ]; + + return $a; + } + + public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'nodeName' => $dom->nodeName, + 'nodeValue' => new CutStub($dom->nodeValue), + 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), + 'parentNode' => new CutStub($dom->parentNode), + 'childNodes' => $dom->childNodes, + 'firstChild' => new CutStub($dom->firstChild), + 'lastChild' => new CutStub($dom->lastChild), + 'previousSibling' => new CutStub($dom->previousSibling), + 'nextSibling' => new CutStub($dom->nextSibling), + 'attributes' => $dom->attributes, + 'ownerDocument' => new CutStub($dom->ownerDocument), + 'namespaceURI' => $dom->namespaceURI, + 'prefix' => $dom->prefix, + 'localName' => $dom->localName, + 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, + 'textContent' => new CutStub($dom->textContent), + ]; + + return $a; + } + + public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'nodeName' => $dom->nodeName, + 'nodeValue' => new CutStub($dom->nodeValue), + 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), + 'prefix' => $dom->prefix, + 'localName' => $dom->localName, + 'namespaceURI' => $dom->namespaceURI, + 'ownerDocument' => new CutStub($dom->ownerDocument), + 'parentNode' => new CutStub($dom->parentNode), + ]; + + return $a; + } + + public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + 'doctype' => $dom->doctype, + 'implementation' => $dom->implementation, + 'documentElement' => new CutStub($dom->documentElement), + 'encoding' => $dom->encoding, + 'xmlEncoding' => $dom->xmlEncoding, + 'xmlStandalone' => $dom->xmlStandalone, + 'xmlVersion' => $dom->xmlVersion, + 'strictErrorChecking' => $dom->strictErrorChecking, + 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, + 'formatOutput' => $dom->formatOutput, + 'validateOnParse' => $dom->validateOnParse, + 'resolveExternals' => $dom->resolveExternals, + 'preserveWhiteSpace' => $dom->preserveWhiteSpace, + 'recover' => $dom->recover, + 'substituteEntities' => $dom->substituteEntities, + ]; + + if (!($filter & Caster::EXCLUDE_VERBOSE)) { + $formatOutput = $dom->formatOutput; + $dom->formatOutput = true; + $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()]; + $dom->formatOutput = $formatOutput; + } + + return $a; + } + + public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'data' => $dom->data, + 'length' => $dom->length, + ]; + + return $a; + } + + public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'name' => $dom->name, + 'specified' => $dom->specified, + 'value' => $dom->value, + 'ownerElement' => $dom->ownerElement, + 'schemaTypeInfo' => $dom->schemaTypeInfo, + ]; + + return $a; + } + + public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'tagName' => $dom->tagName, + 'schemaTypeInfo' => $dom->schemaTypeInfo, + ]; + + return $a; + } + + public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'wholeText' => $dom->wholeText, + ]; + + return $a; + } + + public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'typeName' => $dom->typeName, + 'typeNamespace' => $dom->typeNamespace, + ]; + + return $a; + } + + public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'severity' => $dom->severity, + 'message' => $dom->message, + 'type' => $dom->type, + 'relatedException' => $dom->relatedException, + 'related_data' => $dom->related_data, + 'location' => $dom->location, + ]; + + return $a; + } + + public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'lineNumber' => $dom->lineNumber, + 'columnNumber' => $dom->columnNumber, + 'offset' => $dom->offset, + 'relatedNode' => $dom->relatedNode, + 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, + ]; + + return $a; + } + + public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'name' => $dom->name, + 'entities' => $dom->entities, + 'notations' => $dom->notations, + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + 'internalSubset' => $dom->internalSubset, + ]; + + return $a; + } + + public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + ]; + + return $a; + } + + public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + 'notationName' => $dom->notationName, + ]; + + return $a; + } + + public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'target' => $dom->target, + 'data' => $dom->data, + ]; + + return $a; + } + + public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'document' => $dom->document, + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DateCaster.php b/vendor/symfony/var-dumper/Caster/DateCaster.php new file mode 100644 index 00000000..d07bac58 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DateCaster.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts DateTimeInterface related classes to array representation. + * + * @author Dany Maillard + * + * @final + */ +class DateCaster +{ + private const PERIOD_LIMIT = 3; + + public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter) + { + $prefix = Caster::PREFIX_VIRTUAL; + $location = $d->getTimezone() ? $d->getTimezone()->getLocation() : null; + $fromNow = (new \DateTime())->diff($d); + + $title = $d->format('l, F j, Y') + ."\n".self::formatInterval($fromNow).' from now' + .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') + ; + + unset( + $a[Caster::PREFIX_DYNAMIC.'date'], + $a[Caster::PREFIX_DYNAMIC.'timezone'], + $a[Caster::PREFIX_DYNAMIC.'timezone_type'] + ); + $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); + + $stub->class .= $d->format(' @U'); + + return $a; + } + + public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter) + { + $now = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); + $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); + $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; + + $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; + } + + private static function formatInterval(\DateInterval $i): string + { + $format = '%R '; + + if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { + $d = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); + $i = $d->diff($d->add($i)); // recalculate carry over points + $format .= 0 < $i->days ? '%ad ' : ''; + } else { + $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); + } + + $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; + $format = '%R ' === $format ? '0s' : $format; + + return $i->format(rtrim($format)); + } + + public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter) + { + $location = $timeZone->getLocation(); + $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P'); + $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; + + $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; + } + + public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter) + { + $dates = []; + foreach (clone $p as $i => $d) { + if (self::PERIOD_LIMIT === $i) { + $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC')); + $dates[] = sprintf('%s more', ($end = $p->getEndDate()) + ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) + : $p->recurrences - $i + ); + break; + } + $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); + } + + $period = sprintf( + 'every %s, from %s%s %s', + self::formatInterval($p->getDateInterval()), + $p->include_start_date ? '[' : ']', + self::formatDateTime($p->getStartDate()), + ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end).(\PHP_VERSION_ID >= 80200 && $p->include_end_date ? ']' : '[') : 'recurring '.$p->recurrences.' time/s' + ); + + $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; + } + + private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string + { + return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); + } + + private static function formatSeconds(string $s, string $us): string + { + return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); + } +} diff --git a/vendor/symfony/var-dumper/Caster/DoctrineCaster.php b/vendor/symfony/var-dumper/Caster/DoctrineCaster.php new file mode 100644 index 00000000..129b2cb4 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DoctrineCaster.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Doctrine\Common\Proxy\Proxy as CommonProxy; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Proxy\Proxy as OrmProxy; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Doctrine related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class DoctrineCaster +{ + public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested) + { + foreach (['__cloner__', '__initializer__'] as $k) { + if (\array_key_exists($k, $a)) { + unset($a[$k]); + ++$stub->cut; + } + } + + return $a; + } + + public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested) + { + foreach (['_entityPersister', '_identifier'] as $k) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { + unset($a[$k]); + ++$stub->cut; + } + } + + return $a; + } + + public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested) + { + foreach (['snapshot', 'association', 'typeClass'] as $k) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { + $a[$k] = new CutStub($a[$k]); + } + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DsCaster.php b/vendor/symfony/var-dumper/Caster/DsCaster.php new file mode 100644 index 00000000..b34b6700 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DsCaster.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Ds\Collection; +use Ds\Map; +use Ds\Pair; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Ds extension classes to array representation. + * + * @author Jáchym Toušek + * + * @final + */ +class DsCaster +{ + public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array + { + $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count(); + $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity(); + + if (!$c instanceof Map) { + $a += $c->toArray(); + } + + return $a; + } + + public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array + { + foreach ($c as $k => $v) { + $a[] = new DsPairStub($k, $v); + } + + return $a; + } + + public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array + { + foreach ($c->toArray() as $k => $v) { + $a[Caster::PREFIX_VIRTUAL.$k] = $v; + } + + return $a; + } + + public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array + { + if ($isNested) { + $stub->class = Pair::class; + $stub->value = null; + $stub->handle = 0; + + $a = $c->value; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DsPairStub.php b/vendor/symfony/var-dumper/Caster/DsPairStub.php new file mode 100644 index 00000000..a1dcc156 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DsPairStub.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + */ +class DsPairStub extends Stub +{ + public function __construct($key, $value) + { + $this->value = [ + Caster::PREFIX_VIRTUAL.'key' => $key, + Caster::PREFIX_VIRTUAL.'value' => $value, + ]; + } +} diff --git a/vendor/symfony/var-dumper/Caster/EnumStub.php b/vendor/symfony/var-dumper/Caster/EnumStub.php new file mode 100644 index 00000000..7a4e98a2 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/EnumStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents an enumeration of values. + * + * @author Nicolas Grekas + */ +class EnumStub extends Stub +{ + public $dumpKeys = true; + + public function __construct(array $values, bool $dumpKeys = true) + { + $this->value = $values; + $this->dumpKeys = $dumpKeys; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php new file mode 100644 index 00000000..299f5125 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php @@ -0,0 +1,388 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; +use Symfony\Component\VarDumper\Cloner\Stub; +use Symfony\Component\VarDumper\Exception\ThrowingCasterException; + +/** + * Casts common Exception classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ExceptionCaster +{ + public static $srcContext = 1; + public static $traceArgs = true; + public static $errorTypes = [ + \E_DEPRECATED => 'E_DEPRECATED', + \E_USER_DEPRECATED => 'E_USER_DEPRECATED', + \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', + \E_ERROR => 'E_ERROR', + \E_WARNING => 'E_WARNING', + \E_PARSE => 'E_PARSE', + \E_NOTICE => 'E_NOTICE', + \E_CORE_ERROR => 'E_CORE_ERROR', + \E_CORE_WARNING => 'E_CORE_WARNING', + \E_COMPILE_ERROR => 'E_COMPILE_ERROR', + \E_COMPILE_WARNING => 'E_COMPILE_WARNING', + \E_USER_ERROR => 'E_USER_ERROR', + \E_USER_WARNING => 'E_USER_WARNING', + \E_USER_NOTICE => 'E_USER_NOTICE', + 2048 => 'E_STRICT', + ]; + + private static $framesCache = []; + + public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); + } + + public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter); + } + + public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested) + { + if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) { + $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); + } + + return $a; + } + + public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested) + { + $trace = Caster::PREFIX_VIRTUAL.'trace'; + $prefix = Caster::PREFIX_PROTECTED; + $xPrefix = "\0Exception\0"; + + if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) { + $b = (array) $a[$xPrefix.'previous']; + $class = get_debug_type($a[$xPrefix.'previous']); + self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']); + $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value)); + } + + unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); + + return $a; + } + + public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested) + { + $sPrefix = "\0".SilencedErrorContext::class."\0"; + + if (!isset($a[$s = $sPrefix.'severity'])) { + return $a; + } + + if (isset(self::$errorTypes[$a[$s]])) { + $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); + } + + $trace = [[ + 'file' => $a[$sPrefix.'file'], + 'line' => $a[$sPrefix.'line'], + ]]; + + if (isset($a[$sPrefix.'trace'])) { + $trace = array_merge($trace, $a[$sPrefix.'trace']); + } + + unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); + + return $a; + } + + public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested) + { + if (!$isNested) { + return $a; + } + $stub->class = ''; + $stub->handle = 0; + $frames = $trace->value; + $prefix = Caster::PREFIX_VIRTUAL; + + $a = []; + $j = \count($frames); + if (0 > $i = $trace->sliceOffset) { + $i = max(0, $j + $i); + } + if (!isset($trace->value[$i])) { + return []; + } + $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; + $frames[] = ['function' => '']; + $collapse = false; + + for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { + $f = $frames[$i]; + $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???'; + + $frame = new FrameStub( + [ + 'object' => $f['object'] ?? null, + 'class' => $f['class'] ?? null, + 'type' => $f['type'] ?? null, + 'function' => $f['function'] ?? null, + ] + $frames[$i - 1], + false, + true + ); + $f = self::castFrameStub($frame, [], $frame, true); + if (isset($f[$prefix.'src'])) { + foreach ($f[$prefix.'src']->value as $label => $frame) { + if (str_starts_with($label, "\0~collapse=0")) { + if ($collapse) { + $label = substr_replace($label, '1', 11, 1); + } else { + $collapse = true; + } + } + $label = substr_replace($label, "title=Stack level $j.&", 2, 0); + } + $f = $frames[$i - 1]; + if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) { + $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null); + } + } elseif ('???' !== $lastCall) { + $label = new ClassStub($lastCall); + if (isset($label->attr['ellipsis'])) { + $label->attr['ellipsis'] += 2; + $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()'; + } else { + $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()'; + } + } else { + $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; + } + $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; + + $lastCall = $call; + } + if (null !== $trace->sliceLength) { + $a = \array_slice($a, 0, $trace->sliceLength, true); + } + + return $a; + } + + public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested) + { + if (!$isNested) { + return $a; + } + $f = $frame->value; + $prefix = Caster::PREFIX_VIRTUAL; + + if (isset($f['file'], $f['line'])) { + $cacheKey = $f; + unset($cacheKey['object'], $cacheKey['args']); + $cacheKey[] = self::$srcContext; + $cacheKey = implode('-', $cacheKey); + + if (isset(self::$framesCache[$cacheKey])) { + $a[$prefix.'src'] = self::$framesCache[$cacheKey]; + } else { + if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) { + $f['file'] = substr($f['file'], 0, -\strlen($match[0])); + $f['line'] = (int) $match[1]; + } + $src = $f['line']; + $srcKey = $f['file']; + $ellipsis = new LinkStub($srcKey, 0); + $srcAttr = 'collapse='.(int) $ellipsis->inVendor; + $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0; + $ellipsis = $ellipsis->attr['ellipsis'] ?? 0; + + if (is_file($f['file']) && 0 <= self::$srcContext) { + if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { + $template = null; + if (isset($f['object'])) { + $template = $f['object']; + } elseif ((new \ReflectionClass($f['class']))->isInstantiable()) { + $template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class'])); + } + if (null !== $template) { + $ellipsis = 0; + $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : ''); + $templateInfo = $template->getDebugInfo(); + if (isset($templateInfo[$f['line']])) { + if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) { + $templatePath = null; + } + if ($templateSrc) { + $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f); + $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']]; + } + } + } + } + if ($srcKey == $f['file']) { + $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f); + $srcKey .= ':'.$f['line']; + if ($ellipsis) { + $ellipsis += 1 + \strlen($f['line']); + } + } + $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']); + } else { + $srcAttr .= '&separator=:'; + } + $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; + self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]); + } + } + + unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']); + if ($frame->inTraceStub) { + unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']); + } + foreach ($a as $k => $v) { + if (!$v) { + unset($a[$k]); + } + } + if ($frame->keepArgs && !empty($f['args'])) { + $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); + } + + return $a; + } + + private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array + { + if (isset($a[$xPrefix.'trace'])) { + $trace = $a[$xPrefix.'trace']; + unset($a[$xPrefix.'trace']); // Ensures the trace is always last + } else { + $trace = []; + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); + } + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); + } + if (empty($a[$xPrefix.'previous'])) { + unset($a[$xPrefix.'previous']); + } + unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); + + if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) { + $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; + }, $a[Caster::PREFIX_PROTECTED.'message']); + } + + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); + } + + return $a; + } + + private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void + { + if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) { + return; + } + array_unshift($trace, [ + 'function' => $class ? 'new '.$class : null, + 'file' => $file, + 'line' => $line, + ]); + } + + private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub + { + $srcLines = explode("\n", $srcLines); + $src = []; + + for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { + $src[] = ($srcLines[$i] ?? '')."\n"; + } + + if ($frame['function'] ?? false) { + $stub = new CutStub(new \stdClass()); + $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function']; + $stub->type = Stub::TYPE_OBJECT; + $stub->attr['cut_hash'] = true; + $stub->attr['file'] = $frame['file']; + $stub->attr['line'] = $frame['line']; + + try { + $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']); + $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE)); + + if ($f = $caller->getFileName()) { + $stub->attr['file'] = $f; + $stub->attr['line'] = $caller->getStartLine(); + } + } catch (\ReflectionException $e) { + // ignore fake class/function + } + + $srcLines = ["\0~separator=\0" => $stub]; + } else { + $stub = null; + $srcLines = []; + } + + $ltrim = 0; + do { + $pad = null; + for ($i = $srcContext << 1; $i >= 0; --$i) { + if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { + if (null === $pad) { + $pad = $c; + } + if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { + break; + } + } + } + ++$ltrim; + } while (0 > $i && null !== $pad); + + --$ltrim; + + foreach ($src as $i => $c) { + if ($ltrim) { + $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t"); + } + $c = substr($c, 0, -1); + if ($i !== $srcContext) { + $c = new ConstStub('default', $c); + } else { + $c = new ConstStub($c, $stub ? 'in '.$stub->class : ''); + if (null !== $file) { + $c->attr['file'] = $file; + $c->attr['line'] = $line; + } + } + $c->attr['lang'] = $lang; + $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; + } + + return new EnumStub($srcLines); + } +} diff --git a/vendor/symfony/var-dumper/Caster/FiberCaster.php b/vendor/symfony/var-dumper/Caster/FiberCaster.php new file mode 100644 index 00000000..c74a9e59 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/FiberCaster.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Fiber related classes to array representation. + * + * @author Grégoire Pineau + */ +final class FiberCaster +{ + public static function castFiber(\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($fiber->isTerminated()) { + $status = 'terminated'; + } elseif ($fiber->isRunning()) { + $status = 'running'; + } elseif ($fiber->isSuspended()) { + $status = 'suspended'; + } elseif ($fiber->isStarted()) { + $status = 'started'; + } else { + $status = 'not started'; + } + + $a[$prefix.'status'] = $status; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/FrameStub.php b/vendor/symfony/var-dumper/Caster/FrameStub.php new file mode 100644 index 00000000..87867552 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/FrameStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace(). + * + * @author Nicolas Grekas + */ +class FrameStub extends EnumStub +{ + public $keepArgs; + public $inTraceStub; + + public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false) + { + $this->value = $frame; + $this->keepArgs = $keepArgs; + $this->inTraceStub = $inTraceStub; + } +} diff --git a/vendor/symfony/var-dumper/Caster/GmpCaster.php b/vendor/symfony/var-dumper/Caster/GmpCaster.php new file mode 100644 index 00000000..b018cc7f --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/GmpCaster.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts GMP objects to array representation. + * + * @author Hamza Amrouche + * @author Nicolas Grekas + * + * @final + */ +class GmpCaster +{ + public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array + { + $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp)); + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ImagineCaster.php b/vendor/symfony/var-dumper/Caster/ImagineCaster.php new file mode 100644 index 00000000..d1289da3 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ImagineCaster.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Imagine\Image\ImageInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Grégoire Pineau + */ +final class ImagineCaster +{ + public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array + { + $imgData = $c->get('png'); + if (\strlen($imgData) > 1 * 1000 * 1000) { + $a += [ + Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()), + ]; + } else { + $a += [ + Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()), + ]; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ImgStub.php b/vendor/symfony/var-dumper/Caster/ImgStub.php new file mode 100644 index 00000000..a16681f7 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ImgStub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * @author Grégoire Pineau + */ +class ImgStub extends ConstStub +{ + public function __construct(string $data, string $contentType, string $size = '') + { + $this->value = ''; + $this->attr['img-data'] = $data; + $this->attr['img-size'] = $size; + $this->attr['content-type'] = $contentType; + } +} diff --git a/vendor/symfony/var-dumper/Caster/IntlCaster.php b/vendor/symfony/var-dumper/Caster/IntlCaster.php new file mode 100644 index 00000000..1ed91d4d --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/IntlCaster.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + * @author Jan Schädlich + * + * @final + */ +class IntlCaster +{ + public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + ]; + + return self::castError($c, $a); + } + + public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + ]; + + if ($filter & Caster::EXCLUDE_VERBOSE) { + $stub->cut += 3; + + return self::castError($c, $a); + } + + $a += [ + Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub( + [ + 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), + 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), + 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), + 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), + 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), + 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), + 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), + 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), + 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), + 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), + 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), + 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), + 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), + 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), + 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), + 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), + 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), + 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), + 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), + 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE), + ] + ), + Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub( + [ + 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), + 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), + 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), + 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), + 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), + 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), + 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), + 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS), + ] + ), + Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub( + [ + 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), + 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), + 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), + 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), + 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), + 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), + 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), + 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), + 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), + 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), + 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), + 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), + 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), + 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), + 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), + 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), + 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), + 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), + ] + ), + ]; + + return self::castError($c, $a); + } + + public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(), + Caster::PREFIX_VIRTUAL.'id' => $c->getID(), + Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(), + ]; + + if ($c->useDaylightTime()) { + $a += [ + Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(), + ]; + } + + return self::castError($c, $a); + } + + public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'type' => $c->getType(), + Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(), + Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), + Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), + Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), + Caster::PREFIX_VIRTUAL.'time' => $c->getTime(), + Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(), + Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(), + Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), + ]; + + return self::castError($c, $a); + } + + public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(), + Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(), + Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(), + Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(), + Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), + Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), + ]; + + return self::castError($c, $a); + } + + private static function castError(object $c, array $a): array + { + if ($errorCode = $c->getErrorCode()) { + $a += [ + Caster::PREFIX_VIRTUAL.'error_code' => $errorCode, + Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(), + ]; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/LinkStub.php b/vendor/symfony/var-dumper/Caster/LinkStub.php new file mode 100644 index 00000000..bd4c796a --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/LinkStub.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a file or a URL. + * + * @author Nicolas Grekas + */ +class LinkStub extends ConstStub +{ + public $inVendor = false; + + private static $vendorRoots; + private static $composerRoots; + + public function __construct(string $label, int $line = 0, ?string $href = null) + { + $this->value = $label; + + if (null === $href) { + $href = $label; + } + if (!\is_string($href)) { + return; + } + if (str_starts_with($href, 'file://')) { + if ($href === $label) { + $label = substr($label, 7); + } + $href = substr($href, 7); + } elseif (str_contains($href, '://')) { + $this->attr['href'] = $href; + + return; + } + if (!is_file($href)) { + return; + } + if ($line) { + $this->attr['line'] = $line; + } + if ($label !== $this->attr['file'] = realpath($href) ?: $href) { + return; + } + if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { + $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1; + $this->attr['ellipsis-type'] = 'path'; + $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); + } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) { + $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2))); + $this->attr['ellipsis-type'] = 'path'; + $this->attr['ellipsis-tail'] = 1; + } + } + + private function getComposerRoot(string $file, bool &$inVendor) + { + if (null === self::$vendorRoots) { + self::$vendorRoots = []; + + foreach (get_declared_classes() as $class) { + if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $v = \dirname($r->getFileName(), 2); + if (is_file($v.'/composer/installed.json')) { + self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR; + } + } + } + } + $inVendor = false; + + if (isset(self::$composerRoots[$dir = \dirname($file)])) { + return self::$composerRoots[$dir]; + } + + foreach (self::$vendorRoots as $root) { + if ($inVendor = str_starts_with($file, $root)) { + return $root; + } + } + + $parent = $dir; + while (!@is_file($parent.'/composer.json')) { + if (!@file_exists($parent)) { + // open_basedir restriction in effect + break; + } + if ($parent === \dirname($parent)) { + return self::$composerRoots[$dir] = false; + } + + $parent = \dirname($parent); + } + + return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR; + } +} diff --git a/vendor/symfony/var-dumper/Caster/MemcachedCaster.php b/vendor/symfony/var-dumper/Caster/MemcachedCaster.php new file mode 100644 index 00000000..cfef19ac --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/MemcachedCaster.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Jan Schädlich + * + * @final + */ +class MemcachedCaster +{ + private static $optionConstants; + private static $defaultOptions; + + public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(), + Caster::PREFIX_VIRTUAL.'options' => new EnumStub( + self::getNonDefaultOptions($c) + ), + ]; + + return $a; + } + + private static function getNonDefaultOptions(\Memcached $c): array + { + self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions(); + self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); + + $nonDefaultOptions = []; + foreach (self::$optionConstants as $constantKey => $value) { + if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) { + $nonDefaultOptions[$constantKey] = $option; + } + } + + return $nonDefaultOptions; + } + + private static function discoverDefaultOptions(): array + { + $defaultMemcached = new \Memcached(); + $defaultMemcached->addServer('127.0.0.1', 11211); + + $defaultOptions = []; + self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); + + foreach (self::$optionConstants as $constantKey => $value) { + $defaultOptions[$constantKey] = $defaultMemcached->getOption($value); + } + + return $defaultOptions; + } + + private static function getOptionConstants(): array + { + $reflectedMemcached = new \ReflectionClass(\Memcached::class); + + $optionConstants = []; + foreach ($reflectedMemcached->getConstants() as $constantKey => $value) { + if (str_starts_with($constantKey, 'OPT_')) { + $optionConstants[$constantKey] = $value; + } + } + + return $optionConstants; + } +} diff --git a/vendor/symfony/var-dumper/Caster/MysqliCaster.php b/vendor/symfony/var-dumper/Caster/MysqliCaster.php new file mode 100644 index 00000000..bfe6f082 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/MysqliCaster.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class MysqliCaster +{ + public static function castMysqliDriver(\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array + { + foreach ($a as $k => $v) { + if (isset($c->$k)) { + $a[$k] = $c->$k; + } + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/PdoCaster.php b/vendor/symfony/var-dumper/Caster/PdoCaster.php new file mode 100644 index 00000000..140473b5 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/PdoCaster.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts PDO related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class PdoCaster +{ + private const PDO_ATTRIBUTES = [ + 'CASE' => [ + \PDO::CASE_LOWER => 'LOWER', + \PDO::CASE_NATURAL => 'NATURAL', + \PDO::CASE_UPPER => 'UPPER', + ], + 'ERRMODE' => [ + \PDO::ERRMODE_SILENT => 'SILENT', + \PDO::ERRMODE_WARNING => 'WARNING', + \PDO::ERRMODE_EXCEPTION => 'EXCEPTION', + ], + 'TIMEOUT', + 'PREFETCH', + 'AUTOCOMMIT', + 'PERSISTENT', + 'DRIVER_NAME', + 'SERVER_INFO', + 'ORACLE_NULLS' => [ + \PDO::NULL_NATURAL => 'NATURAL', + \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', + \PDO::NULL_TO_STRING => 'TO_STRING', + ], + 'CLIENT_VERSION', + 'SERVER_VERSION', + 'STATEMENT_CLASS', + 'EMULATE_PREPARES', + 'CONNECTION_STATUS', + 'STRINGIFY_FETCHES', + 'DEFAULT_FETCH_MODE' => [ + \PDO::FETCH_ASSOC => 'ASSOC', + \PDO::FETCH_BOTH => 'BOTH', + \PDO::FETCH_LAZY => 'LAZY', + \PDO::FETCH_NUM => 'NUM', + \PDO::FETCH_OBJ => 'OBJ', + ], + ]; + + public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested) + { + $attr = []; + $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE); + $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + foreach (self::PDO_ATTRIBUTES as $k => $v) { + if (!isset($k[0])) { + $k = $v; + $v = []; + } + + try { + $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k)); + if ($v && isset($v[$attr[$k]])) { + $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]); + } + } catch (\Exception $e) { + } + } + if (isset($attr[$k = 'STATEMENT_CLASS'][1])) { + if ($attr[$k][1]) { + $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]); + } + $attr[$k][0] = new ClassStub($attr[$k][0]); + } + + $prefix = Caster::PREFIX_VIRTUAL; + $a += [ + $prefix.'inTransaction' => method_exists($c, 'inTransaction'), + $prefix.'errorInfo' => $c->errorInfo(), + $prefix.'attributes' => new EnumStub($attr), + ]; + + if ($a[$prefix.'inTransaction']) { + $a[$prefix.'inTransaction'] = $c->inTransaction(); + } else { + unset($a[$prefix.'inTransaction']); + } + + if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { + unset($a[$prefix.'errorInfo']); + } + + $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode); + + return $a; + } + + public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $a[$prefix.'errorInfo'] = $c->errorInfo(); + + if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { + unset($a[$prefix.'errorInfo']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/PgSqlCaster.php b/vendor/symfony/var-dumper/Caster/PgSqlCaster.php new file mode 100644 index 00000000..d8e5b525 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/PgSqlCaster.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts pqsql resources to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class PgSqlCaster +{ + private const PARAM_CODES = [ + 'server_encoding', + 'client_encoding', + 'is_superuser', + 'session_authorization', + 'DateStyle', + 'TimeZone', + 'IntervalStyle', + 'integer_datetimes', + 'application_name', + 'standard_conforming_strings', + ]; + + private const TRANSACTION_STATUS = [ + \PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', + \PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', + \PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', + \PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', + \PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN', + ]; + + private const RESULT_STATUS = [ + \PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', + \PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', + \PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', + \PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', + \PGSQL_COPY_IN => 'PGSQL_COPY_IN', + \PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', + \PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', + \PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR', + ]; + + private const DIAG_CODES = [ + 'severity' => \PGSQL_DIAG_SEVERITY, + 'sqlstate' => \PGSQL_DIAG_SQLSTATE, + 'message' => \PGSQL_DIAG_MESSAGE_PRIMARY, + 'detail' => \PGSQL_DIAG_MESSAGE_DETAIL, + 'hint' => \PGSQL_DIAG_MESSAGE_HINT, + 'statement position' => \PGSQL_DIAG_STATEMENT_POSITION, + 'internal position' => \PGSQL_DIAG_INTERNAL_POSITION, + 'internal query' => \PGSQL_DIAG_INTERNAL_QUERY, + 'context' => \PGSQL_DIAG_CONTEXT, + 'file' => \PGSQL_DIAG_SOURCE_FILE, + 'line' => \PGSQL_DIAG_SOURCE_LINE, + 'function' => \PGSQL_DIAG_SOURCE_FUNCTION, + ]; + + public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested) + { + $a['seek position'] = pg_lo_tell($lo); + + return $a; + } + + public static function castLink($link, array $a, Stub $stub, bool $isNested) + { + $a['status'] = pg_connection_status($link); + $a['status'] = new ConstStub(\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']); + $a['busy'] = pg_connection_busy($link); + + $a['transaction'] = pg_transaction_status($link); + if (isset(self::TRANSACTION_STATUS[$a['transaction']])) { + $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']); + } + + $a['pid'] = pg_get_pid($link); + $a['last error'] = pg_last_error($link); + $a['last notice'] = pg_last_notice($link); + $a['host'] = pg_host($link); + $a['port'] = pg_port($link); + $a['dbname'] = pg_dbname($link); + $a['options'] = pg_options($link); + $a['version'] = pg_version($link); + + foreach (self::PARAM_CODES as $v) { + if (false !== $s = pg_parameter_status($link, $v)) { + $a['param'][$v] = $s; + } + } + + $a['param']['client_encoding'] = pg_client_encoding($link); + $a['param'] = new EnumStub($a['param']); + + return $a; + } + + public static function castResult($result, array $a, Stub $stub, bool $isNested) + { + $a['num rows'] = pg_num_rows($result); + $a['status'] = pg_result_status($result); + if (isset(self::RESULT_STATUS[$a['status']])) { + $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']); + } + $a['command-completion tag'] = pg_result_status($result, \PGSQL_STATUS_STRING); + + if (-1 === $a['num rows']) { + foreach (self::DIAG_CODES as $k => $v) { + $a['error'][$k] = pg_result_error_field($result, $v); + } + } + + $a['affected rows'] = pg_affected_rows($result); + $a['last OID'] = pg_last_oid($result); + + $fields = pg_num_fields($result); + + for ($i = 0; $i < $fields; ++$i) { + $field = [ + 'name' => pg_field_name($result, $i), + 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)), + 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), + 'nullable' => (bool) pg_field_is_null($result, $i), + 'storage' => pg_field_size($result, $i).' bytes', + 'display' => pg_field_prtlen($result, $i).' chars', + ]; + if (' (OID: )' === $field['table']) { + $field['table'] = null; + } + if ('-1 bytes' === $field['storage']) { + $field['storage'] = 'variable size'; + } elseif ('1 bytes' === $field['storage']) { + $field['storage'] = '1 byte'; + } + if ('1 chars' === $field['display']) { + $field['display'] = '1 char'; + } + $a['fields'][] = new EnumStub($field); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php b/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php new file mode 100644 index 00000000..e7120191 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use ProxyManager\Proxy\ProxyInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + * + * @final + */ +class ProxyManagerCaster +{ + public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested) + { + if ($parent = get_parent_class($c)) { + $stub->class .= ' - '.$parent; + } + $stub->class .= '@proxy'; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php b/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php new file mode 100644 index 00000000..db4bba8d --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php @@ -0,0 +1,186 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use RdKafka\Conf; +use RdKafka\Exception as RdKafkaException; +use RdKafka\KafkaConsumer; +use RdKafka\Message; +use RdKafka\Metadata\Broker as BrokerMetadata; +use RdKafka\Metadata\Collection as CollectionMetadata; +use RdKafka\Metadata\Partition as PartitionMetadata; +use RdKafka\Metadata\Topic as TopicMetadata; +use RdKafka\Topic; +use RdKafka\TopicConf; +use RdKafka\TopicPartition; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts RdKafka related classes to array representation. + * + * @author Romain Neutron + */ +class RdKafkaCaster +{ + public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + try { + $assignment = $c->getAssignment(); + } catch (RdKafkaException $e) { + $assignment = []; + } + + $a += [ + $prefix.'subscription' => $c->getSubscription(), + $prefix.'assignment' => $assignment, + ]; + + $a += self::extractMetadata($c); + + return $a; + } + + public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'name' => $c->getName(), + ]; + + return $a; + } + + public static function castTopicPartition(TopicPartition $c, array $a) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'offset' => $c->getOffset(), + $prefix.'partition' => $c->getPartition(), + $prefix.'topic' => $c->getTopic(), + ]; + + return $a; + } + + public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'errstr' => $c->errstr(), + ]; + + return $a; + } + + public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + foreach ($c->dump() as $key => $value) { + $a[$prefix.$key] = $value; + } + + return $a; + } + + public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + foreach ($c->dump() as $key => $value) { + $a[$prefix.$key] = $value; + } + + return $a; + } + + public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'out_q_len' => $c->getOutQLen(), + ]; + + $a += self::extractMetadata($c); + + return $a; + } + + public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested) + { + $a += iterator_to_array($c); + + return $a; + } + + public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'name' => $c->getTopic(), + $prefix.'partitions' => $c->getPartitions(), + ]; + + return $a; + } + + public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'id' => $c->getId(), + $prefix.'err' => $c->getErr(), + $prefix.'leader' => $c->getLeader(), + ]; + + return $a; + } + + public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'id' => $c->getId(), + $prefix.'host' => $c->getHost(), + $prefix.'port' => $c->getPort(), + ]; + + return $a; + } + + private static function extractMetadata($c) + { + $prefix = Caster::PREFIX_VIRTUAL; + + try { + $m = $c->getMetadata(true, null, 500); + } catch (RdKafkaException $e) { + return []; + } + + return [ + $prefix.'orig_broker_id' => $m->getOrigBrokerId(), + $prefix.'orig_broker_name' => $m->getOrigBrokerName(), + $prefix.'brokers' => $m->getBrokers(), + $prefix.'topics' => $m->getTopics(), + ]; + } +} diff --git a/vendor/symfony/var-dumper/Caster/RedisCaster.php b/vendor/symfony/var-dumper/Caster/RedisCaster.php new file mode 100644 index 00000000..8f97eaad --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/RedisCaster.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Redis class from ext-redis to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class RedisCaster +{ + private const SERIALIZERS = [ + \Redis::SERIALIZER_NONE => 'NONE', + \Redis::SERIALIZER_PHP => 'PHP', + 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY + ]; + + private const MODES = [ + \Redis::ATOMIC => 'ATOMIC', + \Redis::MULTI => 'MULTI', + \Redis::PIPELINE => 'PIPELINE', + ]; + + private const COMPRESSION_MODES = [ + 0 => 'NONE', // Redis::COMPRESSION_NONE + 1 => 'LZF', // Redis::COMPRESSION_LZF + ]; + + private const FAILOVER_OPTIONS = [ + \RedisCluster::FAILOVER_NONE => 'NONE', + \RedisCluster::FAILOVER_ERROR => 'ERROR', + \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', + \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES', + ]; + + public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if (!$connected = $c->isConnected()) { + return $a + [ + $prefix.'isConnected' => $connected, + ]; + } + + $mode = $c->getMode(); + + return $a + [ + $prefix.'isConnected' => $connected, + $prefix.'host' => $c->getHost(), + $prefix.'port' => $c->getPort(), + $prefix.'auth' => $c->getAuth(), + $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode, + $prefix.'dbNum' => $c->getDbNum(), + $prefix.'timeout' => $c->getTimeout(), + $prefix.'lastError' => $c->getLastError(), + $prefix.'persistentId' => $c->getPersistentID(), + $prefix.'options' => self::getRedisOptions($c), + ]; + } + + public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + return $a + [ + $prefix.'hosts' => $c->_hosts(), + $prefix.'function' => ClassStub::wrapCallable($c->_function()), + $prefix.'lastError' => $c->getLastError(), + $prefix.'options' => self::getRedisOptions($c), + ]; + } + + public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER); + + $a += [ + $prefix.'_masters' => $c->_masters(), + $prefix.'_redir' => $c->_redir(), + $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), + $prefix.'lastError' => $c->getLastError(), + $prefix.'options' => self::getRedisOptions($c, [ + 'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover, + ]), + ]; + + return $a; + } + + /** + * @param \Redis|\RedisArray|\RedisCluster $redis + */ + private static function getRedisOptions($redis, array $options = []): EnumStub + { + $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); + if (\is_array($serializer)) { + foreach ($serializer as &$v) { + if (isset(self::SERIALIZERS[$v])) { + $v = new ConstStub(self::SERIALIZERS[$v], $v); + } + } + } elseif (isset(self::SERIALIZERS[$serializer])) { + $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer); + } + + $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0; + if (\is_array($compression)) { + foreach ($compression as &$v) { + if (isset(self::COMPRESSION_MODES[$v])) { + $v = new ConstStub(self::COMPRESSION_MODES[$v], $v); + } + } + } elseif (isset(self::COMPRESSION_MODES[$compression])) { + $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression); + } + + $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0; + if (\is_array($retry)) { + foreach ($retry as &$v) { + $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v); + } + } else { + $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry); + } + + $options += [ + 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0, + 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT), + 'COMPRESSION' => $compression, + 'SERIALIZER' => $serializer, + 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX), + 'SCAN' => $retry, + ]; + + return new EnumStub($options); + } +} diff --git a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php new file mode 100644 index 00000000..87e5ffcc --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php @@ -0,0 +1,448 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Reflector related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ReflectionCaster +{ + public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo']; + + private const EXTRA_MAP = [ + 'docComment' => 'getDocComment', + 'extension' => 'getExtensionName', + 'isDisabled' => 'isDisabled', + 'isDeprecated' => 'isDeprecated', + 'isInternal' => 'isInternal', + 'isUserDefined' => 'isUserDefined', + 'isGenerator' => 'isGenerator', + 'isVariadic' => 'isVariadic', + ]; + + public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + $c = new \ReflectionFunction($c); + + $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); + + if (!str_contains($c->name, '{closure')) { + $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; + unset($a[$prefix.'class']); + } + unset($a[$prefix.'extra']); + + $stub->class .= self::getSignature($a); + + if ($f = $c->getFileName()) { + $stub->attr['file'] = $f; + $stub->attr['line'] = $c->getStartLine(); + } + + unset($a[$prefix.'parameters']); + + if ($filter & Caster::EXCLUDE_VERBOSE) { + $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a); + + return []; + } + + if ($f) { + $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine()); + $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine(); + } + + return $a; + } + + public static function unsetClosureFileInfo(\Closure $c, array $a) + { + unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']); + + return $a; + } + + public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested) + { + // Cannot create ReflectionGenerator based on a terminated Generator + try { + $reflectionGenerator = new \ReflectionGenerator($c); + + return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested); + } catch (\Exception $e) { + $a[Caster::PREFIX_VIRTUAL.'closed'] = true; + + return $a; + } + } + + public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($c instanceof \ReflectionNamedType || \PHP_VERSION_ID < 80000) { + $a += [ + $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c, + $prefix.'allowsNull' => $c->allowsNull(), + $prefix.'isBuiltin' => $c->isBuiltin(), + ]; + } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) { + $a[$prefix.'allowsNull'] = $c->allowsNull(); + self::addMap($a, $c, [ + 'types' => 'getTypes', + ]); + } else { + $a[$prefix.'allowsNull'] = $c->allowsNull(); + } + + return $a; + } + + public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested) + { + $map = [ + 'name' => 'getName', + 'arguments' => 'getArguments', + ]; + + if (\PHP_VERSION_ID >= 80400) { + unset($map['name']); + } + + self::addMap($a, $c, $map); + + return $a; + } + + public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($c->getThis()) { + $a[$prefix.'this'] = new CutStub($c->getThis()); + } + $function = $c->getFunction(); + $frame = [ + 'class' => $function->class ?? null, + 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null, + 'function' => $function->name, + 'file' => $c->getExecutingFile(), + 'line' => $c->getExecutingLine(), + ]; + if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) { + $function = new \ReflectionGenerator($c->getExecutingGenerator()); + array_unshift($trace, [ + 'function' => 'yield', + 'file' => $function->getExecutingFile(), + 'line' => $function->getExecutingLine() - (int) (\PHP_VERSION_ID < 80100), + ]); + $trace[] = $frame; + $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); + } else { + $function = new FrameStub($frame, false, true); + $function = ExceptionCaster::castFrameStub($function, [], $function, true); + $a[$prefix.'executing'] = $function[$prefix.'src']; + } + + $a[Caster::PREFIX_VIRTUAL.'closed'] = false; + + return $a; + } + + public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($n = \Reflection::getModifierNames($c->getModifiers())) { + $a[$prefix.'modifiers'] = implode(' ', $n); + } + + self::addMap($a, $c, [ + 'extends' => 'getParentClass', + 'implements' => 'getInterfaceNames', + 'constants' => 'getReflectionConstants', + ]); + + foreach ($c->getProperties() as $n) { + $a[$prefix.'properties'][$n->name] = $n; + } + + foreach ($c->getMethods() as $n) { + $a[$prefix.'methods'][$n->name] = $n; + } + + self::addAttributes($a, $c, $prefix); + + if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { + self::addExtra($a, $c); + } + + return $a; + } + + public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + self::addMap($a, $c, [ + 'returnsReference' => 'returnsReference', + 'returnType' => 'getReturnType', + 'class' => \PHP_VERSION_ID >= 80111 ? 'getClosureCalledClass' : 'getClosureScopeClass', + 'this' => 'getClosureThis', + ]); + + if (isset($a[$prefix.'returnType'])) { + $v = $a[$prefix.'returnType']; + $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; + $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + } + if (isset($a[$prefix.'class'])) { + $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); + } + if (isset($a[$prefix.'this'])) { + $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); + } + + foreach ($c->getParameters() as $v) { + $k = '$'.$v->name; + if ($v->isVariadic()) { + $k = '...'.$k; + } + if ($v->isPassedByReference()) { + $k = '&'.$k; + } + $a[$prefix.'parameters'][$k] = $v; + } + if (isset($a[$prefix.'parameters'])) { + $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']); + } + + self::addAttributes($a, $c, $prefix); + + if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) { + foreach ($v as $k => &$v) { + if (\is_object($v)) { + $a[$prefix.'use']['$'.$k] = new CutStub($v); + } else { + $a[$prefix.'use']['$'.$k] = &$v; + } + } + unset($v); + $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']); + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { + self::addExtra($a, $c); + } + + return $a; + } + + public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); + $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue(); + + self::addAttributes($a, $c); + + return $a; + } + + public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); + + return $a; + } + + public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + self::addMap($a, $c, [ + 'position' => 'getPosition', + 'isVariadic' => 'isVariadic', + 'byReference' => 'isPassedByReference', + 'allowsNull' => 'allowsNull', + ]); + + self::addAttributes($a, $c, $prefix); + + if ($v = $c->getType()) { + $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; + } + + if (isset($a[$prefix.'typeHint'])) { + $v = $a[$prefix.'typeHint']; + $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + } else { + unset($a[$prefix.'allowsNull']); + } + + if ($c->isOptional()) { + try { + $a[$prefix.'default'] = $v = $c->getDefaultValue(); + if ($c->isDefaultValueConstant() && !\is_object($v)) { + $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); + } + if (null === $v) { + unset($a[$prefix.'allowsNull']); + } + } catch (\ReflectionException $e) { + } + } + + return $a; + } + + public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); + + self::addAttributes($a, $c); + self::addExtra($a, $c); + + return $a; + } + + public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId(); + + return $a; + } + + public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested) + { + self::addMap($a, $c, [ + 'version' => 'getVersion', + 'dependencies' => 'getDependencies', + 'iniEntries' => 'getIniEntries', + 'isPersistent' => 'isPersistent', + 'isTemporary' => 'isTemporary', + 'constants' => 'getConstants', + 'functions' => 'getFunctions', + 'classes' => 'getClasses', + ]); + + return $a; + } + + public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested) + { + self::addMap($a, $c, [ + 'version' => 'getVersion', + 'author' => 'getAuthor', + 'copyright' => 'getCopyright', + 'url' => 'getURL', + ]); + + return $a; + } + + public static function getSignature(array $a) + { + $prefix = Caster::PREFIX_VIRTUAL; + $signature = ''; + + if (isset($a[$prefix.'parameters'])) { + foreach ($a[$prefix.'parameters']->value as $k => $param) { + $signature .= ', '; + if ($type = $param->getType()) { + if (!$type instanceof \ReflectionNamedType) { + $signature .= $type.' '; + } else { + if ($param->allowsNull() && 'mixed' !== $type->getName()) { + $signature .= '?'; + } + $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; + } + } + $signature .= $k; + + if (!$param->isDefaultValueAvailable()) { + continue; + } + $v = $param->getDefaultValue(); + $signature .= ' = '; + + if ($param->isDefaultValueConstant()) { + $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1); + } elseif (null === $v) { + $signature .= 'null'; + } elseif (\is_array($v)) { + $signature .= $v ? '[…'.\count($v).']' : '[]'; + } elseif (\is_string($v)) { + $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'"; + } elseif (\is_bool($v)) { + $signature .= $v ? 'true' : 'false'; + } elseif (\is_object($v)) { + $signature .= 'new '.substr(strrchr('\\'.get_debug_type($v), '\\'), 1); + } else { + $signature .= $v; + } + } + } + $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')'; + + if (isset($a[$prefix.'returnType'])) { + $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1); + } + + return $signature; + } + + private static function addExtra(array &$a, \Reflector $c) + { + $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : []; + + if (method_exists($c, 'getFileName') && $m = $c->getFileName()) { + $x['file'] = new LinkStub($m, $c->getStartLine()); + $x['line'] = $c->getStartLine().' to '.$c->getEndLine(); + } + + self::addMap($x, $c, self::EXTRA_MAP, ''); + + if ($x) { + $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x); + } + } + + private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL) + { + foreach ($map as $k => $m) { + if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) { + continue; + } + + if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) { + $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m; + } + } + } + + private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void + { + if (\PHP_VERSION_ID >= 80000) { + foreach ($c->getAttributes() as $n) { + $a[$prefix.'attributes'][] = $n; + } + } + } +} diff --git a/vendor/symfony/var-dumper/Caster/ResourceCaster.php b/vendor/symfony/var-dumper/Caster/ResourceCaster.php new file mode 100644 index 00000000..2c34ca91 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ResourceCaster.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts common resource types to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ResourceCaster +{ + /** + * @param \CurlHandle|resource $h + */ + public static function castCurl($h, array $a, Stub $stub, bool $isNested): array + { + return curl_getinfo($h); + } + + public static function castDba($dba, array $a, Stub $stub, bool $isNested) + { + $list = dba_list(); + $a['file'] = $list[(int) $dba]; + + return $a; + } + + public static function castProcess($process, array $a, Stub $stub, bool $isNested) + { + return proc_get_status($process); + } + + public static function castStream($stream, array $a, Stub $stub, bool $isNested) + { + $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested); + if ($a['uri'] ?? false) { + $a['uri'] = new LinkStub($a['uri']); + } + + return $a; + } + + public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested) + { + return @stream_context_get_params($stream) ?: $a; + } + + public static function castGd($gd, array $a, Stub $stub, bool $isNested) + { + $a['size'] = imagesx($gd).'x'.imagesy($gd); + $a['trueColor'] = imageistruecolor($gd); + + return $a; + } + + public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested) + { + $a['host'] = mysql_get_host_info($h); + $a['protocol'] = mysql_get_proto_info($h); + $a['server'] = mysql_get_server_info($h); + + return $a; + } + + public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested) + { + $stub->cut = -1; + $info = openssl_x509_parse($h, false); + + $pin = openssl_pkey_get_public($h); + $pin = openssl_pkey_get_details($pin)['key']; + $pin = \array_slice(explode("\n", $pin), 1, -2); + $pin = base64_decode(implode('', $pin)); + $pin = base64_encode(hash('sha256', $pin, true)); + + $a += [ + 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])), + 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])), + 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), + 'fingerprint' => new EnumStub([ + 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)), + 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)), + 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)), + 'pin-sha256' => new ConstStub($pin), + ]), + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/SplCaster.php b/vendor/symfony/var-dumper/Caster/SplCaster.php new file mode 100644 index 00000000..d7db8f89 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/SplCaster.php @@ -0,0 +1,246 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts SPL related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class SplCaster +{ + private const SPL_FILE_OBJECT_FLAGS = [ + \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', + \SplFileObject::READ_AHEAD => 'READ_AHEAD', + \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', + \SplFileObject::READ_CSV => 'READ_CSV', + ]; + + public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested) + { + return self::castSplArray($c, $a, $stub, $isNested); + } + + public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested) + { + return self::castSplArray($c, $a, $stub, $isNested); + } + + public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c), + ]; + + return $a; + } + + public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $mode = $c->getIteratorMode(); + $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); + + $a += [ + $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), + $prefix.'dllist' => iterator_to_array($c), + ]; + $c->setIteratorMode($mode); + + return $a; + } + + public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested) + { + static $map = [ + 'path' => 'getPath', + 'filename' => 'getFilename', + 'basename' => 'getBasename', + 'pathname' => 'getPathname', + 'extension' => 'getExtension', + 'realPath' => 'getRealPath', + 'aTime' => 'getATime', + 'mTime' => 'getMTime', + 'cTime' => 'getCTime', + 'inode' => 'getInode', + 'size' => 'getSize', + 'perms' => 'getPerms', + 'owner' => 'getOwner', + 'group' => 'getGroup', + 'type' => 'getType', + 'writable' => 'isWritable', + 'readable' => 'isReadable', + 'executable' => 'isExecutable', + 'file' => 'isFile', + 'dir' => 'isDir', + 'link' => 'isLink', + 'linkTarget' => 'getLinkTarget', + ]; + + $prefix = Caster::PREFIX_VIRTUAL; + unset($a["\0SplFileInfo\0fileName"]); + unset($a["\0SplFileInfo\0pathName"]); + + if (\PHP_VERSION_ID < 80000) { + if (false === $c->getPathname()) { + $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; + + return $a; + } + } else { + try { + $c->isReadable(); + } catch (\RuntimeException $e) { + if ('Object not initialized' !== $e->getMessage()) { + throw $e; + } + + $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; + + return $a; + } catch (\Error $e) { + if ('Object not initialized' !== $e->getMessage()) { + throw $e; + } + + $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; + + return $a; + } + } + + foreach ($map as $key => $accessor) { + try { + $a[$prefix.$key] = $c->$accessor(); + } catch (\Exception $e) { + } + } + + if ($a[$prefix.'realPath'] ?? false) { + $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']); + } + + if (isset($a[$prefix.'perms'])) { + $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']); + } + + static $mapDate = ['aTime', 'mTime', 'cTime']; + foreach ($mapDate as $key) { + if (isset($a[$prefix.$key])) { + $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]); + } + } + + return $a; + } + + public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested) + { + static $map = [ + 'csvControl' => 'getCsvControl', + 'flags' => 'getFlags', + 'maxLineLen' => 'getMaxLineLen', + 'fstat' => 'fstat', + 'eof' => 'eof', + 'key' => 'key', + ]; + + $prefix = Caster::PREFIX_VIRTUAL; + + foreach ($map as $key => $accessor) { + try { + $a[$prefix.$key] = $c->$accessor(); + } catch (\Exception $e) { + } + } + + if (isset($a[$prefix.'flags'])) { + $flagsArray = []; + foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) { + if ($a[$prefix.'flags'] & $value) { + $flagsArray[] = $name; + } + } + $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']); + } + + if (isset($a[$prefix.'fstat'])) { + $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']); + } + + return $a; + } + + public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested) + { + $storage = []; + unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 + unset($a["\0SplObjectStorage\0storage"]); + + $clone = clone $c; + foreach ($clone as $obj) { + $storage[] = [ + 'object' => $obj, + 'info' => $clone->getInfo(), + ]; + } + + $a += [ + Caster::PREFIX_VIRTUAL.'storage' => $storage, + ]; + + return $a; + } + + public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator(); + + return $a; + } + + public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get(); + + return $a; + } + + private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array + { + $prefix = Caster::PREFIX_VIRTUAL; + $flags = $c->getFlags(); + + if (!($flags & \ArrayObject::STD_PROP_LIST)) { + $c->setFlags(\ArrayObject::STD_PROP_LIST); + $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class); + $c->setFlags($flags); + } + + unset($a["\0ArrayObject\0storage"], $a["\0ArrayIterator\0storage"]); + + $a += [ + $prefix.'storage' => $c->getArrayCopy(), + $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), + $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), + ]; + if ($c instanceof \ArrayObject) { + $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/StubCaster.php b/vendor/symfony/var-dumper/Caster/StubCaster.php new file mode 100644 index 00000000..32ead7c2 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/StubCaster.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts a caster's Stub. + * + * @author Nicolas Grekas + * + * @final + */ +class StubCaster +{ + public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->type = $c->type; + $stub->class = $c->class; + $stub->value = $c->value; + $stub->handle = $c->handle; + $stub->cut = $c->cut; + $stub->attr = $c->attr; + + if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) { + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_BINARY; + } + + $a = []; + } + + return $a; + } + + public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested) + { + return $isNested ? $c->preservedSubset : $a; + } + + public static function cutInternals($obj, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->cut += \count($a); + + return []; + } + + return $a; + } + + public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->class = $c->dumpKeys ? '' : null; + $stub->handle = 0; + $stub->value = null; + $stub->cut = $c->cut; + $stub->attr = $c->attr; + + $a = []; + + if ($c->value) { + foreach (array_keys($c->value) as $k) { + $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k; + } + // Preserve references with array_combine() + $a = array_combine($keys, $c->value); + } + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/SymfonyCaster.php b/vendor/symfony/var-dumper/Caster/SymfonyCaster.php new file mode 100644 index 00000000..08428b92 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/SymfonyCaster.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @final + */ +class SymfonyCaster +{ + private const REQUEST_GETTERS = [ + 'pathInfo' => 'getPathInfo', + 'requestUri' => 'getRequestUri', + 'baseUrl' => 'getBaseUrl', + 'basePath' => 'getBasePath', + 'method' => 'getMethod', + 'format' => 'getRequestFormat', + ]; + + public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested) + { + $clone = null; + + foreach (self::REQUEST_GETTERS as $prop => $getter) { + $key = Caster::PREFIX_PROTECTED.$prop; + if (\array_key_exists($key, $a) && null === $a[$key]) { + if (null === $clone) { + $clone = clone $request; + } + $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}(); + } + } + + return $a; + } + + public static function castHttpClient($client, array $a, Stub $stub, bool $isNested) + { + $multiKey = sprintf("\0%s\0multi", \get_class($client)); + if (isset($a[$multiKey])) { + $a[$multiKey] = new CutStub($a[$multiKey]); + } + + return $a; + } + + public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested) + { + $stub->cut += \count($a); + $a = []; + + foreach ($response->getInfo() as $k => $v) { + $a[Caster::PREFIX_VIRTUAL.$k] = $v; + } + + return $a; + } + + public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $uuid->toBase58(); + $a[Caster::PREFIX_VIRTUAL.'toBase32'] = $uuid->toBase32(); + + // symfony/uid >= 5.3 + if (method_exists($uuid, 'getDateTime')) { + $a[Caster::PREFIX_VIRTUAL.'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C'); + } + + return $a; + } + + public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $ulid->toBase58(); + $a[Caster::PREFIX_VIRTUAL.'toRfc4122'] = $ulid->toRfc4122(); + + // symfony/uid >= 5.3 + if (method_exists($ulid, 'getDateTime')) { + $a[Caster::PREFIX_VIRTUAL.'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C'); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/TraceStub.php b/vendor/symfony/var-dumper/Caster/TraceStub.php new file mode 100644 index 00000000..d215d8db --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/TraceStub.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace(). + * + * @author Nicolas Grekas + */ +class TraceStub extends Stub +{ + public $keepArgs; + public $sliceOffset; + public $sliceLength; + public $numberingOffset; + + public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, ?int $sliceLength = null, int $numberingOffset = 0) + { + $this->value = $trace; + $this->keepArgs = $keepArgs; + $this->sliceOffset = $sliceOffset; + $this->sliceLength = $sliceLength; + $this->numberingOffset = $numberingOffset; + } +} diff --git a/vendor/symfony/var-dumper/Caster/UuidCaster.php b/vendor/symfony/var-dumper/Caster/UuidCaster.php new file mode 100644 index 00000000..b1027745 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/UuidCaster.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Ramsey\Uuid\UuidInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Grégoire Pineau + */ +final class UuidCaster +{ + public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array + { + $a += [ + Caster::PREFIX_VIRTUAL.'uuid' => (string) $c, + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php b/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php new file mode 100644 index 00000000..5b455651 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts XmlReader class to array representation. + * + * @author Baptiste Clavié + * + * @final + */ +class XmlReaderCaster +{ + private const NODE_TYPES = [ + \XMLReader::NONE => 'NONE', + \XMLReader::ELEMENT => 'ELEMENT', + \XMLReader::ATTRIBUTE => 'ATTRIBUTE', + \XMLReader::TEXT => 'TEXT', + \XMLReader::CDATA => 'CDATA', + \XMLReader::ENTITY_REF => 'ENTITY_REF', + \XMLReader::ENTITY => 'ENTITY', + \XMLReader::PI => 'PI (Processing Instruction)', + \XMLReader::COMMENT => 'COMMENT', + \XMLReader::DOC => 'DOC', + \XMLReader::DOC_TYPE => 'DOC_TYPE', + \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', + \XMLReader::NOTATION => 'NOTATION', + \XMLReader::WHITESPACE => 'WHITESPACE', + \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', + \XMLReader::END_ELEMENT => 'END_ELEMENT', + \XMLReader::END_ENTITY => 'END_ENTITY', + \XMLReader::XML_DECLARATION => 'XML_DECLARATION', + ]; + + public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested) + { + try { + $properties = [ + 'LOADDTD' => @$reader->getParserProperty(\XMLReader::LOADDTD), + 'DEFAULTATTRS' => @$reader->getParserProperty(\XMLReader::DEFAULTATTRS), + 'VALIDATE' => @$reader->getParserProperty(\XMLReader::VALIDATE), + 'SUBST_ENTITIES' => @$reader->getParserProperty(\XMLReader::SUBST_ENTITIES), + ]; + } catch (\Error $e) { + $properties = [ + 'LOADDTD' => false, + 'DEFAULTATTRS' => false, + 'VALIDATE' => false, + 'SUBST_ENTITIES' => false, + ]; + } + + $props = Caster::PREFIX_VIRTUAL.'parserProperties'; + $info = [ + 'localName' => $reader->localName, + 'prefix' => $reader->prefix, + 'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType), + 'depth' => $reader->depth, + 'isDefault' => $reader->isDefault, + 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, + 'xmlLang' => $reader->xmlLang, + 'attributeCount' => $reader->attributeCount, + 'value' => $reader->value, + 'namespaceURI' => $reader->namespaceURI, + 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, + $props => $properties, + ]; + + if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) { + $info[$props] = new EnumStub($info[$props]); + $info[$props]->cut = $count; + } + + $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count); + // +2 because hasValue and hasAttributes are always filtered + $stub->cut += $count + 2; + + return $a + $info; + } +} diff --git a/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php b/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php new file mode 100644 index 00000000..ba55fced --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts XML resources to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class XmlResourceCaster +{ + private const XML_ERRORS = [ + \XML_ERROR_NONE => 'XML_ERROR_NONE', + \XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', + \XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', + \XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', + \XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', + \XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', + \XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', + \XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', + \XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', + \XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', + \XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', + \XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', + \XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', + \XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', + \XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', + \XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', + \XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', + \XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', + \XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', + \XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', + \XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', + \XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING', + ]; + + public static function castXml($h, array $a, Stub $stub, bool $isNested) + { + $a['current_byte_index'] = xml_get_current_byte_index($h); + $a['current_column_number'] = xml_get_current_column_number($h); + $a['current_line_number'] = xml_get_current_line_number($h); + $a['error_code'] = xml_get_error_code($h); + + if (isset(self::XML_ERRORS[$a['error_code']])) { + $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/AbstractCloner.php b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php new file mode 100644 index 00000000..e811fbf7 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php @@ -0,0 +1,400 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Exception\ThrowingCasterException; + +/** + * AbstractCloner implements a generic caster mechanism for objects and resources. + * + * @author Nicolas Grekas + */ +abstract class AbstractCloner implements ClonerInterface +{ + public static $defaultCasters = [ + '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], + + 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], + 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], + 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], + 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], + + 'Fiber' => ['Symfony\Component\VarDumper\Caster\FiberCaster', 'castFiber'], + + 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], + 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], + 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], + 'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'], + 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], + 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], + 'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'], + 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], + 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], + 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], + 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], + 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], + 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], + 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], + + 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], + 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], + 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], + 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + + 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], + 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], + 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], + 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], + 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], + 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], + 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], + 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], + 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], + 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'], + 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'], + 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'], + 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], + 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], + 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], + 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], + 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], + + 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], + + 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], + 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], + 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], + 'Symfony\Bridge\Monolog\Logger' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\HttpClient\AmpHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], + 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], + 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], + 'Symfony\Component\HttpClient\Response\AmpResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], + 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], + 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], + 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], + 'Symfony\Component\Uid\Ulid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUlid'], + 'Symfony\Component\Uid\Uuid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUuid'], + 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], + 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], + 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], + 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], + + 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], + + 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], + + 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], + 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + + 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], + 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], + + 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], + 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], + 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], + 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], + 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], + + 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], + 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], + 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], + 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], + 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], + 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], + 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], + 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], + 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], + 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], + + 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], + 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], + 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], + + 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], + 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], + 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], + 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], + + 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], + + 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], + 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], + 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], + 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], + 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], + + 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], + + 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], + 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], + 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], + 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], + + 'mysqli_driver' => ['Symfony\Component\VarDumper\Caster\MysqliCaster', 'castMysqliDriver'], + + 'CurlHandle' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], + ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], + + ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], + ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], + + 'GdImage' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], + ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], + + ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'], + ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], + ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], + ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], + ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], + ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], + ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], + + 'OpenSSLCertificate' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], + ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], + + ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], + ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], + + 'XmlParser' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], + ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], + + 'RdKafka' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castRdKafka'], + 'RdKafka\Conf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castConf'], + 'RdKafka\KafkaConsumer' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castKafkaConsumer'], + 'RdKafka\Metadata\Broker' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castBrokerMetadata'], + 'RdKafka\Metadata\Collection' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castCollectionMetadata'], + 'RdKafka\Metadata\Partition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castPartitionMetadata'], + 'RdKafka\Metadata\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicMetadata'], + 'RdKafka\Message' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castMessage'], + 'RdKafka\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopic'], + 'RdKafka\TopicPartition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicPartition'], + 'RdKafka\TopicConf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicConf'], + ]; + + protected $maxItems = 2500; + protected $maxString = -1; + protected $minDepth = 1; + + /** + * @var array> + */ + private $casters = []; + + /** + * @var callable|null + */ + private $prevErrorHandler; + + private $classInfo = []; + private $filter = 0; + + /** + * @param callable[]|null $casters A map of casters + * + * @see addCasters + */ + public function __construct(?array $casters = null) + { + if (null === $casters) { + $casters = static::$defaultCasters; + } + $this->addCasters($casters); + } + + /** + * Adds casters for resources and objects. + * + * Maps resources or objects types to a callback. + * Types are in the key, with a callable caster for value. + * Resource types are to be prefixed with a `:`, + * see e.g. static::$defaultCasters. + * + * @param callable[] $casters A map of casters + */ + public function addCasters(array $casters) + { + foreach ($casters as $type => $callback) { + $this->casters[$type][] = $callback; + } + } + + /** + * Sets the maximum number of items to clone past the minimum depth in nested structures. + */ + public function setMaxItems(int $maxItems) + { + $this->maxItems = $maxItems; + } + + /** + * Sets the maximum cloned length for strings. + */ + public function setMaxString(int $maxString) + { + $this->maxString = $maxString; + } + + /** + * Sets the minimum tree depth where we are guaranteed to clone all the items. After this + * depth is reached, only setMaxItems items will be cloned. + */ + public function setMinDepth(int $minDepth) + { + $this->minDepth = $minDepth; + } + + /** + * Clones a PHP variable. + * + * @param mixed $var Any PHP variable + * @param int $filter A bit field of Caster::EXCLUDE_* constants + * + * @return Data + */ + public function cloneVar($var, int $filter = 0) + { + $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) { + if (\E_RECOVERABLE_ERROR === $type || \E_USER_ERROR === $type) { + // Cloner never dies + throw new \ErrorException($msg, 0, $type, $file, $line); + } + + if ($this->prevErrorHandler) { + return ($this->prevErrorHandler)($type, $msg, $file, $line, $context); + } + + return false; + }); + $this->filter = $filter; + + if ($gc = gc_enabled()) { + gc_disable(); + } + try { + return new Data($this->doClone($var)); + } finally { + if ($gc) { + gc_enable(); + } + restore_error_handler(); + $this->prevErrorHandler = null; + } + } + + /** + * Effectively clones the PHP variable. + * + * @param mixed $var Any PHP variable + * + * @return array + */ + abstract protected function doClone($var); + + /** + * Casts an object to an array representation. + * + * @param bool $isNested True if the object is nested in the dumped structure + * + * @return array + */ + protected function castObject(Stub $stub, bool $isNested) + { + $obj = $stub->value; + $class = $stub->class; + + if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : str_contains($class, "@anonymous\0")) { + $stub->class = get_debug_type($obj); + } + if (isset($this->classInfo[$class])) { + [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class]; + } else { + $i = 2; + $parents = [$class]; + $hasDebugInfo = method_exists($class, '__debugInfo'); + + foreach (class_parents($class) as $p) { + $parents[] = $p; + ++$i; + } + foreach (class_implements($class) as $p) { + $parents[] = $p; + ++$i; + } + $parents[] = '*'; + + $r = new \ReflectionClass($class); + $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [ + 'file' => $r->getFileName(), + 'line' => $r->getStartLine(), + ]; + + $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo]; + } + + $stub->attr += $fileInfo; + $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class); + + try { + while ($i--) { + if (!empty($this->casters[$p = $parents[$i]])) { + foreach ($this->casters[$p] as $callback) { + $a = $callback($obj, $a, $stub, $isNested, $this->filter); + } + } + } + } catch (\Exception $e) { + $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; + } + + return $a; + } + + /** + * Casts a resource to an array representation. + * + * @param bool $isNested True if the object is nested in the dumped structure + * + * @return array + */ + protected function castResource(Stub $stub, bool $isNested) + { + $a = []; + $res = $stub->value; + $type = $stub->class; + + try { + if (!empty($this->casters[':'.$type])) { + foreach ($this->casters[':'.$type] as $callback) { + $a = $callback($res, $a, $stub, $isNested, $this->filter); + } + } + } catch (\Exception $e) { + $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/ClonerInterface.php b/vendor/symfony/var-dumper/Cloner/ClonerInterface.php new file mode 100644 index 00000000..90b14953 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/ClonerInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * @author Nicolas Grekas + */ +interface ClonerInterface +{ + /** + * Clones a PHP variable. + * + * @param mixed $var Any PHP variable + * + * @return Data + */ + public function cloneVar($var); +} diff --git a/vendor/symfony/var-dumper/Cloner/Cursor.php b/vendor/symfony/var-dumper/Cloner/Cursor.php new file mode 100644 index 00000000..1fd796d6 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Cursor.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * Represents the current state of a dumper while dumping. + * + * @author Nicolas Grekas + */ +class Cursor +{ + public const HASH_INDEXED = Stub::ARRAY_INDEXED; + public const HASH_ASSOC = Stub::ARRAY_ASSOC; + public const HASH_OBJECT = Stub::TYPE_OBJECT; + public const HASH_RESOURCE = Stub::TYPE_RESOURCE; + + public $depth = 0; + public $refIndex = 0; + public $softRefTo = 0; + public $softRefCount = 0; + public $softRefHandle = 0; + public $hardRefTo = 0; + public $hardRefCount = 0; + public $hardRefHandle = 0; + public $hashType; + public $hashKey; + public $hashKeyIsBinary; + public $hashIndex = 0; + public $hashLength = 0; + public $hashCut = 0; + public $stop = false; + public $attr = []; + public $skipChildren = false; +} diff --git a/vendor/symfony/var-dumper/Cloner/Data.php b/vendor/symfony/var-dumper/Cloner/Data.php new file mode 100644 index 00000000..ea8f0f33 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Data.php @@ -0,0 +1,468 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; + +/** + * @author Nicolas Grekas + */ +class Data implements \ArrayAccess, \Countable, \IteratorAggregate +{ + private $data; + private $position = 0; + private $key = 0; + private $maxDepth = 20; + private $maxItemsPerDepth = -1; + private $useRefHandles = -1; + private $context = []; + + /** + * @param array $data An array as returned by ClonerInterface::cloneVar() + */ + public function __construct(array $data) + { + $this->data = $data; + } + + /** + * @return string|null + */ + public function getType() + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!$item instanceof Stub) { + return \gettype($item); + } + if (Stub::TYPE_STRING === $item->type) { + return 'string'; + } + if (Stub::TYPE_ARRAY === $item->type) { + return 'array'; + } + if (Stub::TYPE_OBJECT === $item->type) { + return $item->class; + } + if (Stub::TYPE_RESOURCE === $item->type) { + return $item->class.' resource'; + } + + return null; + } + + /** + * Returns a native representation of the original value. + * + * @param array|bool $recursive Whether values should be resolved recursively or not + * + * @return string|int|float|bool|array|Data[]|null + */ + public function getValue($recursive = false) + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!($item = $this->getStub($item)) instanceof Stub) { + return $item; + } + if (Stub::TYPE_STRING === $item->type) { + return $item->value; + } + + $children = $item->position ? $this->data[$item->position] : []; + + foreach ($children as $k => $v) { + if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { + continue; + } + $children[$k] = clone $this; + $children[$k]->key = $k; + $children[$k]->position = $item->position; + + if ($recursive) { + if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { + $recursive = (array) $recursive; + if (isset($recursive[$v->position])) { + continue; + } + $recursive[$v->position] = true; + } + $children[$k] = $children[$k]->getValue($recursive); + } + } + + return $children; + } + + /** + * @return int + */ + #[\ReturnTypeWillChange] + public function count() + { + return \count($this->getValue()); + } + + /** + * @return \Traversable + */ + #[\ReturnTypeWillChange] + public function getIterator() + { + if (!\is_array($value = $this->getValue())) { + throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value))); + } + + yield from $value; + } + + public function __get(string $key) + { + if (null !== $data = $this->seek($key)) { + $item = $this->getStub($data->data[$data->position][$data->key]); + + return $item instanceof Stub || [] === $item ? $data : $item; + } + + return null; + } + + /** + * @return bool + */ + public function __isset(string $key) + { + return null !== $this->seek($key); + } + + /** + * @return bool + */ + #[\ReturnTypeWillChange] + public function offsetExists($key) + { + return $this->__isset($key); + } + + /** + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($key) + { + return $this->__get($key); + } + + /** + * @return void + */ + #[\ReturnTypeWillChange] + public function offsetSet($key, $value) + { + throw new \BadMethodCallException(self::class.' objects are immutable.'); + } + + /** + * @return void + */ + #[\ReturnTypeWillChange] + public function offsetUnset($key) + { + throw new \BadMethodCallException(self::class.' objects are immutable.'); + } + + /** + * @return string + */ + public function __toString() + { + $value = $this->getValue(); + + if (!\is_array($value)) { + return (string) $value; + } + + return sprintf('%s (count=%d)', $this->getType(), \count($value)); + } + + /** + * Returns a depth limited clone of $this. + * + * @return static + */ + public function withMaxDepth(int $maxDepth) + { + $data = clone $this; + $data->maxDepth = $maxDepth; + + return $data; + } + + /** + * Limits the number of elements per depth level. + * + * @return static + */ + public function withMaxItemsPerDepth(int $maxItemsPerDepth) + { + $data = clone $this; + $data->maxItemsPerDepth = $maxItemsPerDepth; + + return $data; + } + + /** + * Enables/disables objects' identifiers tracking. + * + * @param bool $useRefHandles False to hide global ref. handles + * + * @return static + */ + public function withRefHandles(bool $useRefHandles) + { + $data = clone $this; + $data->useRefHandles = $useRefHandles ? -1 : 0; + + return $data; + } + + /** + * @return static + */ + public function withContext(array $context) + { + $data = clone $this; + $data->context = $context; + + return $data; + } + + /** + * Seeks to a specific key in nested data structures. + * + * @param string|int $key The key to seek to + * + * @return static|null + */ + public function seek($key) + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { + return null; + } + $keys = [$key]; + + switch ($item->type) { + case Stub::TYPE_OBJECT: + $keys[] = Caster::PREFIX_DYNAMIC.$key; + $keys[] = Caster::PREFIX_PROTECTED.$key; + $keys[] = Caster::PREFIX_VIRTUAL.$key; + $keys[] = "\0$item->class\0$key"; + // no break + case Stub::TYPE_ARRAY: + case Stub::TYPE_RESOURCE: + break; + default: + return null; + } + + $data = null; + $children = $this->data[$item->position]; + + foreach ($keys as $key) { + if (isset($children[$key]) || \array_key_exists($key, $children)) { + $data = clone $this; + $data->key = $key; + $data->position = $item->position; + break; + } + } + + return $data; + } + + /** + * Dumps data with a DumperInterface dumper. + */ + public function dump(DumperInterface $dumper) + { + $refs = [0]; + $cursor = new Cursor(); + + if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) { + $cursor->attr['if_links'] = true; + $cursor->hashType = -1; + $dumper->dumpScalar($cursor, 'default', '^'); + $cursor->attr = ['if_links' => true]; + $dumper->dumpScalar($cursor, 'default', ' '); + $cursor->hashType = 0; + } + + $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]); + } + + /** + * Depth-first dumping of items. + * + * @param mixed $item A Stub object or the original value being dumped + */ + private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item) + { + $cursor->refIndex = 0; + $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0; + $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0; + $firstSeen = true; + + if (!$item instanceof Stub) { + $cursor->attr = []; + $type = \gettype($item); + if ($item && 'array' === $type) { + $item = $this->getStub($item); + } + } elseif (Stub::TYPE_REF === $item->type) { + if ($item->handle) { + if (!isset($refs[$r = $item->handle - (\PHP_INT_MAX >> 1)])) { + $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; + } else { + $firstSeen = false; + } + $cursor->hardRefTo = $refs[$r]; + $cursor->hardRefHandle = $this->useRefHandles & $item->handle; + $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0; + } + $cursor->attr = $item->attr; + $type = $item->class ?: \gettype($item->value); + $item = $this->getStub($item->value); + } + if ($item instanceof Stub) { + if ($item->refCount) { + if (!isset($refs[$r = $item->handle])) { + $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; + } else { + $firstSeen = false; + } + $cursor->softRefTo = $refs[$r]; + } + $cursor->softRefHandle = $this->useRefHandles & $item->handle; + $cursor->softRefCount = $item->refCount; + $cursor->attr = $item->attr; + $cut = $item->cut; + + if ($item->position && $firstSeen) { + $children = $this->data[$item->position]; + + if ($cursor->stop) { + if ($cut >= 0) { + $cut += \count($children); + } + $children = []; + } + } else { + $children = []; + } + switch ($item->type) { + case Stub::TYPE_STRING: + $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut); + break; + + case Stub::TYPE_ARRAY: + $item = clone $item; + $item->type = $item->class; + $item->class = $item->value; + // no break + case Stub::TYPE_OBJECT: + case Stub::TYPE_RESOURCE: + $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; + $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); + if ($withChildren) { + if ($cursor->skipChildren) { + $withChildren = false; + $cut = -1; + } else { + $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + } + } elseif ($children && 0 <= $cut) { + $cut += \count($children); + } + $cursor->skipChildren = false; + $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); + break; + + default: + throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type)); + } + } elseif ('array' === $type) { + $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false); + $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0); + } elseif ('string' === $type) { + $dumper->dumpString($cursor, $item, false, 0); + } else { + $dumper->dumpScalar($cursor, $type, $item); + } + } + + /** + * Dumps children of hash structures. + * + * @return int The final number of removed items + */ + private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int + { + $cursor = clone $parentCursor; + ++$cursor->depth; + $cursor->hashType = $hashType; + $cursor->hashIndex = 0; + $cursor->hashLength = \count($children); + $cursor->hashCut = $hashCut; + foreach ($children as $key => $child) { + $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key); + $cursor->hashKey = $dumpKeys ? $key : null; + $this->dumpItem($dumper, $cursor, $refs, $child); + if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) { + $parentCursor->stop = true; + + return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut; + } + } + + return $hashCut; + } + + private function getStub($item) + { + if (!$item || !\is_array($item)) { + return $item; + } + + $stub = new Stub(); + $stub->type = Stub::TYPE_ARRAY; + foreach ($item as $stub->class => $stub->position) { + } + if (isset($item[0])) { + $stub->cut = $item[0]; + } + $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); + + return $stub; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/DumperInterface.php b/vendor/symfony/var-dumper/Cloner/DumperInterface.php new file mode 100644 index 00000000..6d60b723 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/DumperInterface.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * DumperInterface used by Data objects. + * + * @author Nicolas Grekas + */ +interface DumperInterface +{ + /** + * Dumps a scalar value. + * + * @param string $type The PHP type of the value being dumped + * @param string|int|float|bool $value The scalar value being dumped + */ + public function dumpScalar(Cursor $cursor, string $type, $value); + + /** + * Dumps a string. + * + * @param string $str The string being dumped + * @param bool $bin Whether $str is UTF-8 or binary encoded + * @param int $cut The number of characters $str has been cut by + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut); + + /** + * Dumps while entering an hash. + * + * @param int $type A Cursor::HASH_* const for the type of hash + * @param string|int $class The object class, resource type or array count + * @param bool $hasChild When the dump of the hash has child item + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild); + + /** + * Dumps while leaving an hash. + * + * @param int $type A Cursor::HASH_* const for the type of hash + * @param string|int $class The object class, resource type or array count + * @param bool $hasChild When the dump of the hash has child item + * @param int $cut The number of items the hash has been cut by + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut); +} diff --git a/vendor/symfony/var-dumper/Cloner/Stub.php b/vendor/symfony/var-dumper/Cloner/Stub.php new file mode 100644 index 00000000..073c56ef --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Stub.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * Represents the main properties of a PHP variable. + * + * @author Nicolas Grekas + */ +class Stub +{ + public const TYPE_REF = 1; + public const TYPE_STRING = 2; + public const TYPE_ARRAY = 3; + public const TYPE_OBJECT = 4; + public const TYPE_RESOURCE = 5; + + public const STRING_BINARY = 1; + public const STRING_UTF8 = 2; + + public const ARRAY_ASSOC = 1; + public const ARRAY_INDEXED = 2; + + public $type = self::TYPE_REF; + public $class = ''; + public $value; + public $cut = 0; + public $handle = 0; + public $refCount = 0; + public $position = 0; + public $attr = []; + + private static $defaultProperties = []; + + /** + * @internal + */ + public function __sleep(): array + { + $properties = []; + + if (!isset(self::$defaultProperties[$c = static::class])) { + self::$defaultProperties[$c] = get_class_vars($c); + + foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { + unset(self::$defaultProperties[$c][$k]); + } + } + + foreach (self::$defaultProperties[$c] as $k => $v) { + if ($this->$k !== $v) { + $properties[] = $k; + } + } + + return $properties; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/VarCloner.php b/vendor/symfony/var-dumper/Cloner/VarCloner.php new file mode 100644 index 00000000..80c4a2f8 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/VarCloner.php @@ -0,0 +1,311 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * @author Nicolas Grekas + */ +class VarCloner extends AbstractCloner +{ + private static $gid; + private static $arrayCache = []; + + /** + * {@inheritdoc} + */ + protected function doClone($var) + { + $len = 1; // Length of $queue + $pos = 0; // Number of cloned items past the minimum depth + $refsCounter = 0; // Hard references counter + $queue = [[$var]]; // This breadth-first queue is the return value + $hardRefs = []; // Map of original zval ids to stub objects + $objRefs = []; // Map of original object handles to their stub object counterpart + $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning + $resRefs = []; // Map of original resource handles to their stub object counterpart + $values = []; // Map of stub objects' ids to original values + $maxItems = $this->maxItems; + $maxString = $this->maxString; + $minDepth = $this->minDepth; + $currentDepth = 0; // Current tree depth + $currentDepthFinalIndex = 0; // Final $queue index for current tree depth + $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached + $cookie = (object) []; // Unique object used to detect hard references + $a = null; // Array cast for nested structures + $stub = null; // Stub capturing the main properties of an original item value + // or null if the original value is used directly + + if (!$gid = self::$gid) { + $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable + } + $arrayStub = new Stub(); + $arrayStub->type = Stub::TYPE_ARRAY; + $fromObjCast = false; + + for ($i = 0; $i < $len; ++$i) { + // Detect when we move on to the next tree depth + if ($i > $currentDepthFinalIndex) { + ++$currentDepth; + $currentDepthFinalIndex = $len - 1; + if ($currentDepth >= $minDepth) { + $minimumDepthReached = true; + } + } + + $refs = $vals = $queue[$i]; + foreach ($vals as $k => $v) { + // $v is the original value or a stub object in case of hard references + + if (\PHP_VERSION_ID >= 70400) { + $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null; + } else { + $refs[$k] = $cookie; + $zvalRef = $vals[$k] === $cookie; + } + + if ($zvalRef) { + $vals[$k] = &$stub; // Break hard references to make $queue completely + unset($stub); // independent from the original structure + if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { + if (\PHP_VERSION_ID >= 70400) { + $v = $vals[$k]; + } else { + $refs[$k] = $vals[$k] = $v; + } + if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { + ++$v->value->refCount; + } + ++$v->refCount; + continue; + } + $vals[$k] = new Stub(); + $vals[$k]->value = $v; + $vals[$k]->handle = ++$refsCounter; + + if (\PHP_VERSION_ID >= 70400) { + $hardRefs[$zvalRef] = $vals[$k]; + } else { + $refs[$k] = $vals[$k]; + $h = spl_object_id($refs[$k]); + $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; + } + } + // Create $stub when the original value $v cannot be used directly + // If $v is a nested structure, put that structure in array $a + switch (true) { + case null === $v: + case \is_bool($v): + case \is_int($v): + case \is_float($v): + continue 2; + case \is_string($v): + if ('' === $v) { + continue 2; + } + if (!preg_match('//u', $v)) { + $stub = new Stub(); + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_BINARY; + if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { + $stub->cut = $cut; + $stub->value = substr($v, 0, -$cut); + } else { + $stub->value = $v; + } + } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { + $stub = new Stub(); + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_UTF8; + $stub->cut = $cut; + $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); + } else { + continue 2; + } + $a = null; + break; + + case \is_array($v): + if (!$v) { + continue 2; + } + $stub = $arrayStub; + + if (\PHP_VERSION_ID >= 80100) { + $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC; + $a = $v; + break; + } + + $stub->class = Stub::ARRAY_INDEXED; + + $j = -1; + foreach ($v as $gk => $gv) { + if ($gk !== ++$j) { + $stub->class = Stub::ARRAY_ASSOC; + $a = $v; + $a[$gid] = true; + break; + } + } + + // Copies of $GLOBALS have very strange behavior, + // let's detect them with some black magic + if (isset($v[$gid])) { + unset($v[$gid]); + $a = []; + foreach ($v as $gk => &$gv) { + if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) { + unset($v); + $v = new Stub(); + $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0]; + $v->handle = -1; + if (\PHP_VERSION_ID >= 70400) { + $gv = &$a[$gk]; + $hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv; + } else { + $gv = &$hardRefs[spl_object_id($v)]; + } + $gv = $v; + } + + $a[$gk] = &$gv; + } + unset($gv); + } else { + $a = $v; + } + break; + + case \is_object($v): + if (empty($objRefs[$h = spl_object_id($v)])) { + $stub = new Stub(); + $stub->type = Stub::TYPE_OBJECT; + $stub->class = \get_class($v); + $stub->value = $v; + $stub->handle = $h; + $a = $this->castObject($stub, 0 < $i); + if ($v !== $stub->value) { + if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { + break; + } + $stub->handle = $h = spl_object_id($stub->value); + } + $stub->value = null; + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { + $stub->cut = \count($a); + $a = null; + } + } + if (empty($objRefs[$h])) { + $objRefs[$h] = $stub; + $objects[] = $v; + } else { + $stub = $objRefs[$h]; + ++$stub->refCount; + $a = null; + } + break; + + default: // resource + if (empty($resRefs[$h = (int) $v])) { + $stub = new Stub(); + $stub->type = Stub::TYPE_RESOURCE; + if ('Unknown' === $stub->class = @get_resource_type($v)) { + $stub->class = 'Closed'; + } + $stub->value = $v; + $stub->handle = $h; + $a = $this->castResource($stub, 0 < $i); + $stub->value = null; + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { + $stub->cut = \count($a); + $a = null; + } + } + if (empty($resRefs[$h])) { + $resRefs[$h] = $stub; + } else { + $stub = $resRefs[$h]; + ++$stub->refCount; + $a = null; + } + break; + } + + if ($a) { + if (!$minimumDepthReached || 0 > $maxItems) { + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($pos < $maxItems) { + if ($maxItems < $pos += \count($a)) { + $a = \array_slice($a, 0, $maxItems - $pos, true); + if ($stub->cut >= 0) { + $stub->cut += $pos - $maxItems; + } + } + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($stub->cut >= 0) { + $stub->cut += \count($a); + $stub->position = 0; + } + } + + if ($arrayStub === $stub) { + if ($arrayStub->cut) { + $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position]; + $arrayStub->cut = 0; + } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { + $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; + } else { + self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position]; + } + } + + if (!$zvalRef) { + $vals[$k] = $stub; + } elseif (\PHP_VERSION_ID >= 70400) { + $hardRefs[$zvalRef]->value = $stub; + } else { + $refs[$k]->value = $stub; + } + } + + if ($fromObjCast) { + $fromObjCast = false; + $refs = $vals; + $vals = []; + $j = -1; + foreach ($queue[$i] as $k => $v) { + foreach ([$k => true] as $gk => $gv) { + } + if ($gk !== $k) { + $vals = (object) $vals; + $vals->{$k} = $refs[++$j]; + $vals = (array) $vals; + } else { + $vals[$k] = $refs[++$j]; + } + } + } + + $queue[$i] = $vals; + } + + foreach ($values as $h => $v) { + $hardRefs[$h] = $v; + } + + return $queue; + } +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php new file mode 100644 index 00000000..2afaa7bf --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * Describe collected data clones for cli output. + * + * @author Maxime Steinhausser + * + * @final + */ +class CliDescriptor implements DumpDescriptorInterface +{ + private $dumper; + private $lastIdentifier; + + public function __construct(CliDumper $dumper) + { + $this->dumper = $dumper; + } + + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void + { + $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); + $this->dumper->setColors($output->isDecorated()); + + $rows = [['date', date('r', (int) $context['timestamp'])]]; + $lastIdentifier = $this->lastIdentifier; + $this->lastIdentifier = $clientId; + + $section = "Received from client #$clientId"; + if (isset($context['request'])) { + $request = $context['request']; + $this->lastIdentifier = $request['identifier']; + $section = sprintf('%s %s', $request['method'], $request['uri']); + if ($controller = $request['controller']) { + $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")]; + } + } elseif (isset($context['cli'])) { + $this->lastIdentifier = $context['cli']['identifier']; + $section = '$ '.$context['cli']['command_line']; + } + + if ($this->lastIdentifier !== $lastIdentifier) { + $io->section($section); + } + + if (isset($context['source'])) { + $source = $context['source']; + $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']); + if ($fileLink = $source['file_link'] ?? null) { + $sourceInfo = sprintf('%s', $fileLink, $sourceInfo); + } + $rows[] = ['source', $sourceInfo]; + $file = $source['file_relative'] ?? $source['file']; + $rows[] = ['file', $file]; + } + + $io->table([], $rows); + + $this->dumper->dump($data); + $io->newLine(); + } +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php b/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php new file mode 100644 index 00000000..267d27bf --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * @author Maxime Steinhausser + */ +interface DumpDescriptorInterface +{ + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void; +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php new file mode 100644 index 00000000..636b6182 --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; + +/** + * Describe collected data clones for html output. + * + * @author Maxime Steinhausser + * + * @final + */ +class HtmlDescriptor implements DumpDescriptorInterface +{ + private $dumper; + private $initialized = false; + + public function __construct(HtmlDumper $dumper) + { + $this->dumper = $dumper; + } + + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void + { + if (!$this->initialized) { + $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css'); + $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js'); + $output->writeln(""); + $this->initialized = true; + } + + $title = '-'; + if (isset($context['request'])) { + $request = $context['request']; + $controller = "{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}"; + $title = sprintf('%s %s', $request['method'], $uri = $request['uri'], $uri); + $dedupIdentifier = $request['identifier']; + } elseif (isset($context['cli'])) { + $title = '$ '.$context['cli']['command_line']; + $dedupIdentifier = $context['cli']['identifier']; + } else { + $dedupIdentifier = uniqid('', true); + } + + $sourceDescription = ''; + if (isset($context['source'])) { + $source = $context['source']; + $projectDir = $source['project_dir'] ?? null; + $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']); + if (isset($source['file_link'])) { + $sourceDescription = sprintf('%s', $source['file_link'], $sourceDescription); + } + } + + $isoDate = $this->extractDate($context, 'c'); + $tags = array_filter([ + 'controller' => $controller ?? null, + 'project dir' => $projectDir ?? null, + ]); + + $output->writeln(<< +
+
+

$title

+ +
+ {$this->renderTags($tags)} +
+
+

+ $sourceDescription +

+ {$this->dumper->dump($data, true)} +
+ +HTML + ); + } + + private function extractDate(array $context, string $format = 'r'): string + { + return date($format, (int) $context['timestamp']); + } + + private function renderTags(array $tags): string + { + if (!$tags) { + return ''; + } + + $renderedTags = ''; + foreach ($tags as $key => $value) { + $renderedTags .= sprintf('
  • %s%s
  • ', $key, $value); + } + + return << +
      + $renderedTags +
    + +HTML; + } +} diff --git a/vendor/symfony/var-dumper/Command/ServerDumpCommand.php b/vendor/symfony/var-dumper/Command/ServerDumpCommand.php new file mode 100644 index 00000000..3a695952 --- /dev/null +++ b/vendor/symfony/var-dumper/Command/ServerDumpCommand.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; +use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface; +use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\DumpServer; + +/** + * Starts a dump server to collect and output dumps on a single place with multiple formats support. + * + * @author Maxime Steinhausser + * + * @final + */ +class ServerDumpCommand extends Command +{ + protected static $defaultName = 'server:dump'; + protected static $defaultDescription = 'Start a dump server that collects and displays dumps in a single place'; + + private $server; + + /** @var DumpDescriptorInterface[] */ + private $descriptors; + + public function __construct(DumpServer $server, array $descriptors = []) + { + $this->server = $server; + $this->descriptors = $descriptors + [ + 'cli' => new CliDescriptor(new CliDumper()), + 'html' => new HtmlDescriptor(new HtmlDumper()), + ]; + + parent::__construct(); + } + + protected function configure() + { + $this + ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli') + ->setDescription(self::$defaultDescription) + ->setHelp(<<<'EOF' +%command.name% starts a dump server that collects and displays +dumps in a single place for debugging you application: + + php %command.full_name% + +You can consult dumped data in HTML format in your browser by providing the --format=html option +and redirecting the output to a file: + + php %command.full_name% --format="html" > dump.html + +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $format = $input->getOption('format'); + + if (!$descriptor = $this->descriptors[$format] ?? null) { + throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format)); + } + + $errorIo = $io->getErrorStyle(); + $errorIo->title('Symfony Var Dumper Server'); + + $this->server->start(); + + $errorIo->success(sprintf('Server listening on %s', $this->server->getHost())); + $errorIo->comment('Quit the server with CONTROL-C.'); + + $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) { + $descriptor->describe($io, $data, $context, $clientId); + }); + + return 0; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestOptionValuesFor('format')) { + $suggestions->suggestValues($this->getAvailableFormats()); + } + } + + private function getAvailableFormats(): array + { + return array_keys($this->descriptors); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php new file mode 100644 index 00000000..66da669d --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\DumperInterface; + +/** + * Abstract mechanism for dumping a Data object. + * + * @author Nicolas Grekas + */ +abstract class AbstractDumper implements DataDumperInterface, DumperInterface +{ + public const DUMP_LIGHT_ARRAY = 1; + public const DUMP_STRING_LENGTH = 2; + public const DUMP_COMMA_SEPARATOR = 4; + public const DUMP_TRAILING_COMMA = 8; + + public static $defaultOutput = 'php://output'; + + protected $line = ''; + protected $lineDumper; + protected $outputStream; + protected $decimalPoint; // This is locale dependent + protected $indentPad = ' '; + protected $flags; + + private $charset = ''; + + /** + * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput + * @param string|null $charset The default character encoding to use for non-UTF8 strings + * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation + */ + public function __construct($output = null, ?string $charset = null, int $flags = 0) + { + $this->flags = $flags; + $this->setCharset($charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8'); + $this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point']; + $this->setOutput($output ?: static::$defaultOutput); + if (!$output && \is_string(static::$defaultOutput)) { + static::$defaultOutput = $this->outputStream; + } + } + + /** + * Sets the output destination of the dumps. + * + * @param callable|resource|string $output A line dumper callable, an opened stream or an output path + * + * @return callable|resource|string The previous output destination + */ + public function setOutput($output) + { + $prev = $this->outputStream ?? $this->lineDumper; + + if (\is_callable($output)) { + $this->outputStream = null; + $this->lineDumper = $output; + } else { + if (\is_string($output)) { + $output = fopen($output, 'w'); + } + $this->outputStream = $output; + $this->lineDumper = [$this, 'echoLine']; + } + + return $prev; + } + + /** + * Sets the default character encoding to use for non-UTF8 strings. + * + * @return string The previous charset + */ + public function setCharset(string $charset) + { + $prev = $this->charset; + + $charset = strtoupper($charset); + $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset; + + $this->charset = $charset; + + return $prev; + } + + /** + * Sets the indentation pad string. + * + * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level + * + * @return string The previous indent pad + */ + public function setIndentPad(string $pad) + { + $prev = $this->indentPad; + $this->indentPad = $pad; + + return $prev; + } + + /** + * Dumps a Data object. + * + * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump + * + * @return string|null The dump as string when $output is true + */ + public function dump(Data $data, $output = null) + { + $this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point']; + + if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\LC_NUMERIC, 0) : null) { + setlocale(\LC_NUMERIC, 'C'); + } + + if ($returnDump = true === $output) { + $output = fopen('php://memory', 'r+'); + } + if ($output) { + $prevOutput = $this->setOutput($output); + } + try { + $data->dump($this); + $this->dumpLine(-1); + + if ($returnDump) { + $result = stream_get_contents($output, -1, 0); + fclose($output); + + return $result; + } + } finally { + if ($output) { + $this->setOutput($prevOutput); + } + if ($locale) { + setlocale(\LC_NUMERIC, $locale); + } + } + + return null; + } + + /** + * Dumps the current line. + * + * @param int $depth The recursive depth in the dumped structure for the line being dumped, + * or -1 to signal the end-of-dump to the line dumper callable + */ + protected function dumpLine(int $depth) + { + ($this->lineDumper)($this->line, $depth, $this->indentPad); + $this->line = ''; + } + + /** + * Generic line dumper callback. + */ + protected function echoLine(string $line, int $depth, string $indentPad) + { + if (-1 !== $depth) { + fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n"); + } + } + + /** + * Converts a non-UTF-8 string to UTF-8. + * + * @return string|null + */ + protected function utf8Encode(?string $s) + { + if (null === $s || preg_match('//u', $s)) { + return $s; + } + + if (!\function_exists('iconv')) { + throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); + } + + if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { + return $c; + } + if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { + return $c; + } + + return iconv('CP850', 'UTF-8', $s); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/CliDumper.php b/vendor/symfony/var-dumper/Dumper/CliDumper.php new file mode 100644 index 00000000..da1d5b2d --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/CliDumper.php @@ -0,0 +1,674 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Cursor; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * CliDumper dumps variables for command line output. + * + * @author Nicolas Grekas + */ +class CliDumper extends AbstractDumper +{ + public static $defaultColors; + public static $defaultOutput = 'php://stdout'; + + protected $colors; + protected $maxStringWidth = 0; + protected $styles = [ + // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + 'default' => '0;38;5;208', + 'num' => '1;38;5;38', + 'const' => '1;38;5;208', + 'str' => '1;38;5;113', + 'note' => '38;5;38', + 'ref' => '38;5;247', + 'public' => '', + 'protected' => '', + 'private' => '', + 'meta' => '38;5;170', + 'key' => '38;5;113', + 'index' => '38;5;38', + ]; + + protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/'; + protected static $controlCharsMap = [ + "\t" => '\t', + "\n" => '\n', + "\v" => '\v', + "\f" => '\f', + "\r" => '\r', + "\033" => '\e', + ]; + + protected $collapseNextHash = false; + protected $expandNextHash = false; + + private $displayOptions = [ + 'fileLinkFormat' => null, + ]; + + private $handlesHrefGracefully; + + /** + * {@inheritdoc} + */ + public function __construct($output = null, ?string $charset = null, int $flags = 0) + { + parent::__construct($output, $charset, $flags); + + if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { + // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI + $this->setStyles([ + 'default' => '31', + 'num' => '1;34', + 'const' => '1;31', + 'str' => '1;32', + 'note' => '34', + 'ref' => '1;30', + 'meta' => '35', + 'key' => '32', + 'index' => '34', + ]); + } + + $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; + } + + /** + * Enables/disables colored output. + */ + public function setColors(bool $colors) + { + $this->colors = $colors; + } + + /** + * Sets the maximum number of characters per line for dumped strings. + */ + public function setMaxStringWidth(int $maxStringWidth) + { + $this->maxStringWidth = $maxStringWidth; + } + + /** + * Configures styles. + * + * @param array $styles A map of style names to style definitions + */ + public function setStyles(array $styles) + { + $this->styles = $styles + $this->styles; + } + + /** + * Configures display options. + * + * @param array $displayOptions A map of display options to customize the behavior + */ + public function setDisplayOptions(array $displayOptions) + { + $this->displayOptions = $displayOptions + $this->displayOptions; + } + + /** + * {@inheritdoc} + */ + public function dumpScalar(Cursor $cursor, string $type, $value) + { + $this->dumpKey($cursor); + $this->collapseNextHash = $this->expandNextHash = false; + + $style = 'const'; + $attr = $cursor->attr; + + switch ($type) { + case 'default': + $style = 'default'; + break; + + case 'integer': + $style = 'num'; + + if (isset($this->styles['integer'])) { + $style = 'integer'; + } + + break; + + case 'double': + $style = 'num'; + + if (isset($this->styles['float'])) { + $style = 'float'; + } + + switch (true) { + case \INF === $value: $value = 'INF'; break; + case -\INF === $value: $value = '-INF'; break; + case is_nan($value): $value = 'NAN'; break; + default: + $value = (string) $value; + if (!str_contains($value, $this->decimalPoint)) { + $value .= $this->decimalPoint.'0'; + } + break; + } + break; + + case 'NULL': + $value = 'null'; + break; + + case 'boolean': + $value = $value ? 'true' : 'false'; + break; + + default: + $attr += ['value' => $this->utf8Encode($value)]; + $value = $this->utf8Encode($type); + break; + } + + $this->line .= $this->style($style, $value, $attr); + + $this->endValue($cursor); + } + + /** + * {@inheritdoc} + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) + { + $this->dumpKey($cursor); + $this->collapseNextHash = $this->expandNextHash = false; + $attr = $cursor->attr; + + if ($bin) { + $str = $this->utf8Encode($str); + } + if ('' === $str) { + $this->line .= '""'; + if ($cut) { + $this->line .= '…'.$cut; + } + $this->endValue($cursor); + } else { + $attr += [ + 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, + 'binary' => $bin, + ]; + $str = $bin && false !== strpos($str, "\0") ? [$str] : explode("\n", $str); + if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) { + unset($str[1]); + $str[0] .= "\n"; + } + $m = \count($str) - 1; + $i = $lineCut = 0; + + if (self::DUMP_STRING_LENGTH & $this->flags) { + $this->line .= '('.$attr['length'].') '; + } + if ($bin) { + $this->line .= 'b'; + } + + if ($m) { + $this->line .= '"""'; + $this->dumpLine($cursor->depth); + } else { + $this->line .= '"'; + } + + foreach ($str as $str) { + if ($i < $m) { + $str .= "\n"; + } + if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) { + $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8'); + $lineCut = $len - $this->maxStringWidth; + } + if ($m && 0 < $cursor->depth) { + $this->line .= $this->indentPad; + } + if ('' !== $str) { + $this->line .= $this->style('str', $str, $attr); + } + if ($i++ == $m) { + if ($m) { + if ('' !== $str) { + $this->dumpLine($cursor->depth); + if (0 < $cursor->depth) { + $this->line .= $this->indentPad; + } + } + $this->line .= '"""'; + } else { + $this->line .= '"'; + } + if ($cut < 0) { + $this->line .= '…'; + $lineCut = 0; + } elseif ($cut) { + $lineCut += $cut; + } + } + if ($lineCut) { + $this->line .= '…'.$lineCut; + $lineCut = 0; + } + + if ($i > $m) { + $this->endValue($cursor); + } else { + $this->dumpLine($cursor->depth); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) + { + if (null === $this->colors) { + $this->colors = $this->supportsColors(); + } + + $this->dumpKey($cursor); + $this->expandNextHash = false; + $attr = $cursor->attr; + + if ($this->collapseNextHash) { + $cursor->skipChildren = true; + $this->collapseNextHash = $hasChild = false; + } + + $class = $this->utf8Encode($class); + if (Cursor::HASH_OBJECT === $type) { + $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{'; + } elseif (Cursor::HASH_RESOURCE === $type) { + $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' '); + } else { + $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '['; + } + + if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) { + $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]); + } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) { + $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]); + } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) { + $prefix = substr($prefix, 0, -1); + } + + $this->line .= $prefix; + + if ($hasChild) { + $this->dumpLine($cursor->depth); + } + } + + /** + * {@inheritdoc} + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) + { + if (empty($cursor->attr['cut_hash'])) { + $this->dumpEllipsis($cursor, $hasChild, $cut); + $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : '')); + } + + $this->endValue($cursor); + } + + /** + * Dumps an ellipsis for cut children. + * + * @param bool $hasChild When the dump of the hash has child item + * @param int $cut The number of items the hash has been cut by + */ + protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut) + { + if ($cut) { + $this->line .= ' …'; + if (0 < $cut) { + $this->line .= $cut; + } + if ($hasChild) { + $this->dumpLine($cursor->depth + 1); + } + } + } + + /** + * Dumps a key in a hash structure. + */ + protected function dumpKey(Cursor $cursor) + { + if (null !== $key = $cursor->hashKey) { + if ($cursor->hashKeyIsBinary) { + $key = $this->utf8Encode($key); + } + $attr = ['binary' => $cursor->hashKeyIsBinary]; + $bin = $cursor->hashKeyIsBinary ? 'b' : ''; + $style = 'key'; + switch ($cursor->hashType) { + default: + case Cursor::HASH_INDEXED: + if (self::DUMP_LIGHT_ARRAY & $this->flags) { + break; + } + $style = 'index'; + // no break + case Cursor::HASH_ASSOC: + if (\is_int($key)) { + $this->line .= $this->style($style, $key).' => '; + } else { + $this->line .= $bin.'"'.$this->style($style, $key).'" => '; + } + break; + + case Cursor::HASH_RESOURCE: + $key = "\0~\0".$key; + // no break + case Cursor::HASH_OBJECT: + if (!isset($key[0]) || "\0" !== $key[0]) { + $this->line .= '+'.$bin.$this->style('public', $key).': '; + } elseif (0 < strpos($key, "\0", 1)) { + $key = explode("\0", substr($key, 1), 2); + + switch ($key[0][0]) { + case '+': // User inserted keys + $attr['dynamic'] = true; + $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": '; + break 2; + case '~': + $style = 'meta'; + if (isset($key[0][1])) { + parse_str(substr($key[0], 1), $attr); + $attr += ['binary' => $cursor->hashKeyIsBinary]; + } + break; + case '*': + $style = 'protected'; + $bin = '#'.$bin; + break; + default: + $attr['class'] = $key[0]; + $style = 'private'; + $bin = '-'.$bin; + break; + } + + if (isset($attr['collapse'])) { + if ($attr['collapse']) { + $this->collapseNextHash = true; + } else { + $this->expandNextHash = true; + } + } + + $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': '); + } else { + // This case should not happen + $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": '; + } + break; + } + + if ($cursor->hardRefTo) { + $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' '; + } + } + } + + /** + * Decorates a value with some style. + * + * @param string $style The type of style being applied + * @param string $value The value being styled + * @param array $attr Optional context information + * + * @return string + */ + protected function style(string $style, string $value, array $attr = []) + { + if (null === $this->colors) { + $this->colors = $this->supportsColors(); + } + + if (null === $this->handlesHrefGracefully) { + $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); + } + + if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { + $prefix = substr($value, 0, -$attr['ellipsis']); + if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) { + $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd])); + } + if (!empty($attr['ellipsis-tail'])) { + $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); + $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); + } else { + $value = substr($value, -$attr['ellipsis']); + } + + $value = $this->style('default', $prefix).$this->style($style, $value); + + goto href; + } + + $map = static::$controlCharsMap; + $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : ''; + $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : ''; + $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) { + $s = $startCchr; + $c = $c[$i = 0]; + do { + $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i])); + } while (isset($c[++$i])); + + return $s.$endCchr; + }, $value, -1, $cchrCount); + + if ($this->colors) { + if ($cchrCount && "\033" === $value[0]) { + $value = substr($value, \strlen($startCchr)); + } else { + $value = "\033[{$this->styles[$style]}m".$value; + } + if ($cchrCount && str_ends_with($value, $endCchr)) { + $value = substr($value, 0, -\strlen($endCchr)); + } else { + $value .= "\033[{$this->styles['default']}m"; + } + } + + href: + if ($this->colors && $this->handlesHrefGracefully) { + if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { + if ('note' === $style) { + $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\"; + } else { + $attr['href'] = $href; + } + } + if (isset($attr['href'])) { + $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\"; + } + } elseif ($attr['if_links'] ?? false) { + return ''; + } + + return $value; + } + + /** + * @return bool + */ + protected function supportsColors() + { + if ($this->outputStream !== static::$defaultOutput) { + return $this->hasColorSupport($this->outputStream); + } + if (null !== static::$defaultColors) { + return static::$defaultColors; + } + if (isset($_SERVER['argv'][1])) { + $colors = $_SERVER['argv']; + $i = \count($colors); + while (--$i > 0) { + if (isset($colors[$i][5])) { + switch ($colors[$i]) { + case '--ansi': + case '--color': + case '--color=yes': + case '--color=force': + case '--color=always': + case '--colors=always': + return static::$defaultColors = true; + + case '--no-ansi': + case '--color=no': + case '--color=none': + case '--color=never': + case '--colors=never': + return static::$defaultColors = false; + } + } + } + } + + $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null]; + $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream; + + return static::$defaultColors = $this->hasColorSupport($h); + } + + /** + * {@inheritdoc} + */ + protected function dumpLine(int $depth, bool $endOfValue = false) + { + if (null === $this->colors) { + $this->colors = $this->supportsColors(); + } + + if ($this->colors) { + $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line); + } + parent::dumpLine($depth); + } + + protected function endValue(Cursor $cursor) + { + if (-1 === $cursor->hashType) { + return; + } + + if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) { + if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) { + $this->line .= ','; + } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) { + $this->line .= ','; + } + } + + $this->dumpLine($cursor->depth, true); + } + + /** + * Returns true if the stream supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @param mixed $stream A CLI output stream + */ + private function hasColorSupport($stream): bool + { + if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { + return false; + } + + // Follow https://no-color.org/ + if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) { + return false; + } + + // Detect msysgit/mingw and assume this is a tty because detection + // does not work correctly, see https://github.com/composer/composer/issues/9690 + if (!@stream_isatty($stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($stream)) { + return true; + } + + if ('Hyper' === getenv('TERM_PROGRAM') + || false !== getenv('COLORTERM') + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + ) { + return true; + } + + if ('dumb' === $term = (string) getenv('TERM')) { + return false; + } + + // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157 + return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term); + } + + /** + * Returns true if the Windows terminal supports true color. + * + * Note that this does not check an output stream, but relies on environment + * variables from known implementations, or a PHP and Windows version that + * supports true color. + */ + private function isWindowsTrueColor(): bool + { + $result = 183 <= getenv('ANSICON_VER') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); + + if (!$result) { + $version = sprintf( + '%s.%s.%s', + PHP_WINDOWS_VERSION_MAJOR, + PHP_WINDOWS_VERSION_MINOR, + PHP_WINDOWS_VERSION_BUILD + ); + $result = $version >= '10.0.15063'; + } + + return $result; + } + + private function getSourceLink(string $file, int $line) + { + if ($fmt = $this->displayOptions['fileLinkFormat']) { + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line); + } + + return false; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php new file mode 100644 index 00000000..38f87897 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +/** + * Tries to provide context on CLI. + * + * @author Maxime Steinhausser + */ +final class CliContextProvider implements ContextProviderInterface +{ + public function getContext(): ?array + { + if ('cli' !== \PHP_SAPI) { + return null; + } + + return [ + 'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []), + 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), + ]; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php new file mode 100644 index 00000000..532aa0f9 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +/** + * Interface to provide contextual data about dump data clones sent to a server. + * + * @author Maxime Steinhausser + */ +interface ContextProviderInterface +{ + public function getContext(): ?array; +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php new file mode 100644 index 00000000..3684a475 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; +use Symfony\Component\VarDumper\Cloner\VarCloner; + +/** + * Tries to provide context from a request. + * + * @author Maxime Steinhausser + */ +final class RequestContextProvider implements ContextProviderInterface +{ + private $requestStack; + private $cloner; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(0); + $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); + } + + public function getContext(): ?array + { + if (null === $request = $this->requestStack->getCurrentRequest()) { + return null; + } + + $controller = $request->attributes->get('_controller'); + + return [ + 'uri' => $request->getUri(), + 'method' => $request->getMethod(), + 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, + 'identifier' => spl_object_hash($request), + ]; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php new file mode 100644 index 00000000..dee887ec --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\VarDumper; +use Twig\Template; + +/** + * Tries to provide context from sources (class name, file, line, code excerpt, ...). + * + * @author Nicolas Grekas + * @author Maxime Steinhausser + */ +final class SourceContextProvider implements ContextProviderInterface +{ + private $limit; + private $charset; + private $projectDir; + private $fileLinkFormatter; + + public function __construct(?string $charset = null, ?string $projectDir = null, ?FileLinkFormatter $fileLinkFormatter = null, int $limit = 9) + { + $this->charset = $charset; + $this->projectDir = $projectDir; + $this->fileLinkFormatter = $fileLinkFormatter; + $this->limit = $limit; + } + + public function getContext(): ?array + { + $trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit); + + $file = $trace[1]['file']; + $line = $trace[1]['line']; + $name = '-' === $file || 'Standard input code' === $file ? 'Standard input code' : false; + $fileExcerpt = false; + + for ($i = 2; $i < $this->limit; ++$i) { + if (isset($trace[$i]['class'], $trace[$i]['function']) + && 'dump' === $trace[$i]['function'] + && VarDumper::class === $trace[$i]['class'] + ) { + $file = $trace[$i]['file'] ?? $file; + $line = $trace[$i]['line'] ?? $line; + + while (++$i < $this->limit) { + if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) { + $file = $trace[$i]['file']; + $line = $trace[$i]['line']; + + break; + } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { + $template = $trace[$i]['object']; + $name = $template->getTemplateName(); + $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); + $info = $template->getDebugInfo(); + if (isset($info[$trace[$i - 1]['line']])) { + $line = $info[$trace[$i - 1]['line']]; + $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; + + if ($src) { + $src = explode("\n", $src); + $fileExcerpt = []; + + for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) { + $fileExcerpt[] = ''.$this->htmlEncode($src[$i - 1]).''; + } + + $fileExcerpt = '
      '.implode("\n", $fileExcerpt).'
    '; + } + } + break; + } + } + break; + } + } + + if (false === $name) { + $name = str_replace('\\', '/', $file); + $name = substr($name, strrpos($name, '/') + 1); + } + + $context = ['name' => $name, 'file' => $file, 'line' => $line]; + $context['file_excerpt'] = $fileExcerpt; + + if (null !== $this->projectDir) { + $context['project_dir'] = $this->projectDir; + if (str_starts_with($file, $this->projectDir)) { + $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); + } + } + + if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) { + $context['file_link'] = $fileLink; + } + + return $context; + } + + private function htmlEncode(string $s): string + { + $html = ''; + + $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); + $dumper->setDumpHeader(''); + $dumper->setDumpBoundaries('', ''); + + $cloner = new VarCloner(); + $dumper->dump($cloner->cloneVar($s)); + + return substr(strip_tags($html), 1, -1); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php b/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php new file mode 100644 index 00000000..76384176 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; + +/** + * @author Kévin Thérage + */ +class ContextualizedDumper implements DataDumperInterface +{ + private $wrappedDumper; + private $contextProviders; + + /** + * @param ContextProviderInterface[] $contextProviders + */ + public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders) + { + $this->wrappedDumper = $wrappedDumper; + $this->contextProviders = $contextProviders; + } + + public function dump(Data $data) + { + $context = []; + foreach ($this->contextProviders as $contextProvider) { + $context[\get_class($contextProvider)] = $contextProvider->getContext(); + } + + $this->wrappedDumper->dump($data->withContext($context)); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php b/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php new file mode 100644 index 00000000..b173bccf --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * DataDumperInterface for dumping Data objects. + * + * @author Nicolas Grekas + */ +interface DataDumperInterface +{ + public function dump(Data $data); +} diff --git a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php new file mode 100644 index 00000000..55030cfd --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php @@ -0,0 +1,986 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Cursor; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * HtmlDumper dumps variables as HTML. + * + * @author Nicolas Grekas + */ +class HtmlDumper extends CliDumper +{ + public static $defaultOutput = 'php://output'; + + protected static $themes = [ + 'dark' => [ + 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', + 'num' => 'font-weight:bold; color:#1299DA', + 'const' => 'font-weight:bold', + 'str' => 'font-weight:bold; color:#56DB3A', + 'note' => 'color:#1299DA', + 'ref' => 'color:#A0A0A0', + 'public' => 'color:#FFFFFF', + 'protected' => 'color:#FFFFFF', + 'private' => 'color:#FFFFFF', + 'meta' => 'color:#B729D9', + 'key' => 'color:#56DB3A', + 'index' => 'color:#1299DA', + 'ellipsis' => 'color:#FF8400', + 'ns' => 'user-select:none;', + ], + 'light' => [ + 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', + 'num' => 'font-weight:bold; color:#1299DA', + 'const' => 'font-weight:bold', + 'str' => 'font-weight:bold; color:#629755;', + 'note' => 'color:#6897BB', + 'ref' => 'color:#6E6E6E', + 'public' => 'color:#262626', + 'protected' => 'color:#262626', + 'private' => 'color:#262626', + 'meta' => 'color:#B729D9', + 'key' => 'color:#789339', + 'index' => 'color:#1299DA', + 'ellipsis' => 'color:#CC7832', + 'ns' => 'user-select:none;', + ], + ]; + + protected $dumpHeader; + protected $dumpPrefix = '
    ';
    +    protected $dumpSuffix = '
    '; + protected $dumpId = 'sf-dump'; + protected $colors = true; + protected $headerIsDumped = false; + protected $lastDepth = -1; + protected $styles; + + private $displayOptions = [ + 'maxDepth' => 1, + 'maxStringLength' => 160, + 'fileLinkFormat' => null, + ]; + private $extraDisplayOptions = []; + + /** + * {@inheritdoc} + */ + public function __construct($output = null, ?string $charset = null, int $flags = 0) + { + AbstractDumper::__construct($output, $charset, $flags); + $this->dumpId = 'sf-dump-'.mt_rand(); + $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->styles = static::$themes['dark'] ?? self::$themes['dark']; + } + + /** + * {@inheritdoc} + */ + public function setStyles(array $styles) + { + $this->headerIsDumped = false; + $this->styles = $styles + $this->styles; + } + + public function setTheme(string $themeName) + { + if (!isset(static::$themes[$themeName])) { + throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); + } + + $this->setStyles(static::$themes[$themeName]); + } + + /** + * Configures display options. + * + * @param array $displayOptions A map of display options to customize the behavior + */ + public function setDisplayOptions(array $displayOptions) + { + $this->headerIsDumped = false; + $this->displayOptions = $displayOptions + $this->displayOptions; + } + + /** + * Sets an HTML header that will be dumped once in the output stream. + */ + public function setDumpHeader(?string $header) + { + $this->dumpHeader = $header; + } + + /** + * Sets an HTML prefix and suffix that will encapse every single dump. + */ + public function setDumpBoundaries(string $prefix, string $suffix) + { + $this->dumpPrefix = $prefix; + $this->dumpSuffix = $suffix; + } + + /** + * {@inheritdoc} + */ + public function dump(Data $data, $output = null, array $extraDisplayOptions = []) + { + $this->extraDisplayOptions = $extraDisplayOptions; + $result = parent::dump($data, $output); + $this->dumpId = 'sf-dump-'.mt_rand(); + + return $result; + } + + /** + * Dumps the HTML header. + */ + protected function getDumpHeader() + { + $this->headerIsDumped = $this->outputStream ?? $this->lineDumper; + + if (null !== $this->dumpHeader) { + return $this->dumpHeader; + } + + $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML' +'.$this->dumpHeader; + } + + /** + * {@inheritdoc} + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) + { + if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { + $this->dumpKey($cursor); + $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []); + $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' ' : ' '; + $this->endValue($cursor); + $this->line .= $this->indentPad; + $this->line .= sprintf('', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); + $this->endValue($cursor); + } else { + parent::dumpString($cursor, $str, $bin, $cut); + } + } + + /** + * {@inheritdoc} + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) + { + if (Cursor::HASH_OBJECT === $type) { + $cursor->attr['depth'] = $cursor->depth; + } + parent::enterHash($cursor, $type, $class, false); + + if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) { + $cursor->skipChildren = false; + $eol = ' class=sf-dump-compact>'; + } else { + $this->expandNextHash = false; + $eol = ' class=sf-dump-expanded>'; + } + + if ($hasChild) { + $this->line .= 'dumpId, $r); + } + $this->line .= $eol; + $this->dumpLine($cursor->depth); + } + } + + /** + * {@inheritdoc} + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) + { + $this->dumpEllipsis($cursor, $hasChild, $cut); + if ($hasChild) { + $this->line .= ''; + } + parent::leaveHash($cursor, $type, $class, $hasChild, 0); + } + + /** + * {@inheritdoc} + */ + protected function style(string $style, string $value, array $attr = []) + { + if ('' === $value) { + return ''; + } + + $v = esc($value); + + if ('ref' === $style) { + if (empty($attr['count'])) { + return sprintf('%s', $v); + } + $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); + + return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v); + } + + if ('const' === $style && isset($attr['value'])) { + $style .= sprintf(' title="%s"', esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); + } elseif ('public' === $style) { + $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); + } elseif ('str' === $style && 1 < $attr['length']) { + $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); + } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { + $style .= ' title=""'; + $attr += [ + 'ellipsis' => \strlen($value) - $c, + 'ellipsis-type' => 'note', + 'ellipsis-tail' => 1, + ]; + } elseif ('protected' === $style) { + $style .= ' title="Protected property"'; + } elseif ('meta' === $style && isset($attr['title'])) { + $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); + } elseif ('private' === $style) { + $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); + } + $map = static::$controlCharsMap; + + if (isset($attr['ellipsis'])) { + $class = 'sf-dump-ellipsis'; + if (isset($attr['ellipsis-type'])) { + $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); + } + $label = esc(substr($value, -$attr['ellipsis'])); + $style = str_replace(' title="', " title=\"$v\n", $style); + $v = sprintf('%s', $class, substr($v, 0, -\strlen($label))); + + if (!empty($attr['ellipsis-tail'])) { + $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); + $v .= sprintf('%s%s', $class, substr($label, 0, $tail), substr($label, $tail)); + } else { + $v .= $label; + } + } + + $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { + $s = $b = ''; + }, $v).''; + + if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { + $attr['href'] = $href; + } + if (isset($attr['href'])) { + $target = isset($attr['file']) ? '' : ' target="_blank"'; + $v = sprintf('%s', esc($this->utf8Encode($attr['href'])), $target, $v); + } + if (isset($attr['lang'])) { + $v = sprintf('%s', esc($attr['lang']), $v); + } + + return $v; + } + + /** + * {@inheritdoc} + */ + protected function dumpLine(int $depth, bool $endOfValue = false) + { + if (-1 === $this->lastDepth) { + $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; + } + if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) { + $this->line = $this->getDumpHeader().$this->line; + } + + if (-1 === $depth) { + $args = ['"'.$this->dumpId.'"']; + if ($this->extraDisplayOptions) { + $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT); + } + // Replace is for BC + $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); + } + $this->lastDepth = $depth; + + $this->line = mb_encode_numericentity($this->line, [0x80, 0x10FFFF, 0, 0x1FFFFF], 'UTF-8'); + + if (-1 === $depth) { + AbstractDumper::dumpLine(0); + } + AbstractDumper::dumpLine($depth); + } + + private function getSourceLink(string $file, int $line) + { + $options = $this->extraDisplayOptions + $this->displayOptions; + + if ($fmt = $options['fileLinkFormat']) { + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); + } + + return false; + } +} + +function esc(string $str) +{ + return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8'); +} diff --git a/vendor/symfony/var-dumper/Dumper/ServerDumper.php b/vendor/symfony/var-dumper/Dumper/ServerDumper.php new file mode 100644 index 00000000..b8871b00 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ServerDumper.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; +use Symfony\Component\VarDumper\Server\Connection; + +/** + * ServerDumper forwards serialized Data clones to a server. + * + * @author Maxime Steinhausser + */ +class ServerDumper implements DataDumperInterface +{ + private $connection; + private $wrappedDumper; + + /** + * @param string $host The server host + * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server + * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name + */ + public function __construct(string $host, ?DataDumperInterface $wrappedDumper = null, array $contextProviders = []) + { + $this->connection = new Connection($host, $contextProviders); + $this->wrappedDumper = $wrappedDumper; + } + + public function getContextProviders(): array + { + return $this->connection->getContextProviders(); + } + + /** + * {@inheritdoc} + */ + public function dump(Data $data) + { + if (!$this->connection->write($data) && $this->wrappedDumper) { + $this->wrappedDumper->dump($data); + } + } +} diff --git a/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php b/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php new file mode 100644 index 00000000..122f0d35 --- /dev/null +++ b/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Exception; + +/** + * @author Nicolas Grekas + */ +class ThrowingCasterException extends \Exception +{ + /** + * @param \Throwable $prev The exception thrown from the caster + */ + public function __construct(\Throwable $prev) + { + parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev); + } +} diff --git a/vendor/symfony/var-dumper/LICENSE b/vendor/symfony/var-dumper/LICENSE new file mode 100644 index 00000000..29f72d5e --- /dev/null +++ b/vendor/symfony/var-dumper/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-present Fabien Potencier + +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. diff --git a/vendor/symfony/var-dumper/README.md b/vendor/symfony/var-dumper/README.md new file mode 100644 index 00000000..a0da8c9a --- /dev/null +++ b/vendor/symfony/var-dumper/README.md @@ -0,0 +1,15 @@ +VarDumper Component +=================== + +The VarDumper component provides mechanisms for walking through any arbitrary +PHP variable. It provides a better `dump()` function that you can use instead +of `var_dump()`. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-dumper/Resources/bin/var-dump-server b/vendor/symfony/var-dumper/Resources/bin/var-dump-server new file mode 100644 index 00000000..f398fcef --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/bin/var-dump-server @@ -0,0 +1,67 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if ('cli' !== PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + +/** + * Starts a dump server to collect and output dumps on a single place with multiple formats support. + * + * @author Maxime Steinhausser + */ + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Logger\ConsoleLogger; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Server\DumpServer; + +function includeIfExists(string $file): bool +{ + return file_exists($file) && include $file; +} + +if ( + !includeIfExists(__DIR__ . '/../../../../autoload.php') && + !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && + !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') +) { + fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); + exit(1); +} + +if (!class_exists(Application::class)) { + fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL); + exit(1); +} + +$input = new ArgvInput(); +$output = new ConsoleOutput(); +$defaultHost = '127.0.0.1:9912'; +$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true); +$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null; + +$app = new Application(); + +$app->getDefinition()->addOption( + new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost) +); + +$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger))) + ->getApplication() + ->setDefaultCommand($command->getName(), true) + ->run($input, $output) +; diff --git a/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css b/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css new file mode 100644 index 00000000..8f706d64 --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css @@ -0,0 +1,130 @@ +body { + display: flex; + flex-direction: column-reverse; + justify-content: flex-end; + max-width: 1140px; + margin: auto; + padding: 15px; + word-wrap: break-word; + background-color: #F9F9F9; + color: #222; + font-family: Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.4; +} +p { + margin: 0; +} +a { + color: #218BC3; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +.text-small { + font-size: 12px !important; +} +article { + margin: 5px; + margin-bottom: 10px; +} +article > header > .row { + display: flex; + flex-direction: row; + align-items: baseline; + margin-bottom: 10px; +} +article > header > .row > .col { + flex: 1; + display: flex; + align-items: baseline; +} +article > header > .row > h2 { + font-size: 14px; + color: #222; + font-weight: normal; + font-family: "Lucida Console", monospace, sans-serif; + word-break: break-all; + margin: 20px 5px 0 0; + user-select: all; +} +article > header > .row > h2 > code { + white-space: nowrap; + user-select: none; + color: #cc2255; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + border-radius: 3px; + margin-right: 5px; + padding: 0 3px; +} +article > header > .row > time.col { + flex: 0; + text-align: right; + white-space: nowrap; + color: #999; + font-style: italic; +} +article > header ul.tags { + list-style: none; + padding: 0; + margin: 0; + font-size: 12px; +} +article > header ul.tags > li { + user-select: all; + margin-bottom: 2px; +} +article > header ul.tags > li > span.badge { + display: inline-block; + padding: .25em .4em; + margin-right: 5px; + border-radius: 4px; + background-color: #6c757d3b; + color: #524d4d; + font-size: 12px; + text-align: center; + font-weight: 700; + line-height: 1; + white-space: nowrap; + vertical-align: baseline; + user-select: none; +} +article > section.body { + border: 1px solid #d8d8d8; + background: #FFF; + padding: 10px; + border-radius: 3px; +} +pre.sf-dump { + border-radius: 3px; + margin-bottom: 0; +} +.hidden { + display: none !important; +} +.dumped-tag > .sf-dump { + display: inline-block; + margin: 0; + padding: 1px 5px; + line-height: 1.4; + vertical-align: top; + background-color: transparent; + user-select: auto; +} +.dumped-tag > pre.sf-dump, +.dumped-tag > .sf-dump-default { + color: #CC7832; + background: none; +} +.dumped-tag > .sf-dump .sf-dump-str { color: #629755; } +.dumped-tag > .sf-dump .sf-dump-private, +.dumped-tag > .sf-dump .sf-dump-protected, +.dumped-tag > .sf-dump .sf-dump-public { color: #262626; } +.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; } +.dumped-tag > .sf-dump .sf-dump-key { color: #789339; } +.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; } +.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } +.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; } +.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; } diff --git a/vendor/symfony/var-dumper/Resources/functions/dump.php b/vendor/symfony/var-dumper/Resources/functions/dump.php new file mode 100644 index 00000000..f26aad5b --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/functions/dump.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\VarDumper\VarDumper; + +if (!function_exists('dump')) { + /** + * @author Nicolas Grekas + */ + function dump($var, ...$moreVars) + { + VarDumper::dump($var); + + foreach ($moreVars as $v) { + VarDumper::dump($v); + } + + if (1 < func_num_args()) { + return func_get_args(); + } + + return $var; + } +} + +if (!function_exists('dd')) { + /** + * @return never + */ + function dd(...$vars) + { + if (!in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + + foreach ($vars as $v) { + VarDumper::dump($v); + } + + exit(1); + } +} diff --git a/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js b/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js new file mode 100644 index 00000000..63101e57 --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js @@ -0,0 +1,10 @@ +document.addEventListener('DOMContentLoaded', function() { + let prev = null; + Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) { + const dedupId = article.dataset.dedupId; + if (dedupId === prev) { + article.getElementsByTagName('header')[0].classList.add('hidden'); + } + prev = dedupId; + }); +}); diff --git a/vendor/symfony/var-dumper/Server/Connection.php b/vendor/symfony/var-dumper/Server/Connection.php new file mode 100644 index 00000000..ebfc6506 --- /dev/null +++ b/vendor/symfony/var-dumper/Server/Connection.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Server; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; + +/** + * Forwards serialized Data clones to a server. + * + * @author Maxime Steinhausser + */ +class Connection +{ + private $host; + private $contextProviders; + + /** + * @var resource|null + */ + private $socket; + + /** + * @param string $host The server host + * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name + */ + public function __construct(string $host, array $contextProviders = []) + { + if (!str_contains($host, '://')) { + $host = 'tcp://'.$host; + } + + $this->host = $host; + $this->contextProviders = $contextProviders; + } + + public function getContextProviders(): array + { + return $this->contextProviders; + } + + public function write(Data $data): bool + { + $socketIsFresh = !$this->socket; + if (!$this->socket = $this->socket ?: $this->createSocket()) { + return false; + } + + $context = ['timestamp' => microtime(true)]; + foreach ($this->contextProviders as $name => $provider) { + $context[$name] = $provider->getContext(); + } + $context = array_filter($context); + $encodedPayload = base64_encode(serialize([$data, $context]))."\n"; + + set_error_handler([self::class, 'nullErrorHandler']); + try { + if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { + return true; + } + if (!$socketIsFresh) { + stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR); + fclose($this->socket); + $this->socket = $this->createSocket(); + } + if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { + return true; + } + } finally { + restore_error_handler(); + } + + return false; + } + + private static function nullErrorHandler(int $t, string $m) + { + // no-op + } + + private function createSocket() + { + set_error_handler([self::class, 'nullErrorHandler']); + try { + return stream_socket_client($this->host, $errno, $errstr, 3); + } finally { + restore_error_handler(); + } + } +} diff --git a/vendor/symfony/var-dumper/Server/DumpServer.php b/vendor/symfony/var-dumper/Server/DumpServer.php new file mode 100644 index 00000000..b006ea12 --- /dev/null +++ b/vendor/symfony/var-dumper/Server/DumpServer.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Server; + +use Psr\Log\LoggerInterface; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * A server collecting Data clones sent by a ServerDumper. + * + * @author Maxime Steinhausser + * + * @final + */ +class DumpServer +{ + private $host; + private $logger; + + /** + * @var resource|null + */ + private $socket; + + public function __construct(string $host, ?LoggerInterface $logger = null) + { + if (!str_contains($host, '://')) { + $host = 'tcp://'.$host; + } + + $this->host = $host; + $this->logger = $logger; + } + + public function start(): void + { + if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) { + throw new \RuntimeException(sprintf('Server start failed on "%s": ', $this->host).$errstr.' '.$errno); + } + } + + public function listen(callable $callback): void + { + if (null === $this->socket) { + $this->start(); + } + + foreach ($this->getMessages() as $clientId => $message) { + if ($this->logger) { + $this->logger->info('Received a payload from client {clientId}', ['clientId' => $clientId]); + } + + $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]); + + // Impossible to decode the message, give up. + if (false === $payload) { + if ($this->logger) { + $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]); + } + + continue; + } + + if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) { + if ($this->logger) { + $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]); + } + + continue; + } + + [$data, $context] = $payload; + + $callback($data, $context, $clientId); + } + } + + public function getHost(): string + { + return $this->host; + } + + private function getMessages(): iterable + { + $sockets = [(int) $this->socket => $this->socket]; + $write = []; + + while (true) { + $read = $sockets; + stream_select($read, $write, $write, null); + + foreach ($read as $stream) { + if ($this->socket === $stream) { + $stream = stream_socket_accept($this->socket); + $sockets[(int) $stream] = $stream; + } elseif (feof($stream)) { + unset($sockets[(int) $stream]); + fclose($stream); + } else { + yield (int) $stream => fgets($stream); + } + } + } + } +} diff --git a/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php b/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php new file mode 100644 index 00000000..5959195c --- /dev/null +++ b/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Test; + +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Nicolas Grekas + */ +trait VarDumperTestTrait +{ + /** + * @internal + */ + private $varDumperConfig = [ + 'casters' => [], + 'flags' => null, + ]; + + protected function setUpVarDumper(array $casters, ?int $flags = null): void + { + $this->varDumperConfig['casters'] = $casters; + $this->varDumperConfig['flags'] = $flags; + } + + /** + * @after + */ + protected function tearDownVarDumper(): void + { + $this->varDumperConfig['casters'] = []; + $this->varDumperConfig['flags'] = null; + } + + public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '') + { + $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); + } + + public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '') + { + $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); + } + + protected function getDump($data, $key = null, int $filter = 0): ?string + { + if (null === $flags = $this->varDumperConfig['flags']) { + $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; + $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; + $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0; + } + + $cloner = new VarCloner(); + $cloner->addCasters($this->varDumperConfig['casters']); + $cloner->setMaxItems(-1); + $dumper = new CliDumper(null, null, $flags); + $dumper->setColors(false); + $data = $cloner->cloneVar($data, $filter)->withRefHandles(false); + if (null !== $key && null === $data = $data->seek($key)) { + return null; + } + + return rtrim($dumper->dump($data, true)); + } + + private function prepareExpectation($expected, int $filter): string + { + if (!\is_string($expected)) { + $expected = $this->getDump($expected, null, $filter); + } + + return rtrim($expected); + } +} diff --git a/vendor/symfony/var-dumper/VarDumper.php b/vendor/symfony/var-dumper/VarDumper.php new file mode 100644 index 00000000..9db5811e --- /dev/null +++ b/vendor/symfony/var-dumper/VarDumper.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Dumper\ServerDumper; + +// Load the global dump() function +require_once __DIR__.'/Resources/functions/dump.php'; + +/** + * @author Nicolas Grekas + */ +class VarDumper +{ + /** + * @var callable|null + */ + private static $handler; + + public static function dump($var) + { + if (null === self::$handler) { + self::register(); + } + + return (self::$handler)($var); + } + + /** + * @return callable|null + */ + public static function setHandler(?callable $callable = null) + { + $prevHandler = self::$handler; + + // Prevent replacing the handler with expected format as soon as the env var was set: + if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { + return $prevHandler; + } + + self::$handler = $callable; + + return $prevHandler; + } + + private static function register(): void + { + $cloner = new VarCloner(); + $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); + + $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null; + switch (true) { + case 'html' === $format: + $dumper = new HtmlDumper(); + break; + case 'cli' === $format: + $dumper = new CliDumper(); + break; + case 'server' === $format: + case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME): + $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format; + $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); + $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders()); + break; + default: + $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); + } + + if (!$dumper instanceof ServerDumper) { + $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]); + } + + self::$handler = function ($var) use ($cloner, $dumper) { + $dumper->dump($cloner->cloneVar($var)); + }; + } + + private static function getDefaultContextProviders(): array + { + $contextProviders = []; + + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && class_exists(Request::class)) { + $requestStack = new RequestStack(); + $requestStack->push(Request::createFromGlobals()); + $contextProviders['request'] = new RequestContextProvider($requestStack); + } + + $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null; + + return $contextProviders + [ + 'cli' => new CliContextProvider(), + 'source' => new SourceContextProvider(null, null, $fileLinkFormatter), + ]; + } +} diff --git a/vendor/symfony/var-dumper/composer.json b/vendor/symfony/var-dumper/composer.json new file mode 100644 index 00000000..ea46a72b --- /dev/null +++ b/vendor/symfony/var-dumper/composer.json @@ -0,0 +1,50 @@ +{ + "name": "symfony/var-dumper", + "type": "library", + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "keywords": ["dump", "debug"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "autoload": { + "files": [ "Resources/functions/dump.php" ], + "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "minimum-stability": "dev" +}