diff --git a/README.md b/README.md index 6dac80adb6f..3c15827a547 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,24 @@ Or with Xdebug: vendor/bin/rector process src/Controller --dry-run --xdebug ``` +To assist with simple debugging Rector provides 2 helpers to pretty-print AST-nodes: + +```php +use PhpParser\Node\Scalar\String_; +$node = new String_('hello world!'); + +// prints node to string, as PHP code displays it +print_node($node); + +// dump nested node object with nested properties +dump_node($node); + +// 2nd argument is how deep the nesting is - this makes sure the dump is short and useful +dump_node($node, 1); +``` + +
+ ## Known Drawbacks ### How to Apply Coding Standards? diff --git a/config/config.php b/config/config.php index a0e36b1b06f..8aa578d50a0 100644 --- a/config/config.php +++ b/config/config.php @@ -101,7 +101,7 @@ return static function (RectorConfig $rectorConfig) : void { } // require only in dev $rectorConfig->import(__DIR__ . '/../utils/compiler/config/config.php', null, 'not_found'); - $services->load('Rector\\Core\\', __DIR__ . '/../src')->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/Console/Style/RectorConsoleOutputStyle.php', __DIR__ . '/../src/Exception', __DIR__ . '/../src/DependencyInjection/CompilerPass', __DIR__ . '/../src/DependencyInjection/Loader', __DIR__ . '/../src/Kernel', __DIR__ . '/../src/ValueObject', __DIR__ . '/../src/Bootstrap', __DIR__ . '/../src/Enum', __DIR__ . '/../src/PhpParser/Node/CustomNode', __DIR__ . '/../src/PhpParser/ValueObject', __DIR__ . '/../src/constants.php']); + $services->load('Rector\\Core\\', __DIR__ . '/../src')->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/Console/Style/RectorConsoleOutputStyle.php', __DIR__ . '/../src/Exception', __DIR__ . '/../src/DependencyInjection/CompilerPass', __DIR__ . '/../src/DependencyInjection/Loader', __DIR__ . '/../src/Kernel', __DIR__ . '/../src/ValueObject', __DIR__ . '/../src/Bootstrap', __DIR__ . '/../src/Enum', __DIR__ . '/../src/functions', __DIR__ . '/../src/PhpParser/Node/CustomNode', __DIR__ . '/../src/PhpParser/ValueObject', __DIR__ . '/../src/constants.php']); $services->alias(Application::class, ConsoleApplication::class); $services->set(EmptyConfigurableRectorCollector::class)->arg('$containerBuilder', service('service_container')); $services->set(SimpleCallableNodeTraverser::class); diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 77e1c9c5443..d6d189ef71f 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = 'e68c8d23cbbdb9dbfef66133af6bb4f1857015ad'; + public const PACKAGE_VERSION = '7f873f0311679c23feacabd3089c8185b9a93c74'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-02-07 12:21:54'; + public const RELEASE_DATE = '2023-02-07 20:06:43'; /** * @var int */ diff --git a/src/functions/node_helper.php b/src/functions/node_helper.php new file mode 100644 index 00000000000..7106354688a --- /dev/null +++ b/src/functions/node_helper.php @@ -0,0 +1,49 @@ + $depth]); + } +} +if (!\function_exists('dn')) { + function dn(Node $node, int $depth = 2) : void + { + \RectorPrefix202302\dump_node($node, $depth); + } +} +if (!\function_exists('dump_node')) { + /** + * @param \PhpParser\Node|mixed[] $node + */ + function dump_node($node, int $depth = 2) : void + { + $nodes = \is_array($node) ? $node : [$node]; + foreach ($nodes as $node) { + Dumper::dump($node, [Dumper::DEPTH => $depth]); + } + } +} +if (!\function_exists('print_node')) { + /** + * @param \PhpParser\Node|mixed[] $node + */ + function print_node($node) : void + { + $standard = new Standard(); + $nodes = \is_array($node) ? $node : [$node]; + foreach ($nodes as $node) { + $printedContent = $standard->prettyPrint([$node]); + Dumper::dump($printedContent); + } + } +} diff --git a/vendor/autoload.php b/vendor/autoload.php index 855db788e3c..91ba611baf4 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) { require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit182ffbcec7715a7c92e1953ca71c39fb::getLoader(); +return ComposerAutoloaderInit1e12be2eb93c8583a8ed506af09bf6f6::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 2f80bbbd5aa..2dc344fb50f 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1072,6 +1072,21 @@ return array( 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\ParallelProcess' => $vendorDir . '/symplify/easy-parallel/src/ValueObject/ParallelProcess.php', 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\ProcessPool' => $vendorDir . '/symplify/easy-parallel/src/ValueObject/ProcessPool.php', 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\Schedule' => $vendorDir . '/symplify/easy-parallel/src/ValueObject/Schedule.php', + 'RectorPrefix202302\\Tracy\\BlueScreen' => $vendorDir . '/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php', + 'RectorPrefix202302\\Tracy\\Debugger' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/Debugger.php', + 'RectorPrefix202302\\Tracy\\DeferredContent' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/DeferredContent.php', + 'RectorPrefix202302\\Tracy\\DevelopmentStrategy' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php', + 'RectorPrefix202302\\Tracy\\Dumper' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Dumper.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Describer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Describer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Exposer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Exposer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Renderer' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Renderer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Value' => $vendorDir . '/tracy/tracy/src/Tracy/Dumper/Value.php', + 'RectorPrefix202302\\Tracy\\FireLogger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger/FireLogger.php', + 'RectorPrefix202302\\Tracy\\Helpers' => $vendorDir . '/tracy/tracy/src/Tracy/Helpers.php', + 'RectorPrefix202302\\Tracy\\ILogger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger/ILogger.php', + 'RectorPrefix202302\\Tracy\\Logger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger/Logger.php', + 'RectorPrefix202302\\Tracy\\OutputDebugger' => $vendorDir . '/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php', + 'RectorPrefix202302\\Tracy\\ProductionStrategy' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger/ProductionStrategy.php', 'RectorPrefix202302\\Triun\\LongestCommonSubstring\\Solver' => $vendorDir . '/triun/longest-common-substring/src/Solver.php', 'RectorPrefix202302\\Triun\\LongestCommonSubstring\\SolverInterface' => $vendorDir . '/triun/longest-common-substring/src/SolverInterface.php', 'RectorPrefix202302\\Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index deb40abf463..276c514683b 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -13,5 +13,7 @@ return array( 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php', '2324d0e5cadd603331d27de142371f0b' => $vendorDir . '/symfony/contracts/Deprecation/function.php', + 'd507e002f7fce7f0c6dbf1f22edcb902' => $vendorDir . '/tracy/tracy/src/Tracy/functions.php', '4508688f3cab21375725e8d11ca194a2' => $baseDir . '/src/constants.php', + '30bca7fff093e8069bed7c55247e2bf8' => $baseDir . '/src/functions/node_helper.php', ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 623a1def8e7..88b82584bd8 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit182ffbcec7715a7c92e1953ca71c39fb +class ComposerAutoloaderInit1e12be2eb93c8583a8ed506af09bf6f6 { private static $loader; @@ -22,17 +22,17 @@ class ComposerAutoloaderInit182ffbcec7715a7c92e1953ca71c39fb return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit182ffbcec7715a7c92e1953ca71c39fb', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit1e12be2eb93c8583a8ed506af09bf6f6', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit182ffbcec7715a7c92e1953ca71c39fb', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit1e12be2eb93c8583a8ed506af09bf6f6', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index bdf328b6fb7..2ee7e272420 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb +class ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6 { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', @@ -14,7 +14,9 @@ class ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php', '2324d0e5cadd603331d27de142371f0b' => __DIR__ . '/..' . '/symfony/contracts/Deprecation/function.php', + 'd507e002f7fce7f0c6dbf1f22edcb902' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/functions.php', '4508688f3cab21375725e8d11ca194a2' => __DIR__ . '/../..' . '/src/constants.php', + '30bca7fff093e8069bed7c55247e2bf8' => __DIR__ . '/../..' . '/src/functions/node_helper.php', ); public static $prefixLengthsPsr4 = array ( @@ -1322,6 +1324,21 @@ class ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\ParallelProcess' => __DIR__ . '/..' . '/symplify/easy-parallel/src/ValueObject/ParallelProcess.php', 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\ProcessPool' => __DIR__ . '/..' . '/symplify/easy-parallel/src/ValueObject/ProcessPool.php', 'RectorPrefix202302\\Symplify\\EasyParallel\\ValueObject\\Schedule' => __DIR__ . '/..' . '/symplify/easy-parallel/src/ValueObject/Schedule.php', + 'RectorPrefix202302\\Tracy\\BlueScreen' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php', + 'RectorPrefix202302\\Tracy\\Debugger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/Debugger.php', + 'RectorPrefix202302\\Tracy\\DeferredContent' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/DeferredContent.php', + 'RectorPrefix202302\\Tracy\\DevelopmentStrategy' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php', + 'RectorPrefix202302\\Tracy\\Dumper' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Dumper.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Describer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Describer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Exposer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Exposer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Renderer' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Renderer.php', + 'RectorPrefix202302\\Tracy\\Dumper\\Value' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Dumper/Value.php', + 'RectorPrefix202302\\Tracy\\FireLogger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Logger/FireLogger.php', + 'RectorPrefix202302\\Tracy\\Helpers' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Helpers.php', + 'RectorPrefix202302\\Tracy\\ILogger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Logger/ILogger.php', + 'RectorPrefix202302\\Tracy\\Logger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Logger/Logger.php', + 'RectorPrefix202302\\Tracy\\OutputDebugger' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php', + 'RectorPrefix202302\\Tracy\\ProductionStrategy' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/Debugger/ProductionStrategy.php', 'RectorPrefix202302\\Triun\\LongestCommonSubstring\\Solver' => __DIR__ . '/..' . '/triun/longest-common-substring/src/Solver.php', 'RectorPrefix202302\\Triun\\LongestCommonSubstring\\SolverInterface' => __DIR__ . '/..' . '/triun/longest-common-substring/src/SolverInterface.php', 'RectorPrefix202302\\Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php', @@ -3089,9 +3106,9 @@ class ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit182ffbcec7715a7c92e1953ca71c39fb::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit1e12be2eb93c8583a8ed506af09bf6f6::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 0ba352271b6..e3a7165609c 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -3172,6 +3172,83 @@ ], "install-path": "..\/symplify\/rule-doc-generator-contracts" }, + { + "name": "tracy\/tracy", + "version": "v2.9.6", + "version_normalized": "2.9.6.0", + "source": { + "type": "git", + "url": "https:\/\/github.com\/nette\/tracy.git", + "reference": "80533f4bda19ce8138c0fc984743533e2a0e1c5c" + }, + "dist": { + "type": "zip", + "url": "https:\/\/api.github.com\/repos\/nette\/tracy\/zipball\/80533f4bda19ce8138c0fc984743533e2a0e1c5c", + "reference": "80533f4bda19ce8138c0fc984743533e2a0e1c5c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-session": "*", + "php": ">=7.2 <8.3" + }, + "conflict": { + "nette\/di": "<3.0" + }, + "require-dev": { + "latte\/latte": "^2.5", + "nette\/di": "^3.0", + "nette\/mail": "^3.0", + "nette\/tester": "^2.2", + "nette\/utils": "^3.0", + "phpstan\/phpstan": "^1.0", + "psr\/log": "^1.0 || ^2.0 || ^3.0" + }, + "time": "2023-02-06T15:31:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src\/Tracy\/functions.php" + ], + "classmap": [ + "src" + ] + }, + "notification-url": "https:\/\/packagist.org\/downloads\/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https:\/\/davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https:\/\/nette.org\/contributors" + } + ], + "description": "\ud83d\ude0e Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "homepage": "https:\/\/tracy.nette.org", + "keywords": [ + "Xdebug", + "debug", + "debugger", + "nette", + "profiler" + ], + "support": { + "issues": "https:\/\/github.com\/nette\/tracy\/issues", + "source": "https:\/\/github.com\/nette\/tracy\/tree\/v2.9.6" + }, + "install-path": "..\/tracy\/tracy" + }, { "name": "triun\/longest-common-substring", "version": "1.0.0", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index b364ee386e4..4bc461d1323 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -2,4 +2,4 @@ namespace RectorPrefix202302; -return array('root' => array('name' => 'rector/rector-src', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(0 => '0.15.x-dev'), 'dev' => \false), 'versions' => array('clue/ndjson-react' => array('pretty_version' => 'v1.3.0', 'version' => '1.3.0.0', 'reference' => '392dc165fce93b5bb5c637b67e59619223c931b0', 'type' => 'library', 'install_path' => __DIR__ . '/../clue/ndjson-react', 'aliases' => array(), 'dev_requirement' => \false), 'composer/pcre' => array('pretty_version' => '3.1.0', 'version' => '3.1.0.0', 'reference' => '4bff79ddd77851fe3cdd11616ed3f92841ba5bd2', 'type' => 'library', 'install_path' => __DIR__ . '/./pcre', 'aliases' => array(), 'dev_requirement' => \false), 'composer/semver' => array('pretty_version' => '3.3.2', 'version' => '3.3.2.0', 'reference' => '3953f23262f2bff1919fc82183ad9acb13ff62c9', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => \false), 'composer/xdebug-handler' => array('pretty_version' => '3.0.3', 'version' => '3.0.3.0', 'reference' => 'ced299686f41dce890debac69273b47ffe98a40c', 'type' => 'library', 'install_path' => __DIR__ . '/./xdebug-handler', 'aliases' => array(), 'dev_requirement' => \false), 'doctrine/inflector' => array('pretty_version' => '2.0.6', 'version' => '2.0.6.0', 'reference' => 'd9d313a36c872fd6ee06d9a6cbcf713eaa40f024', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => \false), 'evenement/evenement' => array('pretty_version' => 'v3.0.1', 'version' => '3.0.1.0', 'reference' => '531bfb9d15f8aa57454f5f0285b18bec903b8fb7', 'type' => 'library', 'install_path' => __DIR__ . '/../evenement/evenement', 'aliases' => array(), 'dev_requirement' => \false), 'fidry/cpu-core-counter' => array('pretty_version' => '0.5.1', 'version' => '0.5.1.0', 'reference' => 'b58e5a3933e541dc286cc91fc4f3898bbc6f1623', 'type' => 'library', 'install_path' => __DIR__ . '/../fidry/cpu-core-counter', 'aliases' => array(), 'dev_requirement' => \false), 'nette/utils' => array('pretty_version' => 'v3.2.9', 'version' => '3.2.9.0', 'reference' => 'c91bac3470c34b2ecd5400f6e6fdf0b64a836a5c', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/utils', 'aliases' => array(), 'dev_requirement' => \false), 'nikic/php-parser' => array('pretty_version' => 'v4.15.3', 'version' => '4.15.3.0', 'reference' => '570e980a201d8ed0236b0a62ddf2c9cbb2034039', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), 'dev_requirement' => \false), 'ondram/ci-detector' => array('pretty_version' => '4.1.0', 'version' => '4.1.0.0', 'reference' => '8a4b664e916df82ff26a44709942dfd593fa6f30', 'type' => 'library', 'install_path' => __DIR__ . '/../ondram/ci-detector', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpdoc-parser' => array('pretty_version' => '1.16.0', 'version' => '1.16.0.0', 'reference' => '57090cfccbfaa639e703c007486d605a6e80f56d', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpstan' => array('pretty_version' => '1.9.16', 'version' => '1.9.16.0', 'reference' => '922e2689bb180575d0f57de0443c431a5a698e8f', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpstan', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpstan-phpunit' => array('pretty_version' => '1.3.3', 'version' => '1.3.3.0', 'reference' => '54a24bd23e9e80ee918cdc24f909d376c2e273f7', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-phpunit', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0')), 'react/cache' => array('pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/cache', 'aliases' => array(), 'dev_requirement' => \false), 'react/child-process' => array('pretty_version' => 'v0.6.5', 'version' => '0.6.5.0', 'reference' => 'e71eb1aa55f057c7a4a0d08d06b0b0a484bead43', 'type' => 'library', 'install_path' => __DIR__ . '/../react/child-process', 'aliases' => array(), 'dev_requirement' => \false), 'react/dns' => array('pretty_version' => 'v1.10.0', 'version' => '1.10.0.0', 'reference' => 'a5427e7dfa47713e438016905605819d101f238c', 'type' => 'library', 'install_path' => __DIR__ . '/../react/dns', 'aliases' => array(), 'dev_requirement' => \false), 'react/event-loop' => array('pretty_version' => 'v1.3.0', 'version' => '1.3.0.0', 'reference' => '187fb56f46d424afb6ec4ad089269c72eec2e137', 'type' => 'library', 'install_path' => __DIR__ . '/../react/event-loop', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise' => array('pretty_version' => 'v2.9.0', 'version' => '2.9.0.0', 'reference' => '234f8fd1023c9158e2314fa9d7d0e6a83db42910', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise-timer' => array('pretty_version' => 'v1.9.0', 'version' => '1.9.0.0', 'reference' => 'aa7a73c74b8d8c0f622f5982ff7b0351bc29e495', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise-timer', 'aliases' => array(), 'dev_requirement' => \false), 'react/socket' => array('pretty_version' => 'v1.12.0', 'version' => '1.12.0.0', 'reference' => '81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/socket', 'aliases' => array(), 'dev_requirement' => \false), 'react/stream' => array('pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => '7a423506ee1903e89f1e08ec5f0ed430ff784ae9', 'type' => 'library', 'install_path' => __DIR__ . '/../react/stream', 'aliases' => array(), 'dev_requirement' => \false), 'rector/extension-installer' => array('pretty_version' => '0.11.2', 'version' => '0.11.2.0', 'reference' => '05544e9b195863b8571ae2a3b903cbec7fa062e0', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../rector/extension-installer', 'aliases' => array(), 'dev_requirement' => \false), 'rector/rector' => array('dev_requirement' => \false, 'replaced' => array(0 => '0.15.x-dev', 1 => 'dev-main')), 'rector/rector-doctrine' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => 'ea9cf46a738e623ecd3e1ed7402eec1afa6032cd', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-doctrine', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-downgrade-php' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '46346e2425dcc68086c540102d8e5e54b3cd97cf', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-downgrade-php', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-php-parser' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9639ef9429f74c14fdc3c7dad9d3b0d916663de0', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-php-parser', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-phpunit' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '933bccdffe41f45b1223ecbfb5750925376ff50b', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-phpunit', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-src' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(0 => '0.15.x-dev'), 'dev_requirement' => \false), 'rector/rector-symfony' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '89e994ffb68921d571bbf5b8e1d59280b7f30a50', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-symfony', 'aliases' => array(0 => '9999999-dev'), 'dev_requirement' => \false), 'sebastian/diff' => array('pretty_version' => '5.0.0', 'version' => '5.0.0.0', 'reference' => '70dd1b20bc198da394ad542e988381b44e64e39f', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/diff', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/config' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'f31b3c78a3650157188a240695e688d6a182aa91', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/config', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/console' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => '3e294254f2191762c1d137aed4b94e966965e985', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/contracts' => array('pretty_version' => 'v3.2.0', 'version' => '3.2.0.0', 'reference' => 'c47da22960a1eb5e39c1ad84120734e680265610', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/dependency-injection' => array('pretty_version' => 'v6.1.12', 'version' => '6.1.12.0', 'reference' => '360c9d0948e1fe675336346d5862e8e55b378d90', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/deprecation-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/event-dispatcher-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/filesystem' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'e59e8a4006afd7f5654786a83b4fcb8da98f4593', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/finder' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'c90dc446976a612e3312a97a6ec0069ab0c2099c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-client-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/polyfill-ctype' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'symfony/polyfill-intl-grapheme' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/service-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/string' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/translation-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symplify/easy-parallel' => array('pretty_version' => '11.1.27', 'version' => '11.1.27.0', 'reference' => '28911142f6a0f4127271f745e2403bb84fcd2b87', 'type' => 'library', 'install_path' => __DIR__ . '/../symplify/easy-parallel', 'aliases' => array(), 'dev_requirement' => \false), 'symplify/rule-doc-generator-contracts' => array('pretty_version' => '11.1.26', 'version' => '11.1.26.0', 'reference' => '3e66b3fec678b74a076395ec629d535fb95293b5', 'type' => 'library', 'install_path' => __DIR__ . '/../symplify/rule-doc-generator-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'triun/longest-common-substring' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'eb353758f4b2ec8c874ad36c2acd35d38cf436d4', 'type' => 'library', 'install_path' => __DIR__ . '/../triun/longest-common-substring', 'aliases' => array(), 'dev_requirement' => \false), 'webmozart/assert' => array('pretty_version' => '1.11.0', 'version' => '1.11.0.0', 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', 'type' => 'library', 'install_path' => __DIR__ . '/../webmozart/assert', 'aliases' => array(), 'dev_requirement' => \false))); +return array('root' => array('name' => 'rector/rector-src', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(0 => '0.15.x-dev'), 'dev' => \false), 'versions' => array('clue/ndjson-react' => array('pretty_version' => 'v1.3.0', 'version' => '1.3.0.0', 'reference' => '392dc165fce93b5bb5c637b67e59619223c931b0', 'type' => 'library', 'install_path' => __DIR__ . '/../clue/ndjson-react', 'aliases' => array(), 'dev_requirement' => \false), 'composer/pcre' => array('pretty_version' => '3.1.0', 'version' => '3.1.0.0', 'reference' => '4bff79ddd77851fe3cdd11616ed3f92841ba5bd2', 'type' => 'library', 'install_path' => __DIR__ . '/./pcre', 'aliases' => array(), 'dev_requirement' => \false), 'composer/semver' => array('pretty_version' => '3.3.2', 'version' => '3.3.2.0', 'reference' => '3953f23262f2bff1919fc82183ad9acb13ff62c9', 'type' => 'library', 'install_path' => __DIR__ . '/./semver', 'aliases' => array(), 'dev_requirement' => \false), 'composer/xdebug-handler' => array('pretty_version' => '3.0.3', 'version' => '3.0.3.0', 'reference' => 'ced299686f41dce890debac69273b47ffe98a40c', 'type' => 'library', 'install_path' => __DIR__ . '/./xdebug-handler', 'aliases' => array(), 'dev_requirement' => \false), 'doctrine/inflector' => array('pretty_version' => '2.0.6', 'version' => '2.0.6.0', 'reference' => 'd9d313a36c872fd6ee06d9a6cbcf713eaa40f024', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => \false), 'evenement/evenement' => array('pretty_version' => 'v3.0.1', 'version' => '3.0.1.0', 'reference' => '531bfb9d15f8aa57454f5f0285b18bec903b8fb7', 'type' => 'library', 'install_path' => __DIR__ . '/../evenement/evenement', 'aliases' => array(), 'dev_requirement' => \false), 'fidry/cpu-core-counter' => array('pretty_version' => '0.5.1', 'version' => '0.5.1.0', 'reference' => 'b58e5a3933e541dc286cc91fc4f3898bbc6f1623', 'type' => 'library', 'install_path' => __DIR__ . '/../fidry/cpu-core-counter', 'aliases' => array(), 'dev_requirement' => \false), 'nette/utils' => array('pretty_version' => 'v3.2.9', 'version' => '3.2.9.0', 'reference' => 'c91bac3470c34b2ecd5400f6e6fdf0b64a836a5c', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/utils', 'aliases' => array(), 'dev_requirement' => \false), 'nikic/php-parser' => array('pretty_version' => 'v4.15.3', 'version' => '4.15.3.0', 'reference' => '570e980a201d8ed0236b0a62ddf2c9cbb2034039', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), 'dev_requirement' => \false), 'ondram/ci-detector' => array('pretty_version' => '4.1.0', 'version' => '4.1.0.0', 'reference' => '8a4b664e916df82ff26a44709942dfd593fa6f30', 'type' => 'library', 'install_path' => __DIR__ . '/../ondram/ci-detector', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpdoc-parser' => array('pretty_version' => '1.16.0', 'version' => '1.16.0.0', 'reference' => '57090cfccbfaa639e703c007486d605a6e80f56d', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpstan' => array('pretty_version' => '1.9.16', 'version' => '1.9.16.0', 'reference' => '922e2689bb180575d0f57de0443c431a5a698e8f', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpstan', 'aliases' => array(), 'dev_requirement' => \false), 'phpstan/phpstan-phpunit' => array('pretty_version' => '1.3.3', 'version' => '1.3.3.0', 'reference' => '54a24bd23e9e80ee918cdc24f909d376c2e273f7', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-phpunit', 'aliases' => array(), 'dev_requirement' => \false), 'psr/cache' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => '2.0.2', 'version' => '2.0.2.0', 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log' => array('pretty_version' => '3.0.0', 'version' => '3.0.0.0', 'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => \false), 'psr/log-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.0|2.0|3.0')), 'react/cache' => array('pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/cache', 'aliases' => array(), 'dev_requirement' => \false), 'react/child-process' => array('pretty_version' => 'v0.6.5', 'version' => '0.6.5.0', 'reference' => 'e71eb1aa55f057c7a4a0d08d06b0b0a484bead43', 'type' => 'library', 'install_path' => __DIR__ . '/../react/child-process', 'aliases' => array(), 'dev_requirement' => \false), 'react/dns' => array('pretty_version' => 'v1.10.0', 'version' => '1.10.0.0', 'reference' => 'a5427e7dfa47713e438016905605819d101f238c', 'type' => 'library', 'install_path' => __DIR__ . '/../react/dns', 'aliases' => array(), 'dev_requirement' => \false), 'react/event-loop' => array('pretty_version' => 'v1.3.0', 'version' => '1.3.0.0', 'reference' => '187fb56f46d424afb6ec4ad089269c72eec2e137', 'type' => 'library', 'install_path' => __DIR__ . '/../react/event-loop', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise' => array('pretty_version' => 'v2.9.0', 'version' => '2.9.0.0', 'reference' => '234f8fd1023c9158e2314fa9d7d0e6a83db42910', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise-timer' => array('pretty_version' => 'v1.9.0', 'version' => '1.9.0.0', 'reference' => 'aa7a73c74b8d8c0f622f5982ff7b0351bc29e495', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise-timer', 'aliases' => array(), 'dev_requirement' => \false), 'react/socket' => array('pretty_version' => 'v1.12.0', 'version' => '1.12.0.0', 'reference' => '81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/socket', 'aliases' => array(), 'dev_requirement' => \false), 'react/stream' => array('pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => '7a423506ee1903e89f1e08ec5f0ed430ff784ae9', 'type' => 'library', 'install_path' => __DIR__ . '/../react/stream', 'aliases' => array(), 'dev_requirement' => \false), 'rector/extension-installer' => array('pretty_version' => '0.11.2', 'version' => '0.11.2.0', 'reference' => '05544e9b195863b8571ae2a3b903cbec7fa062e0', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../rector/extension-installer', 'aliases' => array(), 'dev_requirement' => \false), 'rector/rector' => array('dev_requirement' => \false, 'replaced' => array(0 => '0.15.x-dev', 1 => 'dev-main')), 'rector/rector-doctrine' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => 'ea9cf46a738e623ecd3e1ed7402eec1afa6032cd', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-doctrine', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-downgrade-php' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '46346e2425dcc68086c540102d8e5e54b3cd97cf', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-downgrade-php', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-php-parser' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9639ef9429f74c14fdc3c7dad9d3b0d916663de0', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-php-parser', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-phpunit' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '933bccdffe41f45b1223ecbfb5750925376ff50b', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-phpunit', 'aliases' => array(0 => '0.11.x-dev'), 'dev_requirement' => \false), 'rector/rector-src' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(0 => '0.15.x-dev'), 'dev_requirement' => \false), 'rector/rector-symfony' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '89e994ffb68921d571bbf5b8e1d59280b7f30a50', 'type' => 'rector-extension', 'install_path' => __DIR__ . '/../rector/rector-symfony', 'aliases' => array(0 => '9999999-dev'), 'dev_requirement' => \false), 'sebastian/diff' => array('pretty_version' => '5.0.0', 'version' => '5.0.0.0', 'reference' => '70dd1b20bc198da394ad542e988381b44e64e39f', 'type' => 'library', 'install_path' => __DIR__ . '/../sebastian/diff', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/cache-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/config' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'f31b3c78a3650157188a240695e688d6a182aa91', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/config', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/console' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => '3e294254f2191762c1d137aed4b94e966965e985', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/contracts' => array('pretty_version' => 'v3.2.0', 'version' => '3.2.0.0', 'reference' => 'c47da22960a1eb5e39c1ad84120734e680265610', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/contracts', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/dependency-injection' => array('pretty_version' => 'v6.1.12', 'version' => '6.1.12.0', 'reference' => '360c9d0948e1fe675336346d5862e8e55b378d90', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/deprecation-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/event-dispatcher-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/filesystem' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'e59e8a4006afd7f5654786a83b4fcb8da98f4593', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/finder' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'c90dc446976a612e3312a97a6ec0069ab0c2099c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/http-client-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/polyfill-ctype' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'symfony/polyfill-intl-grapheme' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/service-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symfony/service-implementation' => array('dev_requirement' => \false, 'provided' => array(0 => '1.1|2.0|3.0')), 'symfony/string' => array('pretty_version' => 'v6.2.5', 'version' => '6.2.5.0', 'reference' => 'b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/translation-contracts' => array('dev_requirement' => \false, 'replaced' => array(0 => 'v3.2.0')), 'symplify/easy-parallel' => array('pretty_version' => '11.1.27', 'version' => '11.1.27.0', 'reference' => '28911142f6a0f4127271f745e2403bb84fcd2b87', 'type' => 'library', 'install_path' => __DIR__ . '/../symplify/easy-parallel', 'aliases' => array(), 'dev_requirement' => \false), 'symplify/rule-doc-generator-contracts' => array('pretty_version' => '11.1.26', 'version' => '11.1.26.0', 'reference' => '3e66b3fec678b74a076395ec629d535fb95293b5', 'type' => 'library', 'install_path' => __DIR__ . '/../symplify/rule-doc-generator-contracts', 'aliases' => array(), 'dev_requirement' => \false), 'tracy/tracy' => array('pretty_version' => 'v2.9.6', 'version' => '2.9.6.0', 'reference' => '80533f4bda19ce8138c0fc984743533e2a0e1c5c', 'type' => 'library', 'install_path' => __DIR__ . '/../tracy/tracy', 'aliases' => array(), 'dev_requirement' => \false), 'triun/longest-common-substring' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'eb353758f4b2ec8c874ad36c2acd35d38cf436d4', 'type' => 'library', 'install_path' => __DIR__ . '/../triun/longest-common-substring', 'aliases' => array(), 'dev_requirement' => \false), 'webmozart/assert' => array('pretty_version' => '1.11.0', 'version' => '1.11.0.0', 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', 'type' => 'library', 'install_path' => __DIR__ . '/../webmozart/assert', 'aliases' => array(), 'dev_requirement' => \false))); diff --git a/vendor/scoper-autoload.php b/vendor/scoper-autoload.php index a9089ec5257..bb395e542a8 100644 --- a/vendor/scoper-autoload.php +++ b/vendor/scoper-autoload.php @@ -6,6 +6,26 @@ $loader = require_once __DIR__.'/autoload.php'; // Exposed functions. For more information see: // https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposing-functions +if (!function_exists('dump_with_depth')) { + function dump_with_depth() { + return \RectorPrefix202302\dump_with_depth(...func_get_args()); + } +} +if (!function_exists('dn')) { + function dn() { + return \RectorPrefix202302\dn(...func_get_args()); + } +} +if (!function_exists('dump_node')) { + function dump_node() { + return \RectorPrefix202302\dump_node(...func_get_args()); + } +} +if (!function_exists('print_node')) { + function print_node() { + return \RectorPrefix202302\print_node(...func_get_args()); + } +} if (!function_exists('trigger_deprecation')) { function trigger_deprecation() { return \RectorPrefix202302\trigger_deprecation(...func_get_args()); diff --git a/vendor/tracy/tracy/composer.json b/vendor/tracy/tracy/composer.json new file mode 100644 index 00000000000..6deb7d70bbe --- /dev/null +++ b/vendor/tracy/tracy/composer.json @@ -0,0 +1,60 @@ +{ + "name": "tracy\/tracy", + "description": "\ud83d\ude0e Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "keywords": [ + "debug", + "debugger", + "nette", + "profiler", + "xdebug" + ], + "homepage": "https:\/\/tracy.nette.org", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https:\/\/davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https:\/\/nette.org\/contributors" + } + ], + "require": { + "php": ">=7.2 <8.3", + "ext-session": "*", + "ext-json": "*" + }, + "require-dev": { + "nette\/utils": "^3.0", + "nette\/di": "^3.0", + "nette\/mail": "^3.0", + "nette\/tester": "^2.2", + "latte\/latte": "^2.5", + "psr\/log": "^1.0 || ^2.0 || ^3.0", + "phpstan\/phpstan": "^1.0" + }, + "conflict": { + "nette\/di": "<3.0" + }, + "autoload": { + "classmap": [ + "src" + ], + "files": [ + "src\/Tracy\/functions.php" + ] + }, + "minimum-stability": "dev", + "scripts": { + "phpstan": "phpstan analyse", + "tester": "tester tests" + }, + "extra": { + "branch-alias": { + "dev-master": "2.9-dev" + } + } +} \ No newline at end of file diff --git a/vendor/tracy/tracy/license.md b/vendor/tracy/tracy/license.md new file mode 100644 index 00000000000..5a566176904 --- /dev/null +++ b/vendor/tracy/tracy/license.md @@ -0,0 +1,55 @@ +Licenses +======== + +Good news! You may use Tracy under the terms of either the New BSD License +or the GNU General Public License (GPL) version 2 or 3. + +The BSD License is recommended for most projects. It is easy to understand and it +places almost no restrictions on what you can do with the framework. If the GPL +fits better to your project, you can use the framework under this license. + +You don't have to notify anyone which license you are using. You can freely +use Tracy in commercial projects as long as the copyright header +remains intact. + + +New BSD License +--------------- + +Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of "Tracy" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as is" and +any express or implied warranties, including, but not limited to, the implied +warranties of merchantability and fitness for a particular purpose are +disclaimed. In no event shall the copyright owner or contributors be liable for +any direct, indirect, incidental, special, exemplary, or consequential damages +(including, but not limited to, procurement of substitute goods or services; +loss of use, data, or profits; or business interruption) however caused and on +any theory of liability, whether in contract, strict liability, or tort +(including negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. + + +GNU General Public License +-------------------------- + +GPL licenses are very very long, so instead of including them here we offer +you URLs with full text: + +- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html) +- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html) diff --git a/vendor/tracy/tracy/readme.md b/vendor/tracy/tracy/readme.md new file mode 100644 index 00000000000..db25177b12e --- /dev/null +++ b/vendor/tracy/tracy/readme.md @@ -0,0 +1,434 @@ +[Tracy](https://tracy.nette.org) - PHP debugger +============================================== + +[![Downloads this Month](https://img.shields.io/packagist/dm/tracy/tracy.svg)](https://packagist.org/packages/tracy/tracy) +[![Tests](https://github.com/nette/tracy/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/tracy/actions) +[![Build Status Windows](https://ci.appveyor.com/api/projects/status/github/nette/tracy?branch=master&svg=true)](https://ci.appveyor.com/project/dg/tracy/branch/master) +[![Latest Stable Version](https://poser.pugx.org/tracy/tracy/v/stable)](https://github.com/nette/tracy/releases) +[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/tracy/blob/master/license.md) + + +Introduction +------------ + +Tracy library is a useful helper for everyday PHP programmers. It helps you to: + +- quickly detect and correct errors +- log errors +- dump variables +- measure execution time of scripts/queries +- see memory consumption + + +PHP is a perfect language for making hardly detectable errors because it gives great flexibility to programmers. Tracy\Debugger is more valuable because of that. It is an ultimate tool among the diagnostic ones. +If you are meeting Tracy for the first time, believe me, your life starts to be divided into one before the Tracy and the one with her. Welcome to the good part! + +Documentation can be found on the [website](https://tracy.nette.org). + + +[Support Tracy](https://github.com/sponsors/dg) +----------------------------------------------- + +Do you like Tracy? Are you looking forward to the new features? + +[![Buy me a coffee](https://files.nette.org/icons/donation-3.svg)](https://github.com/sponsors/dg) + +Thank you! + + +Installation and requirements +----------------------------- + +The recommended way to is via Composer: + +```shell +composer require tracy/tracy +``` + +Alternatively, you can download the whole package or [tracy.phar](https://github.com/nette/tracy/releases) file. + +| Tracy | compatible with PHP | compatible with browsers +|-----------|---------------|---------- +| Tracy 2.9 | PHP 7.2 – 8.2 | Chrome 64+, Firefox 69+, Safari 13.1+ and iOS Safari 13.4+ +| Tracy 2.8 | PHP 7.2 – 8.1 | Chrome 55+, Firefox 53+, Safari 11+ and iOS Safari 11+ +| Tracy 2.7 | PHP 7.1 – 8.0 | Chrome 55+, Firefox 53+, MS Edge 16+, Safari 11+ and iOS Safari 11+ +| Tracy 2.6 | PHP 7.1 – 8.0 | Chrome 49+, Firefox 45+, MS Edge 14+, Safari 10+ and iOS Safari 10.2+ +| Tracy 2.5 | PHP 5.4 – 7.4 | Chrome 49+, Firefox 45+, MS Edge 12+, Safari 10+ and iOS Safari 10.2+ +| Tracy 2.4 | PHP 5.4 – 7.2 | Chrome 29+, Firefox 28+, IE 11+ (except AJAX), MS Edge 12+, Safari 9+ and iOS Safari 9.2+ + + +Usage +----- + +Activating Tracy is easy. Simply add these two lines of code, preferably just after library loading (like `require 'vendor/autoload.php'`) and before any output is sent to browser: + +```php +use Tracy\Debugger; + +Debugger::enable(); +``` + +The first thing you will notice on the website is a Debugger Bar. + +(If you do not see anything, it means that Tracy is running in production mode. For security reasons, Tracy is visible only on localhost. +You may force Tracy to run in development mode by passing the `Debugger::Development` as the first parameter of `enable()` method.) + +The `enable()` involves changing the error reporting level to E_ALL. + + +Debugger Bar +------------ + +The Debugger Bar is a floating panel. It is displayed in the bottom right corner of a page. You can move it using the mouse. It will remember its position after the page reloading. + +[![Debugger-Bar](https://nette.github.io/tracy/images/tracy-bar.png)](https://nette.github.io/tracy/tracy-debug-bar.html) + +You can add other useful panels to the Debugger Bar. You can find interesting ones in [addons](https://componette.org) or you can [create your own](https://tracy.nette.org/en/extensions). + +If you do not want to show Debugger Bar, set: + +```php +Debugger::$showBar = false; +``` + + +Visualization of errors and exceptions +-------------------------------------- + +Surely, you know how PHP reports errors: there is something like this in the page source code: + +```pre +Parse error: syntax error, unexpected '}' in HomepagePresenter.php on line 15 +``` + +or uncaught exception: + +```pre +Fatal error: Uncaught Nette\MemberAccessException: Call to undefined method Nette\Application\UI\Form::addTest()? in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php:100 +Stack trace: +#0 /sandbox/vendor/nette/utils/src/Utils/Object.php(75): Nette\Utils\ObjectMixin::call(Object(Nette\Application\UI\Form), 'addTest', Array) +#1 /sandbox/app/forms/SignFormFactory.php(32): Nette\Object->__call('addTest', Array) +#2 /sandbox/app/presenters/SignPresenter.php(21): App\Forms\SignFormFactory->create() +#3 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(181): App\Presenters\SignPresenter->createComponentSignInForm('signInForm') +#4 /sandbox/vendor/nette/component-model/src/ComponentModel/Container.php(139): Nette\ComponentModel\Container->createComponent('signInForm') +#5 /sandbox/temp/cache/latte/15206b353f351f6bfca2c36cc.php(17): Nette\ComponentModel\Co in /sandbox/vendor/nette/utils/src/Utils/ObjectMixin.php on line 100
+``` + +It is not so easy to navigate through this output. If you enable Tracy, both errors and exceptions are displayed in a completely different form: + +[![Uncaught exception rendered by Tracy](https://nette.github.io/tracy/images/tracy-exception.png)](https://nette.github.io/tracy/tracy-exception.html) + +The error message literally screams. You can see a part of the source code with the highlighted line where the error occurred. A message clearly explains an error. The entire site is [interactive, try it](https://nette.github.io/tracy/tracy-exception.html). + +And you know what? Fatal errors are captured and displayed in the same way. No need to install any extension (click for live example): + +[![Fatal error rendered by Tracy](https://nette.github.io/tracy/images/tracy-error.png)](https://nette.github.io/tracy/tracy-error.html) + +Errors like a typo in a variable name or an attempt to open a nonexistent file generate reports of E_NOTICE or E_WARNING level. These can be easily overlooked and/or can be completely hidden in a web page graphic layout. Let Tracy manage them: + +[![Notice rendered by Tracy](https://nette.github.io/tracy/images/tracy-notice2.png)](https://nette.github.io/tracy/tracy-debug-bar.html) + +Or they may be displayed like errors: + +```php +Debugger::$strictMode = true; // display all errors +Debugger::$strictMode = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED; // all errors except deprecated notices +``` + +[![Notice rendered by Tracy](https://nette.github.io/tracy/images/tracy-notice.png)](https://nette.github.io/tracy/tracy-notice.html) + +In order to detect misspellings when assigning to an object, we use [trait Nette\SmartObject](https://doc.nette.org/en/3.0/smartobject). + + +Content Security Policy +----------------------- + +If your site uses Content Security Policy, you'll need to add `'nonce-'` to `script-src` for Tracy to work properly. Some 3rd plugins may require additional directives. +Nonce is not supported in the `style-src` directive, if you use this directive you need to add `'unsafe-inline'`, but this should be avoided in production mode. + +Configuration example for [Nette Framework](https://nette.org): + +```neon +http: + csp: + script-src: nonce +``` + +Example in pure PHP: + +```php +$nonce = base64_encode(random_bytes(20)); +header("Content-Security-Policy: script-src 'nonce-$nonce';"); +``` + + +Faster loading +-------------- + +The basic integration is straightforward, however if you have slow blocking scripts in web page, they can slow the Tracy loading. +The solution is to place `` into your template before +any scripts: + +```html + + + + ...<title> + <?php Tracy\Debugger::renderLoader() ?> + <link rel="stylesheet" href="assets/style.css"> + <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> +</head> +``` + + +AJAX and redirected requests +---------------------------- + +Tracy is able to show Debug bar and Bluescreens for AJAX and redirected requests. Tracy keeps the data in a temporary files and uses the `tracy-session` cookie. Tracy can be configured to use a standard PHP session: + +```php +Debugger::setSessionStorage(new Tracy\NativeSession); +Debugger::enable(); +``` + +In case you use non-standard session handler, you can start Tracy immediately (in order to handle any errors), then initialize your session handler +and then inform Tracy that session is ready to use via `dispatch()`: + +```php +Debugger::setSessionStorage(new Tracy\NativeSession); +Debugger::enable(); + +// initialize session handler +session_start(); + +Debugger::dispatch(); +``` + + +Opening files in the editor +--------------------------- + +When the error page is displayed, you can click on file names and they will open in your editor with the cursor on the corresponding line. Files can also be created (action `create file`) or bug fixed in them (action `fix it`). In order to do this, you need to [configure the browser and the system](https://tracy.nette.org/cs/open-files-in-ide). + + +Production mode and error logging +--------------------------------- + +As you can see, Tracy is quite eloquent. It is appreciated in a development environment, but on a production server, it would cause a disaster. Any debugging information cannot be listed there. Therefore Tracy has an environment autodetection and logging functionality. Instead of showing herself, Tracy stores information into a log file and shows the visitor a user-comprehensible server error message: + +[![Server Error 500](https://nette.github.io/tracy/images/tracy-error2.png)](https://nette.github.io/tracy/tracy-production.html) + +Production output mode suppresses all debugging information which is sent out via `dump()` or `Debugger::fireLog()`, and of course all error messages generated by PHP. So, even if you forget `dump($obj)` in the source code, you do not have to worry about it on your production server. Nothing will be seen. + +The output mode is set by the first parameter of `Debugger::enable()`. You can specify either a constant `Debugger::Production` or `Debugger::Development`. Other option is to set it up in a way, that development mode will be on when the application is accessed from a defined IP address with a defined value of `tracy-debug` cookie. The syntax used to achieve this is `cookie-value@ip-address`. + +If it is not specified, the default value `Debugger::Detect` is used. In this case, the system detects a server by IP address. The production mode is chosen if an application is accessed via a public IP address. A local IP address leads to development mode. It is not necessary to set the mode in most cases. The mode is correctly recognized when you are launching the application on your local server or in production. + +In the production mode, Tracy automatically captures all errors and exceptions into a text log. Unless you specify otherwise, it will be stored in log/error.log. This error logging is extremely useful. Imagine, that all users of your application are actually betatesters. They are doing cutting-edge work for free when hunting bugs and you would be silly if you threw away their valuable reports to a recycle bin unnoticed. + +If you need to log your own messages or caught exceptions, use the method `log()`: + +```php +Debugger::log('Unexpected error'); // text message + +try { + criticalOperation(); +} catch (Exception $e) { + Debugger::log($e); // log exception + // or + Debugger::log($e, Debugger::ERROR); // also sends an email notification +} +``` + +A directory for errors logging can be set by the second parameter of the enable() method: + +```php +Debugger::enable(Debugger::Detect, __DIR__ . '/mylog'); +``` + +If you want Tracy to log PHP errors like `E_NOTICE` or `E_WARNING` with detailed information (HTML report), set `Debugger::$logSeverity`: + +```php +Debugger::$logSeverity = E_NOTICE | E_WARNING; +``` + +For a real professional the error log is a crucial source of information and he or she wants to be notified about any new error immediately. Tracy helps him. She is capable of sending an email for every new error record. The variable $email identifies where to send these e-mails: + +```php +Debugger::$email = 'admin@example.com'; +``` + +If you use the Nette Framework, you can set this and others in the configuration file. + +To protect your e-mail box from flood, Tracy sends **only one message** and creates a file `email-sent`. When a developer receives the e-mail notification, he checks the log, corrects his application and deletes the `email-sent` monitoring file. This activates the e-mail sending again. + + +Variable dumping +---------------- + +Every debugging developer is a good friend with the function `var_dump`, which lists all contents of any variable in detail. Unfortunately, its output is without HTML formatting and outputs the dump into a single line of HTML code, not to mention context escaping. It is necessary to replace the `var_dump` with a more handy function. That is just what `dump()` is. + +```php +$arr = [10, 20.2, true, null, 'hello']; + +dump($arr); +// or Tracy\Debugger::dump($arr); +``` + +generates the output: + +![dump](https://nette.github.io/tracy/images/tracy-dump.png) + +You can also change the nesting depth by `Debugger::$maxDepth` and displayed strings length by `Debugger::$maxLength`. Naturally, lower values accelerate Tracy rendering. + +```php +Debugger::$maxDepth = 2; // default: 7 +Debugger::$maxLength = 50; // default: 150 +Debugger::$dumpTheme = 'dark'; // default: light +``` + +The `dump()` function can display useful location information: + +```php +Debugger::$showLocation = true; // shows tooltip with path to the file, where the dump() was called, and tooltips for every dumped objects +Debugger::$showLocation = Tracy\Dumper::LOCATION_CLASS; // shows only tooltips for every dumped object containing path to the file +Debugger::$showLocation = false; // hides all location information +``` + +Very handy alternative to `dump()` is `dumpe()` (ie. dump and exit) and `bdump()`. This allows us to dump variables in Debugger Bar. This is useful, because dumps don't mess up the output and we can also add a title to the dump. + +```php +bdump([2, 4, 6, 8], 'even numbers up to ten'); +bdump([1, 3, 5, 7, 9], 'odd numbers up to ten'); +``` + +![bar dump](https://nette.github.io/tracy/images/tracy-bardump.png) + + +Timing +------ + +Another useful tool is the debugger stopwatch with a precision of microseconds: + +```php +Debugger::timer(); + +// sweet dreams my cherrie +sleep(2); + +$elapsed = Debugger::timer(); +// $elapsed = 2 +``` + +Multiple measurements at once can be achieved by an optional parameter. + +```php +Debugger::timer('page-generating'); +// some code + +Debugger::timer('rss-generating'); +// some code + +$rssElapsed = Debugger::timer('rss-generating'); +$pageElapsed = Debugger::timer('page-generating'); +``` + +```php +Debugger::timer(); // runs the timer + +... // some time-consuming operation + +echo Debugger::timer(); // elapsed time in seconds +``` + + +FireLogger +---------- + +You cannot always send debugging information to the browser window. This applies to AJAX requests or generating XML files to output. In such cases, you can send the messages by a separate channel into FireLogger. Error, Notice and Warning levels are sent to FireLogger window automatically. It is also possible to log suppressed exceptions in running application when attention to them is important. + +How to do it? + +- install extension [FireLogger for Chrome](https://chrome.google.com/webstore/detail/firelogger-for-chrome/hmagilfopmdjkeomnjpchokglfdfjfeh) +- turn on Chrome DevTools (using Ctrl-Shift-I key) and open Console + +Navigate to the [demo page](https://examples.nette.org/tracy/) and you will see messages sent from PHP. + +Because Tracy\Debugger communicates with FireLogger via HTTP headers, you must call the logging function before the PHP script sends anything to output. It is also possible to enable output buffering and delay the output. + +```php +use Tracy\Debugger; + +Debugger::fireLog('Hello World'); // send string into FireLogger console + +Debugger::fireLog($_SERVER); // or even arrays and objects + +Debugger::fireLog(new Exception('Test Exception')); // or exceptions +``` + +The result looks like this: + +![FireLogger](https://nette.github.io/tracy/images/tracy-firelogger.png) + + +Custom Logger +------------- + +We can create a custom logger to log errors, uncatched exceptions, and also be called by `Tracy\Debugger::log()`. Logger implements the interface Tracy\ILogger. + +```php +use Tracy\ILogger; + +class SlackLogger implements ILogger +{ + public function log($value, $priority = ILogger::INFO) + { + // sends a request to Slack + } +} +``` + +And then we activate it: + +```php +Tracy\Debugger::setLogger(new SlackLogger); +``` + +If we use the full Nette Framework, we can set it in the NEON configuration file: + +```neon +services: + tracy.logger: SlackLogger +``` + + +nginx +----- + +If Tracy does not work on nginx, it is probably misconfigured. If there is something like + +```nginx +try_files $uri $uri/ /index.php; +``` + +change it to + +```nginx +try_files $uri $uri/ /index.php$is_args$args; +``` + + +Integrations +------------ + +This is a list of unofficial integrations to other frameworks and CMS: + +- [Drupal 7](http://drupal.org/project/traced) +- Laravel framework: [recca0120/laravel-tracy](https://github.com/recca0120/laravel-tracy), [whipsterCZ/laravel-tracy](https://github.com/whipsterCZ/laravel-tracy) +- [OpenCart](https://github.com/BurdaPraha/oc_tracy) +- [ProcessWire CMS/CMF](https://github.com/adrianbj/TracyDebugger) +- [Slim Framework](https://github.com/runcmf/runtracy) +- Symfony framework: [kutny/tracy-bundle](https://github.com/kutny/tracy-bundle), [VasekPurchart/Tracy-Blue-Screen-Bundle](https://github.com/VasekPurchart/Tracy-Blue-Screen-Bundle) +- [Wordpress](https://github.com/ktstudio/WP-Tracy) + +... feel free to be famous, create an integration for your favourite platform! diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php b/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php new file mode 100644 index 00000000000..6cfbf83921a --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php @@ -0,0 +1,437 @@ +<?php + +/** + * This file is part of the Tracy (https://tracy.nette.org) + * Copyright (c) 2004 David Grudl (https://davidgrudl.com) + */ +declare (strict_types=1); +namespace RectorPrefix202302\Tracy; + +/** + * Red BlueScreen. + */ +class BlueScreen +{ + private const MaxMessageLength = 2000; + /** @var string[] */ + public $info = []; + /** @var string[] paths to be collapsed in stack trace (e.g. core libraries) */ + public $collapsePaths = []; + /** @var int */ + public $maxDepth = 5; + /** @var int */ + public $maxLength = 150; + /** @var int */ + public $maxItems = 100; + /** @var callable|null a callable returning true for sensitive data; fn(string $key, mixed $val): bool */ + public $scrubber; + /** @var string[] */ + public $keysToHide = ['password', 'passwd', 'pass', 'pwd', 'creditcard', 'credit card', 'cc', 'pin', self::class . '::$snapshot']; + /** @var bool */ + public $showEnvironment = \true; + /** @var callable[] */ + private $panels = []; + /** @var callable[] functions that returns action for exceptions */ + private $actions = []; + /** @var callable[] */ + private $fileGenerators = []; + /** @var array */ + private $snapshot; + /** @var \WeakMap<\Fiber|\Generator> */ + private $fibers; + public function __construct() + { + $this->collapsePaths = \preg_match('#(.+/vendor)/tracy/tracy/src/Tracy/BlueScreen$#', \strtr(__DIR__, '\\', '/'), $m) ? [$m[1] . '/tracy', $m[1] . '/nette', $m[1] . '/latte'] : [\dirname(__DIR__)]; + $this->fileGenerators[] = [self::class, 'generateNewPhpFileContents']; + $this->fibers = \PHP_VERSION_ID < 80000 ? new \SplObjectStorage() : new \WeakMap(); + } + /** + * Add custom panel as function (?\Throwable $e): ?array + * @return static + */ + public function addPanel(callable $panel) : self + { + if (!\in_array($panel, $this->panels, \true)) { + $this->panels[] = $panel; + } + return $this; + } + /** + * Add action. + * @return static + */ + public function addAction(callable $action) : self + { + $this->actions[] = $action; + return $this; + } + /** + * Add new file generator. + * @param callable(string): ?string $generator + * @return static + */ + public function addFileGenerator(callable $generator) : self + { + $this->fileGenerators[] = $generator; + return $this; + } + /** + * @param \Fiber|\Generator $fiber + * @return static + */ + public function addFiber($fiber) : self + { + $this->fibers[$fiber] = \true; + return $this; + } + /** + * Renders blue screen. + */ + public function render(\Throwable $exception) : void + { + if (!\headers_sent()) { + \header('Content-Type: text/html; charset=UTF-8'); + } + $this->renderTemplate($exception, __DIR__ . '/assets/page.phtml'); + } + /** @internal */ + public function renderToAjax(\Throwable $exception, DeferredContent $defer) : void + { + $defer->addSetup('Tracy.BlueScreen.loadAjax', Helpers::capture(function () use($exception) { + $this->renderTemplate($exception, __DIR__ . '/assets/content.phtml'); + })); + } + /** + * Renders blue screen to file (if file exists, it will not be overwritten). + */ + public function renderToFile(\Throwable $exception, string $file) : bool + { + if ($handle = @\fopen($file, 'x')) { + \ob_start(); + // double buffer prevents sending HTTP headers in some PHP + \ob_start(function ($buffer) use($handle) : void { + \fwrite($handle, $buffer); + }, 4096); + $this->renderTemplate($exception, __DIR__ . '/assets/page.phtml', \false); + \ob_end_flush(); + \ob_end_clean(); + \fclose($handle); + return \true; + } + return \false; + } + private function renderTemplate(\Throwable $exception, string $template, $toScreen = \true) : void + { + [$generators, $fibers] = $this->findGeneratorsAndFibers($exception); + $headersSent = \headers_sent($headersFile, $headersLine); + $obStatus = Debugger::$obStatus; + $showEnvironment = $this->showEnvironment && \strpos($exception->getMessage(), 'Allowed memory size') === \false; + $info = \array_filter($this->info); + $source = Helpers::getSource(); + $title = $exception instanceof \ErrorException ? Helpers::errorTypeToString($exception->getSeverity()) : Helpers::getClass($exception); + $lastError = $exception instanceof \ErrorException || $exception instanceof \Error ? null : \error_get_last(); + if (\function_exists('apache_request_headers')) { + $httpHeaders = \apache_request_headers(); + } else { + $httpHeaders = \array_filter($_SERVER, function ($k) { + return \strncmp($k, 'HTTP_', 5) === 0; + }, \ARRAY_FILTER_USE_KEY); + $httpHeaders = \array_combine(\array_map(function ($k) { + return \strtolower(\strtr(\substr($k, 5), '_', '-')); + }, \array_keys($httpHeaders)), $httpHeaders); + } + $snapshot =& $this->snapshot; + $snapshot = []; + $dump = $this->getDumper(); + $css = \array_map('file_get_contents', \array_merge([__DIR__ . '/../assets/reset.css', __DIR__ . '/assets/bluescreen.css', __DIR__ . '/../assets/toggle.css', __DIR__ . '/../assets/table-sort.css', __DIR__ . '/../assets/tabs.css', __DIR__ . '/../Dumper/assets/dumper-light.css'], Debugger::$customCssFiles)); + $css = Helpers::minifyCss(\implode('', $css)); + $nonce = $toScreen ? Helpers::getNonce() : null; + $actions = $toScreen ? $this->renderActions($exception) : []; + require $template; + } + /** + * @return \stdClass[] + */ + private function renderPanels(?\Throwable $ex) : array + { + $obLevel = \ob_get_level(); + $res = []; + foreach ($this->panels as $callback) { + try { + $panel = $callback($ex); + if (empty($panel['tab']) || empty($panel['panel'])) { + continue; + } + $res[] = (object) $panel; + continue; + } catch (\Throwable $e) { + } + while (\ob_get_level() > $obLevel) { + // restore ob-level if broken + \ob_end_clean(); + } + \is_callable($callback, \true, $name); + $res[] = (object) ['tab' => "Error in panel {$name}", 'panel' => \nl2br(Helpers::escapeHtml($e))]; + } + return $res; + } + /** + * @return array[] + */ + private function renderActions(\Throwable $ex) : array + { + $actions = []; + foreach ($this->actions as $callback) { + $action = $callback($ex); + if (!empty($action['link']) && !empty($action['label'])) { + $actions[] = $action; + } + } + if (\property_exists($ex, 'tracyAction') && !empty($ex->tracyAction['link']) && !empty($ex->tracyAction['label'])) { + $actions[] = $ex->tracyAction; + } + if (\preg_match('# ([\'"])(\\w{3,}(?:\\\\\\w{3,})+)\\1#i', $ex->getMessage(), $m)) { + $class = $m[2]; + if (!\class_exists($class, \false) && !\interface_exists($class, \false) && !\trait_exists($class, \false) && ($file = Helpers::guessClassFile($class)) && !\is_file($file)) { + [$content, $line] = $this->generateNewFileContents($file, $class); + $actions[] = ['link' => Helpers::editorUri($file, $line, 'create', '', $content), 'label' => 'create class']; + } + } + if (\preg_match('# ([\'"])((?:/|[a-z]:[/\\\\])\\w[^\'"]+\\.\\w{2,5})\\1#i', $ex->getMessage(), $m)) { + $file = $m[2]; + if (\is_file($file)) { + $label = 'open'; + $content = ''; + $line = 1; + } else { + $label = 'create'; + [$content, $line] = $this->generateNewFileContents($file); + } + $actions[] = ['link' => Helpers::editorUri($file, $line, $label, '', $content), 'label' => $label . ' file']; + } + $query = ($ex instanceof \ErrorException ? '' : Helpers::getClass($ex) . ' ') . \preg_replace('#\'.*\'|".*"#Us', '', $ex->getMessage()); + $actions[] = ['link' => 'https://www.google.com/search?sourceid=tracy&q=' . \urlencode($query), 'label' => 'search', 'external' => \true]; + if ($ex instanceof \ErrorException && !empty($ex->skippable) && \preg_match('#^https?://#', $source = Helpers::getSource())) { + $actions[] = ['link' => $source . (\strpos($source, '?') ? '&' : '?') . '_tracy_skip_error', 'label' => 'skip error']; + } + return $actions; + } + /** + * Returns syntax highlighted source code. + */ + public static function highlightFile(string $file, int $line, int $lines = 15, bool $php = \true, int $column = 0) : ?string + { + $source = @\file_get_contents($file); + // @ file may not exist + if ($source === \false) { + return null; + } + $source = $php ? static::highlightPhp($source, $line, $lines, $column) : '<pre class=tracy-code><div>' . static::highlightLine(\htmlspecialchars($source, \ENT_IGNORE, 'UTF-8'), $line, $lines, $column) . '</div></pre>'; + if ($editor = Helpers::editorUri($file, $line)) { + $source = \substr_replace($source, ' title="Ctrl-Click to open in editor" data-tracy-href="' . Helpers::escapeHtml($editor) . '"', 4, 0); + } + return $source; + } + /** + * Returns syntax highlighted source code. + */ + public static function highlightPhp(string $source, int $line, int $lines = 15, int $column = 0) : string + { + if (\function_exists('ini_set')) { + \ini_set('highlight.comment', '#998; font-style: italic'); + \ini_set('highlight.default', '#000'); + \ini_set('highlight.html', '#06B'); + \ini_set('highlight.keyword', '#D24; font-weight: bold'); + \ini_set('highlight.string', '#080'); + } + $source = \preg_replace('#(__halt_compiler\\s*\\(\\)\\s*;).*#is', '$1', $source); + $source = \str_replace(["\r\n", "\r"], "\n", $source); + $source = \explode("\n", \highlight_string($source, \true)); + $out = $source[0]; + // <code><span color=highlight.html> + $source = \str_replace('<br />', "\n", $source[1]); + $out .= static::highlightLine($source, $line, $lines, $column); + $out = \str_replace(' ', ' ', $out); + return "<pre class='tracy-code'><div>{$out}</div></pre>"; + } + /** + * Returns highlighted line in HTML code. + */ + public static function highlightLine(string $html, int $line, int $lines = 15, int $column = 0) : string + { + $source = \explode("\n", "\n" . \str_replace("\r\n", "\n", $html)); + $out = ''; + $spans = 1; + $start = $i = \max(1, \min($line, \count($source) - 1) - (int) \floor($lines * 2 / 3)); + while (--$i >= 1) { + // find last highlighted block + if (\preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) { + if ($m[1] !== '</span>') { + $spans++; + $out .= $m[1]; + } + break; + } + } + $source = \array_slice($source, $start, $lines, \true); + \end($source); + $numWidth = \strlen((string) \key($source)); + foreach ($source as $n => $s) { + $spans += \substr_count($s, '<span') - \substr_count($s, '</span'); + $s = \str_replace(["\r", "\n"], ['', ''], $s); + \preg_match_all('#<[^>]+>#', $s, $tags); + if ($n == $line) { + $s = \strip_tags($s); + if ($column) { + $s = \preg_replace('#((?:&.*?;|[^&]){' . ($column - 1) . '})(&.*?;|.)#u', '\\1<span class="tracy-column-highlight">\\2</span>', $s . ' ', 1); + } + $out .= \sprintf("<span class='tracy-line-highlight'>%{$numWidth}s: %s\n</span>%s", $n, $s, \implode('', $tags[0])); + } else { + $out .= \sprintf("<span class='tracy-line'>%{$numWidth}s:</span> %s\n", $n, $s); + } + } + $out .= \str_repeat('</span>', $spans) . '</code>'; + return $out; + } + /** + * Returns syntax highlighted source code to Terminal. + */ + public static function highlightPhpCli(string $file, int $line, int $lines = 15, int $column = 0) : ?string + { + $source = @\file_get_contents($file); + // @ file may not exist + if ($source === \false) { + return null; + } + $s = self::highlightPhp($source, $line, $lines); + $colors = ['color: ' . \ini_get('highlight.comment') => '1;30', 'color: ' . \ini_get('highlight.default') => '1;36', 'color: ' . \ini_get('highlight.html') => '1;35', 'color: ' . \ini_get('highlight.keyword') => '1;37', 'color: ' . \ini_get('highlight.string') => '1;32', 'tracy-line' => '1;30', 'tracy-line-highlight' => "1;37m\x1b[41"]; + $stack = ['0']; + $s = \preg_replace_callback('#<\\w+(?: (class|style)=["\'](.*?)["\'])?[^>]*>|</\\w+>#', function ($m) use($colors, &$stack) : string { + if ($m[0][1] === '/') { + \array_pop($stack); + } else { + $stack[] = isset($m[2], $colors[$m[2]]) ? $colors[$m[2]] : '0'; + } + return "\x1b[0m\x1b[" . \end($stack) . 'm'; + }, $s); + $s = \htmlspecialchars_decode(\strip_tags($s), \ENT_QUOTES | \ENT_HTML5); + return $s; + } + /** + * Should a file be collapsed in stack trace? + * @internal + */ + public function isCollapsed(string $file) : bool + { + $file = \strtr($file, '\\', '/') . '/'; + foreach ($this->collapsePaths as $path) { + $path = \strtr($path, '\\', '/') . '/'; + if (\strncmp($file, $path, \strlen($path)) === 0) { + return \true; + } + } + return \false; + } + /** @internal */ + public function getDumper() : \Closure + { + return function ($v, $k = null) : string { + return Dumper::toHtml($v, [Dumper::DEPTH => $this->maxDepth, Dumper::TRUNCATE => $this->maxLength, Dumper::ITEMS => $this->maxItems, Dumper::SNAPSHOT => &$this->snapshot, Dumper::LOCATION => Dumper::LOCATION_CLASS, Dumper::SCRUBBER => $this->scrubber, Dumper::KEYS_TO_HIDE => $this->keysToHide], $k); + }; + } + public function formatMessage(\Throwable $exception) : string + { + $msg = Helpers::encodeString(\trim((string) $exception->getMessage()), self::MaxMessageLength, \false); + // highlight 'string' + $msg = \preg_replace('#\'\\S(?:[^\']|\\\\\')*\\S\'|"\\S(?:[^"]|\\\\")*\\S"#', '<i>$0</i>', $msg); + // clickable class & methods + $msg = \preg_replace_callback('#(\\w+\\\\[\\w\\\\]+\\w)(?:::(\\w+))?#', function ($m) { + if (isset($m[2]) && \method_exists($m[1], $m[2])) { + $r = new \ReflectionMethod($m[1], $m[2]); + } elseif (\class_exists($m[1], \false) || \interface_exists($m[1], \false)) { + $r = new \ReflectionClass($m[1]); + } + if (empty($r) || !$r->getFileName()) { + return $m[0]; + } + return '<a href="' . Helpers::escapeHtml(Helpers::editorUri($r->getFileName(), $r->getStartLine())) . '" class="tracy-editor">' . $m[0] . '</a>'; + }, $msg); + // clickable file name + $msg = \preg_replace_callback('#([\\w\\\\/.:-]+\\.(?:php|phpt|phtml|latte|neon))(?|:(\\d+)| on line (\\d+))?#', function ($m) { + return @\is_file($m[1]) ? '<a href="' . Helpers::escapeHtml(Helpers::editorUri($m[1], isset($m[2]) ? (int) $m[2] : null)) . '" class="tracy-editor">' . $m[0] . '</a>' : $m[0]; + }, $msg); + return $msg; + } + private function renderPhpInfo() : void + { + \ob_start(); + @\phpinfo(\INFO_LICENSE); + // @ phpinfo may be disabled + $license = \ob_get_clean(); + \ob_start(); + @\phpinfo(\INFO_CONFIGURATION | \INFO_MODULES); + // @ phpinfo may be disabled + $info = \ob_get_clean(); + if (\strpos($license, '<body') === \false) { + echo '<pre class="tracy-dump tracy-light">', Helpers::escapeHtml($info), '</pre>'; + } else { + $info = \str_replace('<table', '<table class="tracy-sortable"', $info); + echo \preg_replace('#^.+<body>|</body>.+\\z|<hr />|<h1>Configuration</h1>#s', '', $info); + } + } + /** @internal */ + private function generateNewFileContents(string $file, ?string $class = null) : array + { + foreach (\array_reverse($this->fileGenerators) as $generator) { + $content = $generator($file, $class); + if ($content !== null) { + $line = 1; + $pos = \strpos($content, '$END$'); + if ($pos !== \false) { + $content = \substr_replace($content, '', $pos, 5); + $line = \substr_count($content, "\n", 0, $pos) + 1; + } + return [$content, $line]; + } + } + return ['', 1]; + } + /** @internal */ + public static function generateNewPhpFileContents(string $file, ?string $class = null) : ?string + { + if (\substr($file, -4) !== '.php') { + return null; + } + $res = "<?php\n\ndeclare(strict_types=1);\n\n"; + if (!$class) { + return $res . '$END$'; + } + if ($pos = \strrpos($class, '\\')) { + $res .= 'namespace ' . \substr($class, 0, $pos) . ";\n\n"; + $class = \substr($class, $pos + 1); + } + return $res . "class {$class}\n{\n\$END\$\n}\n"; + } + private function findGeneratorsAndFibers(object $object) : array + { + $generators = $fibers = []; + $add = function ($obj) use(&$generators, &$fibers) { + if ($obj instanceof \Generator) { + try { + new \ReflectionGenerator($obj); + $generators[\spl_object_id($obj)] = $obj; + } catch (\ReflectionException $e) { + } + } elseif ($obj instanceof \Fiber && $obj->isStarted() && !$obj->isTerminated()) { + $fibers[\spl_object_id($obj)] = $obj; + } + }; + foreach ($this->fibers as $k => $v) { + $add($this->fibers instanceof \WeakMap ? $k : $v); + } + if (\PHP_VERSION_ID >= 80000) { + Helpers::traverseValue($object, $add); + } + return [$generators, $fibers]; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css new file mode 100644 index 00000000000..7e007625f05 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css @@ -0,0 +1,418 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +:root { + --tracy-space: 16px; +} + +@media (max-width: 600px) { + :root { + --tracy-space: 8px; + } +} + +html.tracy-bs-visible, +html.tracy-bs-visible body { + display: block; + overflow: auto; +} + +#tracy-bs { + font: 9pt/1.5 Verdana, sans-serif; + background: white; + color: #333; + position: absolute; + z-index: 20000; + left: 0; + top: 0; + width: 100%; + text-align: left; +} + +#tracy-bs a { + text-decoration: none; + color: #328ADC; + padding: 0 4px; + margin: 0 -4px; +} + +#tracy-bs a + a { + margin-left: 0; +} + +#tracy-bs a:hover, +#tracy-bs a:focus { + color: #085AA3; +} + +#tracy-bs-toggle { + position: absolute; + right: .5em; + top: .5em; + text-decoration: none; + background: #CD1818; + color: white !important; + padding: 3px; +} + +#tracy-bs-toggle.tracy-collapsed { + position: fixed; +} + +.tracy-bs-main { + display: flex; + flex-direction: column; + padding-bottom: 80vh; +} + +.tracy-bs-main.tracy-collapsed { + display: none; +} + +#tracy-bs p, +#tracy-bs table, +#tracy-bs pre, +#tracy-bs h1, +#tracy-bs h2, +#tracy-bs h3 { + margin: 0 0 var(--tracy-space); +} + +#tracy-bs h1 { + font-size: 15pt; + font-weight: normal; + text-shadow: 1px 1px 2px rgba(0, 0, 0, .3); +} + +#tracy-bs h1 span { + white-space: pre-wrap; +} + +#tracy-bs h2 { + font-size: 14pt; + font-weight: normal; + margin-top: var(--tracy-space); +} + +#tracy-bs h3 { + font-size: 10pt; + font-weight: bold; +} + +#tracy-bs pre, +#tracy-bs code, +#tracy-bs table { + font: 9pt/1.5 Consolas, monospace !important; +} + +#tracy-bs pre, +#tracy-bs table { + background: #FDF5CE; + padding: .4em .7em; + border: 2px solid #ffffffa6; + box-shadow: 1px 2px 6px #00000005; + overflow: auto; +} + +#tracy-bs table pre { + padding: 0; + margin: 0; + border: none; + box-shadow: none; +} + +#tracy-bs table { + border-collapse: collapse; + width: 100%; +} + +#tracy-bs td, +#tracy-bs th { + vertical-align: top; + text-align: left; + padding: 2px 6px; + border: 1px solid #e6dfbf; +} + +#tracy-bs th { + font-weight: bold; +} + +#tracy-bs tr > :first-child { + width: 20%; +} + +#tracy-bs tr:nth-child(2n), +#tracy-bs tr:nth-child(2n) pre { + background-color: #F7F0CB; +} + +#tracy-bs .tracy-footer--sticky { + position: fixed; + width: 100%; + bottom: 0; +} + +#tracy-bs footer ul { + font-size: 7pt; + padding: var(--tracy-space); + margin: var(--tracy-space) 0 0; + color: #777; + background: #F6F5F3; + border-top: 1px solid #DDD; + list-style: none; +} + +#tracy-bs .tracy-footer-logo { + position: relative; +} + +#tracy-bs .tracy-footer-logo a { + position: absolute; + bottom: 0; + right: 0; + width: 100px; + height: 50px; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAUBAMAAAD/1DctAAAAMFBMVEWupZzj39rEvbTy8O3X0sz9/PvGwLu8tavQysHq6OS0rKP5+Pbd2dT29fPMxbzPx8DKErMJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGUlEQVQoFX3TQWgTQRQA0MWLIJJDYehBTykhG5ERTx56K1u8eEhCYtomE7x5L4iLh0ViF7egewuFFqSIYE6hIHsIYQ6CQSg9CDKn4QsNCRlB59C74J/ZNHW1+An5+bOPyf6/s46oz2P+A0yIeZZ2ieEHi6TOnLKTxvWq+b52mxlVO3xnM1s7xLX1504XQH65OnW2dBqn7cCkYsFsfYsWpyY/2salmFTpEyzeR8zosYqMdiPDXdyU52K1wgEa/SjGpdEwUAxqvRfckQCDOyFearsEHe2grvkh/cFAHKvdtI3lcVceKQIOFpv+FOZaNPQBwJZLPp+hfrvT5JZXaUFsR8zqQc9qSgAharkfS5M/5F6nGJJAtXq/eLr3ucZpHccSxOOIPaQhtHohpCH2Xu6rLmQ0djnr4/+J3C6v+AW8/XWYxwYNdlhWj/P5fPSTQwVr0T9lGxdaBCqErNZaqYnEwbkjEB3NasGF3lPdrHa1nnxNOMgj0+neePUPjd2v/qVvUv29ifvc19huQ48qwXShy/9o8o3OSk0cs37mOFd0Ydgvsf/oZEnPVtggfd66lORn9mDyyzXU13SRtH2L6aR5T/snGAcZPfAXz5J1YlJWBEuxdMYqQecpBrlM49xAbmqyHA+xlA1FxBtqT2xmJoNXZlIt74ZBLeJ9ZGDqByNI7p543idzJ23vXEv7IgnsxiS+eNtwNbFdLq7+Bi4wQ0I4SVb9AAAAAElFTkSuQmCC') no-repeat; + opacity: .6; + padding: 0; + margin: 0; +} + +#tracy-bs .tracy-footer-logo a:hover, +#tracy-bs .tracy-footer-logo a:focus { + opacity: 1; + transition: opacity 0.1s; +} + + +#tracy-bs .tracy-section { + padding-left: calc(1.5 * var(--tracy-space)); + padding-right: calc(1.5 * var(--tracy-space)); +} + +#tracy-bs .tracy-section-panel { + background: #F4F3F1; + padding: var(--tracy-space) var(--tracy-space) 0; + margin: 0 0 var(--tracy-space); + border-radius: 8px; + box-shadow: inset 1px 1px 0px 0 #00000005; + overflow: hidden; +} + +#tracy-bs .outer, /* deprecated */ +#tracy-bs .tracy-pane { + overflow: auto; +} + +#tracy-bs.tracy-mac .tracy-pane { + padding-bottom: 12px; +} + + +/* header */ +#tracy-bs .tracy-section--error { + background: #CD1818; + color: white; + font-size: 13pt; + padding-top: var(--tracy-space); +} + +#tracy-bs .tracy-section--error h1 { + color: white; +} + +#tracy-bs .tracy-section--error::selection, +#tracy-bs .tracy-section--error ::selection { + color: black !important; + background: #FDF5CE !important; +} + +#tracy-bs .tracy-section--error a { + color: #ffefa1 !important; +} + +#tracy-bs .tracy-section--error span span { + font-size: 80%; + color: rgba(255, 255, 255, 0.5); + text-shadow: none; +} + +#tracy-bs .tracy-section--error a.tracy-action { + color: white !important; + opacity: 0; + font-size: .7em; + border-bottom: none !important; +} + +#tracy-bs .tracy-section--error:hover a.tracy-action { + opacity: .6; +} + +#tracy-bs .tracy-section--error a.tracy-action:hover { + opacity: 1; +} + +#tracy-bs .tracy-section--error i { + color: #ffefa1; + font-style: normal; +} + + +/* source code */ +#tracy-bs pre.tracy-code > div { + min-width: 100%; + float: left; + white-space: pre; +} + +#tracy-bs .tracy-line-highlight { + background: #CD1818; + color: white; + font-weight: bold; + font-style: normal; + display: block; + padding: 0 1ch; + margin: 0 -1ch; +} + +#tracy-bs .tracy-column-highlight { + display: inline-block; + backdrop-filter: grayscale(1); + margin: 0 -1px; + padding: 0 1px; +} + +#tracy-bs .tracy-line { + color: #9F9C7F; + font-weight: normal; + font-style: normal; +} + +#tracy-bs a.tracy-editor { + color: inherit; + border-bottom: 1px dotted rgba(0, 0, 0, .3); + border-radius: 3px; +} + +#tracy-bs a.tracy-editor:hover { + background: #0001; +} + +#tracy-bs span[data-tracy-href] { + border-bottom: 1px dotted rgba(0, 0, 0, .3); +} + +#tracy-bs .tracy-dump-whitespace { + color: #0003; +} + +#tracy-bs .tracy-caused { + float: right; + padding: .3em calc(1.5 * var(--tracy-space)); + background: #df8075; + border-radius: 0 0 0 8px; + white-space: nowrap; +} + +#tracy-bs .tracy-caused a { + color: white; +} + +#tracy-bs .tracy-callstack { + display: grid; + grid-template-columns: max-content 1fr; + margin-bottom: calc(.5 * var(--tracy-space)); +} + +#tracy-bs .tracy-callstack-file { + text-align: right; + padding-right: var(--tracy-space); + white-space: nowrap; + height: calc(1.5 * var(--tracy-space)); +} + +#tracy-bs .tracy-callstack-callee { + white-space: nowrap; + height: calc(1.5 * var(--tracy-space)); +} + +#tracy-bs .tracy-callstack-additional { + grid-column-start: 1; + grid-column-end: 3; +} + +#tracy-bs .tracy-callstack-args tr:first-child > * { + position: relative; +} + +#tracy-bs .tracy-callstack-args tr:first-child td:before { + position: absolute; + right: .3em; + content: 'may not be true'; + opacity: .4; +} + +#tracy-bs .tracy-panel-fadein { + animation: tracy-panel-fadein .12s ease; +} + +@keyframes tracy-panel-fadein { + 0% { + opacity: 0; + } +} + +#tracy-bs .tracy-section--causedby { + flex-direction: column; + padding: 0; +} + +#tracy-bs .tracy-section--causedby:not(.tracy-collapsed) { + display: flex; +} + +#tracy-bs .tracy-section--causedby .tracy-section--error { + background: #cd1818a6; +} + +#tracy-bs .tracy-section--error + .tracy-section--stack { + margin-top: calc(1.5 * var(--tracy-space)); +} + + +/* tabs */ +#tracy-bs .tracy-tab-bar { + display: flex; + list-style: none; + padding-left: 0; + margin: 0; + width: 100%; + font-size: 110%; +} + +#tracy-bs .tracy-tab-bar > *:not(:first-child) { + margin-left: var(--tracy-space); +} + +#tracy-bs .tracy-tab-bar a { + display: block; + padding: calc(.5 * var(--tracy-space)) var(--tracy-space); + margin: 0; + height: 100%; + box-sizing: border-box; + border-radius: 5px 5px 0 0; + text-decoration: none; + transition: all 0.1s; +} + +#tracy-bs .tracy-tab-bar > .tracy-active a { + background: white; +} + +#tracy-bs .tracy-tab-panel { + border-top: 2px solid white; + padding-top: var(--tracy-space); + overflow: auto; +} diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js new file mode 100644 index 00000000000..7a1b5b68f42 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js @@ -0,0 +1,77 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +class BlueScreen +{ + static init(ajax) { + BlueScreen.globalInit(); + + let blueScreen = document.getElementById('tracy-bs'); + + document.documentElement.classList.add('tracy-bs-visible'); + if (navigator.platform.indexOf('Mac') > -1) { + blueScreen.classList.add('tracy-mac'); + } + + blueScreen.addEventListener('tracy-toggle', (e) => { + if (e.target.matches('#tracy-bs-toggle')) { // blue screen toggle + document.documentElement.classList.toggle('tracy-bs-visible', !e.detail.collapsed); + + } else if (!e.target.matches('.tracy-dump *') && e.detail.originalEvent) { // panel toggle + e.detail.relatedTarget.classList.toggle('tracy-panel-fadein', !e.detail.collapsed); + } + }); + + if (!ajax) { + document.body.appendChild(blueScreen); + let id = location.href + document.querySelector('.tracy-section--error').textContent; + Tracy.Toggle.persist(blueScreen, sessionStorage.getItem('tracy-toggles-bskey') === id); + sessionStorage.setItem('tracy-toggles-bskey', id); + } + + (new ResizeObserver(stickyFooter)).observe(blueScreen); + + if (document.documentElement.classList.contains('tracy-bs-visible')) { + window.scrollTo(0, 0); + } + } + + + static globalInit() { + // enables toggling via ESC + document.addEventListener('keyup', (e) => { + if (e.keyCode === 27 && !e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) { // ESC + Tracy.Toggle.toggle(document.getElementById('tracy-bs-toggle')); + } + }); + + Tracy.TableSort.init(); + Tracy.Tabs.init(); + + window.addEventListener('scroll', stickyFooter); + + BlueScreen.globalInit = function() {}; + } + + + static loadAjax(content) { + let ajaxBs = document.getElementById('tracy-bs'); + if (ajaxBs) { + ajaxBs.remove(); + } + document.body.insertAdjacentHTML('beforeend', content); + ajaxBs = document.getElementById('tracy-bs'); + Tracy.Dumper.init(ajaxBs); + BlueScreen.init(true); + } +} + +function stickyFooter() { + let footer = document.querySelector('#tracy-bs footer'); + footer.classList.toggle('tracy-footer--sticky', false); // to measure footer.offsetTop + footer.classList.toggle('tracy-footer--sticky', footer.offsetHeight + footer.offsetTop - window.innerHeight - document.documentElement.scrollTop < 0); +} + +let Tracy = window.Tracy = window.Tracy || {}; +Tracy.BlueScreen = Tracy.BlueScreen || BlueScreen; diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml new file mode 100644 index 00000000000..107b6a0c418 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml @@ -0,0 +1,73 @@ +<?php + +declare(strict_types=1); + +namespace Tracy; + +/** + * @var \Throwable $exception + * @var array[] $actions + * @var string[] $info + * @var string $source + * @var ?array $lastError + * @var string[] $httpHeaders + * @var callable $dump + * @var array $snapshot + * @var bool $showEnvironment + * @var BlueScreen $this + * @var bool $headersSent + * @var ?string $headersFile + * @var ?int $headersLine + * @var ?array $obStatus + * @var \Generator[] $generators + * @var \Fiber[] $fibers + */ +?> +<tracy-div id="tracy-bs" itemscope> + <a id="tracy-bs-toggle" href="#" class="tracy-toggle"></a> + <div class="tracy-bs-main"> +<?php $ex = $exception; $exceptions = []; ?> +<?php require __DIR__ . '/section-exception.phtml' ?> + +<?php require __DIR__ . '/section-lastMutedError.phtml' ?> + +<?php $bottomPanels = [] ?> +<?php foreach ($this->renderPanels(null) as $panel): ?> +<?php if (!empty($panel->bottom)) { $bottomPanels[] = $panel; continue; } ?> +<?php $collapsedClass = !isset($panel->collapsed) || $panel->collapsed ? ' tracy-collapsed' : ''; ?> + <section class="tracy-section"> + <h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle<?= $collapsedClass ?>"><?= Helpers::escapeHtml($panel->tab) ?></a></h2> + + <div class="tracy-section-panel<?= $collapsedClass ?>"> + <?= $panel->panel ?> + </div> + </section> +<?php endforeach ?> + +<?php require __DIR__ . '/section-environment.phtml' ?> + +<?php require __DIR__ . '/section-cli.phtml' ?> + +<?php require __DIR__ . '/section-http.phtml' ?> + +<?php foreach ($bottomPanels as $panel): ?> + <section class="tracy-section"> + <h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle"><?= Helpers::escapeHtml($panel->tab) ?></a></h2> + + <div class="tracy-section-panel"> + <?= $panel->panel ?> + </div> + </section> +<?php endforeach ?> + + <footer> + <ul> + <li><b><a href="https://github.com/sponsors/dg" target="_blank" rel="noreferrer noopener">Please support Tracy via a donation 💙️</a></b></li> + <li>Report generated at <?= date('Y/m/d H:i:s') ?></li> + <?php foreach ($info as $item): ?><li><?= Helpers::escapeHtml($item) ?></li><?php endforeach ?> + </ul> + <div class="tracy-footer-logo"><a href="https://tracy.nette.org" rel="noreferrer"></a></div> + </footer> + </div> + <meta itemprop=tracy-snapshot content=<?= Dumper::formatSnapshotAttribute($snapshot) ?>> +</tracy-div> diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml new file mode 100644 index 00000000000..100bd670d1c --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml @@ -0,0 +1,55 @@ +<?php + +declare(strict_types=1); + +namespace Tracy; + +/** + * @var \Throwable $exception + * @var string $title + * @var ?string $nonce + * @var string $css + */ + +$code = $exception->getCode() ? ' #' . $exception->getCode() : ''; +$nonceAttr = $nonce ? ' nonce="' . Helpers::escapeHtml($nonce) . '"' : ''; +$chain = Helpers::getExceptionChain($exception); +?><!DOCTYPE html><!-- "' --></textarea></script></style></pre></xmp></a></iframe></noembed></noframes></noscript></option></select></template>

+ + + + + + + <?= Helpers::escapeHtml($title . ': ' . $exception->getMessage() . $code) ?> + + 1): ?> + + + + + + + + + + +> +'use strict'; + +Tracy.BlueScreen.init(); + + + diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml new file mode 100644 index 00000000000..92fd9e10951 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml @@ -0,0 +1,32 @@ + +
+ + +
+

Process ID

+
php
+ +

Arguments

+
+ + $v): ?> + + +
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml new file mode 100644 index 00000000000..866ec8976fe --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml @@ -0,0 +1,103 @@ + +
+ + +
+ +
+ + + +
+
+ + $v): ?> + + +
+
+ + + +
+
+ + $v): ?> + + +
Nette Session' : $dump($v, $k) ?>
+
+ + + +

Nette Session

+
+ + $v): ?> + + +
+
+ +
+ + + + + +
+ + $v): ?> + + +
+
+ + + +
+ renderPhpInfo() ?> + +
+ + + +
+ 10]) ?> +
+ +
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml new file mode 100644 index 00000000000..8807bf071bd --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml @@ -0,0 +1,29 @@ +getPrevious(); +if (!$ex || in_array($ex, $exceptions, true)) { + return; +} +$exceptions[] = $ex; +?> + +
+ + +
+ + +
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml new file mode 100644 index 00000000000..82af273bc23 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml @@ -0,0 +1,21 @@ + +
+ +
+ +
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-variables.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-variables.phtml new file mode 100644 index 00000000000..ef821c26dcd --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-variables.phtml @@ -0,0 +1,28 @@ +context) || !is_array($ex->context)) { + return; +} +?> +
+ + +
+
+ +context as $k => $v): ?> + + +
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml new file mode 100644 index 00000000000..74517d814fc --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml @@ -0,0 +1,74 @@ + + + +renderPanels($ex) as $panel): ?> +
+ + +
+ panel ?> +
+
+ + + +
+
+
+ + +
+
+ +
+ + +
+ +
+ + + +
+ +
+ +
+
+
+
+ + + + + + + + + diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml new file mode 100644 index 00000000000..8be19a997cb --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml @@ -0,0 +1,35 @@ +getSeverity()) + : Helpers::getClass($ex); +$code = $ex->getCode() ? ' #' . $ex->getCode() : ''; + +?> +
+ getMessage()): ?>

+ + +

formatMessage($ex) ?: Helpers::escapeHtml($title . $code) ?> + + > + +

+
+ +getPrevious()): ?> + + diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml new file mode 100644 index 00000000000..7d34e5c329c --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml @@ -0,0 +1,91 @@ + +
+ + +
+ +
+ + +
+ +
+

+ + +
+ + $v): ?> + + +
+
+ + + + +

$

+ +

empty

+ +
+ + $v): ?> + + +
+
+ + +
+ + +
+

Code:

+ +
+ + + + +
+
+ +

no headers

+ + + + +

Headers have been sent, output started at source

+
+ +

Headers have been sent

+ +

Headers were not sent at the time the exception was thrown

+ +
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml new file mode 100644 index 00000000000..7e5565f4a1e --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml @@ -0,0 +1,29 @@ + +
+ +
+ +

:

+

Note: the last muted error may have nothing to do with the thrown exception.

+ + +

+
+ +

inner-code

+ +
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml new file mode 100644 index 00000000000..fa94d4e5190 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml @@ -0,0 +1,92 @@ + + +
+ + +
+
+ $row): ?> + + +
+ + + + inner-code + + +
+ +
+ + +  + + +
+ + +
+ + + +
+ + +
+
+ +
+ +
+ +
+
+
+ + + + + + + +getParameters(); + } catch (\Exception $e) { + $params = []; + } + foreach ($row['args'] as $k => $v) { + $argName = isset($params[$k]) && !$params[$k]->isVariadic() ? $params[$k]->name : $k; + echo '\n"; + } +?> +
', Helpers::escapeHtml((is_string($argName) ? '$' : '#') . $argName), ''; + echo $dump($v, (string) $argName); + echo "
+ +
+ + +
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml new file mode 100644 index 00000000000..9e9bc66def0 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml @@ -0,0 +1,38 @@ +getTrace(); +$expanded = null; +if ( + (!$ex instanceof \ErrorException + || in_array($ex->getSeverity(), [E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED], true)) + && $this->isCollapsed($ex->getFile()) +) { + foreach ($stack as $key => $row) { + if (isset($row['file']) && !$this->isCollapsed($row['file'])) { + $expanded = $key; + break; + } + } +} + +if (in_array($stack[0]['class'] ?? null, [DevelopmentStrategy::class, ProductionStrategy::class], true)) { + array_shift($stack); +} +if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['function'], ['shutdownHandler', 'errorHandler'], true)) { + array_shift($stack); +} +$file = $ex->getFile(); +$line = $ex->getLine(); + +require __DIR__ . '/section-stack-sourceFile.phtml'; +require __DIR__ . '/section-stack-callStack.phtml'; diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml new file mode 100644 index 00000000000..4427be843e5 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml @@ -0,0 +1,16 @@ +getTrace(); +$expanded = 0; + +require __DIR__ . '/section-stack-callStack.phtml'; diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml new file mode 100644 index 00000000000..60aa6fc1d1a --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml @@ -0,0 +1,21 @@ +getTrace(); +$expanded = null; +$execGenerator = $ref->getExecutingGenerator(); +$refExec = new \ReflectionGenerator($execGenerator); +$file = $refExec->getExecutingFile(); +$line = $refExec->getExecutingLine(); + +require __DIR__ . '/section-stack-sourceFile.phtml'; +require __DIR__ . '/section-stack-callStack.phtml'; diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml new file mode 100644 index 00000000000..a678c2eab1d --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml @@ -0,0 +1,46 @@ + + +
+ + +
+ +
+ + +
+
+

File:

+ +
+ +
+

File:

+ +
+
+
+ +

File:

+ + + +
+
diff --git a/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php b/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php new file mode 100644 index 00000000000..b9bee226e5a --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php @@ -0,0 +1,448 @@ +initialize(); + self::dispatch(); + if (self::$enabled) { + return; + } + \register_shutdown_function([self::class, 'shutdownHandler']); + \set_exception_handler(function (\Throwable $e) { + self::exceptionHandler($e); + exit(255); + }); + \set_error_handler([self::class, 'errorHandler']); + foreach (['Bar/Bar', 'Bar/DefaultBarPanel', 'BlueScreen/BlueScreen', 'Dumper/Describer', 'Dumper/Dumper', 'Dumper/Exposer', 'Dumper/Renderer', 'Dumper/Value', 'Logger/FireLogger', 'Logger/Logger', 'Session/SessionStorage', 'Session/FileSession', 'Session/NativeSession', 'Helpers'] as $path) { + require_once \dirname(__DIR__) . "/{$path}.php"; + } + self::$enabled = \true; + } + public static function dispatch() : void + { + if (!Helpers::isCli() && self::getStrategy()->sendAssets()) { + self::$showBar = \false; + exit; + } + } + /** + * Renders loading + + + +Server Error + + + +
+
+

Server Error

+ +

We're sorry! The server encountered an internal error and + was unable to complete your request. Please try again later.

+ +

error 500 |
Tracy is unable to log error.

+
+
+ + diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php new file mode 100644 index 00000000000..ed2eec7fafd --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php @@ -0,0 +1,281 @@ + */ + public $objectExposers; + /** @var (int|\stdClass)[] */ + public $references = []; + public function describe($var) : \stdClass + { + \uksort($this->objectExposers, function ($a, $b) : int { + return $b === '' || \class_exists($a, \false) && \is_subclass_of($a, $b) ? -1 : 1; + }); + try { + return (object) ['value' => $this->describeVar($var), 'snapshot' => $this->snapshot, 'location' => $this->location ? self::findLocation() : null]; + } finally { + $free = [[], []]; + $this->snapshot =& $free[0]; + $this->references =& $free[1]; + } + } + /** + * @return mixed + */ + private function describeVar($var, int $depth = 0, ?int $refId = null) + { + if ($var === null || \is_bool($var)) { + return $var; + } + $m = 'describe' . \explode(' ', \gettype($var))[0]; + return $this->{$m}($var, $depth, $refId); + } + /** + * @return Value|int + */ + private function describeInteger(int $num) + { + return $num <= self::JsSafeInteger && $num >= -self::JsSafeInteger ? $num : new Value(Value::TypeNumber, "{$num}"); + } + /** + * @return Value|float + */ + private function describeDouble(float $num) + { + if (!\is_finite($num)) { + return new Value(Value::TypeNumber, (string) $num); + } + $js = \json_encode($num); + return \strpos($js, '.') ? $num : new Value(Value::TypeNumber, "{$js}.0"); + // to distinct int and float in JS + } + /** + * @return Value|string + */ + private function describeString(string $s, int $depth = 0) + { + $encoded = Helpers::encodeString($s, $depth ? $this->maxLength : null); + if ($encoded === $s) { + return $encoded; + } elseif (Helpers::isUtf8($s)) { + return new Value(Value::TypeStringHtml, $encoded, Helpers::utf8Length($s)); + } else { + return new Value(Value::TypeBinaryHtml, $encoded, \strlen($s)); + } + } + /** + * @return Value|array + */ + private function describeArray(array $arr, int $depth = 0, ?int $refId = null) + { + if ($refId) { + $res = new Value(Value::TypeRef, 'p' . $refId); + $value =& $this->snapshot[$res->value]; + if ($value && $value->depth <= $depth) { + return $res; + } + $value = new Value(Value::TypeArray); + $value->id = $res->value; + $value->depth = $depth; + if ($this->maxDepth && $depth >= $this->maxDepth) { + $value->length = \count($arr); + return $res; + } elseif ($depth && $this->maxItems && \count($arr) > $this->maxItems) { + $value->length = \count($arr); + $arr = \array_slice($arr, 0, $this->maxItems, \true); + } + $items =& $value->items; + } elseif ($arr && $this->maxDepth && $depth >= $this->maxDepth) { + return new Value(Value::TypeArray, null, \count($arr)); + } elseif ($depth && $this->maxItems && \count($arr) > $this->maxItems) { + $res = new Value(Value::TypeArray, null, \count($arr)); + $res->depth = $depth; + $items =& $res->items; + $arr = \array_slice($arr, 0, $this->maxItems, \true); + } + $items = []; + foreach ($arr as $k => $v) { + $refId = $this->getReferenceId($arr, $k); + $items[] = [$this->describeVar($k, $depth + 1), $this->isSensitive((string) $k, $v) ? new Value(Value::TypeText, self::hideValue($v)) : $this->describeVar($v, $depth + 1, $refId)] + ($refId ? [2 => $refId] : []); + } + return $res ?? $items; + } + private function describeObject(object $obj, int $depth = 0) : Value + { + $id = \spl_object_id($obj); + $value =& $this->snapshot[$id]; + if ($value && $value->depth <= $depth) { + return new Value(Value::TypeRef, $id); + } + $value = new Value(Value::TypeObject, Helpers::getClass($obj)); + $value->id = $id; + $value->depth = $depth; + $value->holder = $obj; + // to be not released by garbage collector in collecting mode + if ($this->location) { + $rc = $obj instanceof \Closure ? new \ReflectionFunction($obj) : new \ReflectionClass($obj); + if ($rc->getFileName() && ($editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine()))) { + $value->editor = (object) ['file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor]; + } + } + if ($this->maxDepth && $depth < $this->maxDepth) { + $value->items = []; + $props = $this->exposeObject($obj, $value); + foreach ($props ?? [] as $k => $v) { + $this->addPropertyTo($value, (string) $k, $v, Value::PropertyVirtual, $this->getReferenceId($props, $k)); + } + } + return new Value(Value::TypeRef, $id); + } + /** + * @param resource $resource + */ + private function describeResource($resource, int $depth = 0) : Value + { + $id = 'r' . (int) $resource; + $value =& $this->snapshot[$id]; + if (!$value) { + $type = \is_resource($resource) ? \get_resource_type($resource) : 'closed'; + $value = new Value(Value::TypeResource, $type . ' resource'); + $value->id = $id; + $value->depth = $depth; + $value->items = []; + if (isset($this->resourceExposers[$type])) { + foreach ($this->resourceExposers[$type]($resource) as $k => $v) { + $value->items[] = [\htmlspecialchars($k), $this->describeVar($v, $depth + 1)]; + } + } + } + return new Value(Value::TypeRef, $id); + } + /** + * @return Value|string + */ + public function describeKey(string $key) + { + if (\preg_match('#^[\\w!\\#$%&*+./;<>?@^{|}~-]{1,50}$#D', $key) && !\preg_match('#^(true|false|null)$#iD', $key)) { + return $key; + } + $value = $this->describeString($key); + return \is_string($value) ? new Value(Value::TypeStringHtml, $key, Helpers::utf8Length($key)) : $value; + } + public function addPropertyTo(Value $value, string $k, $v, $type = Value::PropertyVirtual, ?int $refId = null, ?string $class = null) + { + if ($value->depth && $this->maxItems && \count($value->items ?? []) >= $this->maxItems) { + $value->length = ($value->length ?? \count($value->items)) + 1; + return; + } + $class = $class ?? $value->value; + $value->items[] = [$this->describeKey($k), $type !== Value::PropertyVirtual && $this->isSensitive($k, $v, $class) ? new Value(Value::TypeText, self::hideValue($v)) : $this->describeVar($v, $value->depth + 1, $refId), $type === Value::PropertyPrivate ? $class : $type] + ($refId ? [3 => $refId] : []); + } + private function exposeObject(object $obj, Value $value) : ?array + { + foreach ($this->objectExposers as $type => $dumper) { + if (!$type || $obj instanceof $type) { + return $dumper($obj, $value, $this); + } + } + if ($this->debugInfo && \method_exists($obj, '__debugInfo')) { + return $obj->__debugInfo(); + } + Exposer::exposeObject($obj, $value, $this); + return null; + } + private function isSensitive(string $key, $val, ?string $class = null) : bool + { + return $this->scrubber !== null && ($this->scrubber)($key, $val, $class) || isset($this->keysToHide[\strtolower($key)]) || isset($this->keysToHide[\strtolower($class . '::$' . $key)]); + } + private static function hideValue($var) : string + { + return self::HiddenValue . ' (' . (\is_object($var) ? Helpers::getClass($var) : \gettype($var)) . ')'; + } + public function getReferenceId($arr, $key) : ?int + { + if (\PHP_VERSION_ID >= 70400) { + if (!($rr = \ReflectionReference::fromArrayElement($arr, $key))) { + return null; + } + $tmp =& $this->references[$rr->getId()]; + if ($tmp === null) { + return $tmp = \count($this->references); + } + return $tmp; + } + $uniq = new \stdClass(); + $copy = $arr; + $orig = $copy[$key]; + $copy[$key] = $uniq; + if ($arr[$key] !== $uniq) { + return null; + } + $res = \array_search($uniq, $this->references, \true); + $copy[$key] = $orig; + if ($res === \false) { + $this->references[] =& $arr[$key]; + return \count($this->references); + } + return $res + 1; + } + /** + * Finds the location where dump was called. Returns [file, line, code] + */ + private static function findLocation() : ?array + { + foreach (\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $item) { + if (isset($item['class']) && ($item['class'] === self::class || $item['class'] === Tracy\Dumper::class)) { + $location = $item; + continue; + } elseif (isset($item['function'])) { + try { + $reflection = isset($item['class']) ? new \ReflectionMethod($item['class'], $item['function']) : new \ReflectionFunction($item['function']); + if ($reflection->isInternal() || \preg_match('#\\s@tracySkipLocation\\s#', (string) $reflection->getDocComment())) { + $location = $item; + continue; + } + } catch (\ReflectionException $e) { + } + } + break; + } + if (isset($location['file'], $location['line']) && \is_file($location['file'])) { + $lines = \file($location['file']); + $line = $lines[$location['line'] - 1]; + return [$location['file'], $location['line'], \trim(\preg_match('#\\w*dump(er::\\w+)?\\(.*\\)#i', $line, $m) ? $m[0] : $line)]; + } + return null; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php b/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php new file mode 100644 index 00000000000..cd7409b39a5 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php @@ -0,0 +1,157 @@ + '1;33', 'null' => '1;33', 'number' => '1;32', 'string' => '1;36', 'array' => '1;31', 'public' => '1;37', 'protected' => '1;37', 'private' => '1;37', 'dynamic' => '1;37', 'virtual' => '1;37', 'object' => '1;31', 'resource' => '1;37', 'indent' => '1;30']; + /** @var array */ + public static $resources = ['stream' => 'stream_get_meta_data', 'stream-context' => 'stream_context_get_options', 'curl' => 'curl_getinfo']; + /** @var array */ + public static $objectExporters = [\Closure::class => [Exposer::class, 'exposeClosure'], \UnitEnum::class => [Exposer::class, 'exposeEnum'], \ArrayObject::class => [Exposer::class, 'exposeArrayObject'], \SplFileInfo::class => [Exposer::class, 'exposeSplFileInfo'], \SplObjectStorage::class => [Exposer::class, 'exposeSplObjectStorage'], \__PHP_Incomplete_Class::class => [Exposer::class, 'exposePhpIncompleteClass'], \Generator::class => [Exposer::class, 'exposeGenerator'], \Fiber::class => [Exposer::class, 'exposeFiber'], \DOMNode::class => [Exposer::class, 'exposeDOMNode'], \DOMNodeList::class => [Exposer::class, 'exposeDOMNodeList'], \DOMNamedNodeMap::class => [Exposer::class, 'exposeDOMNodeList'], Ds\Collection::class => [Exposer::class, 'exposeDsCollection'], Ds\Map::class => [Exposer::class, 'exposeDsMap']]; + /** @var Describer */ + private $describer; + /** @var Renderer */ + private $renderer; + /** + * Dumps variable to the output. + * @return mixed variable + */ + public static function dump($var, array $options = []) + { + if (Helpers::isCli()) { + $useColors = self::$terminalColors && Helpers::detectColors(); + $dumper = new self($options); + \fwrite(\STDOUT, $dumper->asTerminal($var, $useColors ? self::$terminalColors : [])); + } elseif (Helpers::isHtmlMode()) { + $options[self::LOCATION] = $options[self::LOCATION] ?? \true; + self::renderAssets(); + echo self::toHtml($var, $options); + } else { + echo self::toText($var, $options); + } + return $var; + } + /** + * Dumps variable to HTML. + */ + public static function toHtml($var, array $options = [], $key = null) : string + { + return (new self($options))->asHtml($var, $key); + } + /** + * Dumps variable to plain text. + */ + public static function toText($var, array $options = []) : string + { + return (new self($options))->asTerminal($var); + } + /** + * Dumps variable to x-terminal. + */ + public static function toTerminal($var, array $options = []) : string + { + return (new self($options))->asTerminal($var, self::$terminalColors); + } + /** + * Renders \n"; + } + } + private function __construct(array $options = []) + { + $location = $options[self::LOCATION] ?? 0; + $location = $location === \true ? ~0 : (int) $location; + $describer = $this->describer = new Describer(); + $describer->maxDepth = (int) ($options[self::DEPTH] ?? $describer->maxDepth); + $describer->maxLength = (int) ($options[self::TRUNCATE] ?? $describer->maxLength); + $describer->maxItems = (int) ($options[self::ITEMS] ?? $describer->maxItems); + $describer->debugInfo = (bool) ($options[self::DEBUGINFO] ?? $describer->debugInfo); + $describer->scrubber = $options[self::SCRUBBER] ?? $describer->scrubber; + $describer->keysToHide = \array_flip(\array_map('strtolower', $options[self::KEYS_TO_HIDE] ?? [])); + $describer->resourceExposers = ($options['resourceExporters'] ?? []) + self::$resources; + $describer->objectExposers = ($options[self::OBJECT_EXPORTERS] ?? []) + self::$objectExporters; + $describer->location = (bool) $location; + if ($options[self::LIVE] ?? \false) { + $tmp =& self::$liveSnapshot; + } elseif (isset($options[self::SNAPSHOT])) { + $tmp =& $options[self::SNAPSHOT]; + } + if (isset($tmp)) { + $tmp[0] = $tmp[0] ?? []; + $tmp[1] = $tmp[1] ?? []; + $describer->snapshot =& $tmp[0]; + $describer->references =& $tmp[1]; + } + $renderer = $this->renderer = new Renderer(); + $renderer->collapseTop = $options[self::COLLAPSE] ?? $renderer->collapseTop; + $renderer->collapseSub = $options[self::COLLAPSE_COUNT] ?? $renderer->collapseSub; + $renderer->collectingMode = isset($options[self::SNAPSHOT]) || !empty($options[self::LIVE]); + $renderer->lazy = $renderer->collectingMode ? \true : $options[self::LAZY] ?? $renderer->lazy; + $renderer->sourceLocation = !(~$location & self::LOCATION_SOURCE); + $renderer->classLocation = !(~$location & self::LOCATION_CLASS); + $renderer->theme = $options[self::THEME] ?? $renderer->theme; + $renderer->hash = $options[self::HASH] ?? \true; + } + /** + * Dumps variable to HTML. + */ + private function asHtml($var, $key = null) : string + { + if ($key === null) { + $model = $this->describer->describe($var); + } else { + $model = $this->describer->describe([$key => $var]); + $model->value = $model->value[0][1]; + } + return $this->renderer->renderAsHtml($model); + } + /** + * Dumps variable to x-terminal. + */ + private function asTerminal($var, array $colors = []) : string + { + $model = $this->describer->describe($var); + return $this->renderer->renderAsText($model, $colors); + } + public static function formatSnapshotAttribute(array &$snapshot) : string + { + $res = "'" . Renderer::jsonEncode($snapshot[0] ?? []) . "'"; + $snapshot = []; + return $res; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php new file mode 100644 index 00000000000..a014bc81278 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php @@ -0,0 +1,182 @@ + $v) { + $describer->addPropertyTo($value, (string) $k, $v, Value::PropertyDynamic, $describer->getReferenceId($values, $k)); + } + foreach ($props as $k => [$name, $class, $type]) { + if (\array_key_exists($k, $values)) { + $describer->addPropertyTo($value, $name, $values[$k], $type, $describer->getReferenceId($values, $k), $class); + } else { + $value->items[] = [$name, new Value(Value::TypeText, 'unset'), $type === Value::PropertyPrivate ? $class : $type]; + } + } + } + private static function getProperties($class) : array + { + static $cache; + if (isset($cache[$class])) { + return $cache[$class]; + } + $rc = new \ReflectionClass($class); + $parentProps = $rc->getParentClass() ? self::getProperties($rc->getParentClass()->getName()) : []; + $props = []; + foreach ($rc->getProperties() as $prop) { + $name = $prop->getName(); + if ($prop->isStatic() || $prop->getDeclaringClass()->getName() !== $class) { + // nothing + } elseif ($prop->isPrivate()) { + $props["\x00" . $class . "\x00" . $name] = [$name, $class, Value::PropertyPrivate]; + } elseif ($prop->isProtected()) { + $props["\x00*\x00" . $name] = [$name, $class, Value::PropertyProtected]; + } else { + $props[$name] = [$name, $class, Value::PropertyPublic]; + unset($parentProps["\x00*\x00" . $name]); + } + } + return $cache[$class] = $props + $parentProps; + } + public static function exposeClosure(\Closure $obj, Value $value, Describer $describer) : void + { + $rc = new \ReflectionFunction($obj); + if ($describer->location) { + $describer->addPropertyTo($value, 'file', $rc->getFileName() . ':' . $rc->getStartLine()); + } + $params = []; + foreach ($rc->getParameters() as $param) { + $params[] = '$' . $param->getName(); + } + $value->value .= '(' . \implode(', ', $params) . ')'; + $uses = []; + $useValue = new Value(Value::TypeObject); + $useValue->depth = $value->depth + 1; + foreach ($rc->getStaticVariables() as $name => $v) { + $uses[] = '$' . $name; + $describer->addPropertyTo($useValue, '$' . $name, $v); + } + if ($uses) { + $useValue->value = \implode(', ', $uses); + $useValue->collapsed = \true; + $value->items[] = ['use', $useValue]; + } + } + public static function exposeEnum(\UnitEnum $enum, Value $value, Describer $describer) : void + { + $value->value = \get_class($enum) . '::' . $enum->name; + if ($enum instanceof \BackedEnum) { + $describer->addPropertyTo($value, 'value', $enum->value); + $value->collapsed = \true; + } + } + public static function exposeArrayObject(\ArrayObject $obj, Value $value, Describer $describer) : void + { + $flags = $obj->getFlags(); + $obj->setFlags(\ArrayObject::STD_PROP_LIST); + self::exposeObject($obj, $value, $describer); + $obj->setFlags($flags); + $describer->addPropertyTo($value, 'storage', $obj->getArrayCopy(), Value::PropertyPrivate, null, \ArrayObject::class); + } + public static function exposeDOMNode(\DOMNode $obj, Value $value, Describer $describer) : void + { + $props = \preg_match_all('#^\\s*\\[([^\\]]+)\\] =>#m', \print_r($obj, \true), $tmp) ? $tmp[1] : []; + \sort($props); + foreach ($props as $p) { + $describer->addPropertyTo($value, $p, $obj->{$p}, Value::PropertyPublic); + } + } + /** + * @param \DOMNodeList|\DOMNamedNodeMap $obj + */ + public static function exposeDOMNodeList($obj, Value $value, Describer $describer) : void + { + $describer->addPropertyTo($value, 'length', $obj->length, Value::PropertyPublic); + $describer->addPropertyTo($value, 'items', \iterator_to_array($obj)); + } + public static function exposeGenerator(\Generator $gen, Value $value, Describer $describer) : void + { + try { + $r = new \ReflectionGenerator($gen); + $describer->addPropertyTo($value, 'file', $r->getExecutingFile() . ':' . $r->getExecutingLine()); + $describer->addPropertyTo($value, 'this', $r->getThis()); + } catch (\ReflectionException $e) { + $value->value = \get_class($gen) . ' (terminated)'; + } + } + public static function exposeFiber(\Fiber $fiber, Value $value, Describer $describer) : void + { + if ($fiber->isTerminated()) { + $value->value = \get_class($fiber) . ' (terminated)'; + } elseif (!$fiber->isStarted()) { + $value->value = \get_class($fiber) . ' (not started)'; + } else { + $r = new \ReflectionFiber($fiber); + $describer->addPropertyTo($value, 'file', $r->getExecutingFile() . ':' . $r->getExecutingLine()); + $describer->addPropertyTo($value, 'callable', $r->getCallable()); + } + } + public static function exposeSplFileInfo(\SplFileInfo $obj) : array + { + return ['path' => $obj->getPathname()]; + } + public static function exposeSplObjectStorage(\SplObjectStorage $obj) : array + { + $res = []; + foreach (clone $obj as $item) { + $res[] = ['object' => $item, 'data' => $obj[$item]]; + } + return $res; + } + public static function exposePhpIncompleteClass(\__PHP_Incomplete_Class $obj, Value $value, Describer $describer) : void + { + $values = (array) $obj; + $class = $values['__PHP_Incomplete_Class_Name']; + unset($values['__PHP_Incomplete_Class_Name']); + foreach ($values as $k => $v) { + $refId = $describer->getReferenceId($values, $k); + if (isset($k[0]) && $k[0] === "\x00") { + $info = \explode("\x00", $k); + $k = \end($info); + $type = $info[1] === '*' ? Value::PropertyProtected : Value::PropertyPrivate; + $decl = $type === Value::PropertyPrivate ? $info[1] : null; + } else { + $type = Value::PropertyPublic; + $k = (string) $k; + $decl = null; + } + $describer->addPropertyTo($value, $k, $v, $type, $refId, $decl); + } + $value->value = $class . ' (Incomplete Class)'; + } + public static function exposeDsCollection(Ds\Collection $obj, Value $value, Describer $describer) : void + { + foreach ($obj as $k => $v) { + $describer->addPropertyTo($value, (string) $k, $v, Value::PropertyVirtual); + } + } + public static function exposeDsMap(Ds\Map $obj, Value $value, Describer $describer) : void + { + $i = 0; + foreach ($obj as $k => $v) { + $describer->addPropertyTo($value, (string) $i++, new Ds\Pair($k, $v), Value::PropertyVirtual); + } + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php new file mode 100644 index 00000000000..5f67c3845be --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php @@ -0,0 +1,327 @@ +value; + $this->snapshot = $model->snapshot; + if ($this->lazy === \false) { + // no lazy-loading + $html = $this->renderVar($value); + $json = $snapshot = null; + } elseif ($this->lazy && (\is_array($value) && $value || \is_object($value))) { + // full lazy-loading + $html = ''; + $snapshot = $this->collectingMode ? null : $this->snapshot; + $json = $value; + } else { + // lazy-loading of collapsed parts + $html = $this->renderVar($value); + $snapshot = $this->snapshotSelection; + $json = null; + } + } finally { + $this->parents = $this->snapshot = $this->above = []; + $this->snapshotSelection = null; + } + $location = null; + if ($model->location && $this->sourceLocation) { + [$file, $line, $code] = $model->location; + $uri = Helpers::editorUri($file, $line); + $location = Helpers::formatHtml('', $uri ?? '#', $file, $line, $uri ? "\nClick to open in editor" : '') . Helpers::encodeString($code, 50) . " 📍"; + } + return '
 100 ? "\n" : '') . '>' . $location . $html . "
\n"; + } + public function renderAsText(\stdClass $model, array $colors = []) : string + { + try { + $this->snapshot = $model->snapshot; + $this->lazy = \false; + $s = $this->renderVar($model->value); + } finally { + $this->parents = $this->snapshot = $this->above = []; + } + $s = $colors ? self::htmlToAnsi($s, $colors) : $s; + $s = \htmlspecialchars_decode(\strip_tags($s), \ENT_QUOTES | \ENT_HTML5); + $s = \str_replace('…', '...', $s); + $s .= \substr($s, -1) === "\n" ? '' : "\n"; + if ($this->sourceLocation && ([$file, $line] = $model->location)) { + $s .= "in {$file}:{$line}\n"; + } + return $s; + } + /** + * @param mixed $value + * @param string|int|null $keyType + */ + private function renderVar($value, int $depth = 0, $keyType = null) : string + { + switch (\true) { + case $value === null: + return 'null'; + case \is_bool($value): + return '' . ($value ? 'true' : 'false') . ''; + case \is_int($value): + return '' . $value . ''; + case \is_float($value): + return '' . self::jsonEncode($value) . ''; + case \is_string($value): + return $this->renderString($value, $depth, $keyType); + case \is_array($value): + case $value->type === Value::TypeArray: + return $this->renderArray($value, $depth); + case $value->type === Value::TypeRef: + return $this->renderVar($this->snapshot[$value->value], $depth, $keyType); + case $value->type === Value::TypeObject: + return $this->renderObject($value, $depth); + case $value->type === Value::TypeNumber: + return '' . Helpers::escapeHtml($value->value) . ''; + case $value->type === Value::TypeText: + return '' . Helpers::escapeHtml($value->value) . ''; + case $value->type === Value::TypeStringHtml: + case $value->type === Value::TypeBinaryHtml: + return $this->renderString($value, $depth, $keyType); + case $value->type === Value::TypeResource: + return $this->renderResource($value, $depth); + default: + throw new \Exception('Unknown type'); + } + } + /** + * @param string|Value $str + * @param string|int|null $keyType + */ + private function renderString($str, int $depth, $keyType) : string + { + if ($keyType === self::TypeArrayKey) { + $indent = ' ' . \str_repeat('| ', $depth - 1) . ' '; + return '' . "'" . (\is_string($str) ? Helpers::escapeHtml($str) : \str_replace("\n", "\n" . $indent, $str->value)) . "'" . ''; + } elseif ($keyType !== null) { + $classes = [Value::PropertyPublic => 'tracy-dump-public', Value::PropertyProtected => 'tracy-dump-protected', Value::PropertyDynamic => 'tracy-dump-dynamic', Value::PropertyVirtual => 'tracy-dump-virtual']; + $indent = ' ' . \str_repeat('| ', $depth - 1) . ' '; + $title = \is_string($keyType) ? ' title="declared in ' . Helpers::escapeHtml($keyType) . '"' : null; + return '' . (\is_string($str) ? Helpers::escapeHtml($str) : "'" . \str_replace("\n", "\n" . $indent, $str->value) . "'") . ''; + } elseif (\is_string($str)) { + $len = Helpers::utf8Length($str); + return ' 1 ? ' title="' . $len . ' characters"' : '') . '>' . "'" . Helpers::escapeHtml($str) . "'" . ''; + } else { + $unit = $str->type === Value::TypeStringHtml ? 'characters' : 'bytes'; + $count = \substr_count($str->value, "\n"); + if ($count) { + $collapsed = $indent1 = $toggle = null; + $indent = ' '; + if ($depth) { + $collapsed = $count >= $this->collapseSub; + $indent1 = ' ' . \str_repeat('| ', $depth) . ''; + $indent = ' ' . \str_repeat('| ', $depth) . ' '; + $toggle = 'string' . "\n"; + } + return $toggle . '
' . $indent1 . ''" . \str_replace("\n", "\n" . $indent, $str->value) . "'" . ($depth ? "\n" : '') . '
'; + } + return 'length > 1 ? " title=\"{$str->length} {$unit}\"" : '') . '>' . "'" . $str->value . "'" . ''; + } + } + /** + * @param array|Value $array + */ + private function renderArray($array, int $depth) : string + { + $out = 'array ('; + if (\is_array($array)) { + $items = $array; + $count = \count($items); + $out .= $count . ')'; + } elseif ($array->items === null) { + return $out . $array->length . ') …'; + } else { + $items = $array->items; + $count = $array->length ?? \count($items); + $out .= $count . ')'; + if ($array->id && isset($this->parents[$array->id])) { + return $out . ' RECURSION'; + } elseif ($array->id && ($array->depth < $depth || isset($this->above[$array->id]))) { + if ($this->lazy !== \false) { + $ref = new Value(Value::TypeRef, $array->id); + $this->copySnapshot($ref); + return '" . $out . ''; + } elseif ($this->hash) { + return $out . (isset($this->above[$array->id]) ? ' see above' : ' see below'); + } + } + } + if (!$count) { + return $out; + } + $collapsed = $depth ? $this->lazy === \false || $depth === 1 ? $count >= $this->collapseSub : \true : (\is_int($this->collapseTop) ? $count >= $this->collapseTop : $this->collapseTop); + $span = 'lazy !== \false) { + $array = isset($array->id) ? new Value(Value::TypeRef, $array->id) : $array; + $this->copySnapshot($array); + return $span . " data-tracy-dump='" . self::jsonEncode($array) . "'>" . $out . ''; + } + $out = $span . '>' . $out . "\n" . ''; + $indent = ' ' . \str_repeat('| ', $depth) . ''; + $this->parents[$array->id ?? null] = $this->above[$array->id ?? null] = \true; + foreach ($items as $info) { + [$k, $v, $ref] = $info + [2 => null]; + $out .= $indent . $this->renderVar($k, $depth + 1, self::TypeArrayKey) . ' => ' . ($ref && $this->hash ? '&' . $ref . ' ' : '') . ($tmp = $this->renderVar($v, $depth + 1)) . (\substr($tmp, -6) === '' ? '' : "\n"); + } + if ($count > \count($items)) { + $out .= $indent . "…\n"; + } + unset($this->parents[$array->id ?? null]); + return $out . ''; + } + private function renderObject(Value $object, int $depth) : string + { + $editorAttributes = ''; + if ($this->classLocation && $object->editor) { + $editorAttributes = Helpers::formatHtml(' title="Declared in file % on line %%%" data-tracy-href="%"', $object->editor->file, $object->editor->line, $object->editor->url ? "\nCtrl-Click to open in editor" : '', "\nAlt-Click to expand/collapse all child nodes", $object->editor->url); + } + $pos = \strrpos($object->value, '\\'); + $out = '' . ($pos ? Helpers::escapeHtml(\substr($object->value, 0, $pos + 1)) . '' . Helpers::escapeHtml(\substr($object->value, $pos + 1)) . '' : Helpers::escapeHtml($object->value)) . '' . ($object->id && $this->hash ? ' #' . $object->id . '' : ''); + if ($object->items === null) { + return $out . ' …'; + } elseif (!$object->items) { + return $out; + } elseif ($object->id && isset($this->parents[$object->id])) { + return $out . ' RECURSION'; + } elseif ($object->id && ($object->depth < $depth || isset($this->above[$object->id]))) { + if ($this->lazy !== \false) { + $ref = new Value(Value::TypeRef, $object->id); + $this->copySnapshot($ref); + return '" . $out . ''; + } elseif ($this->hash) { + return $out . (isset($this->above[$object->id]) ? ' see above' : ' see below'); + } + } + $collapsed = $object->collapsed ?? ($depth ? $this->lazy === \false || $depth === 1 ? \count($object->items) >= $this->collapseSub : \true : (\is_int($this->collapseTop) ? \count($object->items) >= $this->collapseTop : $this->collapseTop)); + $span = 'lazy !== \false) { + $value = $object->id ? new Value(Value::TypeRef, $object->id) : $object; + $this->copySnapshot($value); + return $span . " data-tracy-dump='" . self::jsonEncode($value) . "'>" . $out . ''; + } + $out = $span . '>' . $out . "\n" . ''; + $indent = ' ' . \str_repeat('| ', $depth) . ''; + $this->parents[$object->id] = $this->above[$object->id] = \true; + foreach ($object->items as $info) { + [$k, $v, $type, $ref] = $info + [2 => Value::PropertyVirtual, null]; + $out .= $indent . $this->renderVar($k, $depth + 1, $type) . ': ' . ($ref && $this->hash ? '&' . $ref . ' ' : '') . ($tmp = $this->renderVar($v, $depth + 1)) . (\substr($tmp, -6) === '' ? '' : "\n"); + } + if ($object->length > \count($object->items)) { + $out .= $indent . "…\n"; + } + unset($this->parents[$object->id]); + return $out . ''; + } + private function renderResource(Value $resource, int $depth) : string + { + $out = '' . Helpers::escapeHtml($resource->value) . ' ' . ($this->hash ? '@' . \substr($resource->id, 1) . '' : ''); + if (!$resource->items) { + return $out; + } elseif (isset($this->above[$resource->id])) { + if ($this->lazy !== \false) { + $ref = new Value(Value::TypeRef, $resource->id); + $this->copySnapshot($ref); + return '" . $out . ''; + } + return $out . ' see above'; + } else { + $this->above[$resource->id] = \true; + $out = "{$out}\n
"; + foreach ($resource->items as [$k, $v]) { + $out .= ' ' . \str_repeat('| ', $depth) . '' . $this->renderVar($k, $depth + 1, Value::PropertyVirtual) . ': ' . ($tmp = $this->renderVar($v, $depth + 1)) . (\substr($tmp, -6) === '
' ? '' : "\n"); + } + return $out . ''; + } + } + private function copySnapshot($value) : void + { + if ($this->collectingMode) { + return; + } + if ($this->snapshotSelection === null) { + $this->snapshotSelection = []; + } + if (\is_array($value)) { + foreach ($value as [, $v]) { + $this->copySnapshot($v); + } + } elseif ($value instanceof Value && $value->type === Value::TypeRef) { + if (!isset($this->snapshotSelection[$value->value])) { + $ref = $this->snapshotSelection[$value->value] = $this->snapshot[$value->value]; + $this->copySnapshot($ref); + } + } elseif ($value instanceof Value && $value->items) { + foreach ($value->items as [, $v]) { + $this->copySnapshot($v); + } + } + } + public static function jsonEncode($snapshot) : string + { + $old = @\ini_set('serialize_precision', '-1'); + // @ may be disabled + try { + return \json_encode($snapshot, \JSON_HEX_APOS | \JSON_HEX_AMP | \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES); + } finally { + if ($old !== \false) { + \ini_set('serialize_precision', $old); + } + } + } + private static function htmlToAnsi(string $s, array $colors) : string + { + $stack = ['0']; + $s = \preg_replace_callback('#<\\w+(?: class="tracy-dump-(\\w+)")?[^>]*>|#', function ($m) use($colors, &$stack) : string { + if ($m[0][1] === '/') { + \array_pop($stack); + } else { + $stack[] = isset($m[1], $colors[$m[1]]) ? $colors[$m[1]] : '0'; + } + return "\x1b[" . \end($stack) . 'm'; + }, $s); + $s = \preg_replace('/\\e\\[0m(\\n*)(?=\\e)/', '$1', $s); + return $s; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Value.php b/vendor/tracy/tracy/src/Tracy/Dumper/Value.php new file mode 100644 index 00000000000..df29dc26f10 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/Value.php @@ -0,0 +1,51 @@ +type = $type; + $this->value = $value; + $this->length = $length; + } + public function jsonSerialize() : array + { + $res = [$this->type => $this->value]; + foreach (['length', 'editor', 'items', 'collapsed'] as $k) { + if ($this->{$k} !== null) { + $res[$k] = $this->{$k}; + } + } + return $res; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css new file mode 100644 index 00000000000..349159e715e --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css @@ -0,0 +1,145 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +.tracy-dump.tracy-dark { + text-align: left; + color: #f8f8f2; + background: #29292e; + border-radius: 4px; + padding: 1em; + margin: 1em 0; + word-break: break-all; + white-space: pre-wrap; +} + +.tracy-dump.tracy-dark div { + padding-left: 2.5ex; +} + +.tracy-dump.tracy-dark div div { + border-left: 1px solid rgba(255, 255, 255, .1); + margin-left: .5ex; +} + +.tracy-dump.tracy-dark div div:hover { + border-left-color: rgba(255, 255, 255, .25); +} + +.tracy-dark .tracy-dump-location { + color: silver; + font-size: 80%; + text-decoration: none; + background: none; + opacity: .5; + float: right; + cursor: pointer; +} + +.tracy-dark .tracy-dump-location:hover, +.tracy-dark .tracy-dump-location:focus { + opacity: 1; +} + +.tracy-dark .tracy-dump-array, +.tracy-dark .tracy-dump-object { + color: #f69c2e; + user-select: text; +} + +.tracy-dark .tracy-dump-string { + color: #3cdfef; + white-space: break-spaces; +} + +.tracy-dark div.tracy-dump-string { + position: relative; + padding-left: 3.5ex; +} + +.tracy-dark .tracy-dump-lq { + margin-left: calc(-1ex - 1px); +} + +.tracy-dark div.tracy-dump-string:before { + content: ''; + position: absolute; + left: calc(3ex - 1px); + top: 1.5em; + bottom: 0; + border-left: 1px solid rgba(255, 255, 255, .1); +} + +.tracy-dark .tracy-dump-virtual span, +.tracy-dark .tracy-dump-dynamic span, +.tracy-dark .tracy-dump-string span { + color: rgba(255, 255, 255, 0.5); +} + +.tracy-dark .tracy-dump-virtual i, +.tracy-dark .tracy-dump-dynamic i, +.tracy-dark .tracy-dump-string i { + font-size: 80%; + font-style: normal; + color: rgba(255, 255, 255, 0.5); + user-select: none; +} + +.tracy-dark .tracy-dump-number { + color: #77d285; +} + +.tracy-dark .tracy-dump-null, +.tracy-dark .tracy-dump-bool { + color: #f3cb44; +} + +.tracy-dark .tracy-dump-virtual { + font-style: italic; +} + +.tracy-dark .tracy-dump-public::after { + content: ' pub'; +} + +.tracy-dark .tracy-dump-protected::after { + content: ' pro'; +} + +.tracy-dark .tracy-dump-private::after { + content: ' pri'; +} + +.tracy-dark .tracy-dump-public::after, +.tracy-dark .tracy-dump-protected::after, +.tracy-dark .tracy-dump-private::after, +.tracy-dark .tracy-dump-hash { + font-size: 85%; + color: rgba(255, 255, 255, 0.35); +} + +.tracy-dark .tracy-dump-indent { + display: none; +} + +.tracy-dark .tracy-dump-highlight { + background: #C22; + color: white; + border-radius: 2px; + padding: 0 2px; + margin: 0 -2px; +} + +span[data-tracy-href] { + border-bottom: 1px dotted rgba(255, 255, 255, .2); +} + +.tracy-dark .tracy-dump-flash { + animation: tracy-dump-flash .2s ease; +} + +@keyframes tracy-dump-flash { + 0% { + background: #c0c0c033; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css new file mode 100644 index 00000000000..963dfb8c46e --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css @@ -0,0 +1,145 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +.tracy-dump.tracy-light { + text-align: left; + color: #444; + background: #fdf9e2; + border-radius: 4px; + padding: 1em; + margin: 1em 0; + word-break: break-all; + white-space: pre-wrap; +} + +.tracy-dump.tracy-light div { + padding-left: 2.5ex; +} + +.tracy-dump.tracy-light div div { + border-left: 1px solid rgba(0, 0, 0, .1); + margin-left: .5ex; +} + +.tracy-dump.tracy-light div div:hover { + border-left-color: rgba(0, 0, 0, .25); +} + +.tracy-light .tracy-dump-location { + color: gray; + font-size: 80%; + text-decoration: none; + background: none; + opacity: .5; + float: right; + cursor: pointer; +} + +.tracy-light .tracy-dump-location:hover, +.tracy-light .tracy-dump-location:focus { + opacity: 1; +} + +.tracy-light .tracy-dump-array, +.tracy-light .tracy-dump-object { + color: #C22; + user-select: text; +} + +.tracy-light .tracy-dump-string { + color: #35D; + white-space: break-spaces; +} + +.tracy-light div.tracy-dump-string { + position: relative; + padding-left: 3.5ex; +} + +.tracy-light .tracy-dump-lq { + margin-left: calc(-1ex - 1px); +} + +.tracy-light div.tracy-dump-string:before { + content: ''; + position: absolute; + left: calc(3ex - 1px); + top: 1.5em; + bottom: 0; + border-left: 1px solid rgba(0, 0, 0, .1); +} + +.tracy-light .tracy-dump-virtual span, +.tracy-light .tracy-dump-dynamic span, +.tracy-light .tracy-dump-string span { + color: rgba(0, 0, 0, 0.5); +} + +.tracy-light .tracy-dump-virtual i, +.tracy-light .tracy-dump-dynamic i, +.tracy-light .tracy-dump-string i { + font-size: 80%; + font-style: normal; + color: rgba(0, 0, 0, 0.5); + user-select: none; +} + +.tracy-light .tracy-dump-number { + color: #090; +} + +.tracy-light .tracy-dump-null, +.tracy-light .tracy-dump-bool { + color: #850; +} + +.tracy-light .tracy-dump-virtual { + font-style: italic; +} + +.tracy-light .tracy-dump-public::after { + content: ' pub'; +} + +.tracy-light .tracy-dump-protected::after { + content: ' pro'; +} + +.tracy-light .tracy-dump-private::after { + content: ' pri'; +} + +.tracy-light .tracy-dump-public::after, +.tracy-light .tracy-dump-protected::after, +.tracy-light .tracy-dump-private::after, +.tracy-light .tracy-dump-hash { + font-size: 85%; + color: rgba(0, 0, 0, 0.35); +} + +.tracy-light .tracy-dump-indent { + display: none; +} + +.tracy-light .tracy-dump-highlight { + background: #C22; + color: white; + border-radius: 2px; + padding: 0 2px; + margin: 0 -2px; +} + +span[data-tracy-href] { + border-bottom: 1px dotted rgba(0, 0, 0, .2); +} + +.tracy-light .tracy-dump-flash { + animation: tracy-dump-flash .2s ease; +} + +@keyframes tracy-dump-flash { + 0% { + background: #c0c0c033; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js new file mode 100644 index 00000000000..33cff84d381 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js @@ -0,0 +1,393 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +const + COLLAPSE_COUNT = 7, + COLLAPSE_COUNT_TOP = 14, + TYPE_ARRAY = 'a', + TYPE_OBJECT = 'o', + TYPE_RESOURCE = 'r', + PROP_VIRTUAL = 4, + PROP_PRIVATE = 2; + +const + HINT_CTRL = 'Ctrl-Click to open in editor', + HINT_ALT = 'Alt-Click to expand/collapse all child nodes'; + +class Dumper +{ + static init(context) { + // full lazy + (context || document).querySelectorAll('[data-tracy-snapshot][data-tracy-dump]').forEach((pre) => { //
+			let snapshot = JSON.parse(pre.getAttribute('data-tracy-snapshot'));
+			pre.removeAttribute('data-tracy-snapshot');
+			pre.appendChild(build(JSON.parse(pre.getAttribute('data-tracy-dump')), snapshot, pre.classList.contains('tracy-collapsed')));
+			pre.removeAttribute('data-tracy-dump');
+			pre.classList.remove('tracy-collapsed');
+		});
+
+		// snapshots
+		(context || document).querySelectorAll('meta[itemprop=tracy-snapshot]').forEach((meta) => {
+			let snapshot = JSON.parse(meta.getAttribute('content'));
+			meta.parentElement.querySelectorAll('[data-tracy-dump]').forEach((pre) => { // 
+				if (pre.closest('[data-tracy-snapshot]')) { // ignore unrelated 
+					return;
+				}
+				pre.appendChild(build(JSON.parse(pre.getAttribute('data-tracy-dump')), snapshot, pre.classList.contains('tracy-collapsed')));
+				pre.removeAttribute('data-tracy-dump');
+				pre.classList.remove('tracy-collapsed');
+			});
+			//  must be left for debug bar panel content
+		});
+
+		if (Dumper.inited) {
+			return;
+		}
+		Dumper.inited = true;
+
+		document.documentElement.addEventListener('click', (e) => {
+			let el;
+			// enables  & ctrl key
+			if (e.ctrlKey && (el = e.target.closest('[data-tracy-href]'))) {
+				location.href = el.getAttribute('data-tracy-href');
+				return false;
+			}
+
+		});
+
+		document.documentElement.addEventListener('tracy-beforetoggle', (e) => {
+			let el;
+			// initializes lazy  inside 
+			if ((el = e.target.closest('[data-tracy-snapshot]'))) {
+				let snapshot = JSON.parse(el.getAttribute('data-tracy-snapshot'));
+				el.removeAttribute('data-tracy-snapshot');
+				el.querySelectorAll('[data-tracy-dump]').forEach((toggler) => {
+					if (!toggler.nextSibling) {
+						toggler.after(document.createTextNode('\n')); // enforce \n after toggler
+					}
+					toggler.nextSibling.after(buildStruct(JSON.parse(toggler.getAttribute('data-tracy-dump')), snapshot, toggler, true, []));
+					toggler.removeAttribute('data-tracy-dump');
+				});
+			}
+		});
+
+		document.documentElement.addEventListener('tracy-toggle', (e) => {
+			if (!e.target.matches('.tracy-dump *')) {
+				return;
+			}
+
+			let cont = e.detail.relatedTarget;
+			let origE = e.detail.originalEvent;
+
+			if (origE && origE.usedIds) { // triggered by expandChild()
+				toggleChildren(cont, origE.usedIds);
+				return;
+
+			} else if (origE && origE.altKey && cont.querySelector('.tracy-toggle')) { // triggered by alt key
+				if (e.detail.collapsed) { // reopen
+					e.target.classList.toggle('tracy-collapsed', false);
+					cont.classList.toggle('tracy-collapsed', false);
+					e.detail.collapsed = false;
+				}
+
+				let expand = e.target.tracyAltExpand = !e.target.tracyAltExpand;
+				toggleChildren(cont, expand ? {} : false);
+			}
+
+			cont.classList.toggle('tracy-dump-flash', !e.detail.collapsed);
+		});
+
+		document.documentElement.addEventListener('animationend', (e) => {
+			if (e.animationName === 'tracy-dump-flash') {
+				e.target.classList.toggle('tracy-dump-flash', false);
+			}
+		});
+
+		document.addEventListener('mouseover', (e) => {
+			if (!e.target.matches('.tracy-dump *')) {
+				return;
+			}
+
+			let el;
+
+			if (e.target.matches('.tracy-dump-hash') && (el = e.target.closest('.tracy-dump'))) {
+				el.querySelectorAll('.tracy-dump-hash').forEach((el) => {
+					if (el.textContent === e.target.textContent) {
+						el.classList.add('tracy-dump-highlight');
+					}
+				});
+				return;
+			}
+
+			if ((el = e.target.closest('.tracy-toggle')) && !el.title) {
+				el.title = HINT_ALT;
+			}
+		});
+
+		document.addEventListener('mouseout', (e) => {
+			if (e.target.matches('.tracy-dump-hash')) {
+				document.querySelectorAll('.tracy-dump-hash.tracy-dump-highlight').forEach((el) => {
+					el.classList.remove('tracy-dump-highlight');
+				});
+			}
+		});
+
+		Tracy.Toggle.init();
+	}
+}
+
+
+function build(data, repository, collapsed, parentIds, keyType) {
+	let id, type = data === null ? 'null' : typeof data,
+		collapseCount = collapsed === null ? COLLAPSE_COUNT : COLLAPSE_COUNT_TOP;
+
+	if (type === 'null' || type === 'number' || type === 'boolean') {
+		return createEl(null, null, [
+			createEl(
+				'span',
+				{'class': 'tracy-dump-' + type.replace('ean', '')},
+				[data + '']
+			)
+		]);
+
+	} else if (type === 'string') {
+		data = {
+			string: data.replace(/&/g, '&').replace(/\'' + s + '\''}
+				),
+			]);
+
+		} else if (keyType !== undefined) {
+			if (type !== 'string') {
+				s = '\'' + s + '\'';
+			}
+
+			const classes = [
+				'tracy-dump-public',
+				'tracy-dump-protected',
+				'tracy-dump-private',
+				'tracy-dump-dynamic',
+				'tracy-dump-virtual',
+			];
+			return createEl(null, null, [
+				createEl(
+					'span',
+					{
+						'class': classes[typeof keyType === 'string' ? PROP_PRIVATE : keyType],
+						'title': typeof keyType === 'string' ? 'declared in ' + keyType : null,
+					},
+					{html: s}
+				),
+			]);
+		}
+
+		let count = (s.match(/\n/g) || []).length;
+		if (count) {
+			let collapsed = count >= COLLAPSE_COUNT;
+			return createEl(null, null, [
+				createEl('span', {'class': collapsed ? 'tracy-toggle tracy-collapsed' : 'tracy-toggle'}, ['string']),
+				'\n',
+				createEl(
+					'div',
+					{
+						'class': 'tracy-dump-string' + (collapsed ? ' tracy-collapsed' : ''),
+						'title': data.length + (data.bin ? ' bytes' : ' characters'),
+					},
+					{html: '\'' + s + '\''}
+				),
+			]);
+		}
+
+		return createEl(null, null, [
+			createEl(
+				'span',
+				{
+					'class': 'tracy-dump-string',
+					'title': data.length + (data.bin ? ' bytes' : ' characters'),
+				},
+				{html: '\'' + s + '\''}
+			),
+		]);
+
+	} else if (data.number) {
+		return createEl(null, null, [
+			createEl('span', {'class': 'tracy-dump-number'}, [data.number])
+		]);
+
+	} else if (data.text !== undefined) {
+		return createEl(null, null, [
+			createEl('span', {class: 'tracy-dump-virtual'}, [data.text])
+		]);
+
+	} else { // object || resource || array
+		let pos, nameEl;
+		nameEl = data.object && (pos = data.object.lastIndexOf('\\')) > 0
+			? [data.object.substr(0, pos + 1), createEl('b', null, [data.object.substr(pos + 1)])]
+			: [data.object || data.resource];
+
+		let span = data.array !== undefined
+			? [
+				createEl('span', {'class': 'tracy-dump-array'}, ['array']),
+				' (' + (data.length || data.items.length) + ')'
+			]
+			: [
+				createEl('span', {
+					'class': data.object ? 'tracy-dump-object' : 'tracy-dump-resource',
+					title: data.editor ? 'Declared in file ' + data.editor.file + ' on line ' + data.editor.line + (data.editor.url ? '\n' + HINT_CTRL : '') + '\n' + HINT_ALT : null,
+					'data-tracy-href': data.editor ? data.editor.url : null
+				}, nameEl),
+				...(id ? [' ', createEl('span', {'class': 'tracy-dump-hash'}, [data.resource ? '@' + id.substr(1) : '#' + id])] : [])
+			];
+
+		parentIds = parentIds ? parentIds.slice() : [];
+		let recursive = id && parentIds.indexOf(id) > -1;
+		parentIds.push(id);
+
+		if (recursive || !data.items || !data.items.length) {
+			span.push(recursive ? ' RECURSION' : (!data.items || data.items.length ? ' …' : ''));
+			return createEl(null, null, span);
+		}
+
+		collapsed = collapsed === true || data.collapsed || (data.items && data.items.length >= collapseCount);
+		let toggle = createEl('span', {'class': collapsed ? 'tracy-toggle tracy-collapsed' : 'tracy-toggle'}, span);
+
+		return createEl(null, null, [
+			toggle,
+			'\n',
+			buildStruct(data, repository, toggle, collapsed, parentIds),
+		]);
+	}
+}
+
+
+function buildStruct(data, repository, toggle, collapsed, parentIds) {
+	if (Array.isArray(data)) {
+		data = {items: data};
+
+	} else if (data.ref) {
+		parentIds = parentIds.slice();
+		parentIds.push(data.ref);
+		data = repository[data.ref];
+	}
+
+	let cut = data.items && data.length > data.items.length;
+	let type = data.object ? TYPE_OBJECT : data.resource ? TYPE_RESOURCE : TYPE_ARRAY;
+	let div = createEl('div', {'class': collapsed ? 'tracy-collapsed' : null});
+
+	if (collapsed) {
+		let handler;
+		toggle.addEventListener('tracy-toggle', handler = function() {
+			toggle.removeEventListener('tracy-toggle', handler);
+			createItems(div, data.items, type, repository, parentIds, null);
+			if (cut) {
+				createEl(div, null, ['…\n']);
+			}
+		});
+	} else {
+		createItems(div, data.items, type, repository, parentIds, true);
+		if (cut) {
+			createEl(div, null, ['…\n']);
+		}
+	}
+
+	return div;
+}
+
+
+function createEl(el, attrs, content) {
+	if (!(el instanceof Node)) {
+		el = el ? document.createElement(el) : document.createDocumentFragment();
+	}
+	for (let id in attrs || {}) {
+		if (attrs[id] !== null) {
+			el.setAttribute(id, attrs[id]);
+		}
+	}
+
+	if (content && content.html !== undefined) {
+		el.innerHTML = content.html;
+		return el;
+	}
+
+	content = content || [];
+	el.append(...content.filter((child) => (child !== null)));
+	return el;
+}
+
+
+function createItems(el, items, type, repository, parentIds, collapsed) {
+	let key, val, vis, ref, i, tmp;
+
+	for (i = 0; i < items.length; i++) {
+		if (type === TYPE_ARRAY) {
+			[key, val, ref] = items[i];
+		} else {
+			[key, val, vis = PROP_VIRTUAL, ref] = items[i];
+		}
+
+		createEl(el, null, [
+			build(key, null, null, null, type === TYPE_ARRAY ? TYPE_ARRAY : vis),
+			type === TYPE_ARRAY ? ' => ' : ': ',
+			...(ref ? [createEl('span', {'class': 'tracy-dump-hash'}, ['&' + ref]), ' '] : []),
+			tmp = build(val, repository, collapsed, parentIds),
+			tmp.lastElementChild.tagName === 'DIV' ? '' : '\n',
+		]);
+	}
+}
+
+
+function toggleChildren(cont, usedIds) {
+	let hashEl, id;
+
+	cont.querySelectorAll(':scope > .tracy-toggle').forEach((el) => {
+		hashEl = (el.querySelector('.tracy-dump-hash') || el.previousElementSibling);
+		id = hashEl && hashEl.matches('.tracy-dump-hash') ? hashEl.textContent : null;
+
+		if (!usedIds || (id && usedIds[id])) {
+			Tracy.Toggle.toggle(el, false);
+		} else {
+			usedIds[id] = true;
+			Tracy.Toggle.toggle(el, true, {usedIds: usedIds});
+		}
+	});
+}
+
+
+function UnknownEntityException() {}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.Dumper = Tracy.Dumper || Dumper;
+
+function init() {
+	Tracy.Dumper.init();
+}
+
+if (document.readyState === 'loading') {
+	document.addEventListener('DOMContentLoaded', init);
+} else {
+	init();
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Helpers.php b/vendor/tracy/tracy/src/Tracy/Helpers.php
new file mode 100644
index 00000000000..21509f1cec8
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Helpers.php
@@ -0,0 +1,430 @@
+%%%', $editor, $origFile . ($line ? ":{$line}" : ''), \rtrim(\dirname($file), \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR, \basename($file), $line ? ":{$line}" : '');
+        } else {
+            return self::formatHtml('%', $file . ($line ? ":{$line}" : ''));
+        }
+    }
+    /**
+     * Returns link to editor.
+     */
+    public static function editorUri(string $file, ?int $line = null, string $action = 'open', string $search = '', string $replace = '') : ?string
+    {
+        if (Debugger::$editor && $file && ($action === 'create' || \is_file($file))) {
+            $file = \strtr($file, '/', \DIRECTORY_SEPARATOR);
+            $file = \strtr($file, Debugger::$editorMapping);
+            $search = \str_replace("\n", \PHP_EOL, $search);
+            $replace = \str_replace("\n", \PHP_EOL, $replace);
+            return \strtr(Debugger::$editor, ['%action' => $action, '%file' => \rawurlencode($file), '%line' => $line ?: 1, '%search' => \rawurlencode($search), '%replace' => \rawurlencode($replace)]);
+        }
+        return null;
+    }
+    public static function formatHtml(string $mask) : string
+    {
+        $args = \func_get_args();
+        return \preg_replace_callback('#%#', function () use(&$args, &$count) : string {
+            return \str_replace("\n", '
', self::escapeHtml($args[++$count]));
+        }, $mask);
+    }
+    public static function escapeHtml($s) : string
+    {
+        return \htmlspecialchars((string) $s, \ENT_QUOTES | \ENT_SUBSTITUTE | \ENT_HTML5, 'UTF-8');
+    }
+    public static function findTrace(array $trace, $method, ?int &$index = null) : ?array
+    {
+        $m = \is_array($method) ? $method : \explode('::', $method);
+        foreach ($trace as $i => $item) {
+            if (isset($item['function']) && $item['function'] === \end($m) && isset($item['class']) === isset($m[1]) && (!isset($item['class']) || $m[0] === '*' || \is_a($item['class'], $m[0], \true))) {
+                $index = $i;
+                return $item;
+            }
+        }
+        return null;
+    }
+    public static function getClass($obj) : string
+    {
+        return \explode("\x00", \get_class($obj))[0];
+    }
+    /** @internal */
+    public static function fixStack(\Throwable $exception) : \Throwable
+    {
+        if (\function_exists('xdebug_get_function_stack')) {
+            $stack = [];
+            $trace = @\xdebug_get_function_stack();
+            // @ xdebug compatibility warning
+            $trace = \array_slice(\array_reverse($trace), 2, -1);
+            foreach ($trace as $row) {
+                $frame = ['file' => $row['file'], 'line' => $row['line'], 'function' => $row['function'] ?? '*unknown*', 'args' => []];
+                if (!empty($row['class'])) {
+                    $frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::';
+                    $frame['class'] = $row['class'];
+                }
+                $stack[] = $frame;
+            }
+            $ref = new \ReflectionProperty('Exception', 'trace');
+            $ref->setAccessible(\true);
+            $ref->setValue($exception, $stack);
+        }
+        return $exception;
+    }
+    /** @internal */
+    public static function errorTypeToString(int $type) : string
+    {
+        $types = [\E_ERROR => 'Fatal Error', \E_USER_ERROR => 'User Error', \E_RECOVERABLE_ERROR => 'Recoverable Error', \E_CORE_ERROR => 'Core Error', \E_COMPILE_ERROR => 'Compile Error', \E_PARSE => 'Parse Error', \E_WARNING => 'Warning', \E_CORE_WARNING => 'Core Warning', \E_COMPILE_WARNING => 'Compile Warning', \E_USER_WARNING => 'User Warning', \E_NOTICE => 'Notice', \E_USER_NOTICE => 'User Notice', \E_STRICT => 'Strict standards', \E_DEPRECATED => 'Deprecated', \E_USER_DEPRECATED => 'User Deprecated'];
+        return $types[$type] ?? 'Unknown error';
+    }
+    /** @internal */
+    public static function getSource() : string
+    {
+        if (self::isCli()) {
+            return 'CLI (PID: ' . \getmypid() . ')' . (isset($_SERVER['argv']) ? ': ' . \implode(' ', \array_map([self::class, 'escapeArg'], $_SERVER['argv'])) : '');
+        } elseif (isset($_SERVER['REQUEST_URI'])) {
+            return (!empty($_SERVER['HTTPS']) && \strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') . ($_SERVER['HTTP_HOST'] ?? '') . $_SERVER['REQUEST_URI'];
+        } else {
+            return \PHP_SAPI;
+        }
+    }
+    /** @internal */
+    public static function improveException(\Throwable $e) : void
+    {
+        $message = $e->getMessage();
+        if (!$e instanceof \Error && !$e instanceof \ErrorException || $e instanceof Nette\MemberAccessException || \strpos($e->getMessage(), 'did you mean')) {
+            // do nothing
+        } elseif (\preg_match('#^Call to undefined function (\\S+\\\\)?(\\w+)\\(#', $message, $m)) {
+            $funcs = \array_merge(\get_defined_functions()['internal'], \get_defined_functions()['user']);
+            $hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2]);
+            $message = "Call to undefined function {$m[2]}(), did you mean {$hint}()?";
+            $replace = ["{$m[2]}(", "{$hint}("];
+        } elseif (\preg_match('#^Call to undefined method ([\\w\\\\]+)::(\\w+)#', $message, $m)) {
+            $hint = self::getSuggestion(\get_class_methods($m[1]) ?: [], $m[2]);
+            $message .= ", did you mean {$hint}()?";
+            $replace = ["{$m[2]}(", "{$hint}("];
+        } elseif (\preg_match('#^Undefined variable:? \\$?(\\w+)#', $message, $m) && !empty($e->context)) {
+            $hint = self::getSuggestion(\array_keys($e->context), $m[1]);
+            $message = "Undefined variable \${$m[1]}, did you mean \${$hint}?";
+            $replace = ["\${$m[1]}", "\${$hint}"];
+        } elseif (\preg_match('#^Undefined property: ([\\w\\\\]+)::\\$(\\w+)#', $message, $m)) {
+            $rc = new \ReflectionClass($m[1]);
+            $items = \array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($prop) {
+                return !$prop->isStatic();
+            });
+            $hint = self::getSuggestion($items, $m[2]);
+            $message .= ", did you mean \${$hint}?";
+            $replace = ["->{$m[2]}", "->{$hint}"];
+        } elseif (\preg_match('#^Access to undeclared static property:? ([\\w\\\\]+)::\\$(\\w+)#', $message, $m)) {
+            $rc = new \ReflectionClass($m[1]);
+            $items = \array_filter($rc->getProperties(\ReflectionProperty::IS_STATIC), function ($prop) {
+                return $prop->isPublic();
+            });
+            $hint = self::getSuggestion($items, $m[2]);
+            $message .= ", did you mean \${$hint}?";
+            $replace = ["::\${$m[2]}", "::\${$hint}"];
+        }
+        if (isset($hint)) {
+            $loc = Debugger::mapSource($e->getFile(), $e->getLine()) ?? ['file' => $e->getFile(), 'line' => $e->getLine()];
+            $ref = new \ReflectionProperty($e, 'message');
+            $ref->setAccessible(\true);
+            $ref->setValue($e, $message);
+            @($e->tracyAction = [
+                // dynamic properties are deprecated since PHP 8.2
+                'link' => self::editorUri($loc['file'], $loc['line'], 'fix', $replace[0], $replace[1]),
+                'label' => 'fix it',
+            ]);
+        }
+    }
+    /** @internal */
+    public static function improveError(string $message, array $context = []) : string
+    {
+        if (\preg_match('#^Undefined variable:? \\$?(\\w+)#', $message, $m) && $context) {
+            $hint = self::getSuggestion(\array_keys($context), $m[1]);
+            return $hint ? "Undefined variable \${$m[1]}, did you mean \${$hint}?" : $message;
+        } elseif (\preg_match('#^Undefined property: ([\\w\\\\]+)::\\$(\\w+)#', $message, $m)) {
+            $rc = new \ReflectionClass($m[1]);
+            $items = \array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($prop) {
+                return !$prop->isStatic();
+            });
+            $hint = self::getSuggestion($items, $m[2]);
+            return $hint ? $message . ", did you mean \${$hint}?" : $message;
+        }
+        return $message;
+    }
+    /** @internal */
+    public static function guessClassFile(string $class) : ?string
+    {
+        $segments = \explode('\\', $class);
+        $res = null;
+        $max = 0;
+        foreach (\get_declared_classes() as $class) {
+            $parts = \explode('\\', $class);
+            foreach ($parts as $i => $part) {
+                if ($part !== ($segments[$i] ?? null)) {
+                    break;
+                }
+            }
+            if ($i > $max && $i < \count($segments) && ($file = (new \ReflectionClass($class))->getFileName())) {
+                $max = $i;
+                $res = \array_merge(\array_slice(\explode(\DIRECTORY_SEPARATOR, $file), 0, $i - \count($parts)), \array_slice($segments, $i));
+                $res = \implode(\DIRECTORY_SEPARATOR, $res) . '.php';
+            }
+        }
+        return $res;
+    }
+    /**
+     * Finds the best suggestion.
+     * @internal
+     */
+    public static function getSuggestion(array $items, string $value) : ?string
+    {
+        $best = null;
+        $min = (\strlen($value) / 4 + 1) * 10 + 0.1;
+        $items = \array_map(function ($item) {
+            return $item instanceof \Reflector ? $item->getName() : (string) $item;
+        }, $items);
+        foreach (\array_unique($items) as $item) {
+            if (($len = \levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
+                $min = $len;
+                $best = $item;
+            }
+        }
+        return $best;
+    }
+    /** @internal */
+    public static function isHtmlMode() : bool
+    {
+        return empty($_SERVER['HTTP_X_REQUESTED_WITH']) && empty($_SERVER['HTTP_X_TRACY_AJAX']) && isset($_SERVER['HTTP_HOST']) && !self::isCli() && !\preg_match('#^Content-Type: *+(?!text/html)#im', \implode("\n", \headers_list()));
+    }
+    /** @internal */
+    public static function isAjax() : bool
+    {
+        return isset($_SERVER['HTTP_X_TRACY_AJAX']) && \preg_match('#^\\w{10,15}$#D', $_SERVER['HTTP_X_TRACY_AJAX']);
+    }
+    /** @internal */
+    public static function isRedirect() : bool
+    {
+        return (bool) \preg_match('#^Location:#im', \implode("\n", \headers_list()));
+    }
+    /** @internal */
+    public static function createId() : string
+    {
+        return \bin2hex(\random_bytes(5));
+    }
+    /** @internal */
+    public static function isCli() : bool
+    {
+        return \PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg';
+    }
+    /** @internal */
+    public static function getNonce() : ?string
+    {
+        return \preg_match('#^Content-Security-Policy(?:-Report-Only)?:.*\\sscript-src\\s+(?:[^;]+\\s)?\'nonce-([\\w+/]+=*)\'#mi', \implode("\n", \headers_list()), $m) ? $m[1] : null;
+    }
+    /**
+     * Escape a string to be used as a shell argument.
+     */
+    private static function escapeArg(string $s) : string
+    {
+        if (\preg_match('#^[a-z0-9._=/:-]+$#Di', $s)) {
+            return $s;
+        }
+        return \defined('PHP_WINDOWS_VERSION_BUILD') ? '"' . \str_replace('"', '""', $s) . '"' : \escapeshellarg($s);
+    }
+    /**
+     * Captures PHP output into a string.
+     */
+    public static function capture(callable $func) : string
+    {
+        \ob_start(function () {
+        });
+        try {
+            $func();
+            return \ob_get_clean();
+        } catch (\Throwable $e) {
+            \ob_end_clean();
+            throw $e;
+        }
+    }
+    /** @internal */
+    public static function encodeString(string $s, ?int $maxLength = null, bool $showWhitespaces = \true) : string
+    {
+        $utf8 = self::isUtf8($s);
+        $len = $utf8 ? self::utf8Length($s) : \strlen($s);
+        return $maxLength && $len > $maxLength + 20 ? self::doEncodeString(self::truncateString($s, $maxLength, $utf8), $utf8, $showWhitespaces) . '  ' . self::doEncodeString(self::truncateString($s, -10, $utf8), $utf8, $showWhitespaces) : self::doEncodeString($s, $utf8, $showWhitespaces);
+    }
+    private static function doEncodeString(string $s, bool $utf8, bool $showWhitespaces) : string
+    {
+        $specials = [\true => ["\r" => '\\r', "\n" => "\\n\n", "\t" => '\\t    ', "\x1b" => '\\e', '<' => '<', '&' => '&'], \false => ["\r" => "\r", "\n" => "\n", "\t" => "\t", "\x1b" => '\\e', '<' => '<', '&' => '&']];
+        $special = $specials[$showWhitespaces];
+        $s = \preg_replace_callback($utf8 ? '#[\\p{C}<&]#u' : '#[\\x00-\\x1F\\x7F-\\xFF<&]#', function ($m) use($special) {
+            return $special[$m[0]] ?? (\strlen($m[0]) === 1 ? '\\x' . \str_pad(\strtoupper(\dechex(\ord($m[0]))), 2, '0', \STR_PAD_LEFT) . '' : '\\u{' . \strtoupper(\ltrim(\dechex(self::utf8Ord($m[0])), '0')) . '}');
+        }, $s);
+        $s = \str_replace('', '', $s);
+        $s = \preg_replace('~\\n$~D', '', $s);
+        return $s;
+    }
+    private static function utf8Ord(string $c) : int
+    {
+        $ord0 = \ord($c[0]);
+        if ($ord0 < 0x80) {
+            return $ord0;
+        } elseif ($ord0 < 0xe0) {
+            return ($ord0 << 6) + \ord($c[1]) - 0x3080;
+        } elseif ($ord0 < 0xf0) {
+            return ($ord0 << 12) + (\ord($c[1]) << 6) + \ord($c[2]) - 0xe2080;
+        } else {
+            return ($ord0 << 18) + (\ord($c[1]) << 12) + (\ord($c[2]) << 6) + \ord($c[3]) - 0x3c82080;
+        }
+    }
+    /** @internal */
+    public static function utf8Length(string $s) : int
+    {
+        return \function_exists('mb_strlen') ? \mb_strlen($s, 'UTF-8') : \strlen(\utf8_decode($s));
+    }
+    /** @internal */
+    public static function isUtf8(string $s) : bool
+    {
+        return (bool) \preg_match('##u', $s);
+    }
+    /** @internal */
+    public static function truncateString(string $s, int $len, bool $utf) : string
+    {
+        if (!$utf) {
+            return $len < 0 ? \substr($s, $len) : \substr($s, 0, $len);
+        } elseif (\function_exists('mb_substr')) {
+            return $len < 0 ? \mb_substr($s, $len, -$len, 'UTF-8') : \mb_substr($s, 0, $len, 'UTF-8');
+        } else {
+            $len < 0 ? \preg_match('#.{0,' . -$len . '}\\z#us', $s, $m) : \preg_match("#^.{0,{$len}}#us", $s, $m);
+            return $m[0];
+        }
+    }
+    /** @internal */
+    public static function minifyJs(string $s) : string
+    {
+        // author: Jakub Vrana https://php.vrana.cz/minifikace-javascriptu.php
+        $last = '';
+        return \preg_replace_callback(<<<'XX'
+			(
+				(?:
+					(^|[-+\([{}=,:;!%^&*|?~]|/(?![/*])|return|throw) # context before regexp
+					(?:\s|//[^\n]*+\n|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+					(/(?![/*])(?:\\[^\n]|[^[\n/\\]|\[(?:\\[^\n]|[^]])++)+/) # regexp
+					|(^
+						|'(?:\\.|[^\n'\\])*'
+						|"(?:\\.|[^\n"\\])*"
+						|([0-9A-Za-z_$]+)
+						|([-+]+)
+						|.
+					)
+				)(?:\s|//[^\n]*+\n|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+			())sx
+XX
+, function ($match) use(&$last) {
+            [, $context, $regexp, $result, $word, $operator] = $match;
+            if ($word !== '') {
+                $result = ($last === 'word' ? ' ' : ($last === 'return' ? ' ' : '')) . $result;
+                $last = $word === 'return' || $word === 'throw' || $word === 'break' ? 'return' : 'word';
+            } elseif ($operator) {
+                $result = ($last === $operator[0] ? ' ' : '') . $result;
+                $last = $operator[0];
+            } else {
+                if ($regexp) {
+                    $result = $context . ($context === '/' ? ' ' : '') . $regexp;
+                }
+                $last = '';
+            }
+            return $result;
+        }, $s . "\n");
+    }
+    /** @internal */
+    public static function minifyCss(string $s) : string
+    {
+        $last = '';
+        return \preg_replace_callback(<<<'XX'
+			(
+				(^
+					|'(?:\\.|[^\n'\\])*'
+					|"(?:\\.|[^\n"\\])*"
+					|([0-9A-Za-z_*#.%:()[\]-]+)
+					|.
+				)(?:\s|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+			())sx
+XX
+, function ($match) use(&$last) {
+            [, $result, $word] = $match;
+            if ($last === ';') {
+                $result = $result === '}' ? '}' : ';' . $result;
+                $last = '';
+            }
+            if ($word !== '') {
+                $result = ($last === 'word' ? ' ' : '') . $result;
+                $last = 'word';
+            } elseif ($result === ';') {
+                $last = ';';
+                $result = '';
+            } else {
+                $last = '';
+            }
+            return $result;
+        }, $s . "\n");
+    }
+    public static function detectColors() : bool
+    {
+        return self::isCli() && \getenv('NO_COLOR') === \false && (\getenv('FORCE_COLOR') || (\function_exists('sapi_windows_vt100_support') ? \sapi_windows_vt100_support(\STDOUT) : @\stream_isatty(\STDOUT)));
+    }
+    public static function getExceptionChain(\Throwable $ex) : array
+    {
+        $res = [$ex];
+        while (($ex = $ex->getPrevious()) && !\in_array($ex, $res, \true)) {
+            $res[] = $ex;
+        }
+        return $res;
+    }
+    public static function traverseValue($val, callable $callback, array &$skip = [], ?string $refId = null) : void
+    {
+        if (\is_object($val)) {
+            $id = \spl_object_id($val);
+            if (!isset($skip[$id])) {
+                $skip[$id] = \true;
+                $callback($val);
+                self::traverseValue((array) $val, $callback, $skip);
+            }
+        } elseif (\is_array($val)) {
+            if ($refId) {
+                if (isset($skip[$refId])) {
+                    return;
+                }
+                $skip[$refId] = \true;
+            }
+            foreach ($val as $k => $v) {
+                $refId = ($r = \ReflectionReference::fromArrayElement($val, $k)) ? $r->getId() : null;
+                self::traverseValue($v, $callback, $skip, $refId);
+            }
+        }
+    }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Logger/FireLogger.php b/vendor/tracy/tracy/src/Tracy/Logger/FireLogger.php
new file mode 100644
index 00000000000..e74f1638360
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Logger/FireLogger.php
@@ -0,0 +1,135 @@
+ []];
+    /**
+     * Sends message to FireLogger console.
+     * @param  mixed  $message
+     */
+    public function log($message, $level = self::DEBUG) : bool
+    {
+        if (!isset($_SERVER['HTTP_X_FIRELOGGER']) || \headers_sent()) {
+            return \false;
+        }
+        $item = ['name' => 'PHP', 'level' => $level, 'order' => \count($this->payload['logs']), 'time' => \str_pad(\number_format((\microtime(\true) - Debugger::$time) * 1000, 1, '.', ' '), 8, '0', \STR_PAD_LEFT) . ' ms', 'template' => '', 'message' => '', 'style' => 'background:#767ab6'];
+        $args = \func_get_args();
+        if (isset($args[0]) && \is_string($args[0])) {
+            $item['template'] = \array_shift($args);
+        }
+        if (isset($args[0]) && $args[0] instanceof \Throwable) {
+            $e = \array_shift($args);
+            $trace = $e->getTrace();
+            if (isset($trace[0]['class']) && $trace[0]['class'] === Debugger::class && ($trace[0]['function'] === 'shutdownHandler' || $trace[0]['function'] === 'errorHandler')) {
+                unset($trace[0]);
+            }
+            $file = \str_replace(\dirname($e->getFile(), 3), "…", $e->getFile());
+            $item['template'] = ($e instanceof \ErrorException ? '' : Helpers::getClass($e) . ': ') . $e->getMessage() . ($e->getCode() ? ' #' . $e->getCode() : '') . ' in ' . $file . ':' . $e->getLine();
+            $item['pathname'] = $e->getFile();
+            $item['lineno'] = $e->getLine();
+        } else {
+            $trace = \debug_backtrace();
+            if (isset($trace[1]['class']) && $trace[1]['class'] === Debugger::class && $trace[1]['function'] === 'fireLog') {
+                unset($trace[0]);
+            }
+            foreach ($trace as $frame) {
+                if (isset($frame['file']) && \is_file($frame['file'])) {
+                    $item['pathname'] = $frame['file'];
+                    $item['lineno'] = $frame['line'];
+                    break;
+                }
+            }
+        }
+        $item['exc_info'] = ['', '', []];
+        $item['exc_frames'] = [];
+        foreach ($trace as $frame) {
+            $frame += ['file' => null, 'line' => null, 'class' => null, 'type' => null, 'function' => null, 'object' => null, 'args' => null];
+            $item['exc_info'][2][] = [$frame['file'], $frame['line'], "{$frame['class']}{$frame['type']}{$frame['function']}", $frame['object']];
+            $item['exc_frames'][] = $frame['args'];
+        }
+        if (isset($args[0]) && \in_array($args[0], [self::DEBUG, self::INFO, self::WARNING, self::ERROR, self::CRITICAL], \true)) {
+            $item['level'] = \array_shift($args);
+        }
+        $item['args'] = $args;
+        $this->payload['logs'][] = $this->jsonDump($item, -1);
+        foreach (\str_split(\base64_encode(\json_encode($this->payload, \JSON_INVALID_UTF8_SUBSTITUTE)), 4990) as $k => $v) {
+            \header("FireLogger-de11e-{$k}: {$v}");
+        }
+        return \true;
+    }
+    /**
+     * Dump implementation for JSON.
+     * @param  mixed  $var
+     * @return array|int|float|bool|string|null
+     */
+    private function jsonDump(&$var, int $level = 0)
+    {
+        if (\is_bool($var) || $var === null || \is_int($var) || \is_float($var)) {
+            return $var;
+        } elseif (\is_string($var)) {
+            $var = Helpers::encodeString($var, $this->maxLength);
+            return \htmlspecialchars_decode(\strip_tags($var));
+        } elseif (\is_array($var)) {
+            static $marker;
+            if ($marker === null) {
+                $marker = \uniqid("\x00", \true);
+            }
+            if (isset($var[$marker])) {
+                return "…RECURSION…";
+            } elseif ($level < $this->maxDepth || !$this->maxDepth) {
+                $var[$marker] = \true;
+                $res = [];
+                foreach ($var as $k => &$v) {
+                    if ($k !== $marker) {
+                        $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
+                    }
+                }
+                unset($var[$marker]);
+                return $res;
+            } else {
+                return " … ";
+            }
+        } elseif (\is_object($var)) {
+            $arr = (array) $var;
+            static $list = [];
+            if (\in_array($var, $list, \true)) {
+                return "…RECURSION…";
+            } elseif ($level < $this->maxDepth || !$this->maxDepth) {
+                $list[] = $var;
+                $res = ["\x00" => '(object) ' . Helpers::getClass($var)];
+                foreach ($arr as $k => &$v) {
+                    if (isset($k[0]) && $k[0] === "\x00") {
+                        $k = \substr($k, \strrpos($k, "\x00") + 1);
+                    }
+                    $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
+                }
+                \array_pop($list);
+                return $res;
+            } else {
+                return " … ";
+            }
+        } elseif (\is_resource($var)) {
+            return 'resource ' . \get_resource_type($var);
+        } else {
+            return 'unknown type';
+        }
+    }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php b/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php
new file mode 100644
index 00000000000..da9ebe850bf
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php
@@ -0,0 +1,17 @@
+directory = $directory;
+        $this->email = $email;
+        $this->blueScreen = $blueScreen;
+        $this->mailer = [$this, 'defaultMailer'];
+    }
+    /**
+     * Logs message or exception to file and sends email notification.
+     * @param  mixed  $message
+     * @param  string  $level  one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
+     * @return string|null logged error filename
+     */
+    public function log($message, $level = self::INFO)
+    {
+        if (!$this->directory) {
+            throw new \LogicException('Logging directory is not specified.');
+        } elseif (!\is_dir($this->directory)) {
+            throw new \RuntimeException("Logging directory '{$this->directory}' is not found or is not directory.");
+        }
+        $exceptionFile = $message instanceof \Throwable ? $this->getExceptionFile($message, $level) : null;
+        $line = static::formatLogLine($message, $exceptionFile);
+        $file = $this->directory . '/' . \strtolower($level ?: self::INFO) . '.log';
+        if (!@\file_put_contents($file, $line . \PHP_EOL, \FILE_APPEND | \LOCK_EX)) {
+            // @ is escalated to exception
+            throw new \RuntimeException("Unable to write to log file '{$file}'. Is directory writable?");
+        }
+        if ($exceptionFile) {
+            $this->logException($message, $exceptionFile);
+        }
+        if (\in_array($level, [self::ERROR, self::EXCEPTION, self::CRITICAL], \true)) {
+            $this->sendEmail($message);
+        }
+        return $exceptionFile;
+    }
+    /**
+     * @param  mixed  $message
+     */
+    public static function formatMessage($message) : string
+    {
+        if ($message instanceof \Throwable) {
+            foreach (Helpers::getExceptionChain($message) as $exception) {
+                $tmp[] = ($exception instanceof \ErrorException ? Helpers::errorTypeToString($exception->getSeverity()) . ': ' . $exception->getMessage() : Helpers::getClass($exception) . ': ' . $exception->getMessage() . ($exception->getCode() ? ' #' . $exception->getCode() : '')) . ' in ' . $exception->getFile() . ':' . $exception->getLine();
+            }
+            $message = \implode("\ncaused by ", $tmp);
+        } elseif (!\is_string($message)) {
+            $message = Dumper::toText($message);
+        }
+        return \trim($message);
+    }
+    /**
+     * @param  mixed  $message
+     */
+    public static function formatLogLine($message, ?string $exceptionFile = null) : string
+    {
+        return \implode(' ', [\date('[Y-m-d H-i-s]'), \preg_replace('#\\s*\\r?\\n\\s*#', ' ', static::formatMessage($message)), ' @  ' . Helpers::getSource(), $exceptionFile ? ' @@  ' . \basename($exceptionFile) : null]);
+    }
+    public function getExceptionFile(\Throwable $exception, string $level = self::EXCEPTION) : string
+    {
+        foreach (Helpers::getExceptionChain($exception) as $exception) {
+            $data[] = [\get_class($exception), $exception->getMessage(), $exception->getCode(), $exception->getFile(), $exception->getLine(), \array_map(function (array $item) : array {
+                unset($item['args']);
+                return $item;
+            }, $exception->getTrace())];
+        }
+        $hash = \substr(\md5(\serialize($data)), 0, 10);
+        $dir = \strtr($this->directory . '/', '\\/', \DIRECTORY_SEPARATOR . \DIRECTORY_SEPARATOR);
+        foreach (new \DirectoryIterator($this->directory) as $file) {
+            if (\strpos($file->getBasename(), $hash)) {
+                return $dir . $file;
+            }
+        }
+        return $dir . $level . '--' . \date('Y-m-d--H-i') . "--{$hash}.html";
+    }
+    /**
+     * Logs exception to the file if file doesn't exist.
+     * @return string logged error filename
+     */
+    protected function logException(\Throwable $exception, ?string $file = null) : string
+    {
+        $file = $file ?: $this->getExceptionFile($exception);
+        $bs = $this->blueScreen ?: new BlueScreen();
+        $bs->renderToFile($exception, $file);
+        return $file;
+    }
+    /**
+     * @param  mixed  $message
+     */
+    protected function sendEmail($message) : void
+    {
+        $snooze = \is_numeric($this->emailSnooze) ? $this->emailSnooze : \strtotime($this->emailSnooze) - \time();
+        if ($this->email && $this->mailer && @\filemtime($this->directory . '/email-sent') + $snooze < \time() && @\file_put_contents($this->directory . '/email-sent', 'sent')) {
+            ($this->mailer)($message, \implode(', ', (array) $this->email));
+        }
+    }
+    /**
+     * Default mailer.
+     * @param  mixed  $message
+     * @internal
+     */
+    public function defaultMailer($message, string $email) : void
+    {
+        $host = \preg_replace('#[^\\w.-]+#', '', $_SERVER['SERVER_NAME'] ?? \php_uname('n'));
+        $parts = \str_replace(["\r\n", "\n"], ["\n", \PHP_EOL], ['headers' => \implode("\n", ['From: ' . ($this->fromEmail ?: "noreply@{$host}"), 'X-Mailer: Tracy', 'Content-Type: text/plain; charset=UTF-8', 'Content-Transfer-Encoding: 8bit']) . "\n", 'subject' => "PHP: An error occurred on the server {$host}", 'body' => static::formatMessage($message) . "\n\nsource: " . Helpers::getSource()]);
+        \mail($email, $parts['subject'], $parts['body'], $parts['headers']);
+    }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php b/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php
new file mode 100644
index 00000000000..991151494aa
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php
@@ -0,0 +1,61 @@
+start();
+    }
+    public function start() : void
+    {
+        foreach (\get_included_files() as $file) {
+            if (\fread(\fopen($file, 'r'), 3) === self::BOM) {
+                $this->list[] = [$file, 1, self::BOM];
+            }
+        }
+        \ob_start([$this, 'handler'], 1);
+    }
+    /** @internal */
+    public function handler(string $s, int $phase) : ?string
+    {
+        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
+        if (isset($trace[0]['file'], $trace[0]['line'])) {
+            $stack = $trace;
+            unset($stack[0]['line'], $stack[0]['args']);
+            $i = \count($this->list);
+            if ($i && $this->list[$i - 1][3] === $stack) {
+                $this->list[$i - 1][2] .= $s;
+            } else {
+                $this->list[] = [$trace[0]['file'], $trace[0]['line'], $s, $stack];
+            }
+        }
+        return $phase === \PHP_OUTPUT_HANDLER_FINAL ? $this->renderHtml() : null;
+    }
+    private function renderHtml() : string
+    {
+        $res = '';
+        foreach ($this->list as $item) {
+            $stack = [];
+            foreach (\array_slice($item[3], 1) as $t) {
+                $t += ['class' => '', 'type' => '', 'function' => ''];
+                $stack[] = "{$t['class']}{$t['type']}{$t['function']}()" . (isset($t['file'], $t['line']) ? ' in ' . \basename($t['file']) . ":{$t['line']}" : '');
+            }
+            $res .= '' . Helpers::editorLink($item[0], $item[1]) . ' ' . \str_replace(self::BOM, 'BOM', Dumper::toHtml($item[2])) . "
\n"; + } + return $res . '
'; + } +} diff --git a/vendor/tracy/tracy/src/Tracy/assets/reset.css b/vendor/tracy/tracy/src/Tracy/assets/reset.css new file mode 100644 index 00000000000..e333f841e57 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/reset.css @@ -0,0 +1,376 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +tracy-div:not(a b), +tracy-div:not(a b) * { + font: inherit; + line-height: inherit; + color: inherit; + background: transparent; + margin: 0; + padding: 0; + border: none; + text-align: inherit; + list-style: inherit; + opacity: 1; + border-radius: 0; + box-shadow: none; + text-shadow: none; + box-sizing: border-box; + text-decoration: none; + text-transform: inherit; + white-space: inherit; + float: none; + clear: none; + max-width: initial; + min-width: initial; + max-height: initial; + min-height: initial; +} + +tracy-div:not(a b) *:hover { + color: inherit; + background: transparent; +} + +tracy-div:not(a b) *:not(svg):not(img):not(table) { + width: initial; + height: initial; +} + +tracy-div:not(a b):before, +tracy-div:not(a b):after, +tracy-div:not(a b) *:before, +tracy-div:not(a b) *:after { + all: unset; +} + +tracy-div:not(a b) b, +tracy-div:not(a b) strong { + font-weight: bold; +} + +tracy-div:not(a b) small { + font-size: smaller; +} + +tracy-div:not(a b) i, +tracy-div:not(a b) em { + font-style: italic; +} + +tracy-div:not(a b) big { + font-size: larger; +} + +tracy-div:not(a b) small, +tracy-div:not(a b) sub, +tracy-div:not(a b) sup { + font-size: smaller; +} + +tracy-div:not(a b) ins { + text-decoration: underline; +} + +tracy-div:not(a b) del { + text-decoration: line-through; +} + +tracy-div:not(a b) table { + border-collapse: collapse; +} + +tracy-div:not(a b) pre { + font-family: monospace; + white-space: pre; +} + +tracy-div:not(a b) code, +tracy-div:not(a b) kbd, +tracy-div:not(a b) samp { + font-family: monospace; +} + +tracy-div:not(a b) input { + background-color: white; + padding: 1px; + border: 1px solid; +} + +tracy-div:not(a b) textarea { + background-color: white; + border: 1px solid; + padding: 2px; + white-space: pre-wrap; +} + +tracy-div:not(a b) select { + border: 1px solid; + white-space: pre; +} + +tracy-div:not(a b) article, +tracy-div:not(a b) aside, +tracy-div:not(a b) details, +tracy-div:not(a b) div, +tracy-div:not(a b) figcaption, +tracy-div:not(a b) footer, +tracy-div:not(a b) form, +tracy-div:not(a b) header, +tracy-div:not(a b) hgroup, +tracy-div:not(a b) main, +tracy-div:not(a b) nav, +tracy-div:not(a b) section, +tracy-div:not(a b) summary, +tracy-div:not(a b) pre, +tracy-div:not(a b) p, +tracy-div:not(a b) dl, +tracy-div:not(a b) dd, +tracy-div:not(a b) dt, +tracy-div:not(a b) blockquote, +tracy-div:not(a b) figure, +tracy-div:not(a b) address, +tracy-div:not(a b) h1, +tracy-div:not(a b) h2, +tracy-div:not(a b) h3, +tracy-div:not(a b) h4, +tracy-div:not(a b) h5, +tracy-div:not(a b) h6, +tracy-div:not(a b) ul, +tracy-div:not(a b) ol, +tracy-div:not(a b) li, +tracy-div:not(a b) hr { + display: block; +} + +tracy-div:not(a b) a, +tracy-div:not(a b) b, +tracy-div:not(a b) big, +tracy-div:not(a b) code, +tracy-div:not(a b) em, +tracy-div:not(a b) i, +tracy-div:not(a b) small, +tracy-div:not(a b) span, +tracy-div:not(a b) strong { + display: inline; +} + +tracy-div:not(a b) table { + display: table; +} + +tracy-div:not(a b) tr { + display: table-row; +} + +tracy-div:not(a b) col { + display: table-column; +} + +tracy-div:not(a b) colgroup { + display: table-column-group; +} + +tracy-div:not(a b) tbody { + display: table-row-group; +} + +tracy-div:not(a b) thead { + display: table-header-group; +} + +tracy-div:not(a b) tfoot { + display: table-footer-group; +} + +tracy-div:not(a b) td { + display: table-cell; +} + +tracy-div:not(a b) th { + display: table-cell; +} + + + +/* TableSort */ +tracy-div:not(a b) .tracy-sortable > :first-child > tr:first-child > * { + position: relative; +} + +tracy-div:not(a b) .tracy-sortable > :first-child > tr:first-child > *:hover:before { + position: absolute; + right: .3em; + content: "\21C5"; + opacity: .4; + font-weight: normal; +} + + +/* dump */ +tracy-div:not(a b) .tracy-dump div { + padding-left: 3ex; +} + +tracy-div:not(a b) .tracy-dump div div { + border-left: 1px solid rgba(0, 0, 0, .1); + margin-left: .5ex; +} + +tracy-div:not(a b) .tracy-dump div div:hover { + border-left-color: rgba(0, 0, 0, .25); +} + +tracy-div:not(a b) .tracy-dump { + background: #FDF5CE; + padding: .4em .7em; + border: 1px dotted silver; + overflow: auto; +} + +tracy-div:not(a b) table .tracy-dump.tracy-dump { /* overwrite .tracy-dump.tracy-light etc. */ + padding: 0; + margin: 0; + border: none; +} + +tracy-div:not(a b) .tracy-dump-location { + color: gray; + font-size: 80%; + text-decoration: none; + background: none; + opacity: .5; + float: right; + cursor: pointer; +} + +tracy-div:not(a b) .tracy-dump-location:hover, +tracy-div:not(a b) .tracy-dump-location:focus { + color: gray; + background: none; + opacity: 1; +} + +tracy-div:not(a b) .tracy-dump-array, +tracy-div:not(a b) .tracy-dump-object { + color: #C22; +} + +tracy-div:not(a b) .tracy-dump-string { + color: #35D; + white-space: break-spaces; +} + +tracy-div:not(a b) div.tracy-dump-string { + position: relative; + padding-left: 3.5ex; +} + +tracy-div:not(a b) .tracy-dump-lq { + margin-left: calc(-1ex - 1px); +} + +tracy-div:not(a b) div.tracy-dump-string:before { + content: ''; + position: absolute; + left: calc(3ex - 1px); + top: 1.5em; + bottom: 0; + border-left: 1px solid rgba(0, 0, 0, .1); +} + +tracy-div:not(a b) .tracy-dump-virtual span, +tracy-div:not(a b) .tracy-dump-dynamic span, +tracy-div:not(a b) .tracy-dump-string span { + color: rgba(0, 0, 0, 0.5); +} + +tracy-div:not(a b) .tracy-dump-virtual i, +tracy-div:not(a b) .tracy-dump-dynamic i, +tracy-div:not(a b) .tracy-dump-string i { + font-size: 80%; + font-style: normal; + color: rgba(0, 0, 0, 0.5); + user-select: none; +} + +tracy-div:not(a b) .tracy-dump-number { + color: #090; +} + +tracy-div:not(a b) .tracy-dump-null, +tracy-div:not(a b) .tracy-dump-bool { + color: #850; +} + +tracy-div:not(a b) .tracy-dump-virtual { + font-style: italic; +} + +tracy-div:not(a b) .tracy-dump-public::after { + content: ' pub'; +} + +tracy-div:not(a b) .tracy-dump-protected::after { + content: ' pro'; +} + +tracy-div:not(a b) .tracy-dump-private::after { + content: ' pri'; +} + +tracy-div:not(a b) .tracy-dump-public::after, +tracy-div:not(a b) .tracy-dump-protected::after, +tracy-div:not(a b) .tracy-dump-private::after, +tracy-div:not(a b) .tracy-dump-hash { + font-size: 85%; + color: rgba(0, 0, 0, 0.5); +} + +tracy-div:not(a b) .tracy-dump-indent { + display: none; +} + +tracy-div:not(a b) .tracy-dump-highlight { + background: #C22; + color: white; + border-radius: 2px; + padding: 0 2px; + margin: 0 -2px; +} + +tracy-div:not(a b) span[data-tracy-href] { + border-bottom: 1px dotted rgba(0, 0, 0, .2); +} + + +/* toggle */ +tracy-div:not(a b) .tracy-toggle:after { + content: ''; + display: inline-block; + vertical-align: middle; + line-height: 0; + border-top: .6ex solid; + border-right: .6ex solid transparent; + border-left: .6ex solid transparent; + transform: scale(1, 1.5); + margin: 0 .2ex 0 .7ex; + transition: .1s transform; + opacity: .5; +} + +tracy-div:not(a b) .tracy-toggle.tracy-collapsed:after { + transform: rotate(-90deg) scale(1, 1.5) translate(.1ex, 0); +} + + +/* tabs */ +tracy-div:not(a b) .tracy-tab-label { + user-select: none; +} + +tracy-div:not(a b) .tracy-tab-panel:not(.tracy-active) { + display: none; +} diff --git a/vendor/tracy/tracy/src/Tracy/assets/table-sort.css b/vendor/tracy/tracy/src/Tracy/assets/table-sort.css new file mode 100644 index 00000000000..7967a642c69 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/table-sort.css @@ -0,0 +1,15 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +.tracy-sortable > :first-child > tr:first-child > * { + position: relative; +} + +.tracy-sortable > :first-child > tr:first-child > *:hover:before { + position: absolute; + right: .3em; + content: "\21C5"; + opacity: .4; + font-weight: normal; +} diff --git a/vendor/tracy/tracy/src/Tracy/assets/table-sort.js b/vendor/tracy/tracy/src/Tracy/assets/table-sort.js new file mode 100644 index 00000000000..3a6ac2697b0 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/table-sort.js @@ -0,0 +1,40 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +// enables +class TableSort +{ + static init() { + document.documentElement.addEventListener('click', (e) => { + if (e.target.matches('.tracy-sortable > :first-child > tr:first-child *')) { + TableSort.sort(e.target.closest('td,th')); + } + }); + + TableSort.init = function() {}; + } + + static sort(tcell) { + let tbody = tcell.closest('table').tBodies[0]; + let preserveFirst = !tcell.closest('thead') && !tcell.parentNode.querySelectorAll('td').length; + let asc = !(tbody.tracyAsc === tcell.cellIndex); + tbody.tracyAsc = asc ? tcell.cellIndex : null; + let getText = (cell) => { return cell ? (cell.getAttribute('data-order') || cell.innerText) : ''; }; + + Array.from(tbody.children) + .slice(preserveFirst ? 1 : 0) + .sort((a, b) => { + return function(v1, v2) { + return v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) + ? v1 - v2 + : v1.toString().localeCompare(v2, undefined, {numeric: true, sensitivity: 'base'}); + }(getText((asc ? a : b).children[tcell.cellIndex]), getText((asc ? b : a).children[tcell.cellIndex])); + }) + .forEach((tr) => { tbody.appendChild(tr); }); + } +} + + +let Tracy = window.Tracy = window.Tracy || {}; +Tracy.TableSort = Tracy.TableSort || TableSort; diff --git a/vendor/tracy/tracy/src/Tracy/assets/tabs.css b/vendor/tracy/tracy/src/Tracy/assets/tabs.css new file mode 100644 index 00000000000..9add853a14f --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/tabs.css @@ -0,0 +1,11 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +.tracy-tab-label { + user-select: none; +} + +.tracy-tab-panel:not(.tracy-active) { + display: none; +} diff --git a/vendor/tracy/tracy/src/Tracy/assets/tabs.js b/vendor/tracy/tracy/src/Tracy/assets/tabs.js new file mode 100644 index 00000000000..9e0a55a6087 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/tabs.js @@ -0,0 +1,41 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +// enables .tracy-tabs, .tracy-tab-label, .tracy-tab-panel, .tracy-active +class Tabs +{ + static init() { + document.documentElement.addEventListener('click', (e) => { + let label, context; + if ( + !e.shiftKey && !e.ctrlKey && !e.metaKey + && (label = e.target.closest('.tracy-tab-label')) + && (context = e.target.closest('.tracy-tabs')) + ) { + Tabs.toggle(context, label); + e.preventDefault(); + e.stopImmediatePropagation(); + } + }); + + Tabs.init = function() {}; + } + + static toggle(context, label) { + let labels = context.querySelector('.tracy-tab-label').parentNode.querySelectorAll('.tracy-tab-label'), + panels = context.querySelector('.tracy-tab-panel').parentNode.querySelectorAll(':scope > .tracy-tab-panel'); + + for (let i = 0; i < labels.length; i++) { + labels[i].classList.toggle('tracy-active', labels[i] === label); + } + + for (let i = 0; i < panels.length; i++) { + panels[i].classList.toggle('tracy-active', labels[i] === label); + } + } +} + + +let Tracy = window.Tracy = window.Tracy || {}; +Tracy.Tabs = Tracy.Tabs || Tabs; diff --git a/vendor/tracy/tracy/src/Tracy/assets/toggle.css b/vendor/tracy/tracy/src/Tracy/assets/toggle.css new file mode 100644 index 00000000000..acce8e4f8cc --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/toggle.css @@ -0,0 +1,35 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +.tracy-collapsed { + display: none; +} + +.tracy-toggle.tracy-collapsed { + display: inline; +} + +.tracy-toggle { + cursor: pointer; + user-select: none; + white-space: nowrap; +} + +.tracy-toggle:after { + content: ''; + display: inline-block; + vertical-align: middle; + line-height: 0; + border-top: .6ex solid; + border-right: .6ex solid transparent; + border-left: .6ex solid transparent; + transform: scale(1, 1.5); + margin: 0 .2ex 0 .7ex; + transition: .1s transform; + opacity: .5; +} + +.tracy-toggle.tracy-collapsed:after { + transform: rotate(-90deg) scale(1, 1.5) translate(.1ex, 0); +} diff --git a/vendor/tracy/tracy/src/Tracy/assets/toggle.js b/vendor/tracy/tracy/src/Tracy/assets/toggle.js new file mode 100644 index 00000000000..718aa756747 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/assets/toggle.js @@ -0,0 +1,117 @@ +/** + * This file is part of the Tracy (https://tracy.nette.org) + */ + +const MOVE_THRESHOLD = 100; + +// enables or toggling +class Toggle +{ + static init() { + let start; + document.documentElement.addEventListener('mousedown', (e) => { + start = [e.clientX, e.clientY]; + }); + + document.documentElement.addEventListener('click', (e) => { + let el; + if ( + !e.shiftKey && !e.ctrlKey && !e.metaKey + && (el = e.target.closest('.tracy-toggle')) + && Math.pow(start[0] - e.clientX, 2) + Math.pow(start[1] - e.clientY, 2) < MOVE_THRESHOLD + ) { + Toggle.toggle(el, undefined, e); + e.preventDefault(); + e.stopImmediatePropagation(); + } + }); + Toggle.init = function() {}; + } + + + // changes element visibility + static toggle(el, expand, e) { + let collapsed = el.classList.contains('tracy-collapsed'), + ref = el.getAttribute('data-tracy-ref') || el.getAttribute('href', 2), + dest = el; + + if (typeof expand === 'undefined') { + expand = collapsed; + } + + el.dispatchEvent(new CustomEvent('tracy-beforetoggle', { + bubbles: true, + detail: {collapsed: !expand, originalEvent: e} + })); + + if (!ref || ref === '#') { + ref = '+'; + } else if (ref.substr(0, 1) === '#') { + dest = document; + } + ref = ref.match(/(\^\s*([^+\s]*)\s*)?(\+\s*(\S*)\s*)?(.*)/); + dest = ref[1] ? dest.parentNode : dest; + dest = ref[2] ? dest.closest(ref[2]) : dest; + dest = ref[3] ? Toggle.nextElement(dest.nextElementSibling, ref[4]) : dest; + dest = ref[5] ? dest.querySelector(ref[5]) : dest; + + el.classList.toggle('tracy-collapsed', !expand); + dest.classList.toggle('tracy-collapsed', !expand); + + el.dispatchEvent(new CustomEvent('tracy-toggle', { + bubbles: true, + detail: {relatedTarget: dest, collapsed: !expand, originalEvent: e} + })); + } + + + // save & restore toggles + static persist(baseEl, restore) { + let saved = []; + baseEl.addEventListener('tracy-toggle', (e) => { + if (saved.indexOf(e.target) < 0) { + saved.push(e.target); + } + }); + + let toggles = JSON.parse(sessionStorage.getItem('tracy-toggles-' + baseEl.id)); + if (toggles && restore !== false) { + toggles.forEach((item) => { + let el = baseEl; + for (let i in item.path) { + if (!(el = el.children[item.path[i]])) { + return; + } + } + if (el.textContent === item.text) { + Toggle.toggle(el, item.expand); + } + }); + } + + window.addEventListener('unload', () => { + toggles = saved.map((el) => { + let item = {path: [], text: el.textContent, expand: !el.classList.contains('tracy-collapsed')}; + do { + item.path.unshift(Array.from(el.parentNode.children).indexOf(el)); + el = el.parentNode; + } while (el && el !== baseEl); + return item; + }); + sessionStorage.setItem('tracy-toggles-' + baseEl.id, JSON.stringify(toggles)); + }); + } + + + // finds next matching element + static nextElement(el, selector) { + while (el && selector && !el.matches(selector)) { + el = el.nextElementSibling; + } + return el; + } +} + + +let Tracy = window.Tracy = window.Tracy || {}; +Tracy.Toggle = Tracy.Toggle || Toggle; diff --git a/vendor/tracy/tracy/src/Tracy/functions.php b/vendor/tracy/tracy/src/Tracy/functions.php new file mode 100644 index 00000000000..99f055d6431 --- /dev/null +++ b/vendor/tracy/tracy/src/Tracy/functions.php @@ -0,0 +1,44 @@ +setStub("startBuffering(); +foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/../../src', \RecursiveDirectoryIterator::SKIP_DOTS)) as $file) { + echo "adding: {$iterator->getSubPathname()}\n"; + $s = \file_get_contents($file->getPathname()); + if (\strpos($s, '@tracySkipLocation') === \false) { + $s = \php_strip_whitespace($file->getPathname()); + } + if ($file->getExtension() === 'js') { + $s = compressJs($s); + } elseif ($file->getExtension() === 'css') { + $s = compressCss($s); + } elseif ($file->getExtension() === 'phtml') { + $s = \preg_replace_callback('#(<(script|style).*(?)(.*)(getExtension() !== 'php') { + continue; + } + $phar[$iterator->getSubPathname()] = $s; +} +$phar->stopBuffering(); +$phar->compressFiles(\Phar::GZ); +echo "OK\n"; diff --git a/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh b/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh new file mode 100644 index 00000000000..5a7bfb31787 --- /dev/null +++ b/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# This shell script sets open-editor.sh as handler for editor:// protocol + +matches=0 +while read -r line +do + if [ "editor=" == "${line:0:7}" ]; then + matches=1 + break + fi +done < "open-editor.sh" + +if [ "$matches" == "0" ]; then + echo -e "\e[31;1mError: it seems like you have not set command to run your editor." + echo -e "Before install, set variable \`\$editor\` in file \`open-editor.sh\`.\e[0m" + exit 1 +fi + +# -------------------------------------------------------------- + +echo "[Desktop Entry] +Name=Tracy Open Editor +Exec=tracy-openeditor.sh %u +Terminal=false +NoDisplay=true +Type=Application +MimeType=x-scheme-handler/editor;" > tracy-openeditor.desktop + +chmod +x open-editor.sh +chmod +x tracy-openeditor.desktop + +sudo cp open-editor.sh /usr/bin/tracy-openeditor.sh +sudo xdg-desktop-menu install tracy-openeditor.desktop +sudo update-desktop-database +rm tracy-openeditor.desktop + +echo -e "\e[32;1mDone.\e[0m" diff --git a/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh b/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh new file mode 100644 index 00000000000..5b75316f010 --- /dev/null +++ b/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh @@ -0,0 +1,109 @@ +#!/bin/bash +declare -A mapping + +# +# Configure your editor by setting the $editor variable: +# + +# Visual Studio Code +#editor='code --goto "$FILE":"$LINE"' +# Emacs +#editor='emacs +$LINE "$FILE"' +# gVim +#editor='gvim +$LINE "$FILE"' +# gEdit +#editor='gedit +$LINE "$FILE"' +# Pluma +#editor='pluma +$LINE "$FILE"' +# PHPStorm +# To enable PHPStorm command-line interface, folow this guide: https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html +#editor='phpstorm --line $LINE "$FILE"' +# VS Codium +#editor='codium --goto "$FILE":"$LINE"' +# Visual Studio Code +#editor='code --goto "$FILE":"$LINE"' + +# +# Optionally configure custom mapping here: +# + +#mapping["/remotepath"]="/localpath" +#mapping["/mnt/d/"]="d:/" + +# +# Please, do not modify the code below. +# + +# Find and return URI parameter value. Or nothing, if the param is missing. +# Arguments: 1) URI, 2) Parameter name. +function get_param { + echo "$1" | sed -n -r "s/.*$2=([^&]*).*/\1/ip" +} + +if [[ -z "$editor" ]]; then + echo "You need to set the \$editor variable in file '`realpath $0`'" + exit +fi + +url=$1 +if [ "${url:0:9}" != "editor://" ]; then + exit +fi + +# Parse action and essential data from the URI. +regex='editor\:\/\/(open|create|fix)\/\?(.*)' +action=`echo $url | sed -r "s/$regex/\1/i"` +uri_params=`echo $url | sed -r "s/$regex/\2/i"` + +file=`get_param $uri_params "file"` +line=`get_param $uri_params "line"` +search=`get_param $uri_params "search"` +replace=`get_param $uri_params "replace"` + +# Debug? +#echo "action '$action'" +#echo "file '$file'" +#echo "line '$line'" +#echo "search '$search'" +#echo "replace '$replace'" + +# Convert URI encoded codes to normal characters (e.g. '%2F' => '/'). +printf -v file "${file//%/\\x}" +# And escape double-quotes. +file=${file//\"/\\\"} + +# Apply custom mapping conversion. +for path in "${!mapping[@]}"; do + file="${file//$path/${mapping[$path]}}" +done + +# Action: Create a file (only if it does not already exist). +if [ "$action" == "create" ] && [[ ! -f "$file" ]]; then + mkdir -p $(dirname "$file") + touch "$file" + echo $replace > "$file" +fi + +# Action: Fix the file (if the file exists and while creating backup beforehand). +if [ "$action" == "fix" ]; then + + if [[ ! -f "$file" ]]; then + echo "Cannot fix non-existing file '$file'" + exit + fi + + # Backup the original file. + cp $file "$file.bak" + # Search and replace in place - only on the specified line. + sed -i "${line}s/${search}/${replace}/" $file + +fi + +# Format the command according to the selected editor. +command="${editor//\$FILE/$file}" +command="${command//\$LINE/$line}" + +# Debug? +#echo $command + +eval $command diff --git a/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd b/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd new file mode 100644 index 00000000000..d84112241c1 --- /dev/null +++ b/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd @@ -0,0 +1,9 @@ +@echo off +:: This Windows batch file sets open-editor.js as handler for editor:// protocol + +if defined PROCESSOR_ARCHITEW6432 (set reg="%systemroot%\sysnative\reg.exe") else (set reg=reg) + +%reg% ADD HKCR\editor /ve /d "URL:editor Protocol" /f +%reg% ADD HKCR\editor /v "URL Protocol" /d "" /f +%reg% ADD HKCR\editor\shell\open\command /ve /d "wscript \"%~dp0open-editor.js\" \"%%1\"" /f +%reg% ADD HKLM\SOFTWARE\Policies\Google\Chrome\URLWhitelist /v "123" /d "editor://*" /f diff --git a/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js b/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js new file mode 100644 index 00000000000..164c94f309b --- /dev/null +++ b/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js @@ -0,0 +1,84 @@ +var settings = { + + // PhpStorm + // editor: '"C:\\Program Files\\JetBrains\\PhpStorm 2018.1.2\\bin\\phpstorm64.exe" --line %line% "%file%"', + // title: 'PhpStorm', + + // NetBeans + // editor: '"C:\\Program Files\\NetBeans 8.1\\bin\\netbeans.exe" "%file%:%line%" --console suppress', + + // Nusphere PHPEd + // editor: '"C:\\Program Files\\NuSphere\\PhpED\\phped.exe" "%file%" --line=%line%', + + // SciTE + // editor: '"C:\\Program Files\\SciTE\\scite.exe" "-open:%file%" -goto:%line%', + + // EmEditor + // editor: '"C:\\Program Files\\EmEditor\\EmEditor.exe" "%file%" /l %line%', + + // PSPad Editor + // editor: '"C:\\Program Files\\PSPad editor\\PSPad.exe" -%line% "%file%"', + + // gVim + // editor: '"C:\\Program Files\\Vim\\vim73\\gvim.exe" "%file%" +%line%', + + // Sublime Text 2 + // editor: '"C:\\Program Files\\Sublime Text 2\\sublime_text.exe" "%file%:%line%"', + + // Visual Studio Code / VSCodium + // editor: '"C:\\Program Files\\Microsoft VS Code\\Code.exe" --goto "%file%:%line%"', + + mappings: { + // '/remotepath': '/localpath' + } +}; + + + +if (!settings.editor) { + WScript.Echo('Create variable "settings.editor" in ' + WScript.ScriptFullName); + WScript.Quit(); +} + +var url = WScript.Arguments(0); +var match = /^editor:\/\/(open|create|fix)\/\?file=([^&]+)&line=(\d+)(?:&search=([^&]*)&replace=([^&]*))?/.exec(url); +if (!match) { + WScript.Echo('Unexpected URI ' + url); + WScript.Quit(); +} +for (var i in match) { + match[i] = decodeURIComponent(match[i]).replace(/\+/g, ' '); +} + +var action = match[1]; +var file = match[2]; +var line = match[3]; +var search = match[4]; +var replace = match[5]; + +var shell = new ActiveXObject('WScript.Shell'); +var fileSystem = new ActiveXObject('Scripting.FileSystemObject'); + +for (var id in settings.mappings) { + if (file.indexOf(id) === 0) { + file = settings.mappings[id] + file.substr(id.length); + break; + } +} + +if (action === 'create' && !fileSystem.FileExists(file)) { + shell.Run('cmd /c mkdir "' + fileSystem.GetParentFolderName(file) + '"', 0, 1); + fileSystem.CreateTextFile(file).Write(replace); + +} else if (action === 'fix') { + var lines = fileSystem.OpenTextFile(file).ReadAll().split('\n'); + lines[line-1] = lines[line-1].replace(search, replace); + fileSystem.OpenTextFile(file, 2).Write(lines.join('\n')); +} + +var command = settings.editor.replace(/%line%/, line).replace(/%file%/, file); +shell.Exec(command); + +if (settings.title) { + shell.AppActivate(settings.title); +}