From 5b34d725f94fb0675d761bc55cb886480c85a5a4 Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 4 Jan 2022 00:59:31 +0000 Subject: [PATCH] Release v4.1.6 --- LICENSE | 2 +- app/Config/Filters.php | 12 +- app/Config/Mimes.php | 2 +- app/Config/Security.php | 11 + app/Config/Toolbar.php | 12 + app/Views/errors/html/error_exception.php | 2 +- env | 1 + system/Autoloader/Autoloader.php | 4 +- system/Autoloader/FileLocator.php | 18 +- system/BaseModel.php | 2 +- system/CLI/CLI.php | 8 +- system/Cache/Handlers/FileHandler.php | 1 - system/Cache/Handlers/MemcachedHandler.php | 6 +- system/CodeIgniter.php | 17 +- system/Common.php | 25 +- system/ComposerScripts.php | 19 +- system/Cookie/CookieStore.php | 6 + system/Database/BaseBuilder.php | 104 ++++--- system/Database/BaseConnection.php | 14 +- system/Database/BaseResult.php | 2 - system/Database/BaseUtils.php | 4 +- system/Database/Forge.php | 8 +- system/Database/MySQLi/Connection.php | 18 +- system/Database/Postgre/Connection.php | 8 +- system/Database/Query.php | 34 +-- system/Database/SQLite3/Result.php | 16 +- system/Database/Seeder.php | 4 + system/Debug/Exceptions.php | 7 +- system/Debug/Kint/RichRenderer.php | 75 +++++ system/Debug/Toolbar.php | 4 + system/Debug/Toolbar/Collectors/Database.php | 32 ++- system/Debug/Toolbar/Collectors/Events.php | 2 +- system/Debug/Toolbar/Collectors/Views.php | 6 +- system/Debug/Toolbar/Views/_database.tpl | 11 +- system/Debug/Toolbar/Views/toolbar.css | 10 +- system/Debug/Toolbar/Views/toolbar.js | 26 +- system/Entity/Cast/DatetimeCast.php | 2 +- system/Filters/Filters.php | 7 +- system/Filters/InvalidChars.php | 123 +++++++++ system/Filters/SecureHeaders.php | 71 +++++ system/HTTP/CLIRequest.php | 14 +- system/HTTP/CURLRequest.php | 4 +- system/HTTP/Files/UploadedFile.php | 15 +- system/HTTP/IncomingRequest.php | 12 +- system/HTTP/RequestTrait.php | 1 - system/HTTP/ResponseTrait.php | 77 +++++- system/HTTP/URI.php | 2 +- system/Helpers/array_helper.php | 12 +- system/Helpers/filesystem_helper.php | 4 +- system/Helpers/number_helper.php | 8 +- system/Helpers/text_helper.php | 1 - system/Helpers/url_helper.php | 2 +- system/I18n/Time.php | 34 +-- system/Images/Handlers/GDHandler.php | 6 +- system/Images/Handlers/ImageMagickHandler.php | 6 +- system/Model.php | 17 +- system/Router/Router.php | 1 - .../Security/Exceptions/SecurityException.php | 16 ++ system/Security/Security.php | 60 +++- system/Session/Handlers/DatabaseHandler.php | 1 - system/Session/Handlers/RedisHandler.php | 1 - system/Test/CIUnitTestCase.php | 2 +- system/Test/Fabricator.php | 6 +- system/Test/FeatureTestCase.php | 2 +- system/Test/FeatureTestTrait.php | 2 +- system/Test/Mock/MockConnection.php | 2 +- system/Test/Mock/MockSecurity.php | 8 + system/Test/bootstrap.php | 9 - system/ThirdParty/Escaper/LICENSE.md | 26 ++ system/ThirdParty/Kint/CallFinder.php | 124 ++++++--- system/ThirdParty/Kint/Kint.php | 256 ++++++++---------- system/ThirdParty/Kint/LICENSE | 20 ++ .../Kint/Parser/ArrayLimitPlugin.php | 142 ++++++++++ .../Kint/Parser/ArrayObjectPlugin.php | 6 +- .../ThirdParty/Kint/Parser/Base64Plugin.php | 11 +- .../ThirdParty/Kint/Parser/BinaryPlugin.php | 10 +- .../Kint/Parser/BlacklistPlugin.php | 74 +---- .../Kint/Parser/ClassMethodsPlugin.php | 26 +- .../Kint/Parser/ClassStaticsPlugin.php | 46 ++-- .../ThirdParty/Kint/Parser/ClosurePlugin.php | 26 +- system/ThirdParty/Kint/Parser/ColorPlugin.php | 8 +- .../Kint/Parser/DOMDocumentPlugin.php | 107 ++++---- .../ThirdParty/Kint/Parser/DateTimePlugin.php | 10 +- .../ThirdParty/Kint/Parser/FsPathPlugin.php | 10 +- .../ThirdParty/Kint/Parser/IteratorPlugin.php | 25 +- system/ThirdParty/Kint/Parser/JsonPlugin.php | 10 +- .../Kint/Parser/MicrotimePlugin.php | 10 +- .../ThirdParty/Kint/Parser/MysqliPlugin.php | 98 +++++-- system/ThirdParty/Kint/Parser/Parser.php | 223 ++++++++------- system/ThirdParty/Kint/Parser/Plugin.php | 6 +- system/ThirdParty/Kint/Parser/ProxyPlugin.php | 6 +- .../Kint/Parser/SerializePlugin.php | 18 +- .../Kint/Parser/SimpleXMLElementPlugin.php | 189 ++++++++----- .../Kint/Parser/SplFileInfoPlugin.php | 8 +- .../Kint/Parser/SplObjectStoragePlugin.php | 6 +- .../ThirdParty/Kint/Parser/StreamPlugin.php | 23 +- system/ThirdParty/Kint/Parser/TablePlugin.php | 8 +- .../Kint/Parser/ThrowablePlugin.php | 12 +- .../Kint/Parser/TimestampPlugin.php | 12 +- .../ThirdParty/Kint/Parser/ToStringPlugin.php | 12 +- system/ThirdParty/Kint/Parser/TracePlugin.php | 46 +++- system/ThirdParty/Kint/Parser/XmlPlugin.php | 31 ++- .../ThirdParty/Kint/Renderer/CliRenderer.php | 18 +- .../Kint/Renderer/PlainRenderer.php | 34 +-- system/ThirdParty/Kint/Renderer/Renderer.php | 52 ++-- .../Kint/Renderer/Rich/ArrayLimitPlugin.php | 36 +++ .../Kint/Renderer/Rich/BinaryPlugin.php | 15 +- .../Kint/Renderer/Rich/BlacklistPlugin.php | 6 +- .../Kint/Renderer/Rich/CallablePlugin.php | 40 +-- .../Kint/Renderer/Rich/ClosurePlugin.php | 10 +- .../Kint/Renderer/Rich/ColorPlugin.php | 12 +- .../Kint/Renderer/Rich/DepthLimitPlugin.php | 6 +- .../Kint/Renderer/Rich/DocstringPlugin.php | 10 +- .../Kint/Renderer/Rich/MicrotimePlugin.php | 6 +- .../ThirdParty/Kint/Renderer/Rich/Plugin.php | 7 +- .../Kint/Renderer/Rich/RecursionPlugin.php | 6 +- .../Renderer/Rich/SimpleXMLElementPlugin.php | 20 +- .../Kint/Renderer/Rich/SourcePlugin.php | 6 +- .../Kint/Renderer/Rich/TabPluginInterface.php | 7 +- .../Kint/Renderer/Rich/TablePlugin.php | 8 +- .../Kint/Renderer/Rich/TimestampPlugin.php | 2 +- .../Kint/Renderer/Rich/TraceFramePlugin.php | 10 +- ...Interface.php => ValuePluginInterface.php} | 9 +- .../ThirdParty/Kint/Renderer/RichRenderer.php | 98 ++++--- .../Kint/Renderer/Text/ArrayLimitPlugin.php | 44 +++ .../Kint/Renderer/Text/BlacklistPlugin.php | 4 +- .../Kint/Renderer/Text/DepthLimitPlugin.php | 4 +- .../Kint/Renderer/Text/MicrotimePlugin.php | 8 +- .../ThirdParty/Kint/Renderer/Text/Plugin.php | 7 +- .../Kint/Renderer/Text/RecursionPlugin.php | 4 +- .../Kint/Renderer/Text/TracePlugin.php | 8 +- .../ThirdParty/Kint/Renderer/TextRenderer.php | 36 +-- system/ThirdParty/Kint/Utils.php | 69 +++-- .../BlobObject.php => Zval/BlobValue.php} | 14 +- .../ClosureValue.php} | 10 +- .../DateTimeValue.php} | 6 +- .../InstanceValue.php} | 14 +- .../MethodObject.php => Zval/MethodValue.php} | 32 +-- .../ParameterValue.php} | 7 +- .../Representation/ColorRepresentation.php | 31 +-- .../DocstringRepresentation.php | 4 +- .../MicrotimeRepresentation.php | 4 +- .../Representation/Representation.php | 6 +- .../Representation/SourceRepresentation.php | 6 +- .../SplFileInfoRepresentation.php | 16 +- .../ResourceValue.php} | 6 +- .../Kint/Zval/SimpleXMLElementValue.php | 48 ++++ .../StreamObject.php => Zval/StreamValue.php} | 4 +- .../ThrowableValue.php} | 8 +- .../TraceFrameValue.php} | 31 ++- .../TraceObject.php => Zval/TraceValue.php} | 6 +- .../BasicObject.php => Zval/Value.php} | 28 +- system/ThirdParty/Kint/init.php | 14 +- system/ThirdParty/Kint/init_helpers.php | 16 +- .../Kint/resources/compiled/aante-light.css | 2 +- .../Kint/resources/compiled/microtime.js | 2 +- .../Kint/resources/compiled/original.css | 2 +- .../Kint/resources/compiled/rich.js | 2 +- .../Kint/resources/compiled/shared.js | 2 +- .../resources/compiled/solarized-dark.css | 2 +- .../Kint/resources/compiled/solarized.css | 2 +- system/ThirdParty/PSR/Log/LICENSE | 19 ++ system/Throttle/Throttler.php | 41 +-- system/Validation/FormatRules.php | 78 +++--- system/Validation/Rules.php | 68 ++--- system/Validation/Validation.php | 72 +++-- system/View/Table.php | 3 +- system/View/View.php | 25 +- system/bootstrap.php | 2 +- tests/README.md | 108 ++++++++ .../2020-02-22-222222_example_migration.php | 37 +++ .../_support/Database/Seeds/ExampleSeeder.php | 41 +++ tests/_support/Libraries/ConfigReader.php | 17 ++ tests/_support/Models/ExampleModel.php | 24 ++ tests/database/ExampleDatabaseTest.php | 45 +++ tests/session/ExampleSessionTest.php | 18 ++ tests/unit/HealthTest.php | 50 ++++ 177 files changed, 2853 insertions(+), 1428 deletions(-) create mode 100644 system/Debug/Kint/RichRenderer.php create mode 100644 system/Filters/InvalidChars.php create mode 100644 system/Filters/SecureHeaders.php create mode 100644 system/ThirdParty/Escaper/LICENSE.md create mode 100644 system/ThirdParty/Kint/LICENSE create mode 100644 system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php create mode 100644 system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php rename system/ThirdParty/Kint/Renderer/Rich/{ObjectPluginInterface.php => ValuePluginInterface.php} (88%) create mode 100644 system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php rename system/ThirdParty/Kint/{Object/BlobObject.php => Zval/BlobValue.php} (95%) rename system/ThirdParty/Kint/{Object/ClosureObject.php => Zval/ClosureValue.php} (91%) rename system/ThirdParty/Kint/{Object/DateTimeObject.php => Zval/DateTimeValue.php} (93%) rename system/ThirdParty/Kint/{Object/InstanceObject.php => Zval/InstanceValue.php} (88%) rename system/ThirdParty/Kint/{Object/MethodObject.php => Zval/MethodValue.php} (90%) rename system/ThirdParty/Kint/{Object/ParameterObject.php => Zval/ParameterValue.php} (95%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/ColorRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/DocstringRepresentation.php (97%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/MicrotimeRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/Representation.php (95%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/SourceRepresentation.php (96%) rename system/ThirdParty/Kint/{Object => Zval}/Representation/SplFileInfoRepresentation.php (95%) rename system/ThirdParty/Kint/{Object/ResourceObject.php => Zval/ResourceValue.php} (93%) create mode 100644 system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php rename system/ThirdParty/Kint/{Object/StreamObject.php => Zval/StreamValue.php} (96%) rename system/ThirdParty/Kint/{Object/ThrowableObject.php => Zval/ThrowableValue.php} (88%) rename system/ThirdParty/Kint/{Object/TraceFrameObject.php => Zval/TraceFrameValue.php} (81%) rename system/ThirdParty/Kint/{Object/TraceObject.php => Zval/TraceValue.php} (93%) rename system/ThirdParty/Kint/{Object/BasicObject.php => Zval/Value.php} (91%) create mode 100644 system/ThirdParty/PSR/Log/LICENSE create mode 100644 tests/README.md create mode 100644 tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php create mode 100644 tests/_support/Database/Seeds/ExampleSeeder.php create mode 100644 tests/_support/Libraries/ConfigReader.php create mode 100644 tests/_support/Models/ExampleModel.php create mode 100644 tests/database/ExampleDatabaseTest.php create mode 100644 tests/session/ExampleSessionTest.php create mode 100644 tests/unit/HealthTest.php diff --git a/LICENSE b/LICENSE index daac9e5b..31425034 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The MIT License (MIT) Copyright (c) 2014-2019 British Columbia Institute of Technology -Copyright (c) 2019-2021 CodeIgniter Foundation +Copyright (c) 2019-2022 CodeIgniter Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/app/Config/Filters.php b/app/Config/Filters.php index df90270a..14685207 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -6,6 +6,8 @@ use CodeIgniter\Filters\CSRF; use CodeIgniter\Filters\DebugToolbar; use CodeIgniter\Filters\Honeypot; +use CodeIgniter\Filters\InvalidChars; +use CodeIgniter\Filters\SecureHeaders; class Filters extends BaseConfig { @@ -16,9 +18,11 @@ class Filters extends BaseConfig * @var array */ public $aliases = [ - 'csrf' => CSRF::class, - 'toolbar' => DebugToolbar::class, - 'honeypot' => Honeypot::class, + 'csrf' => CSRF::class, + 'toolbar' => DebugToolbar::class, + 'honeypot' => Honeypot::class, + 'invalidchars' => InvalidChars::class, + 'secureheaders' => SecureHeaders::class, ]; /** @@ -31,10 +35,12 @@ class Filters extends BaseConfig 'before' => [ // 'honeypot', // 'csrf', + // 'invalidchars', ], 'after' => [ 'toolbar', // 'honeypot', + // 'secureheaders', ], ]; diff --git a/app/Config/Mimes.php b/app/Config/Mimes.php index 973fb398..786bc6a1 100644 --- a/app/Config/Mimes.php +++ b/app/Config/Mimes.php @@ -509,7 +509,7 @@ public static function guessExtensionFromType(string $type, ?string $proposedExt { $type = trim(strtolower($type), '. '); - $proposedExtension = trim(strtolower($proposedExtension)); + $proposedExtension = trim(strtolower($proposedExtension ?? '')); if ($proposedExtension !== '') { if (array_key_exists($proposedExtension, static::$mimes) && in_array($type, is_string(static::$mimes[$proposedExtension]) ? [static::$mimes[$proposedExtension]] : static::$mimes[$proposedExtension], true)) { diff --git a/app/Config/Security.php b/app/Config/Security.php index 563cf2f3..05083f8b 100644 --- a/app/Config/Security.php +++ b/app/Config/Security.php @@ -17,6 +17,17 @@ class Security extends BaseConfig */ public $csrfProtection = 'cookie'; + /** + * -------------------------------------------------------------------------- + * CSRF Token Randomization + * -------------------------------------------------------------------------- + * + * Randomize the CSRF Token for added security. + * + * @var bool + */ + public $tokenRandomize = false; + /** * -------------------------------------------------------------------------- * CSRF Token Name diff --git a/app/Config/Toolbar.php b/app/Config/Toolbar.php index 16a37e83..7183e133 100644 --- a/app/Config/Toolbar.php +++ b/app/Config/Toolbar.php @@ -44,6 +44,18 @@ class Toolbar extends BaseConfig Events::class, ]; + /** + * -------------------------------------------------------------------------- + * Collect Var Data + * -------------------------------------------------------------------------- + * + * If set to false var data from the views will not be colleted. Usefull to + * avoid high memory usage when there are lots of data passed to the view. + * + * @var bool + */ + public $collectVarData = true; + /** * -------------------------------------------------------------------------- * Max History diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php index 4477ee08..693afed4 100644 --- a/app/Views/errors/html/error_exception.php +++ b/app/Views/errors/html/error_exception.php @@ -195,7 +195,7 @@ Path - uri) ?> + getUri()) ?> HTTP Method diff --git a/env b/env index 6e30e34b..c60b3672 100644 --- a/env +++ b/env @@ -111,6 +111,7 @@ #-------------------------------------------------------------------- # security.csrfProtection = 'cookie' +# security.tokenRandomize = false # security.tokenName = 'csrf_token_name' # security.headerName = 'X-CSRF-TOKEN' # security.cookieName = 'csrf_cookie_name' diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 3472756a..492fb099 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -114,10 +114,10 @@ public function initialize(Autoload $config, Modules $modules) public function register() { // Prepend the PSR4 autoloader for maximum performance. - spl_autoload_register([$this, 'loadClass'], true, true); // @phpstan-ignore-line + spl_autoload_register([$this, 'loadClass'], true, true); // Now prepend another loader for the files in our class map. - spl_autoload_register([$this, 'loadClassmap'], true, true); // @phpstan-ignore-line + spl_autoload_register([$this, 'loadClassmap'], true, true); // Load our non-class files foreach ($this->files as $file) { diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 6fa8109b..b8bfdf6d 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -55,6 +55,7 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' // Standardize slashes to handle nested directories. $file = strtr($file, '/', '\\'); + $file = ltrim($file, '\\'); $segments = explode('\\', $file); @@ -64,23 +65,20 @@ public function locateFile(string $file, ?string $folder = null, string $ext = ' } $paths = []; - $prefix = ''; $filename = ''; // Namespaces always comes with arrays of paths $namespaces = $this->autoloader->getNamespace(); - while (! empty($segments)) { - $prefix .= empty($prefix) ? array_shift($segments) : '\\' . array_shift($segments); + foreach (array_keys($namespaces) as $namespace) { + if (substr($file, 0, strlen($namespace)) === $namespace) { + // There may be sub-namespaces of the same vendor, + // so overwrite them with namespaces found later. + $paths = $namespaces[$namespace]; - if (empty($namespaces[$prefix])) { - continue; + $fileWithoutNamespace = substr($file, strlen($namespace)); + $filename = ltrim(str_replace('\\', '/', $fileWithoutNamespace), '/'); } - - $paths = $namespaces[$prefix]; - - $filename = implode('/', $segments); - break; } // if no namespaces matched then quit diff --git a/system/BaseModel.php b/system/BaseModel.php index 6b9ef368..97130366 100644 --- a/system/BaseModel.php +++ b/system/BaseModel.php @@ -1578,7 +1578,7 @@ protected function transformDataToArray($data, string $type): array // properties representing the collection elements, we need to grab // them as an array. if (is_object($data) && ! $data instanceof stdClass) { - $data = $this->objectToArray($data, true, true); + $data = $this->objectToArray($data, ($type === 'update'), true); } // If it's still a stdClass, go ahead and convert to diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index ea1e1ad8..347a894f 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -865,10 +865,12 @@ public static function getOptionString(bool $useLongOpts = false, bool $trim = f $out .= "-{$name} "; } - // If there's a space, we need to group - // so it will pass correctly. + if ($value === null) { + continue; + } + if (mb_strpos($value, ' ') !== false) { - $out .= '"' . $value . '" '; + $out .= "\"{$value}\" "; } elseif ($value !== null) { $out .= "{$value} "; } diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index a7df6971..2517c6a5 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -241,7 +241,6 @@ protected function getItem(string $filename) return false; } - // @phpstan-ignore-next-line if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) { // If the file is still there then try to remove it if (is_file($this->path . $filename)) { diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 93c8cc59..f240a5d0 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -146,7 +146,7 @@ public function get(string $key) } } - return is_array($data) ? $data[0] : $data; // @phpstan-ignore-line + return is_array($data) ? $data[0] : $data; } /** @@ -172,7 +172,6 @@ public function save(string $key, $value, int $ttl = 60) return $this->memcached->set($key, $value, 0, $ttl); } - // @phpstan-ignore-next-line return false; } @@ -205,7 +204,6 @@ public function increment(string $key, int $offset = 1) $key = static::validateKey($key, $this->prefix); - // @phpstan-ignore-next-line return $this->memcached->increment($key, $offset, $offset, 60); } @@ -221,7 +219,7 @@ public function decrement(string $key, int $offset = 1) $key = static::validateKey($key, $this->prefix); // FIXME: third parameter isn't other handler actions. - // @phpstan-ignore-next-line + return $this->memcached->decrement($key, $offset, $offset, 60); } diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index a8ebeef1..bcce77f1 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -12,6 +12,7 @@ namespace CodeIgniter; use Closure; +use CodeIgniter\Debug\Kint\RichRenderer; use CodeIgniter\Debug\Timer; use CodeIgniter\Events\Events; use CodeIgniter\Exceptions\FrameworkException; @@ -33,7 +34,6 @@ use Exception; use Kint; use Kint\Renderer\CliRenderer; -use Kint\Renderer\RichRenderer; /** * This class is the core of the framework, and will analyse the @@ -45,7 +45,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.1.5'; + public const CI_VERSION = '4.1.6'; private const MIN_PHP_VERSION = '7.3'; @@ -249,7 +249,7 @@ protected function initializeKint() */ $config = config('Config\Kint'); - Kint::$max_depth = $config->maxDepth; + Kint::$depth_limit = $config->maxDepth; Kint::$display_called_from = $config->displayCalledFrom; Kint::$expanded = $config->expanded; @@ -257,11 +257,13 @@ protected function initializeKint() Kint::$plugins = $config->plugins; } + Kint::$renderers[Kint::MODE_RICH] = RichRenderer::class; + RichRenderer::$theme = $config->richTheme; RichRenderer::$folder = $config->richFolder; RichRenderer::$sort = $config->richSort; if (! empty($config->richObjectPlugins) && is_array($config->richObjectPlugins)) { - RichRenderer::$object_plugins = $config->richObjectPlugins; + RichRenderer::$value_plugins = $config->richObjectPlugins; } if (! empty($config->richTabPlugins) && is_array($config->richTabPlugins)) { RichRenderer::$tab_plugins = $config->richTabPlugins; @@ -537,7 +539,6 @@ protected function getRequestObject() return; } - // @phpstan-ignore-next-line if (is_cli() && ENVIRONMENT !== 'testing') { // @codeCoverageIgnoreStart $this->request = Services::clirequest($this->config); @@ -721,7 +722,7 @@ protected function tryToRouteIt(?RouteCollectionInterface $routes = null) // If a {locale} segment was matched in the final route, // then we need to set the correct locale on our Request. if ($this->router->hasLocale()) { - $this->request->setLocale($this->router->getLocale()); // @phpstan-ignore-line + $this->request->setLocale($this->router->getLocale()); } $this->benchmark->stop('routing'); @@ -816,7 +817,7 @@ protected function createController() protected function runController($class) { // If this is a console request then use the input segments as parameters - $params = defined('SPARKED') ? $this->request->getSegments() : $this->router->params(); // @phpstan-ignore-line + $params = defined('SPARKED') ? $this->request->getSegments() : $this->router->params(); if (method_exists($class, '_remap')) { $output = $class->_remap($this->method, ...$params); @@ -969,7 +970,7 @@ public function spoofRequestMethod() return; } - $method = $this->request->getPost('_method'); // @phpstan-ignore-line + $method = $this->request->getPost('_method'); if (empty($method)) { return; diff --git a/system/Common.php b/system/Common.php index 7c150a01..e132d982 100644 --- a/system/Common.php +++ b/system/Common.php @@ -380,7 +380,7 @@ function env(string $key, $default = null) * If $data is an array, then it loops over it, escaping each * 'value' of the key/value pairs. * - * Valid context values: html, js, css, url, attr, raw, null + * Valid context values: html, js, css, url, attr, raw * * @param array|string $data * @param string $encoding @@ -480,9 +480,9 @@ function force_https(int $duration = 31536000, ?RequestInterface $request = null $uri = URI::createURIString( 'https', $baseURL, - $request->uri->getPath(), // Absolute URIs should use a "/" for an empty path - $request->uri->getQuery(), - $request->uri->getFragment() + $request->getUri()->getPath(), // Absolute URIs should use a "/" for an empty path + $request->getUri()->getQuery(), + $request->getUri()->getFragment() ); // Set an HSTS header @@ -643,16 +643,13 @@ function helper($filenames) */ function is_cli(): bool { - if (defined('STDIN')) { + if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) { return true; } - if (! isset($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']) && isset($_SERVER['argv']) && count($_SERVER['argv']) > 0) { - return true; - } - - // if source of request is from CLI, the `$_SERVER` array will not populate this key - return ! isset($_SERVER['REQUEST_METHOD']); + // PHP_SAPI could be 'cgi-fcgi', 'fpm-fcgi'. + // See https://github.com/codeigniter4/CodeIgniter4/pull/5393 + return ! isset($_SERVER['REMOTE_ADDR']) && ! isset($_SERVER['REQUEST_METHOD']); } } @@ -813,11 +810,6 @@ function old(string $key, $default = null, $escape = 'html') return $default; } - // If the result was serialized array or string, then unserialize it for use... - if (is_string($value) && (strpos($value, 'a:') === 0 || strpos($value, 's:') === 0)) { - $value = unserialize($value); - } - return $escape === false ? $value : esc($value, $escape); } } @@ -1156,7 +1148,6 @@ function class_uses_recursive($class) $results = []; - // @phpstan-ignore-next-line foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) { $results += trait_uses_recursive($class); } diff --git a/system/ComposerScripts.php b/system/ComposerScripts.php index 6972395b..ef4dfe1a 100644 --- a/system/ComposerScripts.php +++ b/system/ComposerScripts.php @@ -43,20 +43,23 @@ final class ComposerScripts */ private static $dependencies = [ 'kint-src' => [ - 'from' => __DIR__ . '/../vendor/kint-php/kint/src/', - 'to' => __DIR__ . '/ThirdParty/Kint/', + 'license' => __DIR__ . '/../vendor/kint-php/kint/LICENSE', + 'from' => __DIR__ . '/../vendor/kint-php/kint/src/', + 'to' => __DIR__ . '/ThirdParty/Kint/', ], 'kint-resources' => [ 'from' => __DIR__ . '/../vendor/kint-php/kint/resources/', 'to' => __DIR__ . '/ThirdParty/Kint/resources/', ], 'escaper' => [ - 'from' => __DIR__ . '/../vendor/laminas/laminas-escaper/src/', - 'to' => __DIR__ . '/ThirdParty/Escaper/', + 'license' => __DIR__ . '/../vendor/laminas/laminas-escaper/LICENSE.md', + 'from' => __DIR__ . '/../vendor/laminas/laminas-escaper/src/', + 'to' => __DIR__ . '/ThirdParty/Escaper/', ], 'psr-log' => [ - 'from' => __DIR__ . '/../vendor/psr/log/Psr/Log/', - 'to' => __DIR__ . '/ThirdParty/PSR/Log/', + 'license' => __DIR__ . '/../vendor/psr/log/LICENSE', + 'from' => __DIR__ . '/../vendor/psr/log/Psr/Log/', + 'to' => __DIR__ . '/ThirdParty/PSR/Log/', ], ]; @@ -70,6 +73,10 @@ public static function postUpdate() foreach (self::$dependencies as $dependency) { self::recursiveMirror($dependency['from'], $dependency['to']); + if (isset($dependency['license'])) { + $license = basename($dependency['license']); + copy($dependency['license'], $dependency['to'] . '/' . $license); + } } self::copyKintInitFiles(); diff --git a/system/Cookie/CookieStore.php b/system/Cookie/CookieStore.php index 87dc472d..af7dd2f0 100644 --- a/system/Cookie/CookieStore.php +++ b/system/Cookie/CookieStore.php @@ -158,6 +158,8 @@ public function remove(string $name, string $prefix = '') /** * Dispatches all cookies in store. + * + * @deprecated Response should dispatch cookies. */ public function dispatch(): void { @@ -232,6 +234,8 @@ protected function validateCookies(array $cookies): void * Extracted call to `setrawcookie()` in order to run unit tests on it. * * @codeCoverageIgnore + * + * @deprecated */ protected function setRawCookie(string $name, string $value, array $options): void { @@ -242,6 +246,8 @@ protected function setRawCookie(string $name, string $value, array $options): vo * Extracted call to `setcookie()` in order to run unit tests on it. * * @codeCoverageIgnore + * + * @deprecated */ protected function setCookie(string $name, string $value, array $options): void { diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 74b9dffa..2a431acc 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -158,6 +158,9 @@ class BaseBuilder * Tracked separately because $QBFrom gets escaped * and prefixed. * + * When $tableName to the constructor has multiple tables, + * the value is empty string. + * * @var string */ protected $tableName; @@ -261,7 +264,9 @@ class BaseBuilder /** * Constructor * - * @param array|string $tableName + * @param array|string $tableName tablename or tablenames with or without aliases + * + * Examples of $tableName: `mytable`, `jobs j`, `jobs j, users u`, `['jobs j','users u']` * * @throws DatabaseException */ @@ -276,7 +281,13 @@ public function __construct($tableName, ConnectionInterface &$db, ?array $option */ $this->db = $db; - $this->tableName = $tableName; + // If it contains `,`, it has multiple tables + if (is_string($tableName) && strpos($tableName, ',') === false) { + $this->tableName = $tableName; // @TODO remove alias if exists + } else { + $this->tableName = ''; + } + $this->from($tableName); if (! empty($options)) { @@ -672,34 +683,34 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type $op = trim(current($op)); - if (substr($k, -1 * strlen($op)) === $op) { - $k = rtrim(strrev(preg_replace(strrev('/' . $op . '/'), strrev(''), strrev($k), 1))); + if (substr($k, -strlen($op)) === $op) { + $k = rtrim(substr($k, 0, -strlen($op))); + $op = " {$op}"; + } else { + $op = ''; } - } - - $bind = $this->setBind($k, $v, $escape); - - if (empty($op)) { - $k .= ' ='; } else { - $k .= " {$op}"; + $op = ' ='; } - if ($v instanceof Closure) { - $builder = $this->cleanClone(); - $v = '(' . str_replace("\n", ' ', $v($builder)->getCompiledSelect()) . ')'; + if ($this->isSubquery($v)) { + $v = $this->buildSubquery($v, true); } else { - $v = " :{$bind}:"; + $bind = $this->setBind($k, $v, $escape); + $v = " :{$bind}:"; } } elseif (! $this->hasOperator($k) && $qbKey !== 'QBHaving') { // value appears not to have been set, assign the test to IS NULL - $k .= ' IS NULL'; + $op = ' IS NULL'; } elseif (preg_match('/\s*(!?=|<>|IS(?:\s+NOT)?)\s*$/i', $k, $match, PREG_OFFSET_CAPTURE)) { - $k = substr($k, 0, $match[0][1]) . ($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL'); + $k = substr($k, 0, $match[0][1]); + $op = $match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL'; + } else { + $op = ''; } $this->{$qbKey}[] = [ - 'condition' => $prefix . $k . $v, + 'condition' => $prefix . $k . $op . $v, 'escape' => $escape, ]; } @@ -711,7 +722,7 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type * Generates a WHERE field IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -724,7 +735,7 @@ public function whereIn(?string $key = null, $values = null, ?bool $escape = nul * Generates a WHERE field IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -737,7 +748,7 @@ public function orWhereIn(?string $key = null, $values = null, ?bool $escape = n * Generates a WHERE field NOT IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -750,7 +761,7 @@ public function whereNotIn(?string $key = null, $values = null, ?bool $escape = * Generates a WHERE field NOT IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -763,7 +774,7 @@ public function orWhereNotIn(?string $key = null, $values = null, ?bool $escape * Generates a HAVING field IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -776,7 +787,7 @@ public function havingIn(?string $key = null, $values = null, ?bool $escape = nu * Generates a HAVING field IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -789,7 +800,7 @@ public function orHavingIn(?string $key = null, $values = null, ?bool $escape = * Generates a HAVING field NOT IN('item', 'item') SQL query, * joined with 'AND' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -802,7 +813,7 @@ public function havingNotIn(?string $key = null, $values = null, ?bool $escape = * Generates a HAVING field NOT IN('item', 'item') SQL query, * joined with 'OR' if appropriate. * - * @param array|Closure|string $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|string $values The values searched on, or anonymous function with subquery * * @return $this */ @@ -817,7 +828,7 @@ public function orHavingNotIn(?string $key = null, $values = null, ?bool $escape * @used-by whereNotIn() * @used-by orWhereNotIn() * - * @param array|Closure|null $values The values searched on, or anonymous function with subquery + * @param array|BaseBuilder|Closure|null $values The values searched on, or anonymous function with subquery * * @throws InvalidArgumentException * @@ -833,7 +844,7 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal return $this; // @codeCoverageIgnore } - if ($values === null || (! is_array($values) && ! ($values instanceof Closure))) { + if ($values === null || (! is_array($values) && ! $this->isSubquery($values))) { if (CI_DEBUG) { throw new InvalidArgumentException(sprintf('%s() expects $values to be of type array or closure', debug_backtrace(0, 2)[1]['function'])); } @@ -853,18 +864,19 @@ protected function _whereIn(?string $key = null, $values = null, bool $not = fal $not = ($not) ? ' NOT' : ''; - if ($values instanceof Closure) { - $builder = $this->cleanClone(); - $ok = str_replace("\n", ' ', $values($builder)->getCompiledSelect()); + if ($this->isSubquery($values)) { + $whereIn = $this->buildSubquery($values, true); + $escape = false; } else { $whereIn = array_values($values); - $ok = $this->setBind($ok, $whereIn, $escape); } + $ok = $this->setBind($ok, $whereIn, $escape); + $prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type); $whereIn = [ - 'condition' => $prefix . $key . $not . ($values instanceof Closure ? " IN ({$ok})" : " IN :{$ok}:"), + 'condition' => "{$prefix}{$key}{$not} IN :{$ok}:", 'escape' => false, ]; @@ -2712,9 +2724,35 @@ protected function setBind(string $key, $value = null, bool $escape = true): str * Returns a clone of a Base Builder with reset query builder values. * * @return $this + * + * @deprecated */ protected function cleanClone() { return (clone $this)->from([], true)->resetQuery(); } + + /** + * @param mixed $value + */ + protected function isSubquery($value): bool + { + return $value instanceof BaseBuilder || $value instanceof Closure; + } + + /** + * @param BaseBuilder|Closure $builder + * @param bool $wrapped Wrap the subquery in brackets + */ + protected function buildSubquery($builder, bool $wrapped = false): string + { + if ($builder instanceof Closure) { + $instance = (clone $this)->from([], true)->resetQuery(); + $builder = $builder($instance); + } + + $subquery = strtr($builder->getCompiledSelect(), "\n", ' '); + + return $wrapped ? '(' . $subquery . ')' : $subquery; + } } diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index ebb63b7f..5f678e51 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -565,7 +565,7 @@ abstract protected function execute(string $sql); * * @param mixed ...$binds * - * @return BaseResult|bool|Query + * @return BaseResult|bool|Query BaseResult when “read” type query, bool when “write” type query, Query when prepared query * * @todo BC set $queryClass default as null in 4.1 */ @@ -835,7 +835,7 @@ abstract protected function _transCommit(): bool; abstract protected function _transRollback(): bool; /** - * Returns an instance of the query builder for this connection. + * Returns a non-shared new instance of the query builder for this connection. * * @param array|string $tableName * @@ -883,7 +883,6 @@ public function prepare(Closure $func, array $options = []) $this->pretend(false); if ($sql instanceof QueryInterface) { - // @phpstan-ignore-next-line $sql = $sql->getOriginalQuery(); } @@ -955,6 +954,8 @@ public function getConnectDuration(int $decimals = 6): string * the correct identifiers. * * @param array|string $item + * @param bool $prefixSingle Prefix an item with no segments? + * @param bool $fieldExists Supplied $item contains a field name? * * @return array|string */ @@ -1012,7 +1013,8 @@ public function protectIdentifiers($item, bool $prefixSingle = false, ?bool $pro // // NOTE: The ! empty() condition prevents this method // from breaking when QB isn't enabled. - if (! empty($this->aliasedTables) && in_array($parts[0], $this->aliasedTables, true)) { + $firstSegment = trim($parts[0], $this->escapeChar); + if (! empty($this->aliasedTables) && in_array($firstSegment, $this->aliasedTables, true)) { if ($protectIdentifiers === true) { foreach ($parts as $key => $val) { if (! in_array($val, $this->reservedIdentifiers, true)) { @@ -1200,10 +1202,6 @@ public function escape($str) return ($str === false) ? 0 : 1; } - if (is_numeric($str) && $str < 0) { - return "'{$str}'"; - } - return $str ?? 'NULL'; } diff --git a/system/Database/BaseResult.php b/system/Database/BaseResult.php index 49a970f5..5d223c7f 100644 --- a/system/Database/BaseResult.php +++ b/system/Database/BaseResult.php @@ -154,7 +154,6 @@ public function getCustomResultObject(string $className) $this->customResultObject[$className][] = $row; } - // @phpstan-ignore-next-line return $this->customResultObject[$className]; } @@ -233,7 +232,6 @@ public function getResultObject(): array $this->resultObject[] = $row; } - // @phpstan-ignore-next-line return $this->resultObject; } diff --git a/system/Database/BaseUtils.php b/system/Database/BaseUtils.php index 5af2b54d..7848ae75 100644 --- a/system/Database/BaseUtils.php +++ b/system/Database/BaseUtils.php @@ -200,7 +200,7 @@ public function repairTable(string $tableName) public function getCSVFromResult(ResultInterface $query, string $delim = ',', string $newline = "\n", string $enclosure = '"') { $out = ''; - // First generate the headings from the table column names + foreach ($query->getFieldNames() as $name) { $out .= $enclosure . str_replace($enclosure, $enclosure . $enclosure, $name) . $enclosure . $delim; } @@ -212,7 +212,7 @@ public function getCSVFromResult(ResultInterface $query, string $delim = ',', st $line = []; foreach ($row as $item) { - $line[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $item) . $enclosure; + $line[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $item ?? '') . $enclosure; } $out .= implode($delim, $line) . $newline; diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 8e0b7e43..406f75b4 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -135,7 +135,7 @@ class Forge * * @var false|string */ - protected $renameTableStr = 'ALTER TABLE %s RENAME TO %s;'; + protected $renameTableStr = 'ALTER TABLE %s RENAME TO %s'; /** * UNSIGNED support @@ -462,7 +462,7 @@ public function dropKey(string $table, string $keyName) public function dropForeignKey(string $table, string $foreignName) { $sql = sprintf( - $this->dropConstraintStr, + (string) $this->dropConstraintStr, $this->db->escapeIdentifiers($this->db->DBPrefix . $table), $this->db->escapeIdentifiers($this->db->DBPrefix . $foreignName) ); @@ -1042,14 +1042,14 @@ protected function _processIndexes(string $table) if (in_array($i, $this->uniqueKeys, true)) { $sqls[] = 'ALTER TABLE ' . $this->db->escapeIdentifiers($table) . ' ADD CONSTRAINT ' . $this->db->escapeIdentifiers($table . '_' . implode('_', $this->keys[$i])) - . ' UNIQUE (' . implode(', ', $this->db->escapeIdentifiers($this->keys[$i])) . ');'; + . ' UNIQUE (' . implode(', ', $this->db->escapeIdentifiers($this->keys[$i])) . ')'; continue; } $sqls[] = 'CREATE INDEX ' . $this->db->escapeIdentifiers($table . '_' . implode('_', $this->keys[$i])) . ' ON ' . $this->db->escapeIdentifiers($table) - . ' (' . implode(', ', $this->db->escapeIdentifiers($this->keys[$i])) . ');'; + . ' (' . implode(', ', $this->db->escapeIdentifiers($this->keys[$i])) . ')'; } return $sqls; diff --git a/system/Database/MySQLi/Connection.php b/system/Database/MySQLi/Connection.php index 62881620..5badaf1c 100644 --- a/system/Database/MySQLi/Connection.php +++ b/system/Database/MySQLi/Connection.php @@ -100,19 +100,19 @@ public function connect(bool $persistent = false) if ($this->strictOn) { $this->mysqli->options( MYSQLI_INIT_COMMAND, - 'SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")' + "SET SESSION sql_mode = CONCAT(@@sql_mode, ',', 'STRICT_ALL_TABLES')" ); } else { $this->mysqli->options( MYSQLI_INIT_COMMAND, - 'SET SESSION sql_mode = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( + "SET SESSION sql_mode = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")' + 'STRICT_ALL_TABLES,', ''), + ',STRICT_ALL_TABLES', ''), + 'STRICT_ALL_TABLES', ''), + 'STRICT_TRANS_TABLES,', ''), + ',STRICT_TRANS_TABLES', ''), + 'STRICT_TRANS_TABLES', '')" ); } } @@ -485,8 +485,10 @@ protected function _foreignKeyData(string $table): array FROM information_schema.TABLE_CONSTRAINTS AS tc INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc ON tc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME + AND tc.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA INNER JOIN information_schema.KEY_COLUMN_USAGE AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME + AND tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA WHERE tc.CONSTRAINT_TYPE = ' . $this->escape('FOREIGN KEY') . ' AND tc.TABLE_SCHEMA = ' . $this->escape($this->database) . ' AND diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index a768e0ec..57b4c78f 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -117,7 +117,6 @@ public function getVersion(): string return $this->dataCache['version']; } - // @phpstan-ignore-next-line if (! $this->connID || ($pgVersion = pg_version($this->connID)) === false) { $this->initialize(); } @@ -433,8 +432,11 @@ protected function buildDSN() $this->DSN = "host={$this->hostname} "; } - if (! empty($this->port) && ctype_digit($this->port)) { - $this->DSN .= "port={$this->port} "; + // ctype_digit only accepts strings + $port = (string) $this->port; + + if ($port !== '' && ctype_digit($port)) { + $this->DSN .= "port={$port} "; } if ($this->username !== '') { diff --git a/system/Database/Query.php b/system/Database/Query.php index a4bb1b2b..91b98c77 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -273,37 +273,25 @@ public function getOriginalQuery(): string */ protected function compileBinds() { - $sql = $this->finalQueryString; + $sql = $this->finalQueryString; + $binds = $this->binds; - $hasBinds = strpos($sql, $this->bindMarker) !== false; - $hasNamedBinds = ! $hasBinds - && preg_match('/:(?!=).+:/', $sql) === 1; - - if (empty($this->binds) - || empty($this->bindMarker) - || (! $hasNamedBinds && ! $hasBinds) - ) { + if (empty($binds)) { return; } - if (! is_array($this->binds)) { - $binds = [$this->binds]; - $bindCount = 1; - } else { - $binds = $this->binds; + if (is_int(array_key_first($binds))) { $bindCount = count($binds); - } + $ml = strlen($this->bindMarker); - // Reverse the binds so that duplicate named binds - // will be processed prior to the original binds. - if (! is_numeric(key(array_slice($binds, 0, 1)))) { + $this->finalQueryString = $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); + } else { + // Reverse the binds so that duplicate named binds + // will be processed prior to the original binds. $binds = array_reverse($binds); - } - - $ml = strlen($this->bindMarker); - $sql = $hasNamedBinds ? $this->matchNamedBinds($sql, $binds) : $this->matchSimpleBinds($sql, $binds, $bindCount, $ml); - $this->finalQueryString = $sql; + $this->finalQueryString = $this->matchNamedBinds($sql, $binds); + } } /** diff --git a/system/Database/SQLite3/Result.php b/system/Database/SQLite3/Result.php index 6ad8e5dc..6afc04c5 100644 --- a/system/Database/SQLite3/Result.php +++ b/system/Database/SQLite3/Result.php @@ -27,7 +27,7 @@ class Result extends BaseResult */ public function getFieldCount(): int { - return $this->resultID->numColumns(); // @phpstan-ignore-line + return $this->resultID->numColumns(); } /** @@ -38,7 +38,7 @@ public function getFieldNames(): array $fieldNames = []; for ($i = 0, $c = $this->getFieldCount(); $i < $c; $i++) { - $fieldNames[] = $this->resultID->columnName($i); // @phpstan-ignore-line + $fieldNames[] = $this->resultID->columnName($i); } return $fieldNames; @@ -58,18 +58,18 @@ public function getFieldData(): array ]; $retVal = []; - $this->resultID->fetchArray(SQLITE3_NUM); // @phpstan-ignore-line + $this->resultID->fetchArray(SQLITE3_NUM); for ($i = 0, $c = $this->getFieldCount(); $i < $c; $i++) { $retVal[$i] = new stdClass(); - $retVal[$i]->name = $this->resultID->columnName($i); // @phpstan-ignore-line - $type = $this->resultID->columnType($i); // @phpstan-ignore-line + $retVal[$i]->name = $this->resultID->columnName($i); + $type = $this->resultID->columnType($i); $retVal[$i]->type = $type; $retVal[$i]->type_name = $dataTypes[$type] ?? null; $retVal[$i]->max_length = null; $retVal[$i]->length = null; } - $this->resultID->reset(); // @phpstan-ignore-line + $this->resultID->reset(); return $retVal; } @@ -100,7 +100,7 @@ public function dataSeek(int $n = 0) throw new DatabaseException('SQLite3 doesn\'t support seeking to other offset.'); } - return $this->resultID->reset(); // @phpstan-ignore-line + return $this->resultID->reset(); } /** @@ -112,7 +112,7 @@ public function dataSeek(int $n = 0) */ protected function fetchAssoc() { - return $this->resultID->fetchArray(SQLITE3_ASSOC); // @phpstan-ignore-line + return $this->resultID->fetchArray(SQLITE3_ASSOC); } /** diff --git a/system/Database/Seeder.php b/system/Database/Seeder.php index b6127af2..92d28196 100644 --- a/system/Database/Seeder.php +++ b/system/Database/Seeder.php @@ -68,6 +68,8 @@ class Seeder * Faker Generator instance. * * @var Generator|null + * + * @deprecated */ private static $faker; @@ -98,6 +100,8 @@ public function __construct(Database $config, ?BaseConnection $db = null) /** * Gets the Faker Generator instance. + * + * @deprecated */ public static function faker(): ?Generator { diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index 04556c5c..d319c2f9 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -70,6 +70,11 @@ public function __construct(ExceptionsConfig $config, IncomingRequest $request, $this->config = $config; $this->request = $request; $this->response = $response; + + // workaround for upgraded users + if (! isset($this->config->sensitiveDataInTrace)) { + $this->config->sensitiveDataInTrace = []; + } } /** @@ -389,7 +394,7 @@ public static function highlightFile(string $file, int $lineNumber, int $lines = $start = max($lineNumber - (int) round($lines / 2), 0); // Get just the lines we need to display, while keeping line numbers... - $source = array_splice($source, $start, $lines, true); // @phpstan-ignore-line + $source = array_splice($source, $start, $lines, true); // Used to format the line number in the source $format = '% ' . strlen((string) ($start + $lines)) . 'd'; diff --git a/system/Debug/Kint/RichRenderer.php b/system/Debug/Kint/RichRenderer.php new file mode 100644 index 00000000..756cac75 --- /dev/null +++ b/system/Debug/Kint/RichRenderer.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Debug\Kint; + +use Kint\Renderer\RichRenderer as KintRichRenderer; + +/** + * Overrides RichRenderer::preRender() for CSP + */ +class RichRenderer extends KintRichRenderer +{ + public function preRender() + { + $output = ''; + + if ($this->pre_render) { + foreach (self::$pre_render_sources as $type => $values) { + $contents = ''; + + foreach ($values as $v) { + $contents .= $v($this); + } + + if (! \strlen($contents)) { + continue; + } + + switch ($type) { + case 'script': + $output .= ''; + break; + + case 'style': + $output .= ''; + break; + + default: + $output .= $contents; + } + } + + // Don't pre-render on every dump + if (! $this->force_pre_render) { + self::$needs_pre_render = false; + } + } + + $output .= '
'; + + return $output; + } +} diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index b951e2ed..3502ae87 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -310,6 +310,10 @@ protected function structureTimelineData(array $elements): array */ protected function collectVarData(): array { + if (! ($this->config->collectVarData ?? true)) { + return []; + } + $data = []; foreach ($this->collectors as $collector) { diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index d8445b80..520ddc7c 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -89,6 +89,7 @@ public static function collect(Query $query) 'query' => $query, 'string' => $queryString, 'duplicate' => in_array($queryString, array_column(static::$queries, 'string', null), true), + 'trace' => debug_backtrace(), ]; } } @@ -133,11 +134,34 @@ public function display(): array $data['queries'] = array_map(static function (array $query) { $isDuplicate = $query['duplicate'] === true; + // Find the first line that doesn't include `system` in the backtrace + $line = []; + + foreach ($query['trace'] as &$traceLine) { + // Clean up the file paths + $traceLine['file'] = str_ireplace(APPPATH, 'APPPATH/', $traceLine['file']); + $traceLine['file'] = str_ireplace(SYSTEMPATH, 'SYSTEMPATH/', $traceLine['file']); + if (defined('VENDORPATH')) { + // VENDORPATH is not defined unless `vendor/autoload.php` exists + $traceLine['file'] = str_ireplace(VENDORPATH, 'VENDORPATH/', $traceLine['file']); + } + $traceLine['file'] = str_ireplace(ROOTPATH, 'ROOTPATH/', $traceLine['file']); + + if (strpos($traceLine['file'], 'SYSTEMPATH') !== false) { + continue; + } + $line = empty($line) ? $traceLine : $line; + } + return [ - 'hover' => $isDuplicate ? 'This query was called more than once.' : '', - 'class' => $isDuplicate ? 'duplicate' : '', - 'duration' => ((float) $query['query']->getDuration(5) * 1000) . ' ms', - 'sql' => $query['query']->debugToolbarDisplay(), + 'hover' => $isDuplicate ? 'This query was called more than once.' : '', + 'class' => $isDuplicate ? 'duplicate' : '', + 'duration' => ((float) $query['query']->getDuration(5) * 1000) . ' ms', + 'sql' => $query['query']->debugToolbarDisplay(), + 'trace' => $query['trace'], + 'trace-file' => str_replace(ROOTPATH, '/', $line['file'] ?? ''), + 'trace-line' => $line['line'] ?? '', + 'qid' => md5($query['query'] . microtime()), ]; }, static::$queries); diff --git a/system/Debug/Toolbar/Collectors/Events.php b/system/Debug/Toolbar/Collectors/Events.php index b8c59f45..a8a7e7aa 100644 --- a/system/Debug/Toolbar/Collectors/Events.php +++ b/system/Debug/Toolbar/Collectors/Events.php @@ -74,7 +74,7 @@ protected function formatTimelineData(): array { $data = []; - $rows = $this->viewer->getPerformanceData(); // @phpstan-ignore-line + $rows = $this->viewer->getPerformanceData(); foreach ($rows as $info) { $data[] = [ diff --git a/system/Debug/Toolbar/Collectors/Views.php b/system/Debug/Toolbar/Collectors/Views.php index 75fea1d6..fae3385f 100644 --- a/system/Debug/Toolbar/Collectors/Views.php +++ b/system/Debug/Toolbar/Collectors/Views.php @@ -89,7 +89,7 @@ protected function formatTimelineData(): array { $data = []; - $rows = $this->viewer->getPerformanceData(); // @phpstan-ignore-line + $rows = $this->viewer->getPerformanceData(); foreach ($rows as $info) { $data[] = [ @@ -122,7 +122,7 @@ protected function formatTimelineData(): array public function getVarData(): array { return [ - // @phpstan-ignore-next-line + 'View Data' => $this->viewer->getData(), ]; } @@ -132,7 +132,7 @@ public function getVarData(): array */ public function getBadgeValue(): int { - return count($this->viewer->getPerformanceData()); // @phpstan-ignore-line + return count($this->viewer->getPerformanceData()); } /** diff --git a/system/Debug/Toolbar/Views/_database.tpl b/system/Debug/Toolbar/Views/_database.tpl index a373b56b..a2f5bd98 100644 --- a/system/Debug/Toolbar/Views/_database.tpl +++ b/system/Debug/Toolbar/Views/_database.tpl @@ -7,9 +7,18 @@ {queries} - + {duration} {! sql !} + {trace-file}:{trace-line} + + + + + {trace} + {file}:{line}
+ {/trace} + {/queries} diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index b5a223b5..ed4230be 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -344,6 +344,8 @@ .debug-view.show-view { border-color: #DD8615; } +#debug-bar tr[data-toggle] { + cursor: pointer; } .debug-view-path { background-color: #FDC894; @@ -407,7 +409,7 @@ #debug-bar .muted { color: #DFDFDF; } #debug-bar .muted td { - color: #434343; } + color: #797979; } #debug-bar .muted:hover td { color: #DFDFDF; } #debug-bar #toolbar-position, @@ -496,7 +498,7 @@ #toolbarContainer.dark #debug-bar .muted { color: #DFDFDF; } #toolbarContainer.dark #debug-bar .muted td { - color: #434343; } + color: #797979; } #toolbarContainer.dark #debug-bar .muted:hover td { color: #DFDFDF; } #toolbarContainer.dark #debug-bar #toolbar-position, @@ -587,9 +589,9 @@ -moz-box-shadow: 0 1px 4px #DFDFDF; -webkit-box-shadow: 0 1px 4px #DFDFDF; } #toolbarContainer.light #debug-bar .muted { - color: #434343; } + color: #797979; } #toolbarContainer.light #debug-bar .muted td { - color: #DFDFDF; } + color: #797979; } #toolbarContainer.light #debug-bar .muted:hover td { color: #434343; } #toolbarContainer.light #debug-bar #toolbar-position, diff --git a/system/Debug/Toolbar/Views/toolbar.js b/system/Debug/Toolbar/Views/toolbar.js index 690535f2..b6883d4b 100644 --- a/system/Debug/Toolbar/Views/toolbar.js +++ b/system/Debug/Toolbar/Views/toolbar.js @@ -58,6 +58,13 @@ var ciDebugBar = { { buttons[i].addEventListener('click', ciDebugBar.showTab, true); } + + // Hook up generic toggle via data attributes `data-toggle="foo"` + var links = document.querySelectorAll('[data-toggle]'); + for (var i = 0; i < links.length; i++) + { + links[i].addEventListener('click', ciDebugBar.toggleRows, true); + } }, showTab: function () { @@ -124,6 +131,21 @@ var ciDebugBar = { } }, + /** + * Toggle display of another object based on + * the data-toggle value of this object + * + * @param event + */ + toggleRows : function(event) { + if(event.target) + { + let row = event.target.closest('tr'); + let target = document.getElementById(row.getAttribute('data-toggle')); + target.style.display = target.style.display === 'none' ? 'table-row' : 'none'; + } + }, + /** * Toggle display of a data table * @@ -137,7 +159,7 @@ var ciDebugBar = { if (obj) { - obj.style.display = obj.style.display == 'none' ? 'block' : 'none'; + obj.style.display = obj.style.display === 'none' ? 'block' : 'none'; } }, @@ -155,7 +177,7 @@ var ciDebugBar = { if (par && obj) { - obj.style.display = obj.style.display == 'none' ? '' : 'none'; + obj.style.display = obj.style.display === 'none' ? '' : 'none'; par.classList.toggle('timeline-parent-open'); } }, diff --git a/system/Entity/Cast/DatetimeCast.php b/system/Entity/Cast/DatetimeCast.php index 4655b4e3..99f425a4 100644 --- a/system/Entity/Cast/DatetimeCast.php +++ b/system/Entity/Cast/DatetimeCast.php @@ -32,7 +32,7 @@ public static function get($value, array $params = []) } if ($value instanceof DateTime) { - return Time::instance($value); + return Time::createFromInstance($value); } if (is_numeric($value)) { diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index faa1df35..edeb8b05 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -397,13 +397,10 @@ protected function processGlobals(?string $uri = null) return; } - $uri = strtolower(trim($uri, '/ ')); + $uri = strtolower(trim($uri ?? '', '/ ')); // Add any global filters, unless they are excluded for this URI - $sets = [ - 'before', - 'after', - ]; + $sets = ['before', 'after']; foreach ($sets as $set) { if (isset($this->config->globals[$set])) { diff --git a/system/Filters/InvalidChars.php b/system/Filters/InvalidChars.php new file mode 100644 index 00000000..4b1d8f7f --- /dev/null +++ b/system/Filters/InvalidChars.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\Security\Exceptions\SecurityException; + +/** + * InvalidChars filter. + * + * Check if user input data ($_GET, $_POST, $_COOKIE, php://input) do not contain + * invalid characters: + * - invalid UTF-8 characters + * - control characters except line break and tab code + */ +class InvalidChars implements FilterInterface +{ + /** + * Data source + * + * @var string + */ + protected $source; + + /** + * Regular expressions for valid control codes + * + * @var string + */ + protected $controlCodeRegex = '/\A[\r\n\t[:^cntrl:]]*\z/u'; + + /** + * Check invalid characters. + * + * @param array|null $arguments + * + * @return void + */ + public function before(RequestInterface $request, $arguments = null) + { + if ($request->isCLI()) { + return; + } + + $data = [ + 'get' => $request->getGet(), + 'post' => $request->getPost(), + 'cookie' => $request->getCookie(), + 'rawInput' => $request->getRawInput(), + ]; + + foreach ($data as $source => $values) { + $this->source = $source; + $this->checkEncoding($values); + $this->checkControl($values); + } + } + + /** + * We don't have anything to do here. + * + * @param array|null $arguments + * + * @return void + */ + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + { + } + + /** + * Check the character encoding is valid UTF-8. + * + * @param array|string $value + * + * @return array|string + */ + protected function checkEncoding($value) + { + if (is_array($value)) { + array_map([$this, 'checkEncoding'], $value); + + return $value; + } + + if (mb_check_encoding($value, 'UTF-8')) { + return $value; + } + + throw SecurityException::forInvalidUTF8Chars($this->source, $value); + } + + /** + * Check for the presence of control characters except line breaks and tabs. + * + * @param array|string $value + * + * @return array|string + */ + protected function checkControl($value) + { + if (is_array($value)) { + array_map([$this, 'checkControl'], $value); + + return $value; + } + + if (preg_match($this->controlCodeRegex, $value) === 1) { + return $value; + } + + throw SecurityException::forInvalidControlChars($this->source, $value); + } +} diff --git a/system/Filters/SecureHeaders.php b/system/Filters/SecureHeaders.php new file mode 100644 index 00000000..fd656af6 --- /dev/null +++ b/system/Filters/SecureHeaders.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Filters; + +use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\ResponseInterface; + +/** + * Add Common Security Headers + */ +class SecureHeaders implements FilterInterface +{ + /** + * @var array + */ + protected $headers = [ + // https://owasp.org/www-project-secure-headers/#x-frame-options + 'X-Frame-Options' => 'SAMEORIGIN', + + // https://owasp.org/www-project-secure-headers/#x-content-type-options + 'X-Content-Type-Options' => 'nosniff', + + // https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/jj542450(v=vs.85)#the-noopen-directive + 'X-Download-Options' => 'noopen', + + // https://owasp.org/www-project-secure-headers/#x-permitted-cross-domain-policies + 'X-Permitted-Cross-Domain-Policies' => 'none', + + // https://owasp.org/www-project-secure-headers/#referrer-policy + 'Referrer-Policy' => 'same-origin', + + // https://owasp.org/www-project-secure-headers/#x-xss-protection + // If you do not need to support legacy browsers, it is recommended that you use + // Content-Security-Policy without allowing unsafe-inline scripts instead. + // 'X-XSS-Protection' => '1; mode=block', + ]; + + /** + * We don't have anything to do here. + * + * @param array|null $arguments + * + * @return void + */ + public function before(RequestInterface $request, $arguments = null) + { + } + + /** + * Add security headers. + * + * @param array|null $arguments + * + * @return void + */ + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + { + foreach ($this->headers as $header => $value) { + $response->setHeader($header, $value); + } + } +} diff --git a/system/HTTP/CLIRequest.php b/system/HTTP/CLIRequest.php index fcc2a513..11bf598f 100644 --- a/system/HTTP/CLIRequest.php +++ b/system/HTTP/CLIRequest.php @@ -139,11 +139,13 @@ public function getOptionString(bool $useLongOpts = false): string $out .= "-{$name} "; } - // If there's a space, we need to group - // so it will pass correctly. + if ($value === null) { + continue; + } + if (mb_strpos($value, ' ') !== false) { $out .= '"' . $value . '" '; - } elseif ($value !== null) { + } else { $out .= "{$value} "; } } @@ -170,17 +172,17 @@ protected function parseCommand() if ($optionValue) { $optionValue = false; } else { - $this->segments[] = esc(strip_tags($arg)); + $this->segments[] = $arg; } continue; } - $arg = esc(strip_tags(ltrim($arg, '-'))); + $arg = ltrim($arg, '-'); $value = null; if (isset($args[$i + 1]) && mb_strpos($args[$i + 1], '-') !== 0) { - $value = esc(strip_tags($args[$i + 1])); + $value = $args[$i + 1]; $optionValue = true; } diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index fffe5725..e00ac44f 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -358,7 +358,7 @@ public function send(string $method, string $url) // Do we need to delay this request? if ($this->delay > 0) { - sleep($this->delay); // @phpstan-ignore-line + sleep($this->delay); } $output = $this->sendRequest($curlOptions); @@ -424,7 +424,7 @@ protected function applyMethod(string $method, array $curlOptions): array $this->method = $method; $curlOptions[CURLOPT_CUSTOMREQUEST] = $method; - $size = strlen($this->body); + $size = strlen($this->body ?? ''); // Have content? if ($size > 0) { diff --git a/system/HTTP/Files/UploadedFile.php b/system/HTTP/Files/UploadedFile.php index 6455a510..b9a67292 100644 --- a/system/HTTP/Files/UploadedFile.php +++ b/system/HTTP/Files/UploadedFile.php @@ -141,10 +141,16 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = $destination = $overwrite ? $targetPath . $name : $this->getDestination($targetPath . $name); try { - move_uploaded_file($this->path, $destination); + $this->hasMoved = move_uploaded_file($this->path, $destination); } catch (Exception $e) { $error = error_get_last(); - $message = isset($error['message']) ? strip_tags($error['message']) : ''; + $message = strip_tags($error['message'] ?? ''); + + throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message); + } + + if ($this->hasMoved === false) { + $message = 'move_uploaded_file() returned false'; throw HTTPException::forMoveFailed(basename($this->path), $targetPath, $message); } @@ -152,9 +158,8 @@ public function move(string $targetPath, ?string $name = null, bool $overwrite = @chmod($targetPath, 0777 & ~umask()); // Success, so store our new information - $this->path = $targetPath; - $this->name = basename($destination); - $this->hasMoved = true; + $this->path = $targetPath; + $this->name = basename($destination); return true; } diff --git a/system/HTTP/IncomingRequest.php b/system/HTTP/IncomingRequest.php index 128d6ee1..071b18e9 100755 --- a/system/HTTP/IncomingRequest.php +++ b/system/HTTP/IncomingRequest.php @@ -64,6 +64,8 @@ class IncomingRequest extends Request * AFTER the script name. So, if hosted in a sub-folder this will * appear different than actual URL. If you need that use getPath(). * + * @TODO should be protected. Use getUri() instead. + * * @var URI */ public $uri; @@ -518,7 +520,7 @@ public function getVar($index = null, $filter = null, $flags = null) */ public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0) { - return json_decode($this->body, $assoc, $depth, $options); + return json_decode($this->body ?? '', $assoc, $depth, $options); } /** @@ -535,7 +537,11 @@ public function getJsonVar(string $index, bool $assoc = false, ?int $filter = nu { helper('array'); - $data = dot_array_search($index, $this->getJSON(true)); + $json = $this->getJSON(true); + if (! is_array($json)) { + return null; + } + $data = dot_array_search($index, $json); if ($data === null) { return null; @@ -563,7 +569,7 @@ public function getJsonVar(string $index, bool $assoc = false, ?int $filter = nu */ public function getRawInput() { - parse_str($this->body, $output); + parse_str($this->body ?? '', $output); return $output; } diff --git a/system/HTTP/RequestTrait.php b/system/HTTP/RequestTrait.php index c0bb0050..327cddcb 100644 --- a/system/HTTP/RequestTrait.php +++ b/system/HTTP/RequestTrait.php @@ -273,7 +273,6 @@ public function fetchGlobal(string $method, $index = null, ?int $filter = null, $value = $this->globals[$method][$index] ?? null; } - // @phpstan-ignore-next-line if (is_array($value) && ( $filter !== FILTER_DEFAULT diff --git a/system/HTTP/ResponseTrait.php b/system/HTTP/ResponseTrait.php index 2b1205a5..278143fd 100644 --- a/system/HTTP/ResponseTrait.php +++ b/system/HTTP/ResponseTrait.php @@ -16,13 +16,14 @@ use CodeIgniter\Cookie\Exceptions\CookieException; use CodeIgniter\HTTP\Exceptions\HTTPException; use CodeIgniter\Pager\PagerInterface; +use CodeIgniter\Security\Exceptions\SecurityException; use Config\Services; use DateTime; use DateTimeZone; use InvalidArgumentException; /** - * Request Trait + * Response Trait * * Additional methods to make a PSR-7 Response class * compliant with the framework's own ResponseInterface. @@ -435,7 +436,7 @@ public function send() if ($this->CSPEnabled === true) { $this->CSP->finalize($this); } else { - $this->body = str_replace(['{csp-style-nonce}', '{csp-script-nonce}'], '', $this->body); + $this->body = str_replace(['{csp-style-nonce}', '{csp-script-nonce}'], '', $this->body ?? ''); } $this->sendHeaders(); @@ -446,7 +447,7 @@ public function send() } /** - * Sends the headers of this HTTP request to the browser. + * Sends the headers of this HTTP response to the browser. * * @return Response */ @@ -535,15 +536,15 @@ public function redirect(string $uri, string $method = 'auto', ?int $code = null * Accepts an arbitrary number of binds (up to 7) or an associative * array in the first parameter containing all the values. * - * @param array|string $name Cookie name or array containing binds - * @param string $value Cookie value - * @param string $expire Cookie expiration time in seconds - * @param string $domain Cookie domain (e.g.: '.yourdomain.com') - * @param string $path Cookie path (default: '/') - * @param string $prefix Cookie name prefix - * @param bool $secure Whether to only transfer cookies via SSL - * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) - * @param string|null $samesite + * @param array|Cookie|string $name Cookie name / array containing binds / Cookie object + * @param string $value Cookie value + * @param string $expire Cookie expiration time in seconds + * @param string $domain Cookie domain (e.g.: '.yourdomain.com') + * @param string $path Cookie path (default: '/') + * @param string $prefix Cookie name prefix + * @param bool $secure Whether to only transfer cookies via SSL + * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) + * @param string|null $samesite * * @return $this */ @@ -558,6 +559,12 @@ public function setCookie( $httponly = false, $samesite = null ) { + if ($name instanceof Cookie) { + $this->cookieStore = $this->cookieStore->put($name); + + return $this; + } + if (is_array($name)) { // always leave 'name' in last place, as the loop will break otherwise, due to $$item foreach (['samesite', 'value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name'] as $item) { @@ -689,7 +696,51 @@ protected function sendCookies() return; } - $this->cookieStore->dispatch(); + $this->dispatchCookies(); + } + + private function dispatchCookies(): void + { + /** @var IncomingRequest $request */ + $request = Services::request(); + + foreach ($this->cookieStore->display() as $cookie) { + if ($cookie->isSecure() && ! $request->isSecure()) { + throw SecurityException::forDisallowedAction(); + } + + $name = $cookie->getPrefixedName(); + $value = $cookie->getValue(); + $options = $cookie->getOptions(); + + if ($cookie->isRaw()) { + $this->doSetRawCookie($name, $value, $options); + } else { + $this->doSetCookie($name, $value, $options); + } + } + + $this->cookieStore->clear(); + } + + /** + * Extracted call to `setrawcookie()` in order to run unit tests on it. + * + * @codeCoverageIgnore + */ + private function doSetRawCookie(string $name, string $value, array $options): void + { + setrawcookie($name, $value, $options); + } + + /** + * Extracted call to `setcookie()` in order to run unit tests on it. + * + * @codeCoverageIgnore + */ + private function doSetCookie(string $name, string $value, array $options): void + { + setcookie($name, $value, $options); } /** diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index c7bdbb13..f9e9d34c 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -625,7 +625,7 @@ public function setAuthority(string $str) if (empty($parts['host']) && $parts['path'] !== '') { $parts['host'] = $parts['path']; - unset($parts['path']); // @phpstan-ignore-line + unset($parts['path']); } $this->applyParts($parts); diff --git a/system/Helpers/array_helper.php b/system/Helpers/array_helper.php index a06d4bb9..2f8a5f9c 100644 --- a/system/Helpers/array_helper.php +++ b/system/Helpers/array_helper.php @@ -20,7 +20,13 @@ */ function dot_array_search(string $index, array $array) { - $segments = preg_split('/(?isDir()) { - mkdir($target, 0755); + if (! is_dir($target)) { + mkdir($target, 0755); + } } elseif (! is_file($target) || ($overwrite && is_file($target))) { copy($origin, $target); } diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index b3d7c80c..a9a2a938 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -77,7 +77,7 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) { // Strip any formatting & ensure numeric input try { - $num = 0 + str_replace(',', '', $num); // @phpstan-ignore-line + $num = 0 + str_replace(',', '', $num); } catch (ErrorException $ee) { return false; } @@ -112,11 +112,7 @@ function number_to_amount($num, int $precision = 0, ?string $locale = null) } if (! function_exists('number_to_currency')) { - /** - * @param string $locale - * @param int $fraction - */ - function number_to_currency(float $num, string $currency, ?string $locale = null, ?int $fraction = null): string + function number_to_currency(float $num, string $currency, ?string $locale = null, int $fraction = 0): string { return format_number($num, 1, $locale, [ 'type' => NumberFormatter::CURRENCY, diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index 5f073842..4e7e5d85 100755 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -564,7 +564,6 @@ function random_string(string $type = 'alnum', int $len = 8): string break; } - // @phpstan-ignore-next-line return substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len); case 'md5': diff --git a/system/Helpers/url_helper.php b/system/Helpers/url_helper.php index 8d089083..42bcdc47 100644 --- a/system/Helpers/url_helper.php +++ b/system/Helpers/url_helper.php @@ -352,7 +352,7 @@ function safe_mailto(string $email, string $title = '', $attributes = ''): strin $temp[] = $ordinal; - if (count($temp) === $count) { // @phpstan-ignore-line + if (count($temp) === $count) { $number = ($count === 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64); $x[] = '|' . $number; $count = 1; diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 919a5a39..01698444 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -75,25 +75,23 @@ class Time extends DateTime */ public function __construct(?string $time = null, $timezone = null, ?string $locale = null) { - // If no locale was provided, grab it from Locale (set by IncomingRequest for web requests) - $this->locale = ! empty($locale) ? $locale : Locale::getDefault(); + $this->locale = $locale ?: Locale::getDefault(); - // If a test instance has been provided, use it instead. - if ($time === null && static::$testNow instanceof self) { - if (empty($timezone)) { - $timezone = static::$testNow->getTimezone(); - } + $time = $time ?? ''; - $time = static::$testNow->toDateTimeString(); + // If a test instance has been provided, use it instead. + if ($time === '' && static::$testNow instanceof self) { + $timezone = $timezone ?: static::$testNow->getTimezone(); + $time = (string) static::$testNow->toDateTimeString(); } - $timezone = ! empty($timezone) ? $timezone : date_default_timezone_get(); + $timezone = $timezone ?: date_default_timezone_get(); $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone); // If the time string was a relative string (i.e. 'next Tuesday') // then we need to adjust the time going in so that we have a current // timezone to work with. - if (! empty($time) && (is_string($time) && static::hasRelativeKeywords($time))) { + if ($time !== '' && static::hasRelativeKeywords($time)) { $instance = new DateTime('now', $this->timezone); $instance->modify($time); $time = $instance->format('Y-m-d H:i:s'); @@ -481,21 +479,7 @@ public function getQuarter(): string */ public function getDst(): bool { - // grab the transactions that would affect today - $start = strtotime('-1 year', $this->getTimestamp()); - $end = strtotime('+2 year', $start); - $transitions = $this->timezone->getTransitions($start, $end); - - $daylightSaving = false; - - foreach ($transitions as $transition) { - if ($transition['time'] > $this->format('U')) { - $daylightSaving = (bool) ($transition['isdst'] ?? $daylightSaving); - break; - } - } - - return $daylightSaving; + return $this->format('I') === '1'; // 1 if Daylight Saving Time, 0 otherwise. } /** diff --git a/system/Images/Handlers/GDHandler.php b/system/Images/Handlers/GDHandler.php index 02d61c40..ab8e0b7e 100644 --- a/system/Images/Handlers/GDHandler.php +++ b/system/Images/Handlers/GDHandler.php @@ -188,7 +188,7 @@ protected function process(string $action) imagesavealpha($dest, true); } - $copy($dest, $src, 0, 0, $this->xAxis, $this->yAxis, $this->width, $this->height, $origWidth, $origHeight); + $copy($dest, $src, 0, 0, (int) $this->xAxis, (int) $this->yAxis, $this->width, $this->height, $origWidth, $origHeight); imagedestroy($src); $this->resource = $dest; @@ -472,9 +472,9 @@ protected function textOverlay(string $text, array $options = [], bool $isShadow // Add the shadow to the source image if (! empty($options['fontPath'])) { // We have to add fontheight because imagettftext locates the bottom left corner, not top-left corner. - imagettftext($src, $options['fontSize'], 0, $xAxis, $yAxis + $options['fontheight'], $color, $options['fontPath'], $text); + imagettftext($src, $options['fontSize'], 0, (int) $xAxis, (int) ($yAxis + $options['fontheight']), $color, $options['fontPath'], $text); } else { - imagestring($src, $options['fontSize'], $xAxis, $yAxis, $text, $color); + imagestring($src, (int) $options['fontSize'], (int) $xAxis, (int) $yAxis, $text, $color); } $this->resource = $src; diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index 5ec6a23c..37bd168e 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -384,10 +384,10 @@ protected function _text(string $text, array $options = []) break; } - $xAxis = $xAxis >= 0 ? '+' . $xAxis : $xAxis; // @phpstan-ignore-line - $yAxis = $yAxis >= 0 ? '+' . $yAxis : $yAxis; // @phpstan-ignore-line + $xAxis = $xAxis >= 0 ? '+' . $xAxis : $xAxis; + $yAxis = $yAxis >= 0 ? '+' . $yAxis : $yAxis; - $cmd .= " -gravity {$gravity} -geometry {$xAxis}{$yAxis}"; // @phpstan-ignore-line + $cmd .= " -gravity {$gravity} -geometry {$xAxis}{$yAxis}"; } // Color diff --git a/system/Model.php b/system/Model.php index c73e5c71..32fa82fc 100644 --- a/system/Model.php +++ b/system/Model.php @@ -158,7 +158,7 @@ protected function doFind(bool $singleton, $id = null) */ protected function doFindColumn(string $columnName) { - return $this->select($columnName)->asArray()->find(); // @phpstan-ignore-line + return $this->select($columnName)->asArray()->find(); } /** @@ -584,12 +584,17 @@ public function set($key, $value = '', ?bool $escape = null) */ protected function shouldUpdate($data): bool { - // When useAutoIncrement feature is disabled check + if (parent::shouldUpdate($data) === false) { + return false; + } + + if ($this->useAutoIncrement === true) { + return true; + } + + // When useAutoIncrement feature is disabled, check // in the database if given record already exists - return parent::shouldUpdate($data) - && $this->useAutoIncrement - ? true - : $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; + return $this->where($this->primaryKey, $this->getIdValue($data))->countAllResults() === 1; } /** diff --git a/system/Router/Router.php b/system/Router/Router.php index 621c54a5..5c4b3f02 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -124,7 +124,6 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request $this->controller = $this->collection->getDefaultController(); $this->method = $this->collection->getDefaultMethod(); - // @phpstan-ignore-next-line $this->collection->setHTTPVerb($request->getMethod() ?? strtolower($_SERVER['REQUEST_METHOD'])); } diff --git a/system/Security/Exceptions/SecurityException.php b/system/Security/Exceptions/SecurityException.php index 254f3ec3..ed118d95 100644 --- a/system/Security/Exceptions/SecurityException.php +++ b/system/Security/Exceptions/SecurityException.php @@ -20,6 +20,22 @@ public static function forDisallowedAction() return new static(lang('Security.disallowedAction'), 403); } + public static function forInvalidUTF8Chars(string $source, string $string) + { + return new static( + 'Invalid UTF-8 characters in ' . $source . ': ' . $string, + 400 + ); + } + + public static function forInvalidControlChars(string $source, string $string) + { + return new static( + 'Invalid Control characters in ' . $source . ': ' . $string, + 400 + ); + } + /** * @deprecated Use `CookieException::forInvalidSameSite()` instead. * diff --git a/system/Security/Security.php b/system/Security/Security.php index d9a44c4c..008e94ae 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -13,12 +13,14 @@ use CodeIgniter\Cookie\Cookie; use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\Response; use CodeIgniter\Security\Exceptions\SecurityException; use CodeIgniter\Session\Session; use Config\App; use Config\Cookie as CookieConfig; use Config\Security as SecurityConfig; use Config\Services; +use LogicException; /** * Class Security @@ -30,6 +32,7 @@ class Security implements SecurityInterface { public const CSRF_PROTECTION_COOKIE = 'cookie'; public const CSRF_PROTECTION_SESSION = 'session'; + protected const CSRF_HASH_BYTES = 16; /** * CSRF Protection Method @@ -40,6 +43,13 @@ class Security implements SecurityInterface */ protected $csrfProtection = self::CSRF_PROTECTION_COOKIE; + /** + * CSRF Token Randomization + * + * @var bool + */ + protected $tokenRandomize = false; + /** * CSRF Hash * @@ -167,6 +177,7 @@ public function __construct(App $config) $this->regenerate = $security->regenerate ?? $this->regenerate; $this->rawCookieName = $security->cookieName ?? $this->rawCookieName; $this->expires = $security->expires ?? $this->expires; + $this->tokenRandomize = $security->tokenRandomize ?? $this->tokenRandomize; } else { // `Config/Security.php` is absence $this->tokenName = $config->CSRFTokenName ?? $this->tokenName; @@ -270,14 +281,15 @@ public function verify(RequestInterface $request) return $this; } - $token = $this->getPostedToken($request); + $token = $this->tokenRandomize ? $this->derandomize($this->getPostedToken($request)) + : $this->getPostedToken($request); // Do the tokens match? if (! isset($token, $this->hash) || ! hash_equals($this->hash, $token)) { throw SecurityException::forDisallowedAction(); } - $json = json_decode($request->getBody()); + $json = json_decode($request->getBody() ?? ''); if (isset($_POST[$this->tokenName])) { // We kill this since we're done and we don't want to pollute the POST array. @@ -312,9 +324,10 @@ private function getPostedToken(RequestInterface $request): ?string if ($request->hasHeader($this->headerName) && ! empty($request->header($this->headerName)->getValue())) { $tokenName = $request->header($this->headerName)->getValue(); } else { - $json = json_decode($request->getBody()); + $body = (string) $request->getBody(); + $json = json_decode($body); - if (! empty($request->getBody()) && ! empty($json) && json_last_error() === JSON_ERROR_NONE) { + if ($body !== '' && ! empty($json) && json_last_error() === JSON_ERROR_NONE) { $tokenName = $json->{$this->tokenName} ?? null; } else { $tokenName = null; @@ -329,7 +342,33 @@ private function getPostedToken(RequestInterface $request): ?string */ public function getHash(): ?string { - return $this->hash; + return $this->tokenRandomize ? $this->randomize($this->hash) : $this->hash; + } + + /** + * Randomize hash to avoid BREACH attacks. + */ + protected function randomize(string $hash): string + { + $keyBinary = random_bytes(static::CSRF_HASH_BYTES); + $hashBinary = hex2bin($hash); + + if ($hashBinary === false) { + throw new LogicException('$hash is invalid: ' . $hash); + } + + return bin2hex(($hashBinary ^ $keyBinary) . $keyBinary); + } + + /** + * Derandomize the token. + */ + protected function derandomize(string $token): string + { + $key = substr($token, -static::CSRF_HASH_BYTES * 2); + $value = substr($token, 0, static::CSRF_HASH_BYTES * 2); + + return bin2hex(hex2bin($value) ^ hex2bin($key)); } /** @@ -461,7 +500,7 @@ protected function generateHash(): string return $this->hash = $this->session->get($this->tokenName); } - $this->hash = bin2hex(random_bytes(16)); + $this->hash = bin2hex(random_bytes(static::CSRF_HASH_BYTES)); if ($this->isCSRFCookie()) { $this->saveHashInCookie(); @@ -490,13 +529,18 @@ private function saveHashInCookie(): void 'expires' => $this->expires === 0 ? 0 : time() + $this->expires, ] ); - $this->sendCookie($this->request); + + /** @var Response $response */ + $response = Services::response(); + $response->setCookie($this->cookie); } /** * CSRF Send Cookie * * @return false|Security + * + * @deprecated Set cookies to Response object instead. */ protected function sendCookie(RequestInterface $request) { @@ -515,6 +559,8 @@ protected function sendCookie(RequestInterface $request) * Extracted for this to be unit tested. * * @codeCoverageIgnore + * + * @deprecated Set cookies to Response object instead. */ protected function doSendCookie(): void { diff --git a/system/Session/Handlers/DatabaseHandler.php b/system/Session/Handlers/DatabaseHandler.php index f0164d2d..dfaa4720 100644 --- a/system/Session/Handlers/DatabaseHandler.php +++ b/system/Session/Handlers/DatabaseHandler.php @@ -69,7 +69,6 @@ public function __construct(AppConfig $config, string $ipAddress) throw SessionException::forMissingDatabaseTable(); } - // @phpstan-ignore-next-line $this->DBGroup = $config->sessionDBGroup ?? config(Database::class)->defaultGroup; $this->db = Database::connect($this->DBGroup); diff --git a/system/Session/Handlers/RedisHandler.php b/system/Session/Handlers/RedisHandler.php index ce6e7bde..93a601ea 100644 --- a/system/Session/Handlers/RedisHandler.php +++ b/system/Session/Handlers/RedisHandler.php @@ -206,7 +206,6 @@ public function close(): bool try { $pingReply = $this->redis->ping(); - // @phpstan-ignore-next-line if (($pingReply === true) || ($pingReply === '+PONG')) { if (isset($this->lockKey)) { $this->redis->del($this->lockKey); diff --git a/system/Test/CIUnitTestCase.php b/system/Test/CIUnitTestCase.php index 50a28e13..e2c6eab6 100644 --- a/system/Test/CIUnitTestCase.php +++ b/system/Test/CIUnitTestCase.php @@ -231,7 +231,7 @@ protected function setUp(): void { parent::setUp(); - if (! $this->app) { // @phpstan-ignore-line + if (! $this->app) { $this->app = $this->createApplication(); } diff --git a/system/Test/Fabricator.php b/system/Test/Fabricator.php index 0fb013cb..d4369765 100644 --- a/system/Test/Fabricator.php +++ b/system/Test/Fabricator.php @@ -510,12 +510,12 @@ protected function createMock(?int $count = null) $fields = []; if (! empty($this->model->useTimestamps)) { - $fields[$this->model->createdField] = $datetime; // @phpstan-ignore-line - $fields[$this->model->updatedField] = $datetime; // @phpstan-ignore-line + $fields[$this->model->createdField] = $datetime; + $fields[$this->model->updatedField] = $datetime; } if (! empty($this->model->useSoftDeletes)) { - $fields[$this->model->deletedField] = null; // @phpstan-ignore-line + $fields[$this->model->deletedField] = null; } // Iterate over new entities and add the necessary fields diff --git a/system/Test/FeatureTestCase.php b/system/Test/FeatureTestCase.php index 87423271..d1a75edb 100644 --- a/system/Test/FeatureTestCase.php +++ b/system/Test/FeatureTestCase.php @@ -349,7 +349,7 @@ protected function populateGlobals(string $method, Request $request, ?array $par // otherwise set it from the URL. $get = ! empty($params) && $method === 'get' ? $params - : $this->getPrivateProperty($request->uri, 'query'); // @phpstan-ignore-line + : $this->getPrivateProperty($request->uri, 'query'); $request->setGlobal('get', $get); if ($method !== 'get') { diff --git a/system/Test/FeatureTestTrait.php b/system/Test/FeatureTestTrait.php index b44ff8c6..afb93376 100644 --- a/system/Test/FeatureTestTrait.php +++ b/system/Test/FeatureTestTrait.php @@ -344,7 +344,7 @@ protected function populateGlobals(string $method, Request $request, ?array $par // otherwise set it from the URL. $get = ! empty($params) && $method === 'get' ? $params - : $this->getPrivateProperty($request->uri, 'query'); // @phpstan-ignore-line + : $this->getPrivateProperty($request->uri, 'query'); $request->setGlobal('get', $get); if ($method !== 'get') { diff --git a/system/Test/Mock/MockConnection.php b/system/Test/Mock/MockConnection.php index 78bd405b..c9d03e76 100644 --- a/system/Test/Mock/MockConnection.php +++ b/system/Test/Mock/MockConnection.php @@ -166,7 +166,7 @@ public function error(): array */ public function insertID(): int { - return $this->connID->insert_id; // @phpstan-ignore-line + return $this->connID->insert_id; } /** diff --git a/system/Test/Mock/MockSecurity.php b/system/Test/Mock/MockSecurity.php index e24221c1..a078154b 100644 --- a/system/Test/Mock/MockSecurity.php +++ b/system/Test/Mock/MockSecurity.php @@ -19,4 +19,12 @@ protected function doSendCookie(): void { $_COOKIE['csrf_cookie_name'] = $this->hash; } + + protected function randomize(string $hash): string + { + $keyBinary = hex2bin('005513c290126d34d41bf41c5265e0f1'); + $hashBinary = hex2bin($hash); + + return bin2hex(($hashBinary ^ $keyBinary) . $keyBinary); + } } diff --git a/system/Test/bootstrap.php b/system/Test/bootstrap.php index f6ddb2ad..00a4341c 100644 --- a/system/Test/bootstrap.php +++ b/system/Test/bootstrap.php @@ -86,15 +86,6 @@ class_alias('Config\Services', 'CodeIgniter\Services'); // Now load Composer's if it's available if (is_file(COMPOSER_PATH)) { - /* - * The path to the vendor directory. - * - * We do not want to enforce this, so set the constant if Composer was used. - */ - if (! defined('VENDORPATH')) { - define('VENDORPATH', realpath(ROOTPATH . 'vendor') . DIRECTORY_SEPARATOR); - } - require_once COMPOSER_PATH; } diff --git a/system/ThirdParty/Escaper/LICENSE.md b/system/ThirdParty/Escaper/LICENSE.md new file mode 100644 index 00000000..10b40f14 --- /dev/null +++ b/system/ThirdParty/Escaper/LICENSE.md @@ -0,0 +1,26 @@ +Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. + +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 Laminas Foundation 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. diff --git a/system/ThirdParty/Kint/CallFinder.php b/system/ThirdParty/Kint/CallFinder.php index e7192a81..e77a6407 100644 --- a/system/ThirdParty/Kint/CallFinder.php +++ b/system/ThirdParty/Kint/CallFinder.php @@ -27,7 +27,7 @@ class CallFinder { - private static $ignore = array( + private static $ignore = [ T_CLOSE_TAG => true, T_COMMENT => true, T_DOC_COMMENT => true, @@ -35,7 +35,7 @@ class CallFinder T_OPEN_TAG => true, T_OPEN_TAG_WITH_ECHO => true, T_WHITESPACE => true, - ); + ]; /** * Things we need to do specially for operator tokens: @@ -43,17 +43,19 @@ class CallFinder * - Wrap the access path in parentheses if there * are any of these in the final short parameter. */ - private static $operator = array( + private static $operator = [ T_AND_EQUAL => true, T_BOOLEAN_AND => true, T_BOOLEAN_OR => true, T_ARRAY_CAST => true, T_BOOL_CAST => true, + T_CLASS => true, T_CLONE => true, T_CONCAT_EQUAL => true, T_DEC => true, T_DIV_EQUAL => true, T_DOUBLE_CAST => true, + T_FUNCTION => true, T_INC => true, T_INCLUDE => true, T_INCLUDE_ONCE => true, @@ -84,6 +86,9 @@ class CallFinder T_STRING_CAST => true, T_UNSET_CAST => true, T_XOR_EQUAL => true, + T_POW => true, + T_POW_EQUAL => true, + T_DOUBLE_ARROW => true, '!' => true, '%' => true, '&' => true, @@ -100,9 +105,9 @@ class CallFinder '^' => true, '|' => true, '~' => true, - ); + ]; - private static $strip = array( + private static $strip = [ '(' => true, ')' => true, '[' => true, @@ -112,39 +117,43 @@ class CallFinder T_OBJECT_OPERATOR => true, T_DOUBLE_COLON => true, T_NS_SEPARATOR => true, - ); + ]; + + private static $classcalls = [ + T_DOUBLE_COLON => true, + T_OBJECT_OPERATOR => true, + ]; + + private static $namespace = [ + T_STRING => true, + ]; public static function getFunctionCalls($source, $line, $function) { - static $up = array( + static $up = [ '(' => true, '[' => true, '{' => true, T_CURLY_OPEN => true, T_DOLLAR_OPEN_CURLY_BRACES => true, - ); - static $down = array( + ]; + static $down = [ ')' => true, ']' => true, '}' => true, - ); - static $modifiers = array( + ]; + static $modifiers = [ '!' => true, '@' => true, '~' => true, '+' => true, '-' => true, - ); - static $identifier = array( + ]; + static $identifier = [ T_DOUBLE_COLON => true, T_STRING => true, T_NS_SEPARATOR => true, - ); - - if (KINT_PHP56) { - self::$operator[T_POW] = true; - self::$operator[T_POW_EQUAL] = true; - } + ]; if (KINT_PHP70) { self::$operator[T_SPACESHIP] = true; @@ -154,11 +163,24 @@ public static function getFunctionCalls($source, $line, $function) self::$operator[T_COALESCE_EQUAL] = true; } + if (KINT_PHP80) { + $up[T_ATTRIBUTE] = true; + self::$operator[T_MATCH] = true; + self::$strip[T_NULLSAFE_OBJECT_OPERATOR] = true; + self::$classcalls[T_NULLSAFE_OBJECT_OPERATOR] = true; + self::$namespace[T_NAME_FULLY_QUALIFIED] = true; + self::$namespace[T_NAME_QUALIFIED] = true; + self::$namespace[T_NAME_RELATIVE] = true; + $identifier[T_NAME_FULLY_QUALIFIED] = true; + $identifier[T_NAME_QUALIFIED] = true; + $identifier[T_NAME_RELATIVE] = true; + } + $tokens = \token_get_all($source); $cursor = 1; - $function_calls = array(); - /** @var array Performance optimization preventing backwards loops */ - $prev_tokens = array(null, null, null); + $function_calls = []; + // Performance optimization preventing backwards loops + $prev_tokens = [null, null, null]; if (\is_array($function)) { $class = \explode('\\', $function[0]); @@ -188,10 +210,16 @@ public static function getFunctionCalls($source, $line, $function) continue; } - $prev_tokens = array($prev_tokens[1], $prev_tokens[2], $token); + $prev_tokens = [$prev_tokens[1], $prev_tokens[2], $token]; // Check if it's the right type to be the function we're looking for - if (T_STRING !== $token[0] || \strtolower($token[1]) !== $function) { + if (!isset(self::$namespace[$token[0]])) { + continue; + } + + $ns = \explode('\\', \strtolower($token[1])); + + if (\end($ns) !== $function) { continue; } @@ -203,7 +231,7 @@ public static function getFunctionCalls($source, $line, $function) // Check if it matches the signature if (null === $class) { - if ($prev_tokens[1] && \in_array($prev_tokens[1][0], array(T_DOUBLE_COLON, T_OBJECT_OPERATOR), true)) { + if ($prev_tokens[1] && isset(self::$classcalls[$prev_tokens[1][0]])) { continue; } } else { @@ -211,7 +239,15 @@ public static function getFunctionCalls($source, $line, $function) continue; } - if (!$prev_tokens[0] || T_STRING !== $prev_tokens[0][0] || \strtolower($prev_tokens[0][1]) !== $class) { + if (!$prev_tokens[0] || !isset(self::$namespace[$prev_tokens[0][0]])) { + continue; + } + + /** @var array{int, string, int} $prev_tokens[0] */ + // All self::$namespace tokens are T_ constants + $ns = \explode('\\', \strtolower($prev_tokens[0][1])); + + if (\end($ns) !== $class) { continue; } } @@ -222,8 +258,8 @@ public static function getFunctionCalls($source, $line, $function) $instring = false; // Whether we're in a string or not $realtokens = false; // Whether the current scope contains anything meaningful or not $paramrealtokens = false; // Whether the current parameter contains anything meaningful - $params = array(); // All our collected parameters - $shortparam = array(); // The short version of the parameter + $params = []; // All our collected parameters + $shortparam = []; // The short version of the parameter $param_start = $offset; // The distance to the start of the parameter // Loop through the following tokens until the function call ends @@ -276,11 +312,11 @@ public static function getFunctionCalls($source, $line, $function) $shortparam[] = '"'; } elseif (1 === $depth) { if (',' === $token[0]) { - $params[] = array( + $params[] = [ 'full' => \array_slice($tokens, $param_start, $offset - $param_start), 'short' => $shortparam, - ); - $shortparam = array(); + ]; + $shortparam = []; $paramrealtokens = false; $param_start = $offset + 1; } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0] && \strlen($token[1]) > 2) { @@ -293,10 +329,10 @@ public static function getFunctionCalls($source, $line, $function) // Depth has dropped to 0 (So we've hit the closing paren) if ($depth <= 0) { if ($paramrealtokens) { - $params[] = array( + $params[] = [ 'full' => \array_slice($tokens, $param_start, $offset - $param_start), 'short' => $shortparam, - ); + ]; } break; @@ -322,11 +358,11 @@ public static function getFunctionCalls($source, $line, $function) } } - $param = array( + $param = [ 'name' => self::tokensToString($name), 'path' => self::tokensToString(self::tokensTrim($param['full'])), 'expression' => $expression, - ); + ]; } // Get the modifiers @@ -340,7 +376,7 @@ public static function getFunctionCalls($source, $line, $function) --$index; } - $mods = array(); + $mods = []; while (isset($tokens[$index])) { if (isset(self::$ignore[$tokens[$index][0]])) { @@ -357,10 +393,10 @@ public static function getFunctionCalls($source, $line, $function) break; } - $function_calls[] = array( + $function_calls[] = [ 'parameters' => $params, 'modifiers' => $mods, - ); + ]; } return $function_calls; @@ -436,10 +472,11 @@ private static function tokensTrim(array $tokens) private static function tokensFormatted(array $tokens) { $space = false; + $attribute = false; $tokens = self::tokensTrim($tokens); - $output = array(); + $output = []; $last = null; foreach ($tokens as $index => $token) { @@ -450,7 +487,10 @@ private static function tokensFormatted(array $tokens) $next = $tokens[self::realTokenIndex($tokens, $index)]; - if (isset(self::$strip[$last[0]]) && !self::tokenIsOperator($next)) { + /** @var array|string $last */ + if ($attribute && ']' === $last[0]) { + $attribute = false; + } elseif (isset(self::$strip[$last[0]]) && !self::tokenIsOperator($next)) { continue; } @@ -461,6 +501,10 @@ private static function tokensFormatted(array $tokens) $token = ' '; $space = true; } else { + if (KINT_PHP80 && $last && T_ATTRIBUTE == $last[0]) { + $attribute = true; + } + $space = false; $last = $token; } diff --git a/system/ThirdParty/Kint/Kint.php b/system/ThirdParty/Kint/Kint.php index e0ce9633..f11ed498 100644 --- a/system/ThirdParty/Kint/Kint.php +++ b/system/ThirdParty/Kint/Kint.php @@ -26,11 +26,11 @@ namespace Kint; use InvalidArgumentException; -use Kint\Object\BasicObject; use Kint\Parser\Parser; use Kint\Parser\Plugin; use Kint\Renderer\Renderer; use Kint\Renderer\TextRenderer; +use Kint\Zval\Value; class Kint { @@ -102,12 +102,12 @@ class Kint * * Defaults to [$_SERVER['DOCUMENT_ROOT'] => ''] */ - public static $app_root_dirs = array(); + public static $app_root_dirs = []; /** - * @var int max array/object levels to go deep, if zero no limits are applied + * @var int depth limit for array/object traversal. 0 for no limit */ - public static $max_depth = 6; + public static $depth_limit = 7; /** * @var bool expand all trees by default for rich view @@ -124,23 +124,24 @@ class Kint /** * @var array Kint aliases. Add debug functions in Kint wrappers here to fix modifiers and backtraces */ - public static $aliases = array( - array('Kint\\Kint', 'dump'), - array('Kint\\Kint', 'trace'), - array('Kint\\Kint', 'dumpArray'), - ); + public static $aliases = [ + ['Kint\\Kint', 'dump'], + ['Kint\\Kint', 'trace'], + ['Kint\\Kint', 'dumpArray'], + ]; /** * @var array Array of modes to renderer class names */ - public static $renderers = array( + public static $renderers = [ self::MODE_RICH => 'Kint\\Renderer\\RichRenderer', self::MODE_PLAIN => 'Kint\\Renderer\\PlainRenderer', self::MODE_TEXT => 'Kint\\Renderer\\TextRenderer', self::MODE_CLI => 'Kint\\Renderer\\CliRenderer', - ); + ]; - public static $plugins = array( + public static $plugins = [ + 'Kint\\Parser\\ArrayLimitPlugin', 'Kint\\Parser\\ArrayObjectPlugin', 'Kint\\Parser\\Base64Plugin', 'Kint\\Parser\\BlacklistPlugin', @@ -162,9 +163,9 @@ class Kint 'Kint\\Parser\\TimestampPlugin', 'Kint\\Parser\\TracePlugin', 'Kint\\Parser\\XmlPlugin', - ); + ]; - protected static $plugin_pool = array(); + protected static $plugin_pool = []; protected $parser; protected $renderer; @@ -199,24 +200,25 @@ public function setStatesFromStatics(array $statics) { $this->renderer->setStatics($statics); - $this->parser->setDepthLimit(isset($statics['max_depth']) ? $statics['max_depth'] : false); + $this->parser->setDepthLimit(isset($statics['depth_limit']) ? $statics['depth_limit'] : 0); $this->parser->clearPlugins(); if (!isset($statics['plugins'])) { return; } - $plugins = array(); + $plugins = []; foreach ($statics['plugins'] as $plugin) { if ($plugin instanceof Plugin) { $plugins[] = $plugin; - } elseif (\is_string($plugin) && \is_subclass_of($plugin, 'Kint\\Parser\\Plugin')) { - if (!isset(self::$plugin_pool[$plugin])) { + } elseif (\is_string($plugin) && \is_subclass_of($plugin, Plugin::class)) { + if (!isset(static::$plugin_pool[$plugin])) { + /** @psalm-suppress UnsafeInstantiation */ $p = new $plugin(); - self::$plugin_pool[$plugin] = $p; + static::$plugin_pool[$plugin] = $p; } - $plugins[] = self::$plugin_pool[$plugin]; + $plugins[] = static::$plugin_pool[$plugin]; } } @@ -232,7 +234,7 @@ public function setStatesFromCallInfo(array $info) $this->renderer->setCallInfo($info); if (isset($info['modifiers']) && \is_array($info['modifiers']) && \in_array('+', $info['modifiers'], true)) { - $this->parser->setDepthLimit(false); + $this->parser->setDepthLimit(0); } $this->parser->setCallerClass(isset($info['caller']['class']) ? $info['caller']['class'] : null); @@ -241,8 +243,8 @@ public function setStatesFromCallInfo(array $info) /** * Renders a list of vars including the pre and post renders. * - * @param array $vars Data to dump - * @param BasicObject[] $base Base objects + * @param array $vars Data to dump + * @param array $base Base Zval\Value objects * * @return string */ @@ -254,13 +256,13 @@ public function dumpAll(array $vars, array $base) $output = $this->renderer->preRender(); - if ($vars === array()) { + if ([] === $vars) { $output .= $this->renderer->renderNothing(); } foreach ($vars as $key => $arg) { - if (!$base[$key] instanceof BasicObject) { - throw new InvalidArgumentException('Kint::dumpAll requires all elements of the second argument to be BasicObject instances'); + if (!$base[$key] instanceof Value) { + throw new InvalidArgumentException('Kint::dumpAll requires all elements of the second argument to be Value instances'); } $output .= $this->dumpVar($arg, $base[$key]); } @@ -273,12 +275,12 @@ public function dumpAll(array $vars, array $base) /** * Dumps and renders a var. * - * @param mixed $var Data to dump - * @param BasicObject $base Base object + * @param mixed $var Data to dump + * @param Value $base Base object * * @return string */ - public function dumpVar(&$var, BasicObject $base) + public function dumpVar(&$var, Value $base) { return $this->renderer->render( $this->parser->parse($var, $base) @@ -292,21 +294,21 @@ public function dumpVar(&$var, BasicObject $base) */ public static function getStatics() { - return array( - 'aliases' => self::$aliases, - 'app_root_dirs' => self::$app_root_dirs, - 'cli_detection' => self::$cli_detection, - 'display_called_from' => self::$display_called_from, - 'enabled_mode' => self::$enabled_mode, - 'expanded' => self::$expanded, - 'file_link_format' => self::$file_link_format, - 'max_depth' => self::$max_depth, - 'mode_default' => self::$mode_default, - 'mode_default_cli' => self::$mode_default_cli, - 'plugins' => self::$plugins, - 'renderers' => self::$renderers, - 'return' => self::$return, - ); + return [ + 'aliases' => static::$aliases, + 'app_root_dirs' => static::$app_root_dirs, + 'cli_detection' => static::$cli_detection, + 'depth_limit' => static::$depth_limit, + 'display_called_from' => static::$display_called_from, + 'enabled_mode' => static::$enabled_mode, + 'expanded' => static::$expanded, + 'file_link_format' => static::$file_link_format, + 'mode_default' => static::$mode_default, + 'mode_default_cli' => static::$mode_default_cli, + 'plugins' => static::$plugins, + 'renderers' => static::$renderers, + 'return' => static::$return, + ]; } /** @@ -325,7 +327,7 @@ public static function createFromStatics(array $statics) if (isset($statics['enabled_mode'])) { $mode = $statics['enabled_mode']; - if (true === $statics['enabled_mode'] && isset($statics['mode_default'])) { + if (true === $mode && isset($statics['mode_default'])) { $mode = $statics['mode_default']; if (PHP_SAPI === 'cli' && !empty($statics['cli_detection']) && isset($statics['mode_default_cli'])) { @@ -334,7 +336,7 @@ public static function createFromStatics(array $statics) } } - if (!$mode) { + if (false === $mode) { return null; } @@ -345,7 +347,8 @@ public static function createFromStatics(array $statics) $renderer = new $statics['renderers'][$mode](); } - return new self(new Parser(), $renderer); + /** @psalm-suppress UnsafeInstantiation */ + return new static(new Parser(), $renderer); } /** @@ -354,11 +357,11 @@ public static function createFromStatics(array $statics) * @param array $params Parameters as returned from getCallInfo * @param int $argc Number of arguments the helper was called with * - * @return BasicObject[] Base objects for the arguments + * @return Value[] Base objects for the arguments */ public static function getBasesFromParamInfo(array $params, $argc) { - static $blacklist = array( + static $blacklist = [ 'null', 'true', 'false', @@ -372,10 +375,10 @@ public static function getBasesFromParamInfo(array $params, $argc) 'b"..."', "'...'", "b'...'", - ); + ]; $params = \array_values($params); - $bases = array(); + $bases = []; for ($i = 0; $i < $argc; ++$i) { if (isset($params[$i])) { @@ -402,7 +405,7 @@ public static function getBasesFromParamInfo(array $params, $argc) $access_path = '$'.$i; } - $bases[] = BasicObject::blank($name, $access_path); + $bases[] = Value::blank($name, $access_path); } return $bases; @@ -424,23 +427,21 @@ public static function getCallInfo(array $aliases, array $trace, $argc) $found = false; $callee = null; $caller = null; - $miniTrace = array(); + $miniTrace = []; foreach ($trace as $index => $frame) { if (Utils::traceFrameIsListed($frame, $aliases)) { $found = true; - $miniTrace = array(); + $miniTrace = []; } - if (!Utils::traceFrameIsListed($frame, array('spl_autoload_call'))) { + if (!Utils::traceFrameIsListed($frame, ['spl_autoload_call'])) { $miniTrace[] = $frame; } } if ($found) { $callee = \reset($miniTrace) ?: null; - - /** @var null|array Psalm bug workaround */ $caller = \next($miniTrace) ?: null; } @@ -455,15 +456,15 @@ public static function getCallInfo(array $aliases, array $trace, $argc) $miniTrace = \array_values($miniTrace); - $call = self::getSingleCall($callee ?: array(), $argc); + $call = static::getSingleCall($callee ?: [], $argc); - $ret = array( + $ret = [ 'params' => null, - 'modifiers' => array(), + 'modifiers' => [], 'callee' => $callee, 'caller' => $caller, 'trace' => $miniTrace, - ); + ]; if ($call) { $ret['params'] = $call['parameters']; @@ -482,23 +483,21 @@ public static function getCallInfo(array $aliases, array $trace, $argc) */ public static function trace() { - if (!self::$enabled_mode) { + if (false === static::$enabled_mode) { return 0; } - Utils::normalizeAliases(self::$aliases); - - $args = \func_get_args(); + Utils::normalizeAliases(static::$aliases); - $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + $call_info = static::getCallInfo(static::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \func_num_args()); - $statics = self::getStatics(); + $statics = static::getStatics(); if (\in_array('~', $call_info['modifiers'], true)) { - $statics['enabled_mode'] = self::MODE_TEXT; + $statics['enabled_mode'] = static::MODE_TEXT; } - $kintstance = self::createFromStatics($statics); + $kintstance = static::createFromStatics($statics); if (!$kintstance) { // Should never happen return 0; // @codeCoverageIgnore @@ -513,23 +512,25 @@ public static function trace() $kintstance->setStatesFromStatics($statics); $kintstance->setStatesFromCallInfo($call_info); - $trimmed_trace = array(); - $trace = \debug_backtrace(true); + $trimmed_trace = []; + $trace = \debug_backtrace(); foreach ($trace as $frame) { - if (Utils::traceFrameIsListed($frame, self::$aliases)) { - $trimmed_trace = array(); + if (Utils::traceFrameIsListed($frame, static::$aliases)) { + $trimmed_trace = []; } $trimmed_trace[] = $frame; } + \array_shift($trimmed_trace); + $output = $kintstance->dumpAll( - array($trimmed_trace), - array(BasicObject::blank('Kint\\Kint::trace()', 'debug_backtrace(true)')) + [$trimmed_trace], + [Value::blank('Kint\\Kint::trace()', 'debug_backtrace()')] ); - if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + if (static::$return || \in_array('@', $call_info['modifiers'], true)) { return $output; } @@ -545,29 +546,29 @@ public static function trace() /** * Dumps some data. * - * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace(true)) + * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace()) * * @return int|string */ public static function dump() { - if (!self::$enabled_mode) { + if (false === static::$enabled_mode) { return 0; } - Utils::normalizeAliases(self::$aliases); + Utils::normalizeAliases(static::$aliases); $args = \func_get_args(); - $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + $call_info = static::getCallInfo(static::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); - $statics = self::getStatics(); + $statics = static::getStatics(); if (\in_array('~', $call_info['modifiers'], true)) { - $statics['enabled_mode'] = self::MODE_TEXT; + $statics['enabled_mode'] = static::MODE_TEXT; } - $kintstance = self::createFromStatics($statics); + $kintstance = static::createFromStatics($statics); if (!$kintstance) { // Should never happen return 0; // @codeCoverageIgnore @@ -582,40 +583,13 @@ public static function dump() $kintstance->setStatesFromStatics($statics); $kintstance->setStatesFromCallInfo($call_info); - // If the call is Kint::dump(1) then dump a backtrace instead - if ($args === array(1) && (!isset($call_info['params'][0]['name']) || '1' === $call_info['params'][0]['name'])) { - $args = \debug_backtrace(true); - $trace = array(); - - foreach ($args as $index => $frame) { - if (Utils::traceFrameIsListed($frame, self::$aliases)) { - $trace = array(); - } - - $trace[] = $frame; - } - - if (isset($call_info['callee']['function'])) { - $tracename = $call_info['callee']['function'].'(1)'; - if (isset($call_info['callee']['class'], $call_info['callee']['type'])) { - $tracename = $call_info['callee']['class'].$call_info['callee']['type'].$tracename; - } - } else { - $tracename = 'Kint\\Kint::dump(1)'; - } - - $tracebase = BasicObject::blank($tracename, 'debug_backtrace(true)'); - - $output = $kintstance->dumpAll(array($trace), array($tracebase)); - } else { - $bases = self::getBasesFromParamInfo( - isset($call_info['params']) ? $call_info['params'] : array(), - \count($args) - ); - $output = $kintstance->dumpAll($args, $bases); - } + $bases = static::getBasesFromParamInfo( + isset($call_info['params']) ? $call_info['params'] : [], + \count($args) + ); + $output = $kintstance->dumpAll($args, $bases); - if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + if (static::$return || \in_array('@', $call_info['modifiers'], true)) { return $output; } @@ -643,7 +617,7 @@ public static function shortenPath($file) $longest_match = 0; $match = '/'; - foreach (self::$app_root_dirs as $path => $alias) { + foreach (static::$app_root_dirs as $path => $alias) { if (empty($path)) { continue; } @@ -657,7 +631,7 @@ public static function shortenPath($file) } if ($longest_match) { - $file = \array_merge(array($match), \array_slice($file, $longest_match)); + $file = \array_merge([$match], \array_slice($file, $longest_match)); return \implode('/', $file); } @@ -676,7 +650,7 @@ public static function shortenPath($file) public static function getIdeLink($file, $line) { - return \str_replace(array('%f', '%l'), array($file, $line), self::$file_link_format); + return \str_replace(['%f', '%l'], [$file, $line], static::$file_link_format); } /** @@ -696,7 +670,7 @@ protected static function getSingleCall(array $frame, $argc) if (empty($frame['class'])) { $callfunc = $frame['function']; } else { - $callfunc = array($frame['class'], $frame['function']); + $callfunc = [$frame['class'], $frame['function']]; } $calls = CallFinder::getFunctionCalls( @@ -711,32 +685,30 @@ protected static function getSingleCall(array $frame, $argc) $is_unpack = false; // Handle argument unpacking as a last resort - if (KINT_PHP56) { - foreach ($call['parameters'] as $i => &$param) { - if (0 === \strpos($param['name'], '...')) { - if ($i < $argc && $i === \count($call['parameters']) - 1) { - for ($j = 1; $j + $i < $argc; ++$j) { - $call['parameters'][] = array( - 'name' => 'array_values('.\substr($param['name'], 3).')['.$j.']', - 'path' => 'array_values('.\substr($param['path'], 3).')['.$j.']', - 'expression' => false, - ); - } - - $param['name'] = 'reset('.\substr($param['name'], 3).')'; - $param['path'] = 'reset('.\substr($param['path'], 3).')'; - $param['expression'] = false; - } else { - $call['parameters'] = \array_slice($call['parameters'], 0, $i); + foreach ($call['parameters'] as $i => &$param) { + if (0 === \strpos($param['name'], '...')) { + if ($i < $argc && $i === \count($call['parameters']) - 1) { + for ($j = 1; $j + $i < $argc; ++$j) { + $call['parameters'][] = [ + 'name' => 'array_values('.\substr($param['name'], 3).')['.$j.']', + 'path' => 'array_values('.\substr($param['path'], 3).')['.$j.']', + 'expression' => false, + ]; } - $is_unpack = true; - break; + $param['name'] = 'reset('.\substr($param['name'], 3).')'; + $param['path'] = 'reset('.\substr($param['path'], 3).')'; + $param['expression'] = false; + } else { + $call['parameters'] = \array_slice($call['parameters'], 0, $i); } - if ($i >= $argc) { - continue 2; - } + $is_unpack = true; + break; + } + + if ($i >= $argc) { + continue 2; } } diff --git a/system/ThirdParty/Kint/LICENSE b/system/ThirdParty/Kint/LICENSE new file mode 100644 index 00000000..01718d49 --- /dev/null +++ b/system/ThirdParty/Kint/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Jonathan Vollebregt (jnvsor@gmail.com), Rokas Šleinius (raveren@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php new file mode 100644 index 00000000..4fa94c63 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ArrayLimitPlugin.php @@ -0,0 +1,142 @@ += self::$trigger) { + throw new InvalidArgumentException('ArrayLimitPlugin::$limit can not be lower than ArrayLimitPlugin::$trigger'); + } + + $depth = $this->parser->getDepthLimit(); + + if (!$depth) { + return; + } + + if ($o->depth >= $depth - 1) { + return; + } + + if (\count($var) < self::$trigger) { + return; + } + + if (self::$numeric_only && Utils::isAssoc($var)) { + return; + } + + $base = clone $o; + $base->depth = $depth - 1; + $obj = $this->parser->parse($var, $base); + + if (!$obj instanceof Value || 'array' != $obj->type) { + return; // @codeCoverageIgnore + } + + $obj->depth = $o->depth; + $i = 0; + + foreach ($obj->value->contents as $child) { + // We only bother setting the correct depth for the first child, + // any deeper children should be cancelled by the depth limit + $child->depth = $o->depth + 1; + $this->recalcDepthLimit($child); + } + + $var2 = \array_slice($var, 0, self::$limit, true); + $base = clone $o; + $slice = $this->parser->parse($var2, $base); + + \array_splice($obj->value->contents, 0, self::$limit, $slice->value->contents); + + $o = $obj; + + $this->parser->haltParse(); + } + + protected function recalcDepthLimit(Value $o) + { + $hintkey = \array_search('depth_limit', $o->hints, true); + if (false !== $hintkey) { + $o->hints[$hintkey] = 'array_limit'; + } + + $reps = $o->getRepresentations(); + if ($o->value) { + $reps[] = $o->value; + } + + foreach ($reps as $rep) { + if ($rep->contents instanceof Value) { + $this->recalcDepthLimit($rep->contents); + } elseif (\is_array($rep->contents)) { + foreach ($rep->contents as $child) { + if ($child instanceof Value) { + $this->recalcDepthLimit($child); + } + } + } + } + } +} diff --git a/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php index 286d255b..f32b4fad 100644 --- a/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php +++ b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php @@ -26,13 +26,13 @@ namespace Kint\Parser; use ArrayObject; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class ArrayObjectPlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_BEGIN; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof ArrayObject) { return; diff --git a/system/ThirdParty/Kint/Parser/Base64Plugin.php b/system/ThirdParty/Kint/Parser/Base64Plugin.php index 3d7d6bc2..5208d7dd 100644 --- a/system/ThirdParty/Kint/Parser/Base64Plugin.php +++ b/system/ThirdParty/Kint/Parser/Base64Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class Base64Plugin extends Plugin { @@ -46,7 +46,7 @@ class Base64Plugin extends Plugin public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -54,7 +54,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) < self::$min_length_hard || \strlen($var) % 4) { return; @@ -68,14 +68,13 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - /** @var false|string */ $data = \base64_decode($var, true); if (false === $data) { return; } - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = 'base64_decode('.$o->name.')'; diff --git a/system/ThirdParty/Kint/Parser/BinaryPlugin.php b/system/ThirdParty/Kint/Parser/BinaryPlugin.php index 327c297c..9a6b117b 100644 --- a/system/ThirdParty/Kint/Parser/BinaryPlugin.php +++ b/system/ThirdParty/Kint/Parser/BinaryPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; +use Kint\Zval\Value; class BinaryPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,9 +40,9 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof BlobObject || !\in_array($o->encoding, array('ASCII', 'UTF-8'), true)) { + if (!$o instanceof BlobValue || !\in_array($o->encoding, ['ASCII', 'UTF-8'], true)) { $o->value->hints[] = 'binary'; } } diff --git a/system/ThirdParty/Kint/Parser/BlacklistPlugin.php b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php index b37e45ff..9c472d43 100644 --- a/system/ThirdParty/Kint/Parser/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; class BlacklistPlugin extends Plugin { @@ -35,32 +35,18 @@ class BlacklistPlugin extends Plugin * * @var array */ - public static $blacklist = array(); + public static $blacklist = []; /** * List of classes and interfaces to blacklist except when dumped directly. * * @var array */ - public static $shallow_blacklist = array(); - - /** - * Maximum size of arrays before blacklisting. - * - * @var int - */ - public static $array_limit = 10000; - - /** - * Maximum size of arrays before blacklisting except when dumped directly. - * - * @var int - */ - public static $shallow_array_limit = 1000; + public static $shallow_blacklist = ['Psr\\Container\\ContainerInterface']; public function getTypes() { - return array('object', 'array'); + return ['object']; } public function getTriggers() @@ -68,21 +54,11 @@ public function getTriggers() return Parser::TRIGGER_BEGIN; } - public function parse(&$var, BasicObject &$o, $trigger) - { - if (\is_object($var)) { - return $this->parseObject($var, $o); - } - if (\is_array($var)) { - return $this->parseArray($var, $o); - } - } - - protected function parseObject(&$var, BasicObject &$o) + public function parse(&$var, Value &$o, $trigger) { foreach (self::$blacklist as $class) { if ($var instanceof $class) { - return $this->blacklistObject($var, $o); + return $this->blacklistValue($var, $o); } } @@ -92,17 +68,17 @@ protected function parseObject(&$var, BasicObject &$o) foreach (self::$shallow_blacklist as $class) { if ($var instanceof $class) { - return $this->blacklistObject($var, $o); + return $this->blacklistValue($var, $o); } } } - protected function blacklistObject(&$var, BasicObject &$o) + protected function blacklistValue(&$var, Value &$o) { - $object = new InstanceObject(); + $object = new InstanceValue(); $object->transplant($o); $object->classname = \get_class($var); - $object->hash = \spl_object_hash($var); + $object->spl_object_hash = \spl_object_hash($var); $object->clearRepresentations(); $object->value = null; $object->size = null; @@ -112,32 +88,4 @@ protected function blacklistObject(&$var, BasicObject &$o) $this->parser->haltParse(); } - - protected function parseArray(array &$var, BasicObject &$o) - { - if (\count($var) > self::$array_limit) { - return $this->blacklistArray($var, $o); - } - - if ($o->depth <= 0) { - return; - } - - if (\count($var) > self::$shallow_array_limit) { - return $this->blacklistArray($var, $o); - } - } - - protected function blacklistArray(array &$var, BasicObject &$o) - { - $object = new BasicObject(); - $object->transplant($o); - $object->value = null; - $object->size = \count($var); - $object->hints[] = 'blacklist'; - - $o = $object; - - $this->parser->haltParse(); - } } diff --git a/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php index e4c23716..152e59d9 100644 --- a/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php +++ b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php @@ -25,19 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\MethodObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\InstanceValue; +use Kint\Zval\MethodValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; class ClassMethodsPlugin extends Plugin { - private static $cache = array(); + private static $cache = []; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -45,21 +45,21 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $class = \get_class($var); // assuming class definition will not change inside one request if (!isset(self::$cache[$class])) { - $methods = array(); + $methods = []; $reflection = new ReflectionClass($class); foreach ($reflection->getMethods() as $method) { - $methods[] = new MethodObject($method); + $methods[] = new MethodValue($method); } - \usort($methods, array('Kint\\Parser\\ClassMethodsPlugin', 'sort')); + \usort($methods, ['Kint\\Parser\\ClassMethodsPlugin', 'sort']); self::$cache[$class] = $methods; } @@ -91,19 +91,19 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - private static function sort(MethodObject $a, MethodObject $b) + private static function sort(MethodValue $a, MethodValue $b) { $sort = ((int) $a->static) - ((int) $b->static); if ($sort) { return $sort; } - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - $sort = InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + $sort = InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); if ($sort) { return $sort; } diff --git a/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php index 0ba58ca2..89601af2 100644 --- a/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php +++ b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php @@ -25,19 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; use ReflectionProperty; class ClassStaticsPlugin extends Plugin { - private static $cache = array(); + private static $cache = []; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -45,7 +45,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $class = \get_class($var); $reflection = new ReflectionClass($class); @@ -53,14 +53,14 @@ public function parse(&$var, BasicObject &$o, $trigger) // Constants // TODO: PHP 7.1 allows private consts but reflection doesn't have a way to check them yet if (!isset(self::$cache[$class])) { - $consts = array(); + $consts = []; foreach ($reflection->getConstants() as $name => $val) { - $const = BasicObject::blank($name, '\\'.$class.'::'.$name); + $const = Value::blank($name, '\\'.$class.'::'.$name); $const->const = true; $const->depth = $o->depth + 1; $const->owner_class = $class; - $const->operator = BasicObject::OPERATOR_STATIC; + $const->operator = Value::OPERATOR_STATIC; $const = $this->parser->parse($val, $const); $consts[] = $const; @@ -73,18 +73,18 @@ public function parse(&$var, BasicObject &$o, $trigger) $statics->contents = self::$cache[$class]; foreach ($reflection->getProperties(ReflectionProperty::IS_STATIC) as $static) { - $prop = new BasicObject(); + $prop = new Value(); $prop->name = '$'.$static->getName(); $prop->depth = $o->depth + 1; $prop->static = true; - $prop->operator = BasicObject::OPERATOR_STATIC; + $prop->operator = Value::OPERATOR_STATIC; $prop->owner_class = $static->getDeclaringClass()->name; - $prop->access = BasicObject::ACCESS_PUBLIC; + $prop->access = Value::ACCESS_PUBLIC; if ($static->isProtected()) { - $prop->access = BasicObject::ACCESS_PROTECTED; + $prop->access = Value::ACCESS_PROTECTED; } elseif ($static->isPrivate()) { - $prop->access = BasicObject::ACCESS_PRIVATE; + $prop->access = Value::ACCESS_PRIVATE; } if ($this->parser->childHasPath($o, $prop)) { @@ -92,31 +92,37 @@ public function parse(&$var, BasicObject &$o, $trigger) } $static->setAccessible(true); - $static = $static->getValue(); - $statics->contents[] = $this->parser->parse($static, $prop); + + if (KINT_PHP74 && !$static->isInitialized()) { + $prop->type = 'uninitialized'; + $statics->contents[] = $prop; + } else { + $static = $static->getValue(); + $statics->contents[] = $this->parser->parse($static, $prop); + } } if (empty($statics->contents)) { return; } - \usort($statics->contents, array('Kint\\Parser\\ClassStaticsPlugin', 'sort')); + \usort($statics->contents, ['Kint\\Parser\\ClassStaticsPlugin', 'sort']); $o->addRepresentation($statics); } - private static function sort(BasicObject $a, BasicObject $b) + private static function sort(Value $a, Value $b) { $sort = ((int) $a->const) - ((int) $b->const); if ($sort) { return $sort; } - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + return InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); } } diff --git a/system/ThirdParty/Kint/Parser/ClosurePlugin.php b/system/ThirdParty/Kint/Parser/ClosurePlugin.php index 73e367b2..f4a68f5d 100644 --- a/system/ThirdParty/Kint/Parser/ClosurePlugin.php +++ b/system/ThirdParty/Kint/Parser/ClosurePlugin.php @@ -26,17 +26,17 @@ namespace Kint\Parser; use Closure; -use Kint\Object\BasicObject; -use Kint\Object\ClosureObject; -use Kint\Object\ParameterObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\ClosureValue; +use Kint\Zval\ParameterValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionFunction; class ClosurePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -44,13 +44,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Closure) { return; } - $object = new ClosureObject(); + $object = new ClosureValue(); $object->transplant($o); $o = $object; $object->removeRepresentation('properties'); @@ -61,24 +61,24 @@ public function parse(&$var, BasicObject &$o, $trigger) $o->startline = $closure->getStartLine(); foreach ($closure->getParameters() as $param) { - $o->parameters[] = new ParameterObject($param); + $o->parameters[] = new ParameterValue($param); } $p = new Representation('Parameters'); $p->contents = &$o->parameters; $o->addRepresentation($p, 0); - $statics = array(); + $statics = []; - if (\method_exists($closure, 'getClosureThis') && $v = $closure->getClosureThis()) { - $statics = array('this' => $v); + if ($v = $closure->getClosureThis()) { + $statics = ['this' => $v]; } if (\count($statics = $statics + $closure->getStaticVariables())) { - $statics_parsed = array(); + $statics_parsed = []; foreach ($statics as $name => &$static) { - $obj = BasicObject::blank('$'.$name); + $obj = Value::blank('$'.$name); $obj->depth = $o->depth + 1; $statics_parsed[$name] = $this->parser->parse($static, $obj); if (null === $statics_parsed[$name]->value) { diff --git a/system/ThirdParty/Kint/Parser/ColorPlugin.php b/system/ThirdParty/Kint/Parser/ColorPlugin.php index 0d748f2c..a00b338c 100644 --- a/system/ThirdParty/Kint/Parser/ColorPlugin.php +++ b/system/ThirdParty/Kint/Parser/ColorPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\ColorRepresentation; +use Kint\Zval\Representation\ColorRepresentation; +use Kint\Zval\Value; class ColorPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) > 32) { return; diff --git a/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php index ec08d311..53329820 100644 --- a/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php +++ b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php @@ -28,9 +28,10 @@ use DOMNamedNodeMap; use DOMNode; use DOMNodeList; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; /** * The DOMDocument parser plugin is particularly useful as it is both the only @@ -63,14 +64,14 @@ class DOMDocumentPlugin extends Plugin * * @var array */ - public static $blacklist = array( + public static $blacklist = [ 'parentNode' => 'DOMNode', 'firstChild' => 'DOMNode', 'lastChild' => 'DOMNode', 'previousSibling' => 'DOMNode', 'nextSibling' => 'DOMNode', 'ownerDocument' => 'DOMDocument', - ); + ]; /** * Show all properties and methods. @@ -81,7 +82,7 @@ class DOMDocumentPlugin extends Plugin public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -89,9 +90,9 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof InstanceObject) { + if (!$o instanceof InstanceValue) { return; } @@ -104,10 +105,10 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - protected function parseList(&$var, InstanceObject &$o, $trigger) + protected function parseList(&$var, InstanceValue &$o, $trigger) { // Recursion should never happen, should always be stopped at the parent - // DOMNode. Depth limit on the other hand we're going to skip since + // DOMNode. Depth limit on the other hand we're going to skip since // that would show an empty iterator and rather useless. Let the depth // limit hit the children (DOMNodeList only has DOMNode as children) if ($trigger & Parser::TRIGGER_RECURSION) { @@ -125,36 +126,42 @@ protected function parseList(&$var, InstanceObject &$o, $trigger) // Depth limit // Make empty iterator representation since we need it in DOMNode to point out depth limits if ($this->parser->getDepthLimit() && $o->depth + 1 >= $this->parser->getDepthLimit()) { - $b = new BasicObject(); + $b = new Value(); $b->name = $o->classname.' Iterator Contents'; $b->access_path = 'iterator_to_array('.$o->access_path.')'; $b->depth = $o->depth + 1; $b->hints[] = 'depth_limit'; $r = new Representation('Iterator'); - $r->contents = array($b); + $r->contents = [$b]; $o->replaceRepresentation($r, 0); return; } - $data = \iterator_to_array($var); - $r = new Representation('Iterator'); $o->replaceRepresentation($r, 0); - foreach ($data as $key => $item) { - $base_obj = new BasicObject(); + foreach ($var as $key => $item) { + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = $item->nodeName; if ($o->access_path) { if ($var instanceof DOMNamedNodeMap) { - $base_obj->access_path = $o->access_path.'->getNamedItem('.\var_export($key, true).')'; + // We can't use getNamedItem() for attributes without a + // namespace because it will pick the first matching + // attribute of *any* namespace. + // + // Contrary to the PHP docs, getNamedItemNS takes null + // as a namespace argument for an unnamespaced item. + $base_obj->access_path = $o->access_path.'->getNamedItemNS('; + $base_obj->access_path .= \var_export($item->namespaceURI, true); + $base_obj->access_path .= ', '; + $base_obj->access_path .= \var_export($item->name, true); + $base_obj->access_path .= ')'; } elseif ($var instanceof DOMNodeList) { $base_obj->access_path = $o->access_path.'->item('.\var_export($key, true).')'; - } else { - $base_obj->access_path = 'iterator_to_array('.$o->access_path.')'; } } @@ -162,19 +169,19 @@ protected function parseList(&$var, InstanceObject &$o, $trigger) } } - protected function parseNode(&$var, InstanceObject &$o) + protected function parseNode(&$var, InstanceValue &$o) { // Fill the properties // They can't be enumerated through reflection or casting, // so we have to trust the docs and try them one at a time - $known_properties = array( + $known_properties = [ 'nodeValue', 'childNodes', 'attributes', - ); + ]; if (self::$verbose) { - $known_properties = array( + $known_properties = [ 'nodeName', 'nodeValue', 'nodeType', @@ -191,11 +198,11 @@ protected function parseNode(&$var, InstanceObject &$o) 'localName', 'baseURI', 'textContent', - ); + ]; } - $childNodes = array(); - $attributes = array(); + $childNodes = null; + $attributes = null; $rep = $o->value; @@ -217,7 +224,9 @@ protected function parseNode(&$var, InstanceObject &$o) // Attributes and comments and text nodes don't // need children or attributes of their own - if (\in_array($o->classname, array('DOMAttr', 'DOMText', 'DOMComment'), true)) { + if (\in_array($o->classname, ['DOMAttr', 'DOMText', 'DOMComment'], true)) { + $o = self::textualNodeToString($o); + return; } @@ -225,7 +234,7 @@ protected function parseNode(&$var, InstanceObject &$o) if ($attributes) { $a = new Representation('Attributes'); foreach ($attributes->contents as $attribute) { - $a->contents[] = self::textualNodeToString($attribute); + $a->contents[] = $attribute; } $o->addRepresentation($a, 0); } @@ -235,21 +244,16 @@ protected function parseNode(&$var, InstanceObject &$o) $c = new Representation('Children'); if (1 === \count($childNodes->contents) && ($node = \reset($childNodes->contents)) && \in_array('depth_limit', $node->hints, true)) { - $n = new InstanceObject(); + $n = new InstanceValue(); $n->transplant($node); $n->name = 'childNodes'; $n->classname = 'DOMNodeList'; - $c->contents = array($n); + $c->contents = [$n]; } else { - foreach ($childNodes->contents as $index => $node) { - // Shortcircuit text nodes to plain strings - if ('DOMText' === $node->classname || 'DOMComment' === $node->classname) { - $node = self::textualNodeToString($node); - - // And remove them if they're empty - if (\ctype_space($node->value->contents) || '' === $node->value->contents) { - continue; - } + foreach ($childNodes->contents as $node) { + // Remove text nodes if theyre empty + if ($node instanceof BlobValue && '#text' === $node->name && (\ctype_space($node->value->contents) || '' === $node->value->contents)) { + continue; } $c->contents[] = $node; @@ -259,8 +263,8 @@ protected function parseNode(&$var, InstanceObject &$o) $o->addRepresentation($c, 0); } - if (isset($c) && \count($c->contents)) { - $o->size = \count($c->contents); + if ($childNodes) { + $o->size = \count($childNodes->contents); } if (!$o->size) { @@ -268,15 +272,15 @@ protected function parseNode(&$var, InstanceObject &$o) } } - protected function parseProperty(InstanceObject $o, $prop, &$var) + protected function parseProperty(InstanceValue $o, $prop, &$var) { // Duplicating (And slightly optimizing) the Parser::parseObject() code here - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->owner_class = $o->classname; $base_obj->name = $prop; - $base_obj->operator = BasicObject::OPERATOR_OBJECT; - $base_obj->access = BasicObject::ACCESS_PUBLIC; + $base_obj->operator = Value::OPERATOR_OBJECT; + $base_obj->access = Value::ACCESS_PUBLIC; if (null !== $o->access_path) { $base_obj->access_path = $o->access_path; @@ -291,14 +295,19 @@ protected function parseProperty(InstanceObject $o, $prop, &$var) if (!isset($var->{$prop})) { $base_obj->type = 'null'; } elseif (isset(self::$blacklist[$prop])) { - $b = new InstanceObject(); + $b = new InstanceValue(); $b->transplant($base_obj); $base_obj = $b; $base_obj->hints[] = 'blacklist'; $base_obj->classname = self::$blacklist[$prop]; } elseif ('attributes' === $prop) { - $base_obj = $this->parser->parseDeep($var->{$prop}, $base_obj); + // Attributes are strings. If we're too deep set the + // depth limit to enable parsing them, but no deeper. + if ($this->parser->getDepthLimit() && $this->parser->getDepthLimit() - 2 < $base_obj->depth) { + $base_obj->depth = $this->parser->getDepthLimit() - 2; + } + $base_obj = $this->parser->parse($var->{$prop}, $base_obj); } else { $base_obj = $this->parser->parse($var->{$prop}, $base_obj); } @@ -306,13 +315,13 @@ protected function parseProperty(InstanceObject $o, $prop, &$var) return $base_obj; } - protected static function textualNodeToString(InstanceObject $o) + protected static function textualNodeToString(InstanceValue $o) { if (empty($o->value) || empty($o->value->contents) || empty($o->classname)) { return; } - if (!\in_array($o->classname, array('DOMText', 'DOMAttr', 'DOMComment'), true)) { + if (!\in_array($o->classname, ['DOMText', 'DOMAttr', 'DOMComment'], true)) { return; } diff --git a/system/ThirdParty/Kint/Parser/DateTimePlugin.php b/system/ThirdParty/Kint/Parser/DateTimePlugin.php index f2cebb64..1c546fd7 100644 --- a/system/ThirdParty/Kint/Parser/DateTimePlugin.php +++ b/system/ThirdParty/Kint/Parser/DateTimePlugin.php @@ -26,14 +26,14 @@ namespace Kint\Parser; use DateTime; -use Kint\Object\BasicObject; -use Kint\Object\DateTimeObject; +use Kint\Zval\DateTimeValue; +use Kint\Zval\Value; class DateTimePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -41,13 +41,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof DateTime) { return; } - $object = new DateTimeObject($var); + $object = new DateTimeValue($var); $object->transplant($o); $o = $object; diff --git a/system/ThirdParty/Kint/Parser/FsPathPlugin.php b/system/ThirdParty/Kint/Parser/FsPathPlugin.php index 3a8d1e05..79ed3288 100644 --- a/system/ThirdParty/Kint/Parser/FsPathPlugin.php +++ b/system/ThirdParty/Kint/Parser/FsPathPlugin.php @@ -25,17 +25,17 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SplFileInfoRepresentation; +use Kint\Zval\Representation\SplFileInfoRepresentation; +use Kint\Zval\Value; use SplFileInfo; class FsPathPlugin extends Plugin { - public static $blacklist = array('/', '.'); + public static $blacklist = ['/', '.']; public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -43,7 +43,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\strlen($var) > 2048) { return; diff --git a/system/ThirdParty/Kint/Parser/IteratorPlugin.php b/system/ThirdParty/Kint/Parser/IteratorPlugin.php index 0487a381..8aa1c342 100644 --- a/system/ThirdParty/Kint/Parser/IteratorPlugin.php +++ b/system/ThirdParty/Kint/Parser/IteratorPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use Traversable; class IteratorPlugin extends Plugin @@ -40,17 +40,17 @@ class IteratorPlugin extends Plugin * * @var array */ - public static $blacklist = array( + public static $blacklist = [ 'DOMNamedNodeMap', 'DOMNodeList', 'mysqli_result', 'PDOStatement', 'SplFileObject', - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -58,7 +58,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Traversable) { return; @@ -66,14 +66,14 @@ public function parse(&$var, BasicObject &$o, $trigger) foreach (self::$blacklist as $class) { if ($var instanceof $class) { - $b = new BasicObject(); + $b = new Value(); $b->name = $class.' Iterator Contents'; $b->access_path = 'iterator_to_array('.$o->access_path.', true)'; $b->depth = $o->depth + 1; $b->hints[] = 'blacklist'; $r = new Representation('Iterator'); - $r->contents = array($b); + $r->contents = [$b]; $o->addRepresentation($r); @@ -81,14 +81,9 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - /** @var array|false */ $data = \iterator_to_array($var); - if (false === $data) { - return; - } - - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { @@ -101,7 +96,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $primary = $o->getRepresentations(); $primary = \reset($primary); - if ($primary && $primary === $o->value && $primary->contents === array()) { + if ($primary && $primary === $o->value && [] === $primary->contents) { $o->addRepresentation($r, 0); } else { $o->addRepresentation($r); diff --git a/system/ThirdParty/Kint/Parser/JsonPlugin.php b/system/ThirdParty/Kint/Parser/JsonPlugin.php index 84b25195..a105b8fd 100644 --- a/system/ThirdParty/Kint/Parser/JsonPlugin.php +++ b/system/ThirdParty/Kint/Parser/JsonPlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class JsonPlugin extends Plugin { public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!isset($var[0]) || ('{' !== $var[0] && '[' !== $var[0])) { return; @@ -54,7 +54,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $json = (array) $json; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { diff --git a/system/ThirdParty/Kint/Parser/MicrotimePlugin.php b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php index 5062b59a..782c11f8 100644 --- a/system/ThirdParty/Kint/Parser/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\MicrotimeRepresentation; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Value; class MicrotimePlugin extends Plugin { @@ -37,7 +37,7 @@ class MicrotimePlugin extends Plugin public function getTypes() { - return array('string', 'double'); + return ['string', 'double']; } public function getTriggers() @@ -45,7 +45,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (0 !== $o->depth) { return; @@ -79,7 +79,7 @@ public function parse(&$var, BasicObject &$o, $trigger) self::$start = $time; } - self::$last = array($sec, $usec); + self::$last = [$sec, $usec]; if (null !== $lap) { $total = $time - self::$start; diff --git a/system/ThirdParty/Kint/Parser/MysqliPlugin.php b/system/ThirdParty/Kint/Parser/MysqliPlugin.php index 265299be..4c95d790 100644 --- a/system/ThirdParty/Kint/Parser/MysqliPlugin.php +++ b/system/ThirdParty/Kint/Parser/MysqliPlugin.php @@ -25,8 +25,10 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; use Mysqli; +use ReflectionClass; +use Throwable; /** * Adds support for Mysqli object parsing. @@ -37,21 +39,21 @@ class MysqliPlugin extends Plugin { // These 'properties' are actually globals - protected $always_readable = array( + protected $always_readable = [ 'client_version' => true, 'connect_errno' => true, 'connect_error' => true, - ); + ]; // These are readable on empty mysqli objects, but not on failed connections - protected $empty_readable = array( + protected $empty_readable = [ 'client_info' => true, 'errno' => true, 'error' => true, - ); + ]; // These are only readable on connected mysqli objects - protected $connected_readable = array( + protected $connected_readable = [ 'affected_rows' => true, 'error_list' => true, 'field_count' => true, @@ -60,16 +62,15 @@ class MysqliPlugin extends Plugin 'insert_id' => true, 'server_info' => true, 'server_version' => true, - 'stat' => true, 'sqlstate' => true, 'protocol_version' => true, 'thread_id' => true, 'warning_count' => true, - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -77,19 +78,24 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Mysqli) { return; } - $connected = false; - $empty = false; + try { + $connected = \is_string(@$var->sqlstate); + } catch (Throwable $t) { + $connected = false; + } - if (\is_string(@$var->sqlstate)) { - $connected = true; - } elseif (\is_string(@$var->client_info)) { - $empty = true; + try { + $empty = !$connected && \is_string(@$var->client_info); + } catch (Throwable $t) { // @codeCoverageIgnore + // Only possible in PHP 8.0. Before 8.0 there's no exception, + // after 8.1 there are no failed connection objects + $empty = false; // @codeCoverageIgnore } foreach ($o->value->contents as $key => $obj) { @@ -98,8 +104,9 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } } elseif (isset($this->empty_readable[$obj->name])) { - if (!$connected && !$empty) { - continue; + // No failed connections after PHP 8.1 + if (!$connected && !$empty) { // @codeCoverageIgnore + continue; // @codeCoverageIgnore } } elseif (!isset($this->always_readable[$obj->name])) { continue; @@ -109,13 +116,17 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } + // @codeCoverageIgnoreStart + // All of this is irellevant after 8.1, + // we have separate logic for that below + $param = $var->{$obj->name}; if (null === $param) { continue; } - $base = BasicObject::blank($obj->name, $obj->access_path); + $base = Value::blank($obj->name, $obj->access_path); $base->depth = $obj->depth; $base->owner_class = $obj->owner_class; @@ -124,6 +135,55 @@ public function parse(&$var, BasicObject &$o, $trigger) $base->reference = $obj->reference; $o->value->contents[$key] = $this->parser->parse($param, $base); + + // @codeCoverageIgnoreEnd + } + + // PHP81 returns an empty array when casting a Mysqli instance + if (KINT_PHP81) { + $r = new ReflectionClass(Mysqli::class); + + $basepropvalues = []; + + foreach ($r->getProperties() as $prop) { + if ($prop->isStatic()) { + continue; // @codeCoverageIgnore + } + + $pname = $prop->getName(); + $param = null; + + if (isset($this->connected_readable[$pname])) { + if ($connected) { + $param = $var->{$pname}; + } + } else { + $param = $var->{$pname}; + } + + $child = new Value(); + $child->depth = $o->depth + 1; + $child->owner_class = Mysqli::class; + $child->operator = Value::OPERATOR_OBJECT; + $child->name = $pname; + + if ($prop->isPublic()) { + $child->access = Value::ACCESS_PUBLIC; + } elseif ($prop->isProtected()) { // @codeCoverageIgnore + $child->access = Value::ACCESS_PROTECTED; // @codeCoverageIgnore + } elseif ($prop->isPrivate()) { // @codeCoverageIgnore + $child->access = Value::ACCESS_PRIVATE; // @codeCoverageIgnore + } + + // We only do base Mysqli properties so we don't need to worry about complex names + if ($this->parser->childHasPath($o, $child)) { + $child->access_path .= $o->access_path.'->'.$child->name; + } + + $basepropvalues[] = $this->parser->parse($param, $child); + } + + $o->value->contents = \array_merge($basepropvalues, $o->value->contents); } } } diff --git a/system/ThirdParty/Kint/Parser/Parser.php b/system/ThirdParty/Kint/Parser/Parser.php index b7f81c62..d658b092 100644 --- a/system/ThirdParty/Kint/Parser/Parser.php +++ b/system/ThirdParty/Kint/Parser/Parser.php @@ -27,11 +27,11 @@ use DomainException; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; -use Kint\Object\ResourceObject; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\ResourceValue; +use Kint\Zval\Value; use ReflectionObject; use stdClass; @@ -58,25 +58,22 @@ class Parser const TRIGGER_COMPLETE = 14; protected $caller_class; - protected $depth_limit = false; + protected $depth_limit = 0; protected $marker; - protected $object_hashes = array(); + protected $object_hashes = []; protected $parse_break = false; - protected $plugins = array(); + protected $plugins = []; /** - * @param false|int $depth_limit Maximum depth to parse data + * @param int $depth_limit Maximum depth to parse data * @param null|string $caller Caller class name */ - public function __construct($depth_limit = false, $caller = null) + public function __construct($depth_limit = 0, $caller = null) { $this->marker = \uniqid("kint\0", true); + $this->depth_limit = $depth_limit; $this->caller_class = $caller; - - if ($depth_limit) { - $this->depth_limit = $depth_limit; - } } /** @@ -99,9 +96,9 @@ public function getCallerClass() /** * Set the depth limit. * - * @param false|int $depth_limit Maximum depth to parse data + * @param int $depth_limit Maximum depth to parse data */ - public function setDepthLimit($depth_limit = false) + public function setDepthLimit($depth_limit = 0) { $this->noRecurseCall(); @@ -113,37 +110,15 @@ public function getDepthLimit() return $this->depth_limit; } - /** - * Disables the depth limit and parses a variable. - * - * This should not be used unless you know what you're doing! - * - * @param mixed $var The input variable - * @param BasicObject $o The base object - * - * @return BasicObject - */ - public function parseDeep(&$var, BasicObject $o) - { - $depth_limit = $this->depth_limit; - $this->depth_limit = false; - - $out = $this->parse($var, $o); - - $this->depth_limit = $depth_limit; - - return $out; - } - /** * Parses a variable into a Kint object structure. * - * @param mixed $var The input variable - * @param BasicObject $o The base object + * @param mixed $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - public function parse(&$var, BasicObject $o) + public function parse(&$var, Value $o) { $o->type = \strtolower(\gettype($var)); @@ -165,8 +140,10 @@ public function parse(&$var, BasicObject $o) return $this->parseResource($var, $o); case 'string': return $this->parseString($var, $o); + case 'unknown type': + case 'resource (closed)': default: - return $this->parseUnknown($var, $o); + return $this->parseResourceClosed($var, $o); } } @@ -184,12 +161,12 @@ public function addPlugin(Plugin $p) foreach ($types as $type) { if (!isset($this->plugins[$type])) { - $this->plugins[$type] = array( - self::TRIGGER_BEGIN => array(), - self::TRIGGER_SUCCESS => array(), - self::TRIGGER_RECURSION => array(), - self::TRIGGER_DEPTH_LIMIT => array(), - ); + $this->plugins[$type] = [ + self::TRIGGER_BEGIN => [], + self::TRIGGER_SUCCESS => [], + self::TRIGGER_RECURSION => [], + self::TRIGGER_DEPTH_LIMIT => [], + ]; } foreach ($this->plugins[$type] as $trigger => &$pool) { @@ -204,7 +181,7 @@ public function addPlugin(Plugin $p) public function clearPlugins() { - $this->plugins = array(); + $this->plugins = []; } public function haltParse() @@ -212,18 +189,18 @@ public function haltParse() $this->parse_break = true; } - public function childHasPath(InstanceObject $parent, BasicObject $child) + public function childHasPath(InstanceValue $parent, Value $child) { if ('object' === $parent->type && (null !== $parent->access_path || $child->static || $child->const)) { - if (BasicObject::ACCESS_PUBLIC === $child->access) { + if (Value::ACCESS_PUBLIC === $child->access) { return true; } - if (BasicObject::ACCESS_PRIVATE === $child->access && $this->caller_class) { + if (Value::ACCESS_PRIVATE === $child->access && $this->caller_class) { if ($this->caller_class === $child->owner_class) { return true; } - } elseif (BasicObject::ACCESS_PROTECTED === $child->access && $this->caller_class) { + } elseif (Value::ACCESS_PROTECTED === $child->access && $this->caller_class) { if ($this->caller_class === $child->owner_class) { return true; } @@ -262,9 +239,9 @@ protected function noRecurseCall() { $bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS); - $caller_frame = array( + $caller_frame = [ 'function' => __FUNCTION__, - ); + ]; while (isset($bt[0]['object']) && $bt[0]['object'] === $this) { $caller_frame = \array_shift($bt); @@ -277,7 +254,7 @@ protected function noRecurseCall() } } - private function parseGeneric(&$var, BasicObject $o) + private function parseGeneric(&$var, Value $o) { $rep = new Representation('Contents'); $rep->contents = $var; @@ -291,19 +268,19 @@ private function parseGeneric(&$var, BasicObject $o) } /** - * Parses a string into a Kint BlobObject structure. + * Parses a string into a Kint BlobValue structure. * - * @param string $var The input variable - * @param BasicObject $o The base object + * @param string $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseString(&$var, BasicObject $o) + private function parseString(&$var, Value $o) { - $string = new BlobObject(); + $string = new BlobValue(); $string->transplant($o); - $string->encoding = BlobObject::detectEncoding($var); - $string->size = BlobObject::strlen($var, $string->encoding); + $string->encoding = BlobValue::detectEncoding($var); + $string->size = \strlen($var); $rep = new Representation('Contents'); $rep->contents = $var; @@ -320,14 +297,14 @@ private function parseString(&$var, BasicObject $o) /** * Parses an array into a Kint object structure. * - * @param array $var The input variable - * @param BasicObject $o The base object + * @param array $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseArray(array &$var, BasicObject $o) + private function parseArray(array &$var, Value $o) { - $array = new BasicObject(); + $array = new Value(); $array->transplant($o); $array->size = \count($var); @@ -379,11 +356,11 @@ private function parseArray(array &$var, BasicObject $o) continue; } - $child = new BasicObject(); + $child = new Value(); $child->name = $key; $child->depth = $array->depth + 1; - $child->access = BasicObject::ACCESS_NONE; - $child->operator = BasicObject::OPERATOR_ARRAY; + $child->access = Value::ACCESS_NONE; + $child->operator = Value::OPERATOR_ARRAY; if (null !== $array->access_path) { if (\is_string($key) && (string) (int) $key === $key) { @@ -411,22 +388,22 @@ private function parseArray(array &$var, BasicObject $o) } /** - * Parses an object into a Kint InstanceObject structure. + * Parses an object into a Kint InstanceValue structure. * - * @param object $var The input variable - * @param BasicObject $o The base object + * @param object $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseObject(&$var, BasicObject $o) + private function parseObject(&$var, Value $o) { $hash = \spl_object_hash($var); $values = (array) $var; - $object = new InstanceObject(); + $object = new InstanceValue(); $object->transplant($o); $object->classname = \get_class($var); - $object->hash = $hash; + $object->spl_object_hash = $hash; $object->size = \count($values); if (isset($this->object_hashes[$hash])) { @@ -457,6 +434,48 @@ private function parseObject(&$var, BasicObject $o) $rep = new Representation('Properties'); + if (KINT_PHP74) { + $rprops = $reflector->getProperties(); + + foreach ($rprops as $rprop) { + if ($rprop->isStatic()) { + continue; + } + + $rprop->setAccessible(true); + if ($rprop->isInitialized($var)) { + continue; + } + + $undefined = null; + + $child = new Value(); + $child->type = 'undefined'; + $child->depth = $object->depth + 1; + $child->owner_class = $rprop->getDeclaringClass()->getName(); + $child->operator = Value::OPERATOR_OBJECT; + $child->name = $rprop->getName(); + + if ($rprop->isPublic()) { + $child->access = Value::ACCESS_PUBLIC; + } elseif ($rprop->isProtected()) { + $child->access = Value::ACCESS_PROTECTED; + } elseif ($rprop->isPrivate()) { + $child->access = Value::ACCESS_PRIVATE; + } + + // Can't dynamically add undefined properties, so no need to use var_export + if ($this->childHasPath($object, $child)) { + $child->access_path .= $object->access_path.'->'.$child->name; + } + + if ($this->applyPlugins($undefined, $child, self::TRIGGER_BEGIN)) { + $this->applyPlugins($undefined, $child, self::TRIGGER_SUCCESS); + } + $rep->contents[] = $child; + } + } + $copy = \array_values($values); $refmarker = new stdClass(); $i = 0; @@ -470,20 +489,20 @@ private function parseObject(&$var, BasicObject $o) // public properties show in the form "$property_name"; // http://www.php.net/manual/en/language.types.array.php#language.types.array.casting - $child = new BasicObject(); + $child = new Value(); $child->depth = $object->depth + 1; $child->owner_class = $object->classname; - $child->operator = BasicObject::OPERATOR_OBJECT; - $child->access = BasicObject::ACCESS_PUBLIC; + $child->operator = Value::OPERATOR_OBJECT; + $child->access = Value::ACCESS_PUBLIC; $split_key = \explode("\0", $key, 3); if (3 === \count($split_key) && '' === $split_key[0]) { $child->name = $split_key[2]; if ('*' === $split_key[1]) { - $child->access = BasicObject::ACCESS_PROTECTED; + $child->access = Value::ACCESS_PROTECTED; } else { - $child->access = BasicObject::ACCESS_PRIVATE; + $child->access = Value::ACCESS_PRIVATE; $child->owner_class = $split_key[1]; } } elseif (KINT_PHP72) { @@ -524,16 +543,16 @@ private function parseObject(&$var, BasicObject $o) } /** - * Parses a resource into a Kint ResourceObject structure. + * Parses a resource into a Kint ResourceValue structure. * - * @param resource $var The input variable - * @param BasicObject $o The base object + * @param resource $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseResource(&$var, BasicObject $o) + private function parseResource(&$var, Value $o) { - $resource = new ResourceObject(); + $resource = new ResourceValue(); $resource->transplant($o); $resource->resource_type = \get_resource_type($var); @@ -543,16 +562,16 @@ private function parseResource(&$var, BasicObject $o) } /** - * Parses an unknown into a Kint object structure. + * Parses a closed resource into a Kint object structure. * - * @param mixed $var The input variable - * @param BasicObject $o The base object + * @param mixed $var The input variable + * @param Value $o The base object * - * @return BasicObject + * @return Value */ - private function parseUnknown(&$var, BasicObject $o) + private function parseResourceClosed(&$var, Value $o) { - $o->type = 'unknown'; + $o->type = 'resource (closed)'; $this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); return $o; @@ -561,20 +580,20 @@ private function parseUnknown(&$var, BasicObject $o) /** * Applies plugins for an object type. * - * @param mixed $var variable - * @param BasicObject $o Kint object parsed so far - * @param int $trigger The trigger to check for the plugins + * @param mixed $var variable + * @param Value $o Kint object parsed so far + * @param int $trigger The trigger to check for the plugins * * @return bool Continue parsing */ - private function applyPlugins(&$var, BasicObject &$o, $trigger) + private function applyPlugins(&$var, Value &$o, $trigger) { $break_stash = $this->parse_break; /** @var bool Psalm bug workaround */ $this->parse_break = false; - $plugins = array(); + $plugins = []; if (isset($this->plugins[$o->type][$trigger])) { $plugins = $this->plugins[$o->type][$trigger]; diff --git a/system/ThirdParty/Kint/Parser/Plugin.php b/system/ThirdParty/Kint/Parser/Plugin.php index 51d5f0b1..981d2aa5 100644 --- a/system/ThirdParty/Kint/Parser/Plugin.php +++ b/system/ThirdParty/Kint/Parser/Plugin.php @@ -25,7 +25,7 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; abstract class Plugin { @@ -43,7 +43,7 @@ public function setParser(Parser $p) */ public function getTypes() { - return array(); + return []; } public function getTriggers() @@ -51,5 +51,5 @@ public function getTriggers() return Parser::TRIGGER_NONE; } - abstract public function parse(&$variable, BasicObject &$o, $trigger); + abstract public function parse(&$var, Value &$o, $trigger); } diff --git a/system/ThirdParty/Kint/Parser/ProxyPlugin.php b/system/ThirdParty/Kint/Parser/ProxyPlugin.php index 3376d3aa..116f3883 100644 --- a/system/ThirdParty/Kint/Parser/ProxyPlugin.php +++ b/system/ThirdParty/Kint/Parser/ProxyPlugin.php @@ -26,7 +26,7 @@ namespace Kint\Parser; use InvalidArgumentException; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class ProxyPlugin extends Plugin { @@ -59,8 +59,8 @@ public function getTriggers() return $this->triggers; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - return \call_user_func_array($this->callback, array(&$var, &$o, $trigger, $this->parser)); + return \call_user_func_array($this->callback, [&$var, &$o, $trigger, $this->parser]); } } diff --git a/system/ThirdParty/Kint/Parser/SerializePlugin.php b/system/ThirdParty/Kint/Parser/SerializePlugin.php index c5dadb88..5924483f 100644 --- a/system/ThirdParty/Kint/Parser/SerializePlugin.php +++ b/system/ThirdParty/Kint/Parser/SerializePlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class SerializePlugin extends Plugin { @@ -45,11 +45,11 @@ class SerializePlugin extends Plugin * @var bool */ public static $safe_mode = true; - public static $options = array(true); + public static $options = [true]; public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -57,7 +57,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $trimmed = \rtrim($var); @@ -65,7 +65,7 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - if (!self::$safe_mode || !\in_array($trimmed[0], array('C', 'O', 'a'), true)) { + if (!self::$safe_mode || !\in_array($trimmed[0], ['C', 'O', 'a'], true)) { // Second parameter only supported on PHP 7 if (KINT_PHP70) { // Suppress warnings on unserializeable variable @@ -79,15 +79,15 @@ public function parse(&$var, BasicObject &$o, $trigger) } } - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = 'unserialize('.$o->name.')'; if ($o->access_path) { $base_obj->access_path = 'unserialize('.$o->access_path; - if (!KINT_PHP70 || self::$options === array(true)) { + if (!KINT_PHP70 || self::$options === [true]) { $base_obj->access_path .= ')'; - } elseif (self::$options === array(false)) { + } elseif (self::$options === [false]) { $base_obj->access_path .= ', false)'; } else { $base_obj->access_path .= ', Serialize::$options)'; diff --git a/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php index b90c863f..9e44e538 100644 --- a/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php +++ b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php @@ -25,9 +25,10 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\BlobValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\SimpleXMLElementValue; +use Kint\Zval\Value; use SimpleXMLElement; class SimpleXMLElementPlugin extends Plugin @@ -41,7 +42,7 @@ class SimpleXMLElementPlugin extends Plugin public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -49,106 +50,168 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SimpleXMLElement) { return; } - $o->hints[] = 'simplexml_element'; - if (!self::$verbose) { $o->removeRepresentation('properties'); $o->removeRepresentation('iterator'); $o->removeRepresentation('methods'); } + // An invalid SimpleXMLElement can gum up the works with + // warnings if we call stuff children/attributes on it. + if (!$var) { + $o->size = null; + + return; + } + + $x = new SimpleXMLElementValue(); + $x->transplant($o); + + $namespaces = \array_merge([null], $var->getDocNamespaces()); + // Attributes $a = new Representation('Attributes'); - $base_obj = new BasicObject(); - $base_obj->depth = $o->depth; + $base_obj = new Value(); + $base_obj->depth = $x->depth; - if ($o->access_path) { - $base_obj->access_path = '(string) '.$o->access_path; + if ($x->access_path) { + $base_obj->access_path = '(string) '.$x->access_path; } - if ($attribs = $var->attributes()) { - $attribs = \iterator_to_array($attribs); - $attribs = \array_map('strval', $attribs); - } else { - $attribs = array(); + // Attributes are strings. If we're too deep set the + // depth limit to enable parsing them, but no deeper. + if ($this->parser->getDepthLimit() && $this->parser->getDepthLimit() - 2 < $base_obj->depth) { + $base_obj->depth = $this->parser->getDepthLimit() - 2; } - // XML attributes are by definition strings and don't have children, - // so up the depth limit in case we're just below the limit since - // there won't be any recursive stuff anyway. - $a->contents = $this->parser->parseDeep($attribs, $base_obj)->value->contents; + $attribs = []; - $o->addRepresentation($a, 0); + foreach ($namespaces as $nsAlias => $nsUrl) { + if ($nsAttribs = $var->attributes($nsUrl)) { + $cleanAttribs = []; + foreach ($nsAttribs as $name => $attrib) { + $cleanAttribs[(string) $name] = $attrib; + } - // Children - // We need to check children() separately from the values we already parsed because - // text contents won't show up in children() but they will show up in properties. - // - // Why do we still need to check for attributes if we already have an attributes() - // method? Hell if I know! - $children = $var->children(); - - if ($o->value) { - $c = new Representation('Children'); - - foreach ($o->value->contents as $value) { - if ('@attributes' === $value->name) { - continue; + if (null === $nsUrl) { + $obj = clone $base_obj; + if ($obj->access_path) { + $obj->access_path .= '->attributes()'; + } + + $a->contents = $this->parser->parse($cleanAttribs, $obj)->value->contents; + } else { + $obj = clone $base_obj; + if ($obj->access_path) { + $obj->access_path .= '->attributes('.\var_export($nsAlias, true).', true)'; + } + + $cleanAttribs = $this->parser->parse($cleanAttribs, $obj)->value->contents; + + foreach ($cleanAttribs as $attribute) { + $attribute->name = $nsAlias.':'.$attribute->name; + $a->contents[] = $attribute; + } } + } + } + + $x->addRepresentation($a, 0); - if (isset($children->{$value->name})) { - $i = 0; + // Children + $c = new Representation('Children'); + + foreach ($namespaces as $nsAlias => $nsUrl) { + // This is doubling items because of the root namespace + // and the implicit namespace on its children. + $thisNs = $var->getNamespaces(); + if (isset($thisNs['']) && $thisNs[''] === $nsUrl) { + continue; + } - while (isset($children->{$value->name}[$i])) { - $base_obj = new BasicObject(); - $base_obj->depth = $o->depth + 1; - $base_obj->name = $value->name; - if ($value->access_path) { - $base_obj->access_path = $value->access_path.'['.$i.']'; + if ($nsChildren = $var->children($nsUrl)) { + $nsap = []; + foreach ($nsChildren as $name => $child) { + $obj = new Value(); + $obj->depth = $x->depth + 1; + $obj->name = (string) $name; + if ($x->access_path) { + if (null === $nsUrl) { + $obj->access_path = $x->access_path.'->children()->'; + } else { + $obj->access_path = $x->access_path.'->children('.\var_export($nsAlias, true).', true)->'; } - $value = $this->parser->parse($children->{$value->name}[$i], $base_obj); + if (\preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]+$/', (string) $name)) { + $obj->access_path .= (string) $name; + } else { + $obj->access_path .= '{'.\var_export((string) $name, true).'}'; + } - if ($value->access_path && 'string' === $value->type) { - $value->access_path = '(string) '.$value->access_path; + if (isset($nsap[$obj->access_path])) { + ++$nsap[$obj->access_path]; + $obj->access_path .= '['.$nsap[$obj->access_path].']'; + } else { + $nsap[$obj->access_path] = 0; } + } - $c->contents[] = $value; + $value = $this->parser->parse($child, $obj); - ++$i; + if ($value->access_path && 'string' === $value->type) { + $value->access_path = '(string) '.$value->access_path; } + + $c->contents[] = $value; } } + } - $o->size = \count($c->contents); + $x->size = \count($c->contents); - if (!$o->size) { - $o->size = null; + if ($x->size) { + $x->addRepresentation($c, 0); + } else { + $x->size = null; + + if (\strlen((string) $var)) { + $base_obj = new BlobValue(); + $base_obj->depth = $x->depth + 1; + $base_obj->name = $x->name; + if ($x->access_path) { + $base_obj->access_path = '(string) '.$x->access_path; + } + + $value = (string) $var; + + $s = $this->parser->parse($value, $base_obj); + $srep = $s->getRepresentation('contents'); + $svalrep = $s->value && 'contents' == $s->value->getName() ? $s : null; - if (\strlen((string) $var)) { - $base_obj = new BlobObject(); - $base_obj->depth = $o->depth + 1; - $base_obj->name = $o->name; - if ($o->access_path) { - $base_obj->access_path = '(string) '.$o->access_path; + if ($srep || $svalrep) { + $x->setIsStringValue(true); + $x->value = $srep ?: $svalrep; + + if ($srep) { + $x->replaceRepresentation($x->value, 0); } + } - $value = (string) $var; + $reps = \array_reverse($s->getRepresentations()); - $c = new Representation('Contents'); - $c->implicit_label = true; - $c->contents = array($this->parser->parseDeep($value, $base_obj)); + foreach ($reps as $rep) { + $x->addRepresentation($rep, 0); } } - - $o->addRepresentation($c, 0); } + + $o = $x; } } diff --git a/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php index 8b72193b..ada3e1fb 100644 --- a/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php +++ b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php @@ -25,8 +25,8 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SplFileInfoRepresentation; +use Kint\Zval\Representation\SplFileInfoRepresentation; +use Kint\Zval\Value; use SplFileInfo; use SplFileObject; @@ -34,7 +34,7 @@ class SplFileInfoPlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -42,7 +42,7 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SplFileInfo || $var instanceof SplFileObject) { return; diff --git a/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php index 03ff301d..359774d3 100644 --- a/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php +++ b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; use SplObjectStorage; class SplObjectStoragePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_COMPLETE; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof SplObjectStorage || !($r = $o->getRepresentation('iterator'))) { return; diff --git a/system/ThirdParty/Kint/Parser/StreamPlugin.php b/system/ThirdParty/Kint/Parser/StreamPlugin.php index 464a3fff..76608d94 100644 --- a/system/ThirdParty/Kint/Parser/StreamPlugin.php +++ b/system/ThirdParty/Kint/Parser/StreamPlugin.php @@ -25,16 +25,16 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; -use Kint\Object\ResourceObject; -use Kint\Object\StreamObject; +use Kint\Zval\Representation\Representation; +use Kint\Zval\ResourceValue; +use Kint\Zval\StreamValue; +use Kint\Zval\Value; class StreamPlugin extends Plugin { public function getTypes() { - return array('resource'); + return ['resource']; } public function getTriggers() @@ -42,20 +42,23 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { - if (!$o instanceof ResourceObject || 'stream' !== $o->resource_type) { + if (!$o instanceof ResourceValue || 'stream' !== $o->resource_type) { return; } - if (!$meta = \stream_get_meta_data($var)) { + // Doublecheck that the resource is open before we get the metadata + if (!\is_resource($var)) { return; } + $meta = \stream_get_meta_data($var); + $rep = new Representation('Stream'); $rep->implicit_label = true; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth; if ($o->access_path) { @@ -71,7 +74,7 @@ public function parse(&$var, BasicObject &$o, $trigger) $o->addRepresentation($rep, 0); $o->value = $rep; - $stream = new StreamObject($meta); + $stream = new StreamValue($meta); $stream->transplant($o); $o = $stream; } diff --git a/system/ThirdParty/Kint/Parser/TablePlugin.php b/system/ThirdParty/Kint/Parser/TablePlugin.php index 510c4ff0..c6ca6e24 100644 --- a/system/ThirdParty/Kint/Parser/TablePlugin.php +++ b/system/ThirdParty/Kint/Parser/TablePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class TablePlugin extends Plugin { public function getTypes() { - return array('array'); + return ['array']; } public function getTriggers() @@ -40,7 +40,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (empty($o->value->contents)) { return; diff --git a/system/ThirdParty/Kint/Parser/ThrowablePlugin.php b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php index 8490d1d4..ea343e96 100644 --- a/system/ThirdParty/Kint/Parser/ThrowablePlugin.php +++ b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php @@ -26,16 +26,16 @@ namespace Kint\Parser; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\Representation\SourceRepresentation; -use Kint\Object\ThrowableObject; +use Kint\Zval\Representation\SourceRepresentation; +use Kint\Zval\ThrowableValue; +use Kint\Zval\Value; use Throwable; class ThrowablePlugin extends Plugin { public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -43,13 +43,13 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$var instanceof Exception && (!KINT_PHP70 || !$var instanceof Throwable)) { return; } - $throw = new ThrowableObject($var); + $throw = new ThrowableValue($var); $throw->transplant($o); $r = new SourceRepresentation($var->getFile(), $var->getLine()); $r->showfilename = true; diff --git a/system/ThirdParty/Kint/Parser/TimestampPlugin.php b/system/ThirdParty/Kint/Parser/TimestampPlugin.php index 72958d64..fa8d743d 100644 --- a/system/ThirdParty/Kint/Parser/TimestampPlugin.php +++ b/system/ThirdParty/Kint/Parser/TimestampPlugin.php @@ -25,20 +25,20 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class TimestampPlugin extends Plugin { - public static $blacklist = array( + public static $blacklist = [ 2147483648, 2147483647, 1073741824, 1073741823, - ); + ]; public function getTypes() { - return array('string', 'integer'); + return ['string', 'integer']; } public function getTriggers() @@ -46,7 +46,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (\is_string($var) && !\ctype_digit($var)) { return; @@ -56,7 +56,7 @@ public function parse(&$var, BasicObject &$o, $trigger) return; } - $len = \strlen($var); + $len = \strlen((string) $var); // Guess for anything between March 1973 and November 2286 if (9 === $len || 10 === $len) { diff --git a/system/ThirdParty/Kint/Parser/ToStringPlugin.php b/system/ThirdParty/Kint/Parser/ToStringPlugin.php index 8b7a65fe..d13cb29c 100644 --- a/system/ThirdParty/Kint/Parser/ToStringPlugin.php +++ b/system/ThirdParty/Kint/Parser/ToStringPlugin.php @@ -25,20 +25,20 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; use ReflectionClass; class ToStringPlugin extends Plugin { - public static $blacklist = array( + public static $blacklist = [ 'SimpleXMLElement', 'SplFileObject', - ); + ]; public function getTypes() { - return array('object'); + return ['object']; } public function getTriggers() @@ -46,7 +46,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { $reflection = new ReflectionClass($var); if (!$reflection->hasMethod('__toString')) { diff --git a/system/ThirdParty/Kint/Parser/TracePlugin.php b/system/ThirdParty/Kint/Parser/TracePlugin.php index 3554993d..ccdcadec 100644 --- a/system/ThirdParty/Kint/Parser/TracePlugin.php +++ b/system/ThirdParty/Kint/Parser/TracePlugin.php @@ -25,18 +25,19 @@ namespace Kint\Parser; -use Kint\Object\BasicObject; -use Kint\Object\TraceFrameObject; -use Kint\Object\TraceObject; use Kint\Utils; +use Kint\Zval\TraceFrameValue; +use Kint\Zval\TraceValue; +use Kint\Zval\Value; class TracePlugin extends Plugin { - public static $blacklist = array('spl_autoload_call'); + public static $blacklist = ['spl_autoload_call']; + public static $path_blacklist = []; public function getTypes() { - return array('array'); + return ['array']; } public function getTriggers() @@ -44,27 +45,29 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if (!$o->value) { return; } + /** @var array[] $trace Psalm workaround */ $trace = $this->parser->getCleanArray($var); if (\count($trace) !== \count($o->value->contents) || !Utils::isTrace($trace)) { return; } - $traceobj = new TraceObject(); + $traceobj = new TraceValue(); $traceobj->transplant($o); $rep = $traceobj->value; $old_trace = $rep->contents; Utils::normalizeAliases(self::$blacklist); + $path_blacklist = self::normalizePaths(self::$path_blacklist); - $rep->contents = array(); + $rep->contents = []; foreach ($old_trace as $frame) { $index = $frame->name; @@ -78,7 +81,16 @@ public function parse(&$var, BasicObject &$o, $trigger) continue; } - $rep->contents[$index] = new TraceFrameObject($frame, $trace[$index]); + if (isset($trace[$index]['file'])) { + $realfile = \realpath($trace[$index]['file']); + foreach ($path_blacklist as $path) { + if (0 === \strpos($realfile, $path)) { + continue 2; + } + } + } + + $rep->contents[$index] = new TraceFrameValue($frame, $trace[$index]); } \ksort($rep->contents); @@ -89,4 +101,20 @@ public function parse(&$var, BasicObject &$o, $trigger) $traceobj->size = \count($rep->contents); $o = $traceobj; } + + protected static function normalizePaths(array $paths) + { + $normalized = []; + + foreach ($paths as $path) { + $realpath = \realpath($path); + if (\is_dir($realpath)) { + $realpath .= DIRECTORY_SEPARATOR; + } + + $normalized[] = $realpath; + } + + return $normalized; + } } diff --git a/system/ThirdParty/Kint/Parser/XmlPlugin.php b/system/ThirdParty/Kint/Parser/XmlPlugin.php index 0947e9a6..a4fa2b0c 100644 --- a/system/ThirdParty/Kint/Parser/XmlPlugin.php +++ b/system/ThirdParty/Kint/Parser/XmlPlugin.php @@ -27,8 +27,8 @@ use DOMDocument; use Exception; -use Kint\Object\BasicObject; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class XmlPlugin extends Plugin { @@ -45,7 +45,7 @@ class XmlPlugin extends Plugin public function getTypes() { - return array('string'); + return ['string']; } public function getTriggers() @@ -53,7 +53,7 @@ public function getTriggers() return Parser::TRIGGER_SUCCESS; } - public function parse(&$var, BasicObject &$o, $trigger) + public function parse(&$var, Value &$o, $trigger) { if ('access_path); + $xml = \call_user_func([\get_class($this), 'xmlTo'.self::$parse_method], $var, $o->access_path); if (empty($xml)) { return; @@ -71,7 +71,7 @@ public function parse(&$var, BasicObject &$o, $trigger) list($xml, $access_path, $name) = $xml; - $base_obj = new BasicObject(); + $base_obj = new Value(); $base_obj->depth = $o->depth + 1; $base_obj->name = $name; $base_obj->access_path = $access_path; @@ -96,7 +96,7 @@ protected static function xmlToSimpleXML($var, $parent_path) return; } - if (!$xml) { + if (false === $xml) { return; } @@ -108,7 +108,7 @@ protected static function xmlToSimpleXML($var, $parent_path) $name = $xml->getName(); - return array($xml, $access_path, $name); + return [$xml, $access_path, $name]; } /** @@ -135,16 +135,23 @@ protected static function xmlToDOMDocument($var, $parent_path) $xml = new DOMDocument(); $xml->loadXML($var); - $xml = $xml->firstChild; + + if ($xml->childNodes->count() > 1) { + $xml = $xml->childNodes; + $access_path = 'childNodes'; + } else { + $xml = $xml->firstChild; + $access_path = 'firstChild'; + } if (null === $parent_path) { $access_path = null; } else { - $access_path = '@\\DOMDocument::loadXML('.$parent_path.')->firstChild'; + $access_path = '(function($s){$x = new \\DomDocument(); $x->loadXML($s); return $x;})('.$parent_path.')->'.$access_path; } - $name = $xml->nodeName; + $name = isset($xml->nodeName) ? $xml->nodeName : null; - return array($xml, $access_path, $name); + return [$xml, $access_path, $name]; } } diff --git a/system/ThirdParty/Kint/Renderer/CliRenderer.php b/system/ThirdParty/Kint/Renderer/CliRenderer.php index 0d0846a4..f86671ff 100644 --- a/system/ThirdParty/Kint/Renderer/CliRenderer.php +++ b/system/ThirdParty/Kint/Renderer/CliRenderer.php @@ -25,7 +25,9 @@ namespace Kint\Renderer; -use Kint\Object\BasicObject; +use Exception; +use Kint\Zval\Value; +use Throwable; class CliRenderer extends TextRenderer { @@ -73,7 +75,13 @@ public function __construct() if (!self::$terminal_width) { if (!KINT_WIN && self::$detect_width) { - self::$terminal_width = \exec('tput cols'); + try { + self::$terminal_width = \exec('tput cols'); + } catch (Exception $e) { + self::$terminal_width = self::$default_width; + } catch (Throwable $t) { + self::$terminal_width = self::$default_width; + } } if (self::$terminal_width < self::$min_terminal_width) { @@ -113,7 +121,7 @@ public function colorTitle($string) return "\x1b[36m".\str_replace("\n", "\x1b[0m\n\x1b[36m", $string)."\x1b[0m"; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { if ($this->windows_output) { return $this->utf8ToWindows(parent::renderTitle($o)); @@ -144,8 +152,8 @@ public function escape($string, $encoding = false) protected function utf8ToWindows($string) { return \str_replace( - array('┌', '═', '┐', '│', '└', '─', '┘'), - array("\xda", "\xdc", "\xbf", "\xb3", "\xc0", "\xc4", "\xd9"), + ['┌', '═', '┐', '│', '└', '─', '┘'], + ["\xda", "\xdc", "\xbf", "\xb3", "\xc0", "\xc4", "\xd9"], $string ); } diff --git a/system/ThirdParty/Kint/Renderer/PlainRenderer.php b/system/ThirdParty/Kint/Renderer/PlainRenderer.php index 493a7743..4b8102a4 100644 --- a/system/ThirdParty/Kint/Renderer/PlainRenderer.php +++ b/system/ThirdParty/Kint/Renderer/PlainRenderer.php @@ -26,21 +26,21 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; +use Kint\Zval\Value; class PlainRenderer extends TextRenderer { - public static $pre_render_sources = array( - 'script' => array( - array('Kint\\Renderer\\PlainRenderer', 'renderJs'), - array('Kint\\Renderer\\Text\\MicrotimePlugin', 'renderJs'), - ), - 'style' => array( - array('Kint\\Renderer\\PlainRenderer', 'renderCss'), - ), - 'raw' => array(), - ); + public static $pre_render_sources = [ + 'script' => [ + ['Kint\\Renderer\\PlainRenderer', 'renderJs'], + ['Kint\\Renderer\\Text\\MicrotimePlugin', 'renderJs'], + ], + 'style' => [ + ['Kint\\Renderer\\PlainRenderer', 'renderCss'], + ], + 'raw' => [], + ]; /** * Path to the CSS file to load by default. @@ -118,7 +118,7 @@ public function colorTitle($string) return ''.$string.''; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { if (self::$disable_utf8) { return $this->utf8ToHtmlentity(parent::renderTitle($o)); @@ -193,7 +193,7 @@ public function ideLink($file, $line) public function escape($string, $encoding = false) { if (false === $encoding) { - $encoding = BlobObject::detectEncoding($string); + $encoding = BlobValue::detectEncoding($string); } $original_encoding = $encoding; @@ -206,7 +206,7 @@ public function escape($string, $encoding = false) // this call converts all non-ASCII characters into numeirc htmlentities if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { - $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + $string = \mb_encode_numericentity($string, [0x80, 0xFFFF, 0, 0xFFFF], $encoding); } return $string; @@ -215,8 +215,8 @@ public function escape($string, $encoding = false) protected function utf8ToHtmlentity($string) { return \str_replace( - array('┌', '═', '┐', '│', '└', '─', '┘'), - array('┌', '═', '┐', '│', '└', '─', '┘'), + ['┌', '═', '┐', '│', '└', '─', '┘'], + ['┌', '═', '┐', '│', '└', '─', '┘'], $string ); } diff --git a/system/ThirdParty/Kint/Renderer/Renderer.php b/system/ThirdParty/Kint/Renderer/Renderer.php index cf8b0a78..0ed7ce08 100644 --- a/system/ThirdParty/Kint/Renderer/Renderer.php +++ b/system/ThirdParty/Kint/Renderer/Renderer.php @@ -25,8 +25,8 @@ namespace Kint\Renderer; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; abstract class Renderer { @@ -34,11 +34,11 @@ abstract class Renderer const SORT_VISIBILITY = 1; const SORT_FULL = 2; - protected $call_info = array(); - protected $statics = array(); + protected $call_info = []; + protected $statics = []; protected $show_trace = true; - abstract public function render(BasicObject $o); + abstract public function render(Value $o); abstract public function renderNothing(); @@ -49,7 +49,7 @@ public function setCallInfo(array $info) } if (!isset($info['modifiers']) || !\is_array($info['modifiers'])) { - $info['modifiers'] = array(); + $info['modifiers'] = []; } if (!isset($info['callee'])) { @@ -61,16 +61,16 @@ public function setCallInfo(array $info) } if (!isset($info['trace']) || !\is_array($info['trace'])) { - $info['trace'] = array(); + $info['trace'] = []; } - $this->call_info = array( + $this->call_info = [ 'params' => $info['params'], 'modifiers' => $info['modifiers'], 'callee' => $info['callee'], 'caller' => $info['caller'], 'trace' => $info['trace'], - ); + ]; } public function getCallInfo() @@ -109,7 +109,7 @@ public function getShowTrace() */ public function matchPlugins(array $plugins, array $hints) { - $out = array(); + $out = []; foreach ($hints as $key) { if (isset($plugins[$key])) { @@ -135,40 +135,40 @@ public function postRender() return ''; } - public static function sortPropertiesFull(BasicObject $a, BasicObject $b) + public static function sortPropertiesFull(Value $a, Value $b) { - $sort = BasicObject::sortByAccess($a, $b); + $sort = Value::sortByAccess($a, $b); if ($sort) { return $sort; } - $sort = BasicObject::sortByName($a, $b); + $sort = Value::sortByName($a, $b); if ($sort) { return $sort; } - return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + return InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class); } /** - * Sorts an array of BasicObject. + * Sorts an array of Value. * - * @param BasicObject[] $contents Object properties to sort - * @param int $sort + * @param Value[] $contents Object properties to sort + * @param int $sort * - * @return BasicObject[] + * @return Value[] */ public static function sortProperties(array $contents, $sort) { switch ($sort) { case self::SORT_VISIBILITY: - /** @var array Containers to quickly stable sort by type */ - $containers = array( - BasicObject::ACCESS_PUBLIC => array(), - BasicObject::ACCESS_PROTECTED => array(), - BasicObject::ACCESS_PRIVATE => array(), - BasicObject::ACCESS_NONE => array(), - ); + // Containers to quickly stable sort by type + $containers = [ + Value::ACCESS_PUBLIC => [], + Value::ACCESS_PROTECTED => [], + Value::ACCESS_PRIVATE => [], + Value::ACCESS_NONE => [], + ]; foreach ($contents as $item) { $containers[$item->access][] = $item; @@ -176,7 +176,7 @@ public static function sortProperties(array $contents, $sort) return \call_user_func_array('array_merge', $containers); case self::SORT_FULL: - \usort($contents, array('Kint\\Renderer\\Renderer', 'sortPropertiesFull')); + \usort($contents, ['Kint\\Renderer\\Renderer', 'sortPropertiesFull']); // no break default: return $contents; diff --git a/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php new file mode 100644 index 00000000..e6ebe569 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/ArrayLimitPlugin.php @@ -0,0 +1,36 @@ +'.$this->renderLockedHeader($o, 'Array Limit').''; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php index 5b4d613f..b12690a4 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php @@ -25,7 +25,7 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; class BinaryPlugin extends Plugin implements TabPluginInterface { @@ -36,12 +36,17 @@ public function renderTab(Representation $r) { $out = '
';
 
-        $chunks = \str_split($r->contents, self::$line_length);
+        /** @var string[] Psalm bug workaround */
+        $lines = \str_split($r->contents, self::$line_length);
 
-        foreach ($chunks as $index => $chunk) {
+        foreach ($lines as $index => $line) {
             $out .= \sprintf('%08X', $index * self::$line_length).":\t";
-            $out .= \implode(' ', \str_split(\str_pad(\bin2hex($chunk), 2 * self::$line_length, ' '), self::$chunk_length));
-            $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $chunk)."\n";
+
+            /** @var string[] Psalm bug workaround */
+            $chunks = \str_split(\str_pad(\bin2hex($line), 2 * self::$line_length, ' '), self::$chunk_length);
+
+            $out .= \implode(' ', $chunks);
+            $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $line)."\n";
         }
 
         $out .= '
'; diff --git a/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php index fcfedc1a..ed7f4ec9 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class BlacklistPlugin extends Plugin implements ObjectPluginInterface +class BlacklistPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
'.$this->renderLockedHeader($o, 'Blacklisted').'
'; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php index 5834017b..b28b56a0 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php @@ -25,30 +25,30 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\ClosureObject; -use Kint\Object\MethodObject; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\ClosureValue; +use Kint\Zval\MethodValue; +use Kint\Zval\Value; -class CallablePlugin extends Plugin implements ObjectPluginInterface +class CallablePlugin extends Plugin implements ValuePluginInterface { - protected static $method_cache = array(); + protected static $method_cache = []; - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { - if ($o instanceof MethodObject) { + if ($o instanceof MethodValue) { return $this->renderMethod($o); } - if ($o instanceof ClosureObject) { + if ($o instanceof ClosureValue) { return $this->renderClosure($o); } return $this->renderCallable($o); } - protected function renderClosure(ClosureObject $o) + protected function renderClosure(ClosureValue $o) { $children = $this->renderer->renderChildren($o); @@ -63,8 +63,8 @@ protected function renderClosure(ClosureObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } @@ -72,7 +72,7 @@ protected function renderClosure(ClosureObject $o) return '
'.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
'; } - protected function renderCallable(BasicObject $o) + protected function renderCallable(Value $o) { $children = $this->renderer->renderChildren($o); @@ -87,8 +87,8 @@ protected function renderCallable(BasicObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } @@ -96,7 +96,7 @@ protected function renderCallable(BasicObject $o) return '
'.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
'; } - protected function renderMethod(MethodObject $o) + protected function renderMethod(MethodValue $o) { if (!empty(self::$method_cache[$o->owner_class][$o->name])) { $children = self::$method_cache[$o->owner_class][$o->name]['children']; @@ -154,17 +154,17 @@ protected function renderMethod(MethodObject $o) } if (null !== ($s = $o->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } $header .= ' '.$this->renderer->escape($s); } if (\strlen($o->owner_class) && \strlen($o->name)) { - self::$method_cache[$o->owner_class][$o->name] = array( + self::$method_cache[$o->owner_class][$o->name] = [ 'header' => $header, 'children' => $children, - ); + ]; } $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); diff --git a/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php index 79a9926c..44813e3e 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php @@ -26,16 +26,16 @@ namespace Kint\Renderer\Rich; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\ClosureObject; +use Kint\Zval\ClosureValue; +use Kint\Zval\Value; -class ClosurePlugin extends Plugin implements ObjectPluginInterface +class ClosurePlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $children = $this->renderer->renderChildren($o); - if (!($o instanceof ClosureObject)) { + if (!($o instanceof ClosureValue)) { $header = $this->renderer->renderHeader($o); } else { $header = ''; diff --git a/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php index 241a8154..ebd02cb5 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php @@ -25,13 +25,13 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\Representation\ColorRepresentation; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\ColorRepresentation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; -class ColorPlugin extends Plugin implements TabPluginInterface, ObjectPluginInterface +class ColorPlugin extends Plugin implements TabPluginInterface, ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $r = $o->getRepresentation('color'); @@ -92,7 +92,7 @@ public function renderTab(Representation $r) } if (!\strlen($out)) { - return false; + return; } return '
'.$out.'
'; diff --git a/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php index cd92b417..69808c7c 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class DepthLimitPlugin extends Plugin implements ObjectPluginInterface +class DepthLimitPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
'.$this->renderLockedHeader($o, 'Depth Limit').'
'; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php index 19c53095..cb53a74f 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php @@ -26,25 +26,25 @@ namespace Kint\Renderer\Rich; use Kint\Kint; -use Kint\Object\Representation\DocstringRepresentation; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\DocstringRepresentation; +use Kint\Zval\Representation\Representation; class DocstringPlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof DocstringRepresentation)) { - return false; + return; } - $docstring = array(); + $docstring = []; foreach (\explode("\n", $r->contents) as $line) { $docstring[] = \trim($line); } $docstring = \implode("\n", $docstring); - $location = array(); + $location = []; if ($r->class) { $location[] = 'Inherited from '.$this->renderer->escape($r->class); diff --git a/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php index a56bb23e..3d06b529 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php @@ -25,16 +25,16 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\MicrotimeRepresentation; -use Kint\Object\Representation\Representation; use Kint\Utils; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Representation\Representation; class MicrotimePlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof MicrotimeRepresentation)) { - return false; + return; } $out = $r->getDateTime()->format('Y-m-d H:i:s.u'); diff --git a/system/ThirdParty/Kint/Renderer/Rich/Plugin.php b/system/ThirdParty/Kint/Renderer/Rich/Plugin.php index 06710bcc..58e22cb2 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/Plugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; use Kint\Renderer\RichRenderer; +use Kint\Zval\Value; abstract class Plugin implements PluginInterface { @@ -40,10 +40,9 @@ public function __construct(RichRenderer $r) /** * Renders a locked header. * - * @param BasicObject $o - * @param string $content + * @param string $content */ - public function renderLockedHeader(BasicObject $o, $content) + public function renderLockedHeader(Value $o, $content) { $header = '
'; diff --git a/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php index 618d2176..baad2ecb 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/RecursionPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -class RecursionPlugin extends Plugin implements ObjectPluginInterface +class RecursionPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { return '
'.$this->renderLockedHeader($o, 'Recursion').'
'; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php index 6c18931e..718cd67a 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php @@ -25,13 +25,13 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\Value; -class SimpleXMLElementPlugin extends Plugin implements ObjectPluginInterface +class SimpleXMLElementPlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { $children = $this->renderer->renderChildren($o); @@ -63,15 +63,11 @@ public function renderObject(BasicObject $o) $header .= '('.$this->renderer->escape($s).') '; } - if (null === $s && $c = $o->getRepresentation('contents')) { - $c = \reset($c->contents); - - if ($c && null !== ($s = $c->getValueShort())) { - if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { - $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; - } - $header .= $this->renderer->escape($s); + if (null !== ($s = $o->getValueShort())) { + if (RichRenderer::$strlen_max) { + $s = Utils::truncateString($s, RichRenderer::$strlen_max); } + $header .= $this->renderer->escape($s); } $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); diff --git a/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php index 5443dbfd..4be024b6 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php @@ -25,15 +25,15 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; -use Kint\Object\Representation\SourceRepresentation; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Representation\SourceRepresentation; class SourcePlugin extends Plugin implements TabPluginInterface { public function renderTab(Representation $r) { if (!($r instanceof SourceRepresentation) || empty($r->source)) { - return false; + return; } $source = $r->source; diff --git a/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php index 7cdbde72..779e13ac 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php @@ -25,9 +25,12 @@ namespace Kint\Renderer\Rich; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; interface TabPluginInterface extends PluginInterface { - public function renderTab(Representation $o); + /** + * @return null|string + */ + public function renderTab(Representation $r); } diff --git a/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php index cc3ee0f0..ac345a16 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TablePlugin.php @@ -25,9 +25,9 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BlobObject; -use Kint\Object\Representation\Representation; use Kint\Renderer\RichRenderer; +use Kint\Utils; +use Kint\Zval\Representation\Representation; class TablePlugin extends Plugin implements TabPluginInterface { @@ -89,8 +89,8 @@ public function renderTab(Representation $r) case 'string': if ($field->encoding) { $val = $field->value->contents; - if (RichRenderer::$strlen_max && self::$respect_str_length && BlobObject::strlen($val) > RichRenderer::$strlen_max) { - $val = \substr($val, 0, RichRenderer::$strlen_max).'...'; + if (RichRenderer::$strlen_max && self::$respect_str_length) { + $val = Utils::truncateString($val, RichRenderer::$strlen_max); } $out .= $this->renderer->escape($val); diff --git a/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php index 6e3a2f8c..f0c58e67 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php @@ -27,7 +27,7 @@ use DateTime; use DateTimeZone; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; class TimestampPlugin extends Plugin implements TabPluginInterface { diff --git a/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php index 6ca19bb6..ea7048bc 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php @@ -25,14 +25,14 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; -use Kint\Object\TraceFrameObject; +use Kint\Zval\TraceFrameValue; +use Kint\Zval\Value; -class TraceFramePlugin extends Plugin implements ObjectPluginInterface +class TraceFramePlugin extends Plugin implements ValuePluginInterface { - public function renderObject(BasicObject $o) + public function renderValue(Value $o) { - if (!$o instanceof TraceFrameObject) { + if (!$o instanceof TraceFrameValue) { return; } diff --git a/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php similarity index 88% rename from system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php rename to system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php index f46aa294..8f750eda 100644 --- a/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php +++ b/system/ThirdParty/Kint/Renderer/Rich/ValuePluginInterface.php @@ -25,9 +25,12 @@ namespace Kint\Renderer\Rich; -use Kint\Object\BasicObject; +use Kint\Zval\Value; -interface ObjectPluginInterface extends PluginInterface +interface ValuePluginInterface extends PluginInterface { - public function renderObject(BasicObject $o); + /** + * @return null|string + */ + public function renderValue(Value $o); } diff --git a/system/ThirdParty/Kint/Renderer/RichRenderer.php b/system/ThirdParty/Kint/Renderer/RichRenderer.php index dcd39eec..94b7f98a 100644 --- a/system/ThirdParty/Kint/Renderer/RichRenderer.php +++ b/system/ThirdParty/Kint/Renderer/RichRenderer.php @@ -26,18 +26,19 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\BlobObject; -use Kint\Object\InstanceObject; -use Kint\Object\Representation\Representation; use Kint\Utils; +use Kint\Zval\BlobValue; +use Kint\Zval\InstanceValue; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Value; class RichRenderer extends Renderer { /** - * RichRenderer object plugins should implement Kint\Renderer\Rich\ObjectPluginInterface. + * RichRenderer value plugins should implement Kint\Renderer\Rich\ValuePluginInterface. */ - public static $object_plugins = array( + public static $value_plugins = [ + 'array_limit' => 'Kint\\Renderer\\Rich\\ArrayLimitPlugin', 'blacklist' => 'Kint\\Renderer\\Rich\\BlacklistPlugin', 'callable' => 'Kint\\Renderer\\Rich\\CallablePlugin', 'closure' => 'Kint\\Renderer\\Rich\\ClosurePlugin', @@ -46,12 +47,12 @@ class RichRenderer extends Renderer 'recursion' => 'Kint\\Renderer\\Rich\\RecursionPlugin', 'simplexml_element' => 'Kint\\Renderer\\Rich\\SimpleXMLElementPlugin', 'trace_frame' => 'Kint\\Renderer\\Rich\\TraceFramePlugin', - ); + ]; /** * RichRenderer tab plugins should implement Kint\Renderer\Rich\TabPluginInterface. */ - public static $tab_plugins = array( + public static $tab_plugins = [ 'binary' => 'Kint\\Renderer\\Rich\\BinaryPlugin', 'color' => 'Kint\\Renderer\\Rich\\ColorPlugin', 'docstring' => 'Kint\\Renderer\\Rich\\DocstringPlugin', @@ -59,18 +60,18 @@ class RichRenderer extends Renderer 'source' => 'Kint\\Renderer\\Rich\\SourcePlugin', 'table' => 'Kint\\Renderer\\Rich\\TablePlugin', 'timestamp' => 'Kint\\Renderer\\Rich\\TimestampPlugin', - ); - - public static $pre_render_sources = array( - 'script' => array( - array('Kint\\Renderer\\RichRenderer', 'renderJs'), - array('Kint\\Renderer\\Rich\\MicrotimePlugin', 'renderJs'), - ), - 'style' => array( - array('Kint\\Renderer\\RichRenderer', 'renderCss'), - ), - 'raw' => array(), - ); + ]; + + public static $pre_render_sources = [ + 'script' => [ + ['Kint\\Renderer\\RichRenderer', 'renderJs'], + ['Kint\\Renderer\\Rich\\MicrotimePlugin', 'renderJs'], + ], + 'style' => [ + ['Kint\\Renderer\\RichRenderer', 'renderCss'], + ], + 'raw' => [], + ]; /** * Whether or not to render access paths. @@ -118,7 +119,7 @@ class RichRenderer extends Renderer * * @var bool */ - public static $folder = true; + public static $folder = false; /** * Sort mode for object properties. @@ -132,7 +133,7 @@ class RichRenderer extends Renderer public static $always_pre_render = false; - protected $plugin_objs = array(); + protected $plugin_objs = []; protected $expand = false; protected $force_pre_render = false; protected $pre_render; @@ -193,7 +194,6 @@ public function setForcePreRender() public function setPreRender($pre_render) { - $this->setForcePreRender(); // TODO: Remove line in next major version $this->pre_render = $pre_render; } @@ -212,10 +212,11 @@ public function getUseFolder() return $this->use_folder; } - public function render(BasicObject $o) + public function render(Value $o) { - if ($plugin = $this->getPlugin(self::$object_plugins, $o->hints)) { - if (\strlen($output = $plugin->renderObject($o))) { + if ($plugin = $this->getPlugin(self::$value_plugins, $o->hints)) { + $output = $plugin->renderValue($o); + if (null !== $output && \strlen($output)) { return $output; } } @@ -231,7 +232,7 @@ public function renderNothing() return '
No argument
'; } - public function renderHeaderWrapper(BasicObject $o, $has_children, $contents) + public function renderHeaderWrapper(Value $o, $has_children, $contents) { $out = ''; } - public function renderHeader(BasicObject $o) + public function renderHeader(Value $o) { $output = ''; @@ -319,10 +320,10 @@ public function renderHeader(BasicObject $o) return \trim($output); } - public function renderChildren(BasicObject $o) + public function renderChildren(Value $o) { - $contents = array(); - $tabs = array(); + $contents = []; + $tabs = []; foreach ($o->getRepresentations() as $rep) { $result = $this->renderTab($o, $rep); @@ -353,10 +354,16 @@ public function renderChildren(BasicObject $o) $output .= $this->escape($tab->getLabel()).''; } - $output .= '
    '; + $output .= '
    '; - foreach ($contents as $tab) { - $output .= '
  • '.$tab.'
  • '; + foreach ($contents as $i => $tab) { + if (0 === $i) { + $output .= '
  • '; + } else { + $output .= '
  • '; + } + + $output .= $tab.'
  • '; } $output .= '
'; @@ -441,7 +448,7 @@ public function postRender() !empty($this->call_info['callee']['class']) || !\in_array( $this->call_info['callee']['function'], - array('include', 'include_once', 'require', 'require_once'), + ['include', 'include_once', 'require', 'require_once'], true ) ) @@ -465,7 +472,7 @@ public function postRender() $output .= '
  • '.$this->ideLink($step['file'], $step['line']); // closing tag not required if (isset($step['function']) - && !\in_array($step['function'], array('include', 'include_once', 'require', 'require_once'), true) + && !\in_array($step['function'], ['include', 'include_once', 'require', 'require_once'], true) ) { $output .= ' ['; if (isset($step['class'])) { @@ -488,7 +495,7 @@ public function postRender() public function escape($string, $encoding = false) { if (false === $encoding) { - $encoding = BlobObject::detectEncoding($string); + $encoding = BlobValue::detectEncoding($string); } $original_encoding = $encoding; @@ -501,7 +508,7 @@ public function escape($string, $encoding = false) // this call converts all non-ASCII characters into numeirc htmlentities if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { - $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + $string = \mb_encode_numericentity($string, [0x80, 0xFFFF, 0, 0xFFFF], $encoding); } return $string; @@ -525,10 +532,11 @@ public function ideLink($file, $line) return ''.$path.''; } - protected function renderTab(BasicObject $o, Representation $rep) + protected function renderTab(Value $o, Representation $rep) { if ($plugin = $this->getPlugin(self::$tab_plugins, $rep->hints)) { - if (\strlen($output = $plugin->renderTab($rep))) { + $output = $plugin->renderTab($rep); + if (null !== $output && \strlen($output)) { return $output; } } @@ -536,7 +544,7 @@ protected function renderTab(BasicObject $o, Representation $rep) if (\is_array($rep->contents)) { $output = ''; - if ($o instanceof InstanceObject && 'properties' === $rep->getName()) { + if ($o instanceof InstanceValue && 'properties' === $rep->getName()) { foreach (self::sortProperties($rep->contents, self::$sort) as $obj) { $output .= $this->render($obj); } @@ -559,7 +567,7 @@ protected function renderTab(BasicObject $o, Representation $rep) } else { if (\preg_match('/(:?[\\r\\n\\t\\f\\v]| {2})/', $rep->contents)) { $show_contents = true; - } elseif (self::$strlen_max && BlobObject::strlen($o->getValueShort()) > self::$strlen_max) { + } elseif (self::$strlen_max && null !== $o->getValueShort() && BlobValue::strlen($o->getValueShort()) > self::$strlen_max) { $show_contents = true; } @@ -573,9 +581,11 @@ protected function renderTab(BasicObject $o, Representation $rep) } } - if ($rep->contents instanceof BasicObject) { + if ($rep->contents instanceof Value) { return $this->render($rep->contents); } + + return ''; } protected function getPlugin(array $plugins, array $hints) @@ -607,6 +617,6 @@ protected static function renderCss() protected static function renderFolder() { - return '
    Kint
    '; + return '
    Kint
    '; } } diff --git a/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php new file mode 100644 index 00000000..12c16f39 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/ArrayLimitPlugin.php @@ -0,0 +1,44 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).' '.$this->renderer->colorValue('ARRAY LIMIT').PHP_EOL; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php index 127d32a1..441368b1 100644 --- a/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class BlacklistPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php index 310b87e4..cea6cdf8 100644 --- a/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class DepthLimitPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php index 9128032c..ce63a544 100644 --- a/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php @@ -25,12 +25,12 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; -use Kint\Object\Representation\MicrotimeRepresentation; use Kint\Renderer\PlainRenderer; use Kint\Renderer\Rich\MicrotimePlugin as RichPlugin; use Kint\Renderer\TextRenderer; use Kint\Utils; +use Kint\Zval\Representation\MicrotimeRepresentation; +use Kint\Zval\Value; class MicrotimePlugin extends Plugin { @@ -45,12 +45,12 @@ public function __construct(TextRenderer $r) } } - public function render(BasicObject $o) + public function render(Value $o) { $r = $o->getRepresentation('microtime'); if (!$r instanceof MicrotimeRepresentation) { - return false; + return; } $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/Plugin.php b/system/ThirdParty/Kint/Renderer/Text/Plugin.php index 9de25c1a..61a1820f 100644 --- a/system/ThirdParty/Kint/Renderer/Text/Plugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/Plugin.php @@ -25,8 +25,8 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; use Kint\Renderer\TextRenderer; +use Kint\Zval\Value; abstract class Plugin { @@ -37,5 +37,8 @@ public function __construct(TextRenderer $r) $this->renderer = $r; } - abstract public function render(BasicObject $o); + /** + * @return null|string + */ + abstract public function render(Value $o); } diff --git a/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php index 72c2257c..21956b6e 100644 --- a/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php @@ -25,11 +25,11 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; +use Kint\Zval\Value; class RecursionPlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; diff --git a/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php index 5833840c..b25f113e 100644 --- a/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php +++ b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php @@ -25,12 +25,12 @@ namespace Kint\Renderer\Text; -use Kint\Object\BasicObject; -use Kint\Object\MethodObject; +use Kint\Zval\MethodValue; +use Kint\Zval\Value; class TracePlugin extends Plugin { - public function render(BasicObject $o) + public function render(Value $o) { $out = ''; @@ -66,7 +66,7 @@ public function render(BasicObject $o) if (\is_string($frame->trace['function'])) { $framedesc .= $this->renderer->escape($frame->trace['function']).'(...)'; - } elseif ($frame->trace['function'] instanceof MethodObject) { + } elseif ($frame->trace['function'] instanceof MethodValue) { $framedesc .= $this->renderer->escape($frame->trace['function']->getName()); $framedesc .= '('.$this->renderer->escape($frame->trace['function']->getParams()).')'; } diff --git a/system/ThirdParty/Kint/Renderer/TextRenderer.php b/system/ThirdParty/Kint/Renderer/TextRenderer.php index 43b6c40d..0cfba527 100644 --- a/system/ThirdParty/Kint/Renderer/TextRenderer.php +++ b/system/ThirdParty/Kint/Renderer/TextRenderer.php @@ -26,33 +26,36 @@ namespace Kint\Renderer; use Kint\Kint; -use Kint\Object\BasicObject; -use Kint\Object\InstanceObject; use Kint\Utils; +use Kint\Zval\InstanceValue; +use Kint\Zval\Value; class TextRenderer extends Renderer { /** * TextRenderer plugins should be instances of Kint\Renderer\Text\Plugin. */ - public static $plugins = array( + public static $plugins = [ + 'array_limit' => 'Kint\\Renderer\\Text\\ArrayLimitPlugin', 'blacklist' => 'Kint\\Renderer\\Text\\BlacklistPlugin', 'depth_limit' => 'Kint\\Renderer\\Text\\DepthLimitPlugin', 'microtime' => 'Kint\\Renderer\\Text\\MicrotimePlugin', 'recursion' => 'Kint\\Renderer\\Text\\RecursionPlugin', 'trace' => 'Kint\\Renderer\\Text\\TracePlugin', - ); + ]; /** * Parser plugins must be instanceof one of these or * it will be removed for performance reasons. */ - public static $parser_plugin_whitelist = array( + public static $parser_plugin_whitelist = [ + 'Kint\\Parser\\ArrayLimitPlugin', + 'Kint\\Parser\\ArrayObjectPlugin', 'Kint\\Parser\\BlacklistPlugin', 'Kint\\Parser\\MicrotimePlugin', 'Kint\\Parser\\StreamPlugin', 'Kint\\Parser\\TracePlugin', - ); + ]; /** * The maximum length of a string before it is truncated. @@ -94,7 +97,7 @@ class TextRenderer extends Renderer public $header_width = 80; public $indent_width = 4; - protected $plugin_objs = array(); + protected $plugin_objs = []; public function __construct() { @@ -102,10 +105,11 @@ public function __construct() $this->indent_width = self::$default_indent; } - public function render(BasicObject $o) + public function render(Value $o) { if ($plugin = $this->getPlugin(self::$plugins, $o->hints)) { - if (\strlen($output = $plugin->render($o))) { + $output = $plugin->render($o); + if (null !== $output && \strlen($output)) { return $output; } } @@ -149,7 +153,7 @@ public function boxText($text, $width) return $out; } - public function renderTitle(BasicObject $o) + public function renderTitle(Value $o) { $name = (string) $o->getName(); @@ -160,9 +164,9 @@ public function renderTitle(BasicObject $o) return Utils::truncateString($name, $this->header_width); } - public function renderHeader(BasicObject $o) + public function renderHeader(Value $o) { - $output = array(); + $output = []; if ($o->depth) { if (null !== ($s = $o->getModifiers())) { @@ -200,7 +204,7 @@ public function renderHeader(BasicObject $o) return \str_repeat(' ', $o->depth * $this->indent_width).\implode(' ', $output); } - public function renderChildren(BasicObject $o) + public function renderChildren(Value $o) { if ('array' === $o->type) { $output = ' ['; @@ -213,7 +217,7 @@ public function renderChildren(BasicObject $o) $children = ''; if ($o->value && \is_array($o->value->contents)) { - if ($o instanceof InstanceObject && 'properties' === $o->value->getName()) { + if ($o instanceof InstanceValue && 'properties' === $o->value->getName()) { foreach (self::sortProperties($o->value->contents, self::$sort) as $obj) { $children .= $this->render($obj); } @@ -274,7 +278,7 @@ public function postRender() public function filterParserPlugins(array $plugins) { - $return = array(); + $return = []; foreach ($plugins as $index => $plugin) { foreach (self::$parser_plugin_whitelist as $whitelist) { @@ -313,7 +317,7 @@ protected function calledFrom() !empty($this->call_info['callee']['class']) || !\in_array( $this->call_info['callee']['function'], - array('include', 'include_once', 'require', 'require_once'), + ['include', 'include_once', 'require', 'require_once'], true ) ) diff --git a/system/ThirdParty/Kint/Utils.php b/system/ThirdParty/Kint/Utils.php index 27a24913..5143731c 100644 --- a/system/ThirdParty/Kint/Utils.php +++ b/system/ThirdParty/Kint/Utils.php @@ -25,8 +25,7 @@ namespace Kint; -use InvalidArgumentException; -use Kint\Object\BlobObject; +use Kint\Zval\BlobValue; use ReflectionNamedType; use ReflectionType; @@ -51,15 +50,36 @@ private function __construct() */ public static function getHumanReadableBytes($value) { - static $unit = array('B', 'KB', 'MB', 'GB', 'TB'); + static $unit = ['B', 'KB', 'MB', 'GB', 'TB']; + + $negative = $value < 0; + $value = \abs($value); + + if ($value < 1024) { + $i = 0; + $value = \floor($value); + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 40) { + $i = 1; + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 30) { + $i = 2; + } elseif ($value < 0xFFFCCCCCCCCCCCC >> 20) { + $i = 3; + } else { + $i = 4; + } - $i = \floor(\log($value, 1024)); - $i = \min($i, 4); // Only go up to TB + if ($i) { + $value = $value / \pow(1024, $i); + } + + if ($negative) { + $value *= -1; + } - return array( - 'value' => (float) ($value / \pow(1024, $i)), + return [ + 'value' => \round($value, 1), 'unit' => $unit[$i], - ); + ]; } public static function isSequential(array $array) @@ -67,9 +87,14 @@ public static function isSequential(array $array) return \array_keys($array) === \range(0, \count($array) - 1); } + public static function isAssoc(array $array) + { + return (bool) \count(\array_filter(\array_keys($array), 'is_string')); + } + public static function composerGetExtras($key = 'kint') { - $extras = array(); + $extras = []; if (0 === \strpos(KINT_DIR, 'phar://')) { // Only run inside phar file, so skip for code coverage @@ -131,7 +156,7 @@ public static function isTrace(array $trace) return false; } - static $bt_structure = array( + static $bt_structure = [ 'function' => 'string', 'line' => 'integer', 'file' => 'string', @@ -139,7 +164,7 @@ public static function isTrace(array $trace) 'object' => 'object', 'type' => 'string', 'args' => 'array', - ); + ]; $file_found = false; @@ -169,7 +194,7 @@ public static function isTrace(array $trace) public static function traceFrameIsListed(array $frame, array $matches) { if (isset($frame['class'])) { - $called = array(\strtolower($frame['class']), \strtolower($frame['function'])); + $called = [\strtolower($frame['class']), \strtolower($frame['function'])]; } else { $called = \strtolower($frame['function']); } @@ -189,10 +214,10 @@ public static function normalizeAliases(array &$aliases) \preg_match('/^'.$name_regex.'$/', $alias[1]) && \preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias[0]) ) { - $alias = array( + $alias = [ \strtolower(\ltrim($alias[0], '\\')), \strtolower($alias[1]), - ); + ]; } else { unset($aliases[$index]); continue; @@ -216,14 +241,15 @@ public static function normalizeAliases(array &$aliases) public static function truncateString($input, $length = PHP_INT_MAX, $end = '...', $encoding = false) { $length = (int) $length; - $endlength = BlobObject::strlen($end); + $endlength = BlobValue::strlen($end); if ($endlength >= $length) { - throw new InvalidArgumentException('Can\'t truncate a string to '.$length.' characters if ending with string '.$endlength.' characters long'); + $endlength = 0; + $end = ''; } - if (BlobObject::strlen($input, $encoding) > $length) { - return BlobObject::substr($input, 0, $length - $endlength, $encoding).$end; + if (BlobValue::strlen($input, $encoding) > $length) { + return BlobValue::substr($input, 0, $length - $endlength, $encoding).$end; } return $input; @@ -232,7 +258,12 @@ public static function truncateString($input, $length = PHP_INT_MAX, $end = '... public static function getTypeString(ReflectionType $type) { if ($type instanceof ReflectionNamedType) { - return $type->getName(); + $name = $type->getName(); + if ($type->allowsNull() && false === \strpos($name, '|')) { + $name = '?'.$name; + } + + return $name; } return (string) $type; // @codeCoverageIgnore diff --git a/system/ThirdParty/Kint/Object/BlobObject.php b/system/ThirdParty/Kint/Zval/BlobValue.php similarity index 95% rename from system/ThirdParty/Kint/Object/BlobObject.php rename to system/ThirdParty/Kint/Zval/BlobValue.php index 66d508ff..c5ac53ac 100644 --- a/system/ThirdParty/Kint/Object/BlobObject.php +++ b/system/ThirdParty/Kint/Zval/BlobValue.php @@ -23,9 +23,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class BlobObject extends BasicObject +class BlobValue extends Value { /** * @var array Character encodings to detect @@ -51,10 +51,10 @@ class BlobObject extends BasicObject * * This depends on the mbstring extension */ - public static $char_encodings = array( + public static $char_encodings = [ 'ASCII', 'UTF-8', - ); + ]; /** * @var array Legacy character encodings to detect @@ -74,11 +74,11 @@ class BlobObject extends BasicObject * * This depends on the iconv extension */ - public static $legacy_encodings = array(); + public static $legacy_encodings = []; public $type = 'string'; public $encoding = false; - public $hints = array('string'); + public $hints = ['string']; public function getType() { @@ -100,7 +100,7 @@ public function getValueShort() } } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); diff --git a/system/ThirdParty/Kint/Object/ClosureObject.php b/system/ThirdParty/Kint/Zval/ClosureValue.php similarity index 91% rename from system/ThirdParty/Kint/Object/ClosureObject.php rename to system/ThirdParty/Kint/Zval/ClosureValue.php index 344eceb2..95dd3fea 100644 --- a/system/ThirdParty/Kint/Object/ClosureObject.php +++ b/system/ThirdParty/Kint/Zval/ClosureValue.php @@ -23,12 +23,12 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class ClosureObject extends InstanceObject +class ClosureValue extends InstanceValue { - public $parameters = array(); - public $hints = array('object', 'callable', 'closure'); + public $parameters = []; + public $hints = ['object', 'callable', 'closure']; private $paramcache; @@ -49,7 +49,7 @@ public function getParams() return $this->paramcache; } - $out = array(); + $out = []; foreach ($this->parameters as $p) { $type = $p->getType(); diff --git a/system/ThirdParty/Kint/Object/DateTimeObject.php b/system/ThirdParty/Kint/Zval/DateTimeValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/DateTimeObject.php rename to system/ThirdParty/Kint/Zval/DateTimeValue.php index f8b1b3fd..1a8084ec 100644 --- a/system/ThirdParty/Kint/Object/DateTimeObject.php +++ b/system/ThirdParty/Kint/Zval/DateTimeValue.php @@ -23,15 +23,15 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use DateTime; -class DateTimeObject extends InstanceObject +class DateTimeValue extends InstanceValue { public $dt; - public $hints = array('object', 'datetime'); + public $hints = ['object', 'datetime']; public function __construct(DateTime $dt) { diff --git a/system/ThirdParty/Kint/Object/InstanceObject.php b/system/ThirdParty/Kint/Zval/InstanceValue.php similarity index 88% rename from system/ThirdParty/Kint/Object/InstanceObject.php rename to system/ThirdParty/Kint/Zval/InstanceValue.php index 943b33d8..1c26600c 100644 --- a/system/ThirdParty/Kint/Object/InstanceObject.php +++ b/system/ThirdParty/Kint/Zval/InstanceValue.php @@ -23,29 +23,29 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class InstanceObject extends BasicObject +class InstanceValue extends Value { public $type = 'object'; public $classname; - public $hash; + public $spl_object_hash; public $filename; public $startline; - public $hints = array('object'); + public $hints = ['object']; public function getType() { return $this->classname; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); if ($old instanceof self) { $this->classname = $old->classname; - $this->hash = $old->hash; + $this->spl_object_hash = $old->spl_object_hash; $this->filename = $old->filename; $this->startline = $old->startline; } @@ -56,7 +56,7 @@ public static function sortByHierarchy($a, $b) if (\is_string($a) && \is_string($b)) { $aclass = $a; $bclass = $b; - } elseif (!($a instanceof BasicObject) || !($b instanceof BasicObject)) { + } elseif (!($a instanceof Value) || !($b instanceof Value)) { return 0; } elseif ($a instanceof self && $b instanceof self) { $aclass = $a->classname; diff --git a/system/ThirdParty/Kint/Object/MethodObject.php b/system/ThirdParty/Kint/Zval/MethodValue.php similarity index 90% rename from system/ThirdParty/Kint/Object/MethodObject.php rename to system/ThirdParty/Kint/Zval/MethodValue.php index 78d49de2..5d59a507 100644 --- a/system/ThirdParty/Kint/Object/MethodObject.php +++ b/system/ThirdParty/Kint/Zval/MethodValue.php @@ -23,27 +23,27 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\DocstringRepresentation; use Kint\Utils; +use Kint\Zval\Representation\DocstringRepresentation; use ReflectionFunctionAbstract; use ReflectionMethod; -class MethodObject extends BasicObject +class MethodValue extends Value { public $type = 'method'; public $filename; public $startline; public $endline; - public $parameters = array(); + public $parameters = []; public $abstract; public $final; public $internal; public $docstring; public $returntype; public $return_reference = false; - public $hints = array('callable', 'method'); + public $hints = ['callable', 'method']; public $showparams = true; private $paramcache; @@ -61,7 +61,7 @@ public function __construct(ReflectionFunctionAbstract $method) $this->return_reference = $method->returnsReference(); foreach ($method->getParameters() as $param) { - $this->parameters[] = new ParameterObject($param); + $this->parameters[] = new ParameterValue($param); } if (KINT_PHP70) { @@ -73,15 +73,15 @@ public function __construct(ReflectionFunctionAbstract $method) if ($method instanceof ReflectionMethod) { $this->static = $method->isStatic(); - $this->operator = $this->static ? BasicObject::OPERATOR_STATIC : BasicObject::OPERATOR_OBJECT; + $this->operator = $this->static ? Value::OPERATOR_STATIC : Value::OPERATOR_OBJECT; $this->abstract = $method->isAbstract(); $this->final = $method->isFinal(); $this->owner_class = $method->getDeclaringClass()->name; - $this->access = BasicObject::ACCESS_PUBLIC; + $this->access = Value::ACCESS_PUBLIC; if ($method->isProtected()) { - $this->access = BasicObject::ACCESS_PROTECTED; + $this->access = Value::ACCESS_PROTECTED; } elseif ($method->isPrivate()) { - $this->access = BasicObject::ACCESS_PRIVATE; + $this->access = Value::ACCESS_PRIVATE; } } @@ -100,9 +100,9 @@ public function __construct(ReflectionFunctionAbstract $method) $this->value = $docstring; } - public function setAccessPathFrom(InstanceObject $parent) + public function setAccessPathFrom(InstanceValue $parent) { - static $magic = array( + static $magic = [ '__call' => true, '__callstatic' => true, '__clone' => true, @@ -118,7 +118,7 @@ public function setAccessPathFrom(InstanceObject $parent) '__tostring' => true, '__unset' => true, '__wakeup' => true, - ); + ]; $name = \strtolower($this->name); @@ -172,12 +172,12 @@ public function getValueShort() public function getModifiers() { - $mods = array( + $mods = [ $this->abstract ? 'abstract' : null, $this->final ? 'final' : null, $this->getAccess(), $this->static ? 'static' : null, - ); + ]; $out = ''; @@ -209,7 +209,7 @@ public function getParams() return $this->paramcache; } - $out = array(); + $out = []; foreach ($this->parameters as $p) { $type = $p->getType(); diff --git a/system/ThirdParty/Kint/Object/ParameterObject.php b/system/ThirdParty/Kint/Zval/ParameterValue.php similarity index 95% rename from system/ThirdParty/Kint/Object/ParameterObject.php rename to system/ThirdParty/Kint/Zval/ParameterValue.php index 4bed551f..29bcbe72 100644 --- a/system/ThirdParty/Kint/Object/ParameterObject.php +++ b/system/ThirdParty/Kint/Zval/ParameterValue.php @@ -23,18 +23,18 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Kint\Utils; use ReflectionException; use ReflectionParameter; -class ParameterObject extends BasicObject +class ParameterValue extends Value { public $type_hint; public $default; public $position; - public $hints = array('parameter'); + public $hints = ['parameter']; public function __construct(ReflectionParameter $param) { @@ -64,7 +64,6 @@ public function __construct(ReflectionParameter $param) $this->position = $param->getPosition(); if ($param->isDefaultValueAvailable()) { - /** @var mixed Psalm bug workaround */ $default = $param->getDefaultValue(); switch (\gettype($default)) { case 'NULL': diff --git a/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php index d6a072f5..533ccb35 100644 --- a/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/ColorRepresentation.php @@ -23,7 +23,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use InvalidArgumentException; @@ -39,7 +39,7 @@ class ColorRepresentation extends Representation const COLOR_HEX_4 = 8; const COLOR_HEX_8 = 9; - public static $color_map = array( + public static $color_map = [ 'aliceblue' => 'f0f8ff', 'antiquewhite' => 'faebd7', 'aqua' => '00ffff', @@ -191,7 +191,7 @@ class ColorRepresentation extends Representation 'whitesmoke' => 'f5f5f5', 'yellow' => 'ffff00', 'yellowgreen' => '9acd32', - ); + ]; public $r = 0; public $g = 0; @@ -199,7 +199,7 @@ class ColorRepresentation extends Representation public $a = 1.0; public $variant; public $implicit_label = true; - public $hints = array('color'); + public $hints = ['color']; public function __construct($value) { @@ -254,7 +254,7 @@ public function getColor($variant = null) return \sprintf('hsla(%d, %d%%, %d%%, %s)', $val[0], $val[1], $val[2], \round($this->a, 4)); case self::COLOR_HEX_4: - if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11 && 0 === ($this->a * 255) % 0x11) { + if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11 && 0 === ((int) ($this->a * 255)) % 0x11) { return \sprintf( '#%1X%1X%1X%1X', \round($this->r / 0x11), @@ -413,21 +413,19 @@ protected function setValuesFromFunction($value) if (3 === $i) { $color = $color / 100; - } elseif (\in_array($variant, array(self::COLOR_RGB, self::COLOR_RGBA), true)) { + } elseif (\in_array($variant, [self::COLOR_RGB, self::COLOR_RGBA], true)) { $color = \round($color / 100 * 0xFF); } } $color = (float) $color; - if (0 === $i && \in_array($variant, array(self::COLOR_HSL, self::COLOR_HSLA), true)) { - $color = ($color % 360 + 360) % 360; + if (0 === $i && \in_array($variant, [self::COLOR_HSL, self::COLOR_HSLA], true)) { + $color = \fmod(\fmod($color, 360) + 360, 360); } } - /** @var float[] Psalm bug workaround */ - $params = \array_map('floatval', $params); - + /** @var non-empty-array $params Psalm bug workaround */ switch ($variant) { case self::COLOR_RGBA: case self::COLOR_RGB: @@ -486,11 +484,11 @@ public static function hslToRgb($h, $s, $l) $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l * $s; $m1 = $l * 2 - $m2; - return array( + return [ (int) \round(self::hueToRgb($m1, $m2, $h + 1 / 3) * 0xFF), (int) \round(self::hueToRgb($m1, $m2, $h) * 0xFF), (int) \round(self::hueToRgb($m1, $m2, $h - 1 / 3) * 0xFF), - ); + ]; } /** @@ -541,17 +539,16 @@ public static function rgbToHsl($red, $green, $blue) } } - return array( - (float) ($H * 360 % 360), + return [ + \fmod($H * 360, 360), (float) ($S * 100), (float) ($L * 100), - ); + ]; } /** * Helper function for hslToRgb. Even blacker magic. * - * * @param float $m1 * @param float $m2 * @param float $hue diff --git a/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php similarity index 97% rename from system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php index 488d8d6e..8acdcc1e 100644 --- a/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/DocstringRepresentation.php @@ -23,14 +23,14 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class DocstringRepresentation extends Representation { public $file; public $line; public $class; - public $hints = array('docstring'); + public $hints = ['docstring']; public function __construct($docstring, $file, $line, $class = null) { diff --git a/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php index b9f4dacb..aedc2edf 100644 --- a/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/MicrotimeRepresentation.php @@ -23,7 +23,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use DateTime; @@ -40,7 +40,7 @@ class MicrotimeRepresentation extends Representation public $mem_real = 0; public $mem_peak = 0; public $mem_peak_real = 0; - public $hints = array('microtime'); + public $hints = ['microtime']; public function __construct($seconds, $microseconds, $group, $lap = null, $total = null, $i = 0) { diff --git a/system/ThirdParty/Kint/Object/Representation/Representation.php b/system/ThirdParty/Kint/Zval/Representation/Representation.php similarity index 95% rename from system/ThirdParty/Kint/Object/Representation/Representation.php rename to system/ThirdParty/Kint/Zval/Representation/Representation.php index 0c911a4e..2d649d07 100644 --- a/system/ThirdParty/Kint/Object/Representation/Representation.php +++ b/system/ThirdParty/Kint/Zval/Representation/Representation.php @@ -23,14 +23,14 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class Representation { public $label; public $implicit_label = false; - public $hints = array(); - public $contents = array(); + public $hints = []; + public $contents = []; protected $name; diff --git a/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php similarity index 96% rename from system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php index c2cf1204..65077d62 100644 --- a/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/SourceRepresentation.php @@ -23,12 +23,12 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; class SourceRepresentation extends Representation { - public $hints = array('source'); - public $source = array(); + public $hints = ['source']; + public $source = []; public $filename; public $line = 0; public $showfilename = false; diff --git a/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php similarity index 95% rename from system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php rename to system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php index 3df50e6a..6208451b 100644 --- a/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php +++ b/system/ThirdParty/Kint/Zval/Representation/SplFileInfoRepresentation.php @@ -23,29 +23,29 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object\Representation; +namespace Kint\Zval\Representation; use Kint\Utils; use SplFileInfo; class SplFileInfoRepresentation extends Representation { - public $perms; + public $perms = null; public $flags; public $path; - public $realpath; - public $linktarget; + public $realpath = null; + public $linktarget = null; public $size; public $is_dir = false; public $is_file = false; public $is_link = false; - public $owner; - public $group; + public $owner = null; + public $group = null; public $ctime; public $mtime; public $typename = 'Unknown file'; public $typeflag = '-'; - public $hints = array('fspath'); + public $hints = ['fspath']; public function __construct(SplFileInfo $fileInfo) { @@ -109,7 +109,7 @@ public function __construct(SplFileInfo $fileInfo) break; } - $this->flags = array($this->typeflag); + $this->flags = [$this->typeflag]; // User $this->flags[] = (($this->perms & 0400) ? 'r' : '-'); diff --git a/system/ThirdParty/Kint/Object/ResourceObject.php b/system/ThirdParty/Kint/Zval/ResourceValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/ResourceObject.php rename to system/ThirdParty/Kint/Zval/ResourceValue.php index a43f85d9..ef1c5541 100644 --- a/system/ThirdParty/Kint/Object/ResourceObject.php +++ b/system/ThirdParty/Kint/Zval/ResourceValue.php @@ -23,9 +23,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class ResourceObject extends BasicObject +class ResourceValue extends Value { public $resource_type; @@ -38,7 +38,7 @@ public function getType() return 'resource'; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { parent::transplant($old); diff --git a/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php b/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php new file mode 100644 index 00000000..b385bc6d --- /dev/null +++ b/system/ThirdParty/Kint/Zval/SimpleXMLElementValue.php @@ -0,0 +1,48 @@ +is_string_value = $is_string_value; + } + + public function getValueShort() + { + if ($this->is_string_value && ($rep = $this->value) && 'contents' === $rep->getName() && 'string' === \gettype($rep->contents)) { + return '"'.$rep->contents.'"'; + } + } +} diff --git a/system/ThirdParty/Kint/Object/StreamObject.php b/system/ThirdParty/Kint/Zval/StreamValue.php similarity index 96% rename from system/ThirdParty/Kint/Object/StreamObject.php rename to system/ThirdParty/Kint/Zval/StreamValue.php index 358f2743..af909c84 100644 --- a/system/ThirdParty/Kint/Object/StreamObject.php +++ b/system/ThirdParty/Kint/Zval/StreamValue.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Kint\Kint; -class StreamObject extends ResourceObject +class StreamValue extends ResourceValue { public $stream_meta; diff --git a/system/ThirdParty/Kint/Object/ThrowableObject.php b/system/ThirdParty/Kint/Zval/ThrowableValue.php similarity index 88% rename from system/ThirdParty/Kint/Object/ThrowableObject.php rename to system/ThirdParty/Kint/Zval/ThrowableValue.php index 2a86d575..26676481 100644 --- a/system/ThirdParty/Kint/Object/ThrowableObject.php +++ b/system/ThirdParty/Kint/Zval/ThrowableValue.php @@ -23,21 +23,21 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; use Exception; use InvalidArgumentException; use Throwable; -class ThrowableObject extends InstanceObject +class ThrowableValue extends InstanceValue { public $message; - public $hints = array('object', 'throwable'); + public $hints = ['object', 'throwable']; public function __construct($throw) { if (!$throw instanceof Exception && (!KINT_PHP70 || !$throw instanceof Throwable)) { - throw new InvalidArgumentException('ThrowableObject must be constructed with a Throwable'); + throw new InvalidArgumentException('ThrowableValue must be constructed with a Throwable'); } parent::__construct(); diff --git a/system/ThirdParty/Kint/Object/TraceFrameObject.php b/system/ThirdParty/Kint/Zval/TraceFrameValue.php similarity index 81% rename from system/ThirdParty/Kint/Object/TraceFrameObject.php rename to system/ThirdParty/Kint/Zval/TraceFrameValue.php index 4259aeee..62f78291 100644 --- a/system/ThirdParty/Kint/Object/TraceFrameObject.php +++ b/system/ThirdParty/Kint/Zval/TraceFrameValue.php @@ -23,52 +23,57 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\Representation; -use Kint\Object\Representation\SourceRepresentation; +use InvalidArgumentException; +use Kint\Zval\Representation\Representation; +use Kint\Zval\Representation\SourceRepresentation; use ReflectionFunction; use ReflectionMethod; -class TraceFrameObject extends BasicObject +class TraceFrameValue extends Value { public $trace; - public $hints = array('trace_frame'); + public $hints = ['trace_frame']; - public function __construct(BasicObject $base, array $raw_frame) + public function __construct(Value $base, array $raw_frame) { parent::__construct(); $this->transplant($base); - $this->trace = array( - 'function' => isset($raw_frame['function']) ? $raw_frame['function'] : null, + if (!isset($this->value)) { + throw new InvalidArgumentException('Tried to create TraceFrameValue from Value with no value representation'); + } + + $this->trace = [ + 'function' => $raw_frame['function'], 'line' => isset($raw_frame['line']) ? $raw_frame['line'] : null, 'file' => isset($raw_frame['file']) ? $raw_frame['file'] : null, 'class' => isset($raw_frame['class']) ? $raw_frame['class'] : null, 'type' => isset($raw_frame['type']) ? $raw_frame['type'] : null, 'object' => null, 'args' => null, - ); + ]; if ($this->trace['class'] && \method_exists($this->trace['class'], $this->trace['function'])) { $func = new ReflectionMethod($this->trace['class'], $this->trace['function']); - $this->trace['function'] = new MethodObject($func); + $this->trace['function'] = new MethodValue($func); } elseif (!$this->trace['class'] && \function_exists($this->trace['function'])) { $func = new ReflectionFunction($this->trace['function']); - $this->trace['function'] = new MethodObject($func); + $this->trace['function'] = new MethodValue($func); } foreach ($this->value->contents as $frame_prop) { if ('object' === $frame_prop->name) { $this->trace['object'] = $frame_prop; $this->trace['object']->name = null; - $this->trace['object']->operator = BasicObject::OPERATOR_NONE; + $this->trace['object']->operator = Value::OPERATOR_NONE; } if ('args' === $frame_prop->name) { $this->trace['args'] = $frame_prop->value->contents; - if ($this->trace['function'] instanceof MethodObject) { + if ($this->trace['function'] instanceof MethodValue) { foreach (\array_values($this->trace['function']->parameters) as $param) { if (isset($this->trace['args'][$param->position])) { $this->trace['args'][$param->position]->name = $param->getName(); diff --git a/system/ThirdParty/Kint/Object/TraceObject.php b/system/ThirdParty/Kint/Zval/TraceValue.php similarity index 93% rename from system/ThirdParty/Kint/Object/TraceObject.php rename to system/ThirdParty/Kint/Zval/TraceValue.php index a780b082..4d0edc42 100644 --- a/system/ThirdParty/Kint/Object/TraceObject.php +++ b/system/ThirdParty/Kint/Zval/TraceValue.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -class TraceObject extends BasicObject +class TraceValue extends Value { - public $hints = array('trace'); + public $hints = ['trace']; public function getType() { diff --git a/system/ThirdParty/Kint/Object/BasicObject.php b/system/ThirdParty/Kint/Zval/Value.php similarity index 91% rename from system/ThirdParty/Kint/Object/BasicObject.php rename to system/ThirdParty/Kint/Zval/Value.php index d69347eb..747efb5f 100644 --- a/system/ThirdParty/Kint/Object/BasicObject.php +++ b/system/ThirdParty/Kint/Zval/Value.php @@ -23,11 +23,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace Kint\Object; +namespace Kint\Zval; -use Kint\Object\Representation\Representation; +use Kint\Zval\Representation\Representation; -class BasicObject +class Value { const ACCESS_NONE = null; const ACCESS_PUBLIC = 1; @@ -51,9 +51,9 @@ class BasicObject public $depth = 0; public $size; public $value; - public $hints = array(); + public $hints = []; - protected $representations = array(); + protected $representations = []; public function __construct() { @@ -70,7 +70,7 @@ public function addRepresentation(Representation $rep, $pos = null) } else { $this->representations = \array_merge( \array_slice($this->representations, 0, $pos), - array($rep->getName() => $rep), + [$rep->getName() => $rep], \array_slice($this->representations, $pos) ); } @@ -111,7 +111,7 @@ public function getRepresentations() public function clearRepresentations() { - $this->representations = array(); + $this->representations = []; } public function getType() @@ -131,7 +131,7 @@ public function getModifiers() $out .= ' static'; } - if (\strlen($out)) { + if (null !== $out && \strlen($out)) { return \ltrim($out); } } @@ -188,7 +188,7 @@ public function getAccessPath() return $this->access_path; } - public function transplant(BasicObject $old) + public function transplant(Value $old) { $this->name = $old->name; $this->size = $old->size; @@ -212,7 +212,7 @@ public function transplant(BasicObject $old) * @param null|string $name * @param null|string $access_path * - * @return \Kint\Object\BasicObject + * @return \Kint\Zval\Value */ public static function blank($name = null, $access_path = null) { @@ -223,19 +223,19 @@ public static function blank($name = null, $access_path = null) return $o; } - public static function sortByAccess(BasicObject $a, BasicObject $b) + public static function sortByAccess(Value $a, Value $b) { - static $sorts = array( + static $sorts = [ self::ACCESS_PUBLIC => 1, self::ACCESS_PROTECTED => 2, self::ACCESS_PRIVATE => 3, self::ACCESS_NONE => 4, - ); + ]; return $sorts[$a->access] - $sorts[$b->access]; } - public static function sortByName(BasicObject $a, BasicObject $b) + public static function sortByName(Value $a, Value $b) { $ret = \strnatcasecmp($a->name, $b->name); diff --git a/system/ThirdParty/Kint/init.php b/system/ThirdParty/Kint/init.php index 952e0414..2e7c62b4 100644 --- a/system/ThirdParty/Kint/init.php +++ b/system/ThirdParty/Kint/init.php @@ -30,31 +30,33 @@ return; } -if (\version_compare(PHP_VERSION, '5.3') < 0) { - throw new Exception('Kint 3.0 requires PHP 5.3 or higher'); +if (\version_compare(PHP_VERSION, '5.6') < 0) { + throw new Exception('Kint 4.0 requires PHP 5.6 or higher'); } \define('KINT_DIR', __DIR__); \define('KINT_WIN', DIRECTORY_SEPARATOR !== '/'); -\define('KINT_PHP56', (\version_compare(PHP_VERSION, '5.6') >= 0)); \define('KINT_PHP70', (\version_compare(PHP_VERSION, '7.0') >= 0)); +\define('KINT_PHP71', (\version_compare(PHP_VERSION, '7.1') >= 0)); \define('KINT_PHP72', (\version_compare(PHP_VERSION, '7.2') >= 0)); \define('KINT_PHP73', (\version_compare(PHP_VERSION, '7.3') >= 0)); \define('KINT_PHP74', (\version_compare(PHP_VERSION, '7.4') >= 0)); +\define('KINT_PHP80', (\version_compare(PHP_VERSION, '8.0') >= 0)); +\define('KINT_PHP81', (\version_compare(PHP_VERSION, '8.1') >= 0)); // Dynamic default settings Kint::$file_link_format = \ini_get('xdebug.file_link_format'); if (isset($_SERVER['DOCUMENT_ROOT'])) { - Kint::$app_root_dirs = array( + Kint::$app_root_dirs = [ $_SERVER['DOCUMENT_ROOT'] => '', \realpath($_SERVER['DOCUMENT_ROOT']) => '', - ); + ]; } Utils::composerSkipFlags(); if ((!\defined('KINT_SKIP_FACADE') || !KINT_SKIP_FACADE) && !\class_exists('Kint')) { - \class_alias('Kint\\Kint', 'Kint'); + \class_alias(Kint::class, 'Kint'); } if (!\defined('KINT_SKIP_HELPERS') || !KINT_SKIP_HELPERS) { diff --git a/system/ThirdParty/Kint/init_helpers.php b/system/ThirdParty/Kint/init_helpers.php index b961d67f..3dca84c3 100644 --- a/system/ThirdParty/Kint/init_helpers.php +++ b/system/ThirdParty/Kint/init_helpers.php @@ -24,6 +24,7 @@ */ use Kint\Kint; +use Kint\Renderer\CliRenderer; if (!\function_exists('d')) { /** @@ -35,7 +36,7 @@ function d() { $args = \func_get_args(); - return \call_user_func_array(array('Kint', 'dump'), $args); + return \call_user_func_array(['Kint', 'dump'], $args); } Kint::$aliases[] = 'd'; @@ -59,23 +60,28 @@ function d() */ function s() { - if (!Kint::$enabled_mode) { + if (false === Kint::$enabled_mode) { return 0; } - $stash = Kint::$enabled_mode; + $kstash = Kint::$enabled_mode; + $cstash = CliRenderer::$cli_colors; if (Kint::MODE_TEXT !== Kint::$enabled_mode) { Kint::$enabled_mode = Kint::MODE_PLAIN; + if (PHP_SAPI === 'cli' && true === Kint::$cli_detection) { Kint::$enabled_mode = Kint::$mode_default_cli; } } + CliRenderer::$cli_colors = false; + $args = \func_get_args(); - $out = \call_user_func_array(array('Kint', 'dump'), $args); + $out = \call_user_func_array(['Kint', 'dump'], $args); - Kint::$enabled_mode = $stash; + Kint::$enabled_mode = $kstash; + CliRenderer::$cli_colors = $cstash; return $out; } diff --git a/system/ThirdParty/Kint/resources/compiled/aante-light.css b/system/ThirdParty/Kint/resources/compiled/aante-light.css index 2de17acc..dc7a40a7 100644 --- a/system/ThirdParty/Kint/resources/compiled/aante-light.css +++ b/system/ThirdParty/Kint/resources/compiled/aante-light.css @@ -1 +1 @@ -.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#aaa;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#aaa}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxwYXRoIGQ9Ik02IDdoMThsLTkgMTV6bTAgMzBoMThsLTkgMTV6bTAgNDVoMThsLTktMTV6bTAgMzBoMThsLTktMTV6bTAgMTJsMTggMThtLTE4IDBsMTgtMTgiIGZpbGw9IiM1NTUiLz48cGF0aCBkPSJNNiAxMjZsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSIjNTU1Ii8+PC9zdmc+") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #d7d7d7}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#06f;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:red}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#f8f8f8;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#f8f8f8}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #d7d7d7;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#f8f8f8;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#f8f8f8;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f8f8f8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#f8f8f8;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #d7d7d7}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}.kint-rich ul.kint-tabs>li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#aaa;color:red}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#aaa;color:red}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #d7d7d7;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#aaa}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}.kint-rich table td{background:#f8f8f8;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}.kint-rich table tr:hover var{color:red}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #f8f8f8}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #aaa;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#f8f8f8}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #aaa,0 1px #aaa,1px 0 #aaa,0 -1px #aaa;color:#f8f8f8;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich dt{font-weight:normal}.kint-rich dt.kint-parent{margin-top:4px}.kint-rich dl dl{margin-top:4px;padding-left:25px;border-left:none}.kint-rich>dl>dt{background:#f8f8f8}.kint-rich ul{margin:0;padding-left:0}.kint-rich ul:not(.kint-tabs)>li{border-left:0}.kint-rich ul.kint-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}.kint-rich ul.kint-tabs li,.kint-rich ul.kint-tabs li+li{margin:0 0 0 4px}.kint-rich ul.kint-tabs li{border-bottom-width:0;height:25px}.kint-rich ul.kint-tabs li:first-child{margin-left:0}.kint-rich ul.kint-tabs li.kint-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}.kint-rich ul.kint-tabs li.kint-active-tab:hover{border-bottom:1px solid #fff}.kint-rich ul>li>pre{border:1px solid #d7d7d7}.kint-rich dt:hover+dd>ul{border-color:#aaa}.kint-rich pre{background:#fff;margin-top:4px;margin-left:25px}.kint-rich .kint-source{margin-left:-1px}.kint-rich .kint-source .kint-highlight{background:#cfc}.kint-rich .kint-parent.kint-show>.kint-search{border-bottom-width:1px}.kint-rich table td{background:#fff}.kint-rich table td>dl{padding:0;margin:0}.kint-rich table td>dl>dt.kint-parent{margin:0}.kint-rich table td:first-child,.kint-rich table td,.kint-rich table th{padding:2px 4px}.kint-rich table dd,.kint-rich table dt{background:#fff}.kint-rich table tr:hover>td{box-shadow:none;background:#cfc} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#aaa;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#aaa}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxwYXRoIGQ9Ik02IDdoMThsLTkgMTV6bTAgMzBoMThsLTkgMTV6bTAgNDVoMThsLTktMTV6bTAgMzBoMThsLTktMTV6bTAgMTJsMTggMThtLTE4IDBsMTgtMTgiIGZpbGw9IiM1NTUiLz48cGF0aCBkPSJNNiAxMjZsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSIjNTU1Ii8+PC9zdmc+") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #d7d7d7}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#06f;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:red}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#f8f8f8;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#f8f8f8}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #d7d7d7;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#f8f8f8;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#f8f8f8;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f8f8f8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#f8f8f8;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #d7d7d7}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}.kint-rich ul.kint-tabs>li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#aaa;color:red}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#aaa;color:red}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #d7d7d7;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#aaa}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}.kint-rich table td{background:#f8f8f8;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}.kint-rich table tr:hover var{color:red}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #f8f8f8}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #aaa;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#f8f8f8}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #aaa,0 1px #aaa,1px 0 #aaa,0 -1px #aaa;color:#f8f8f8;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich dt{font-weight:normal}.kint-rich dt.kint-parent{margin-top:4px}.kint-rich dl dl{margin-top:4px;padding-left:25px;border-left:none}.kint-rich>dl>dt{background:#f8f8f8}.kint-rich ul{margin:0;padding-left:0}.kint-rich ul:not(.kint-tabs)>li{border-left:0}.kint-rich ul.kint-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}.kint-rich ul.kint-tabs li,.kint-rich ul.kint-tabs li+li{margin:0 0 0 4px}.kint-rich ul.kint-tabs li{border-bottom-width:0;height:25px}.kint-rich ul.kint-tabs li:first-child{margin-left:0}.kint-rich ul.kint-tabs li.kint-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}.kint-rich ul.kint-tabs li.kint-active-tab:hover{border-bottom:1px solid #fff}.kint-rich ul>li>pre{border:1px solid #d7d7d7}.kint-rich dt:hover+dd>ul{border-color:#aaa}.kint-rich pre{background:#fff;margin-top:4px;margin-left:25px}.kint-rich .kint-source{margin-left:-1px}.kint-rich .kint-source .kint-highlight{background:#cfc}.kint-rich .kint-parent.kint-show>.kint-search{border-bottom-width:1px}.kint-rich table td{background:#fff}.kint-rich table td>dl{padding:0;margin:0}.kint-rich table td>dl>dt.kint-parent{margin:0}.kint-rich table td:first-child,.kint-rich table td,.kint-rich table th{padding:2px 4px}.kint-rich table dd,.kint-rich table dt{background:#fff}.kint-rich table tr:hover>td{box-shadow:none;background:#cfc} diff --git a/system/ThirdParty/Kint/resources/compiled/microtime.js b/system/ThirdParty/Kint/resources/compiled/microtime.js index 20e3445b..c9b8f00a 100644 --- a/system/ThirdParty/Kint/resources/compiled/microtime.js +++ b/system/ThirdParty/Kint/resources/compiled/microtime.js @@ -1 +1 @@ -void 0===window.kintMicrotimeInitialized&&(window.kintMicrotimeInitialized=1,window.addEventListener("load",function(){"use strict";var c={},i=Array.prototype.slice.call(document.querySelectorAll("[data-kint-microtime-group]"),0);i.forEach(function(i){if(i.querySelector(".kint-microtime-lap")){var t=i.getAttribute("data-kint-microtime-group"),e=parseFloat(i.querySelector(".kint-microtime-lap").innerHTML),r=parseFloat(i.querySelector(".kint-microtime-avg").innerHTML);void 0===c[t]&&(c[t]={}),(void 0===c[t].min||c[t].min>e)&&(c[t].min=e),(void 0===c[t].max||c[t].maxe)&&(a[i].min=e),(void 0===a[i].max||a[i].maxdl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxnIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEgMWgyOHYyOEgxem01IDE0aDE4bS05IDlWNk0xIDYxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzM3OSIvPjxwYXRoIGQ9Ik0xIDMxaDI4djI4SDF6bTUgMTRoMThtLTkgOVYzNk0xIDkxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzVBMyIvPjxwYXRoIGQ9Ik0xIDEyMWgyOHYyOEgxem01IDVsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZT0iI0NDQyIvPjwvZz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #b6cedb}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#0092db;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#5cb730}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#e0eaef;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#e0eaef}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #b6cedb;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#c1d4df;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#d0d0d0;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#e8e8e8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#c1d4df;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #b6cedb}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint-rich ul.kint-tabs>li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#0092db;color:#5cb730}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db;color:#5cb730}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #b6cedb;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#0092db}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #b6cedb;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-rich table td{background:#e0eaef;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-rich table tr:hover var{color:#5cb730}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #c1d4df}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #0092db;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#c1d4df}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #0092db,0 1px #0092db,1px 0 #0092db,0 -1px #0092db;color:#e0eaef;font-weight:bold}.kint-rich>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}.kint-rich ul.kint-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li{background:#e0eaef}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint-rich>dl.kint-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}.kint-rich .kint-source .kint-highlight{background:#f0eb96} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#0092db;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #5cb730}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#e0eaef;border:1px solid #b6cedb;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#0092db}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxnIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEgMWgyOHYyOEgxem01IDE0aDE4bS05IDlWNk0xIDYxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzM3OSIvPjxwYXRoIGQ9Ik0xIDMxaDI4djI4SDF6bTUgMTRoMThtLTkgOVYzNk0xIDkxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzVBMyIvPjxwYXRoIGQ9Ik0xIDEyMWgyOHYyOEgxem01IDVsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZT0iI0NDQyIvPjwvZz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #b6cedb}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#0092db;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#5cb730}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#e0eaef;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#e0eaef}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #b6cedb;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#c1d4df;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#d0d0d0;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#e8e8e8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#c1d4df;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #b6cedb}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint-rich ul.kint-tabs>li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#0092db;color:#5cb730}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db;color:#5cb730}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #b6cedb;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#0092db}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #b6cedb;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-rich table td{background:#e0eaef;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-rich table tr:hover var{color:#5cb730}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #c1d4df}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #0092db;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#c1d4df}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #0092db,0 1px #0092db,1px 0 #0092db,0 -1px #0092db;color:#e0eaef;font-weight:bold}.kint-rich>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}.kint-rich ul.kint-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li{background:#e0eaef}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint-rich>dl.kint-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}.kint-rich .kint-source .kint-highlight{background:#f0eb96} diff --git a/system/ThirdParty/Kint/resources/compiled/rich.js b/system/ThirdParty/Kint/resources/compiled/rich.js index 18fb072e..5648cda6 100644 --- a/system/ThirdParty/Kint/resources/compiled/rich.js +++ b/system/ThirdParty/Kint/resources/compiled/rich.js @@ -1 +1 @@ -void 0===window.kintRich&&(window.kintRich=function(){"use strict";var n={selectText:function(e){var t=window.getSelection(),a=document.createRange();a.selectNodeContents(e),t.removeAllRanges(),t.addRange(a)},each:function(e,t){Array.prototype.slice.call(document.querySelectorAll(e),0).forEach(t)},hasClass:function(e,t){return!!e.classList&&(void 0===t&&(t="kint-show"),e.classList.contains(t))},addClass:function(e,t){void 0===t&&(t="kint-show"),e.classList.add(t)},removeClass:function(e,t){return void 0===t&&(t="kint-show"),e.classList.remove(t),e},toggle:function(e,t){var a=n.getChildren(e);a&&(void 0===t&&(t=n.hasClass(e)),t?n.removeClass(e):n.addClass(e),1===a.childNodes.length&&(a=a.childNodes[0].childNodes[0])&&n.hasClass(a,"kint-parent")&&n.toggle(a,t))},toggleChildren:function(e,t){var a=n.getChildren(e);if(a){var r=a.getElementsByClassName("kint-parent"),o=r.length;for(void 0===t&&(t=!n.hasClass(e));o--;)n.toggle(r[o],t)}},toggleAll:function(e){for(var t=document.getElementsByClassName("kint-parent"),a=t.length,r=!n.hasClass(e.parentNode);a--;)n.toggle(t[a],r)},switchTab:function(e){var t,a=e.previousSibling,r=0;for(n.removeClass(e.parentNode.getElementsByClassName("kint-active-tab")[0],"kint-active-tab"),n.addClass(e,"kint-active-tab");a;)1===a.nodeType&&r++,a=a.previousSibling;t=e.parentNode.nextSibling.childNodes;for(var o=0;o"},openInNewWindow:function(e){var t=window.open();t&&(t.document.open(),t.document.write(n.mktag("html")+n.mktag("head")+n.mktag("title")+"Kint ("+(new Date).toISOString()+")"+n.mktag("/title")+n.mktag('meta charset="utf-8"')+document.getElementsByClassName("kint-rich-script")[0].outerHTML+document.getElementsByClassName("kint-rich-style")[0].outerHTML+n.mktag("/head")+n.mktag("body")+'
    '+e.parentNode.outerHTML+"
    "+n.mktag("/body")),t.document.close())},sortTable:function(e,a){var t=e.tBodies[0];[].slice.call(e.tBodies[0].rows).sort(function(e,t){if(e=e.cells[a].textContent.trim().toLocaleLowerCase(),t=t.cells[a].textContent.trim().toLocaleLowerCase(),isNaN(e)||isNaN(t)){if(isNaN(e)&&!isNaN(t))return 1;if(isNaN(t)&&!isNaN(e))return-1}else e=parseFloat(e),t=parseFloat(t);return eli:not(.kint-active-tab)",function(e){0===e.offsetWidth&&0===e.offsetHeight||n.keyboardNav.targets.push(e)})},sync:function(e){var t=document.querySelector(".kint-focused");if(t&&n.removeClass(t,"kint-focused"),n.keyboardNav.active){var a=n.keyboardNav.targets[n.keyboardNav.target];n.addClass(a,"kint-focused"),e||n.keyboardNav.scroll(a)}},scroll:function(e){var t=function(e){return e.offsetTop+(e.offsetParent?t(e.offsetParent):0)},a=t(e);if(n.folder){var r=n.folder.querySelector("dd.kint-folder");r.scrollTo(0,a-r.clientHeight/2)}else window.scrollTo(0,a-window.innerHeight/2)},moveCursor:function(e){for(n.keyboardNav.target+=e;n.keyboardNav.target<0;)n.keyboardNav.target+=n.keyboardNav.targets.length;for(;n.keyboardNav.target>=n.keyboardNav.targets.length;)n.keyboardNav.target-=n.keyboardNav.targets.length;n.keyboardNav.sync()},setCursor:function(e){n.keyboardNav.fetchTargets();for(var t=0;t"},openInNewWindow:function(e){var t=window.open();t&&(t.document.open(),t.document.write(i.mktag("html")+i.mktag("head")+i.mktag("title")+"Kint ("+(new Date).toISOString()+")"+i.mktag("/title")+i.mktag('meta charset="utf-8"')+document.getElementsByClassName("kint-rich-script")[0].outerHTML+document.getElementsByClassName("kint-rich-style")[0].outerHTML+i.mktag("/head")+i.mktag("body")+'
    '+e.parentNode.outerHTML+"
    "+i.mktag("/body")),t.document.close())},sortTable:function(e,a){var t=e.tBodies[0];[].slice.call(e.tBodies[0].rows).sort(function(e,t){if(e=e.cells[a].textContent.trim().toLocaleLowerCase(),t=t.cells[a].textContent.trim().toLocaleLowerCase(),isNaN(e)||isNaN(t)){if(isNaN(e)&&!isNaN(t))return 1;if(isNaN(t)&&!isNaN(e))return-1}else e=parseFloat(e),t=parseFloat(t);return eli:not(.kint-active-tab)",function(e){i.isFolderOpen()&&!i.folder.contains(e)||0===e.offsetWidth&&0===e.offsetHeight||i.keyboardNav.targets.push(e)}),e&&-1!==i.keyboardNav.targets.indexOf(e)&&(i.keyboardNav.target=i.keyboardNav.targets.indexOf(e))},sync:function(e){var t=document.querySelector(".kint-focused");t&&i.removeClass(t,"kint-focused"),i.keyboardNav.active&&(t=i.keyboardNav.targets[i.keyboardNav.target],i.addClass(t,"kint-focused"),e||i.keyboardNav.scroll(t))},scroll:function(e){var t,a;e!==i.folder.querySelector("dt > nav")&&(a=(t=function(e){return e.offsetTop+(e.offsetParent?t(e.offsetParent):0)})(e),i.isFolderOpen()?(e=i.folder.querySelector("dd.kint-foldout")).scrollTo(0,a-e.clientHeight/2):window.scrollTo(0,a-window.innerHeight/2))},moveCursor:function(e){for(i.keyboardNav.target+=e;i.keyboardNav.target<0;)i.keyboardNav.target+=i.keyboardNav.targets.length;for(;i.keyboardNav.target>=i.keyboardNav.targets.length;)i.keyboardNav.target-=i.keyboardNav.targets.length;i.keyboardNav.sync()},setCursor:function(e){if(i.isFolderOpen()&&!i.folder.contains(e))return!1;i.keyboardNav.fetchTargets();for(var t=0;tdl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:#073642}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#839496}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#839496;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} diff --git a/system/ThirdParty/Kint/resources/compiled/solarized.css b/system/ThirdParty/Kint/resources/compiled/solarized.css index db5da0d2..fa04f2de 100644 --- a/system/ThirdParty/Kint/resources/compiled/solarized.css +++ b/system/ThirdParty/Kint/resources/compiled/solarized.css @@ -1 +1 @@ -.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#657b83}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #93a1a1}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#586e75}.kint-rich pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(101,123,131,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#fdf6e3;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#657b83;background:#fdf6e3}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #93a1a1;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#586e75;background:#eee8d5;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#e2e2e2;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f0f0f0}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#eee8d5;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#657b83}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#657b83;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #93a1a1}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint-rich ul.kint-tabs>li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #93a1a1;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #93a1a1;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-rich table td{background:#fdf6e3;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #eee8d5}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#eee8d5}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#fdf6e3;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px} +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:block}.kint-rich.kint-folder dd.kint-foldout{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll;display:none}.kint-rich.kint-folder dd.kint-foldout.kint-show{display:block}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#657b83}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #93a1a1}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#586e75}.kint-rich pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(101,123,131,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#fdf6e3;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#657b83;background:#fdf6e3}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #93a1a1;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#586e75;background:#eee8d5;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#e2e2e2;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f0f0f0}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#eee8d5;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#657b83}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#657b83;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #93a1a1}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint-rich ul.kint-tabs>li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul.kint-tab-contents>li{display:none}.kint-rich ul.kint-tab-contents>li.kint-show{display:block}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #93a1a1;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #93a1a1;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-rich table td{background:#fdf6e3;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #eee8d5}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#eee8d5}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#fdf6e3;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px} diff --git a/system/ThirdParty/PSR/Log/LICENSE b/system/ThirdParty/PSR/Log/LICENSE new file mode 100644 index 00000000..474c952b --- /dev/null +++ b/system/ThirdParty/PSR/Log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/system/Throttle/Throttler.php b/system/Throttle/Throttler.php index 0bdf8a95..89c32981 100644 --- a/system/Throttle/Throttler.php +++ b/system/Throttle/Throttler.php @@ -79,10 +79,9 @@ public function getTokenTime(): int * * Example: * - * if (! $throttler->check($request->ipAddress(), 60, MINUTE)) - * { + * if (! $throttler->check($request->ipAddress(), 60, MINUTE)) { * die('You submitted over 60 requests within a minute.'); - * } + * } * * @param string $key The name to use as the "bucket" name. * @param int $capacity The number of requests the "bucket" can hold @@ -95,12 +94,20 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): { $tokenName = $this->prefix . $key; + // Number of tokens to add back per second + $rate = $capacity / $seconds; + // Number of seconds to get one token + $refresh = 1 / $rate; + // Check to see if the bucket has even been created yet. if (($tokens = $this->cache->get($tokenName)) === null) { // If it hasn't been created, then we'll set it to the maximum // capacity - 1, and save it to the cache. - $this->cache->save($tokenName, $capacity - $cost, $seconds); - $this->cache->save($tokenName . 'Time', time(), $seconds); + $tokens = $capacity - $cost; + $this->cache->save($tokenName, $tokens, $seconds); + $this->cache->save($tokenName . 'Time', $this->time(), $seconds); + + $this->tokenTime = 0; return true; } @@ -110,15 +117,6 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): $throttleTime = $this->cache->get($tokenName . 'Time'); $elapsed = $this->time() - $throttleTime; - // Number of tokens to add back per second - $rate = $capacity / $seconds; - - // How many seconds till a new token is available. - // We must have a minimum wait of 1 second for a new token. - // Primarily stored to allow devs to report back to users. - $newTokenAvailable = (1 / $rate) - $elapsed; - $this->tokenTime = max(1, $newTokenAvailable); - // Add tokens based up on number per second that // should be refilled, then checked against capacity // to be sure the bucket didn't overflow. @@ -128,12 +126,21 @@ public function check(string $key, int $capacity, int $seconds, int $cost = 1): // If $tokens >= 1, then we are safe to perform the action, but // we need to decrement the number of available tokens. if ($tokens >= 1) { - $this->cache->save($tokenName, $tokens - $cost, $seconds); - $this->cache->save($tokenName . 'Time', time(), $seconds); + $tokens = $tokens - $cost; + $this->cache->save($tokenName, $tokens, $seconds); + $this->cache->save($tokenName . 'Time', $this->time(), $seconds); + + $this->tokenTime = 0; return true; } + // How many seconds till a new token is available. + // We must have a minimum wait of 1 second for a new token. + // Primarily stored to allow devs to report back to users. + $newTokenAvailable = (int) ($refresh - $elapsed - $refresh * $tokens); + $this->tokenTime = max(1, $newTokenAvailable); + return false; } @@ -164,6 +171,8 @@ public function setTestTime(int $time) /** * Return the test time, defaulting to current. + * + * @TODO should be private */ public function time(): int { diff --git a/system/Validation/FormatRules.php b/system/Validation/FormatRules.php index 2167e28c..4d02f221 100644 --- a/system/Validation/FormatRules.php +++ b/system/Validation/FormatRules.php @@ -23,7 +23,7 @@ class FormatRules */ public function alpha(?string $str = null): bool { - return ctype_alpha($str); + return ctype_alpha($str ?? ''); } /** @@ -45,11 +45,16 @@ public function alpha_space(?string $value = null): bool /** * Alphanumeric with underscores and dashes + * + * @see https://regex101.com/r/XfVY3d/1 */ public function alpha_dash(?string $str = null): bool { - // @see https://regex101.com/r/XfVY3d/1 - return (bool) preg_match('/\A[a-z0-9_-]+\z/i', $str); + if ($str === null) { + return false; + } + + return preg_match('/\A[a-z0-9_-]+\z/i', $str) === 1; } /** @@ -59,14 +64,19 @@ public function alpha_dash(?string $str = null): bool * _ underscore, + plus, = equals, | vertical bar, : colon, . period * ~ ! # $ % & * - _ + = | : . * - * @param string $str + * @param string|null $str * * @return bool + * + * @see https://regex101.com/r/6N8dDY/1 */ public function alpha_numeric_punct($str) { - // @see https://regex101.com/r/6N8dDY/1 - return (bool) preg_match('/\A[A-Z0-9 ~!#$%\&\*\-_+=|:.]+\z/i', $str); + if ($str === null) { + return false; + } + + return preg_match('/\A[A-Z0-9 ~!#$%\&\*\-_+=|:.]+\z/i', $str) === 1; } /** @@ -74,7 +84,7 @@ public function alpha_numeric_punct($str) */ public function alpha_numeric(?string $str = null): bool { - return ctype_alnum($str); + return ctype_alnum($str ?? ''); } /** @@ -83,7 +93,7 @@ public function alpha_numeric(?string $str = null): bool public function alpha_numeric_space(?string $str = null): bool { // @see https://regex101.com/r/0AZDME/1 - return (bool) preg_match('/\A[A-Z0-9 ]+\z/i', $str); + return (bool) preg_match('/\A[A-Z0-9 ]+\z/i', $str ?? ''); } /** @@ -105,7 +115,7 @@ public function string($str = null): bool public function decimal(?string $str = null): bool { // @see https://regex101.com/r/HULifl/2/ - return (bool) preg_match('/\A[-+]?\d{0,}\.?\d+\z/', $str); + return (bool) preg_match('/\A[-+]?\d{0,}\.?\d+\z/', $str ?? ''); } /** @@ -113,7 +123,7 @@ public function decimal(?string $str = null): bool */ public function hex(?string $str = null): bool { - return ctype_xdigit($str); + return ctype_xdigit($str ?? ''); } /** @@ -121,7 +131,7 @@ public function hex(?string $str = null): bool */ public function integer(?string $str = null): bool { - return (bool) preg_match('/\A[\-+]?\d+\z/', $str); + return (bool) preg_match('/\A[\-+]?\d+\z/', $str ?? ''); } /** @@ -129,7 +139,7 @@ public function integer(?string $str = null): bool */ public function is_natural(?string $str = null): bool { - return ctype_digit($str); + return ctype_digit($str ?? ''); } /** @@ -137,7 +147,7 @@ public function is_natural(?string $str = null): bool */ public function is_natural_no_zero(?string $str = null): bool { - return $str !== '0' && ctype_digit($str); + return $str !== '0' && ctype_digit($str ?? ''); } /** @@ -146,7 +156,7 @@ public function is_natural_no_zero(?string $str = null): bool public function numeric(?string $str = null): bool { // @see https://regex101.com/r/bb9wtr/2 - return (bool) preg_match('/\A[\-+]?\d*\.?\d+\z/', $str); + return (bool) preg_match('/\A[\-+]?\d*\.?\d+\z/', $str ?? ''); } /** @@ -158,7 +168,7 @@ public function regex_match(?string $str, string $pattern): bool $pattern = "/{$pattern}/"; } - return (bool) preg_match($pattern, $str); + return (bool) preg_match($pattern, $str ?? ''); } /** @@ -171,7 +181,7 @@ public function regex_match(?string $str, string $pattern): bool */ public function timezone(?string $str = null): bool { - return in_array($str, timezone_identifiers_list(), true); + return in_array($str ?? '', timezone_identifiers_list(), true); } /** @@ -184,6 +194,10 @@ public function timezone(?string $str = null): bool */ public function valid_base64(?string $str = null): bool { + if ($str === null) { + return false; + } + return base64_encode(base64_decode($str, true)) === $str; } @@ -194,7 +208,7 @@ public function valid_base64(?string $str = null): bool */ public function valid_json(?string $str = null): bool { - json_decode($str); + json_decode($str ?? ''); return json_last_error() === JSON_ERROR_NONE; } @@ -207,7 +221,7 @@ public function valid_json(?string $str = null): bool public function valid_email(?string $str = null): bool { // @see https://regex101.com/r/wlJG1t/1/ - if (function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches)) { + if (function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46') && preg_match('#\A([^@]+)@(.+)\z#', $str ?? '', $matches)) { $str = $matches[1] . '@' . idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46); } @@ -224,8 +238,9 @@ public function valid_email(?string $str = null): bool */ public function valid_emails(?string $str = null): bool { - foreach (explode(',', $str) as $email) { + foreach (explode(',', $str ?? '') as $email) { $email = trim($email); + if ($email === '') { return false; } @@ -241,8 +256,7 @@ public function valid_emails(?string $str = null): bool /** * Validate an IP address (human readable format or binary string - inet_pton) * - * @param string $ip IP Address - * @param string $which IP protocol: 'ipv4' or 'ipv6' + * @param string|null $which IP protocol: 'ipv4' or 'ipv6' */ public function valid_ip(?string $ip = null, ?string $which = null): bool { @@ -250,7 +264,7 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool return false; } - switch (strtolower($which)) { + switch (strtolower($which ?? '')) { case 'ipv4': $which = FILTER_FLAG_IPV4; break; @@ -260,11 +274,11 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool break; default: - $which = null; - break; + $which = 0; } - return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which) || (! ctype_print($ip) && (bool) filter_var(inet_ntop($ip), FILTER_VALIDATE_IP, $which)); + return filter_var($ip, FILTER_VALIDATE_IP, $which) !== false + || (! ctype_print($ip) && filter_var(inet_ntop($ip), FILTER_VALIDATE_IP, $which) !== false); } /** @@ -272,8 +286,6 @@ public function valid_ip(?string $ip = null, ?string $which = null): bool * * Warning: this rule will pass basic strings like * "banana"; use valid_url_strict for a stricter rule. - * - * @param string $str */ public function valid_url(?string $str = null): bool { @@ -305,7 +317,7 @@ public function valid_url_strict(?string $str = null, ?string $validSchemes = nu return false; } - $scheme = strtolower(parse_url($str, PHP_URL_SCHEME)); + $scheme = strtolower(parse_url($str, PHP_URL_SCHEME) ?? ''); // absent scheme gives null $validSchemes = explode( ',', strtolower($validSchemes ?? 'http,https') @@ -317,18 +329,16 @@ public function valid_url_strict(?string $str = null, ?string $validSchemes = nu /** * Checks for a valid date and matches a given date format - * - * @param string $str - * @param string $format */ public function valid_date(?string $str = null, ?string $format = null): bool { if (empty($format)) { - return (bool) strtotime($str); + return strtotime($str) !== false; } - $date = DateTime::createFromFormat($format, $str); + $date = DateTime::createFromFormat($format, $str); + $errors = DateTime::getLastErrors(); - return (bool) $date && DateTime::getLastErrors()['warning_count'] === 0 && DateTime::getLastErrors()['error_count'] === 0; + return $date !== false && $errors !== false && $errors['warning_count'] === 0 && $errors['error_count'] === 0; } } diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 20f558e5..aba9ff11 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -22,8 +22,7 @@ class Rules /** * The value does not match another field in $data. * - * @param string $str - * @param array $data Other field/value pairs + * @param array $data Other field/value pairs */ public function differs(?string $str, string $field, array $data): bool { @@ -36,8 +35,6 @@ public function differs(?string $str, string $field, array $data): bool /** * Equals the static value provided. - * - * @param string $str */ public function equals(?string $str, string $val): bool { @@ -47,15 +44,13 @@ public function equals(?string $str, string $val): bool /** * Returns true if $str is $val characters long. * $val = "5" (one) | "5,8,12" (multiple values) - * - * @param string $str */ public function exact_length(?string $str, string $val): bool { $val = explode(',', $val); foreach ($val as $tmp) { - if (is_numeric($tmp) && (int) $tmp === mb_strlen($str)) { + if (is_numeric($tmp) && (int) $tmp === mb_strlen($str ?? '')) { return true; } } @@ -65,8 +60,6 @@ public function exact_length(?string $str, string $val): bool /** * Greater than - * - * @param string $str */ public function greater_than(?string $str, string $min): bool { @@ -75,8 +68,6 @@ public function greater_than(?string $str, string $min): bool /** * Equal to or Greater than - * - * @param string $str */ public function greater_than_equal_to(?string $str, string $min): bool { @@ -91,8 +82,6 @@ public function greater_than_equal_to(?string $str, string $min): bool * Example: * is_not_unique[table.field,where_field,where_value] * is_not_unique[menu.id,active,1] - * - * @param string $str */ public function is_not_unique(?string $str, string $field, array $data): bool { @@ -102,9 +91,8 @@ public function is_not_unique(?string $str, string $field, array $data): bool // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); - $db = Database::connect($data['DBGroup'] ?? null); - - $row = $db->table($table) + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) ->select('1') ->where($field, $str) ->limit(1); @@ -118,8 +106,6 @@ public function is_not_unique(?string $str, string $field, array $data): bool /** * Value should be within an array of values - * - * @param string $value */ public function in_list(?string $value, string $list): bool { @@ -136,20 +122,15 @@ public function in_list(?string $value, string $list): bool * Example: * is_unique[table.field,ignore_field,ignore_value] * is_unique[users.email,id,5] - * - * @param string $str */ public function is_unique(?string $str, string $field, array $data): bool { - // Grab any data for exclusion of a single row. [$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null); - // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); - $db = Database::connect($data['DBGroup'] ?? null); - - $row = $db->table($table) + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) ->select('1') ->where($field, $str) ->limit(1); @@ -163,8 +144,6 @@ public function is_unique(?string $str, string $field, array $data): bool /** * Less than - * - * @param string $str */ public function less_than(?string $str, string $max): bool { @@ -173,8 +152,6 @@ public function less_than(?string $str, string $max): bool /** * Equal to or Less than - * - * @param string $str */ public function less_than_equal_to(?string $str, string $max): bool { @@ -184,8 +161,7 @@ public function less_than_equal_to(?string $str, string $max): bool /** * Matches the value of another field in $data. * - * @param string $str - * @param array $data Other field/value pairs + * @param array $data Other field/value pairs */ public function matches(?string $str, string $field, array $data): bool { @@ -198,22 +174,18 @@ public function matches(?string $str, string $field, array $data): bool /** * Returns true if $str is $val or fewer characters in length. - * - * @param string $str */ public function max_length(?string $str, string $val): bool { - return is_numeric($val) && $val >= mb_strlen($str); + return is_numeric($val) && $val >= mb_strlen($str ?? ''); } /** * Returns true if $str is at least $val length. - * - * @param string $str */ public function min_length(?string $str, string $val): bool { - return is_numeric($val) && $val <= mb_strlen($str); + return is_numeric($val) && $val <= mb_strlen($str ?? ''); } /** @@ -237,19 +209,23 @@ public function not_in_list(?string $value, string $list): bool } /** - * Required - * - * @param mixed $str Value - * - * @return bool True if valid, false if not + * @param mixed $str */ public function required($str = null): bool { + if ($str === null) { + return false; + } + if (is_object($str)) { return true; } - return is_array($str) ? ! empty($str) : (trim($str) !== ''); + if (is_array($str)) { + return $str !== []; + } + + return trim((string) $str) !== ''; } /** @@ -270,11 +246,10 @@ public function required_with($str = null, ?string $fields = null, array $data = throw new InvalidArgumentException('You must supply the parameters: fields, data.'); } - $fields = explode(',', $fields); - // If the field is present we can safely assume that // the field is here, no matter whether the corresponding // search field is present or not. + $fields = explode(',', $fields); $present = $this->required($str ?? ''); if ($present) { @@ -311,11 +286,10 @@ public function required_without($str = null, ?string $fields = null, array $dat throw new InvalidArgumentException('You must supply the parameters: fields, data.'); } - $fields = explode(',', $fields); - // If the field is present we can safely assume that // the field is here, no matter whether the corresponding // search field is present or not. + $fields = explode(',', $fields); $present = $this->required($str ?? ''); if ($present) { diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index 8bd14817..39af6703 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -139,16 +139,22 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup } $values = dot_array_search($field, $data); - $values = is_array($values) ? $values : [$values]; if ($values === []) { // We'll process the values right away if an empty array $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data); + + continue; } - foreach ($values as $value) { - // Otherwise, we'll let the loop do the job - $this->processRules($field, $setup['label'] ?? $field, $value, $rules, $data); + if (strpos($field, '*') !== false && is_array($values)) { + // Process multiple fields + foreach ($values as $value) { + $this->processRules($field, $setup['label'] ?? $field, $value, $rules, $data); + } + } else { + // Process single field + $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data); } } @@ -194,11 +200,15 @@ protected function processRules(string $field, ?string $label, $value, $rules = // that can be used later $ifExistField = str_replace('\.\*', '\.(?:[^\.]+)', preg_quote($field, '/')); - $dataIsExisting = array_reduce(array_keys($flattenedData), static function ($carry, $item) use ($ifExistField) { - $pattern = sprintf('/%s/u', $ifExistField); + $dataIsExisting = array_reduce( + array_keys($flattenedData), + static function ($carry, $item) use ($ifExistField) { + $pattern = sprintf('/%s/u', $ifExistField); - return $carry || preg_match($pattern, $item) === 1; - }, false); + return $carry || preg_match($pattern, $item) === 1; + }, + false + ); } else { $dataIsExisting = array_key_exists($ifExistField, $flattenedData); } @@ -215,7 +225,10 @@ protected function processRules(string $field, ?string $label, $value, $rules = } if (in_array('permit_empty', $rules, true)) { - if (! in_array('required', $rules, true) && (is_array($value) ? empty($value) : (trim($value) === ''))) { + if ( + ! in_array('required', $rules, true) + && (is_array($value) ? $value === [] : trim((string) $value) === '') + ) { $passed = true; foreach ($rules as $rule) { @@ -261,7 +274,7 @@ protected function processRules(string $field, ?string $label, $value, $rules = // Placeholder for custom errors from the rules. $error = null; - // If it's a callable, call and and get out of here. + // If it's a callable, call and get out of here. if ($isCallable) { $passed = $param === false ? $rule($value) : $rule($value, $param, $data); } else { @@ -274,7 +287,9 @@ protected function processRules(string $field, ?string $label, $value, $rules = } $found = true; - $passed = $param === false ? $set->{$rule}($value, $error) : $set->{$rule}($value, $param, $data, $error); + $passed = $param === false + ? $set->{$rule}($value, $error) + : $set->{$rule}($value, $param, $data, $error); break; } @@ -295,7 +310,15 @@ protected function processRules(string $field, ?string $label, $value, $rules = $value = json_encode($value); } - $this->errors[$field] = $error ?? $this->getErrorMessage($rule, $field, $label, $param, $value); + $param = ($param === false) ? '' : $param; + + $this->errors[$field] = $error ?? $this->getErrorMessage( + $rule, + $field, + $label, + $param, + (string) $value + ); return false; } @@ -570,13 +593,13 @@ protected function fillPlaceholders(array $rules, array $data): array continue; } - $row = strtr($row, $replacements); + $row = strtr($row ?? '', $replacements); } continue; } - $rule = strtr($rule, $replacements); + $rule = strtr($rule ?? '', $replacements); } } @@ -594,10 +617,6 @@ public function hasError(string $field): bool /** * Returns the error(s) for a specified $field (or empty string if not * set). - * - * @param string $field Field. - * - * @return string Error(s). */ public function getError(?string $field = null): string { @@ -617,9 +636,7 @@ public function getError(?string $field = null): string * 'field2' => 'error message', * ] * - * @return array - * - * Excluded from code coverage because that it always run as cli + * @return array * * @codeCoverageIgnore */ @@ -648,11 +665,12 @@ public function setError(string $field, string $error): ValidationInterface /** * Attempts to find the appropriate error message * - * @param string $param - * @param string $value The value that caused the validation to fail. + * @param string|null $value The value that caused the validation to fail. */ protected function getErrorMessage(string $rule, string $field, ?string $label = null, ?string $param = null, ?string $value = null): string { + $param = $param ?? ''; + // Check if custom message has been defined by user if (isset($this->customErrors[$field][$rule])) { $message = lang($this->customErrors[$field][$rule]); @@ -664,9 +682,13 @@ protected function getErrorMessage(string $rule, string $field, ?string $label = } $message = str_replace('{field}', empty($label) ? $field : lang($label), $message); - $message = str_replace('{param}', empty($this->rules[$param]['label']) ? $param : lang($this->rules[$param]['label']), $message); + $message = str_replace( + '{param}', + empty($this->rules[$param]['label']) ? $param : lang($this->rules[$param]['label']), + $message + ); - return str_replace('{value}', $value, $message); + return str_replace('{value}', $value ?? '', $message); } /** diff --git a/system/View/Table.php b/system/View/Table.php index d57a7092..539fd193 100644 --- a/system/View/Table.php +++ b/system/View/Table.php @@ -179,9 +179,8 @@ public function makeColumns($array = [], $columnLimit = 0) } $new[] = $temp; - } while (count($array) > 0); + } while ($array !== []); - // @phpstan-ignore-next-line return $new; } diff --git a/system/View/View.php b/system/View/View.php index 6005b5f4..e65416e5 100644 --- a/system/View/View.php +++ b/system/View/View.php @@ -199,11 +199,7 @@ public function render(string $view, ?array $options = null, ?bool $saveData = n } // Make our view data available to the view. - $this->tempData = $this->tempData ?? $this->data; - - if ($saveData) { - $this->data = $this->tempData; - } + $this->prepareTemplateData($saveData); // Save current vars $renderVars = $this->renderVars; @@ -275,13 +271,9 @@ public function render(string $view, ?array $options = null, ?bool $saveData = n */ public function renderString(string $view, ?array $options = null, ?bool $saveData = null): string { - $start = microtime(true); - $saveData = $saveData ?? $this->saveData; - $this->tempData = $this->tempData ?? $this->data; - - if ($saveData) { - $this->data = $this->tempData; - } + $start = microtime(true); + $saveData = $saveData ?? $this->saveData; + $this->prepareTemplateData($saveData); $output = (function (string $view): string { extract($this->tempData); @@ -454,4 +446,13 @@ protected function logPerformance(float $start, float $end, string $view) ]; } } + + protected function prepareTemplateData(bool $saveData): void + { + $this->tempData = $this->tempData ?? $this->data; + + if ($saveData) { + $this->data = $this->tempData; + } + } } diff --git a/system/bootstrap.php b/system/bootstrap.php index 17226d09..4549fbc2 100644 --- a/system/bootstrap.php +++ b/system/bootstrap.php @@ -117,7 +117,7 @@ class_alias('Config\Services', 'CodeIgniter\Services'); * We do not want to enforce this, so set the constant if Composer was used. */ if (! defined('VENDORPATH')) { - define('VENDORPATH', realpath(ROOTPATH . 'vendor') . DIRECTORY_SEPARATOR); + define('VENDORPATH', dirname(COMPOSER_PATH) . DIRECTORY_SEPARATOR); } require_once COMPOSER_PATH; diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..1edb1017 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,108 @@ +# Running Application Tests + +This is the quick-start to CodeIgniter testing. Its intent is to describe what +it takes to set up your application and get it ready to run unit tests. +It is not intended to be a full description of the test features that you can +use to test your application. Those details can be found in the documentation. + +## Resources +* [CodeIgniter 4 User Guide on Testing](https://codeigniter4.github.io/userguide/testing/index.html) +* [PHPUnit docs](https://phpunit.readthedocs.io/en/8.5/index.html) + +## Requirements + +It is recommended to use the latest version of PHPUnit. At the time of this +writing we are running version 8.5.13. Support for this has been built into the +**composer.json** file that ships with CodeIgniter and can easily be installed +via [Composer](https://getcomposer.org/) if you don't already have it installed globally. + + > composer install + +If running under OS X or Linux, you can create a symbolic link to make running tests a touch nicer. + + > ln -s ./vendor/bin/phpunit ./phpunit + +You also need to install [XDebug](https://xdebug.org/index.php) in order +for code coverage to be calculated successfully. + +## Setting Up + +A number of the tests use a running database. +In order to set up the database edit the details for the `tests` group in +**app/Config/Database.php** or **phpunit.xml**. Make sure that you provide a database engine +that is currently running on your machine. More details on a test database setup are in the +*Docs>>Testing>>Testing Your Database* section of the documentation. + +If you want to run the tests without using live database you can +exclude @DatabaseLive group. Or make a copy of **phpunit.dist.xml** - +call it **phpunit.xml** - and comment out the named "database". This will make +the tests run quite a bit faster. + +## Running the tests + +The entire test suite can be run by simply typing one command-line command from the main directory. + + > ./phpunit + +You can limit tests to those within a single test directory by specifying the +directory name after phpunit. + + > ./phpunit app/Models + +## Generating Code Coverage + +To generate coverage information, including HTML reports you can view in your browser, +you can use the following command: + + > ./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m + +This runs all of the tests again collecting information about how many lines, +functions, and files are tested. It also reports the percentage of the code that is covered by tests. +It is collected in two formats: a simple text file that provides an overview as well +as a comprehensive collection of HTML files that show the status of every line of code in the project. + +The text file can be found at **tests/coverage.txt**. +The HTML files can be viewed by opening **tests/coverage/index.html** in your favorite browser. + +## PHPUnit XML Configuration + +The repository has a ``phpunit.xml.dist`` file in the project root that's used for +PHPUnit configuration. This is used to provide a default configuration if you +do not have your own configuration file in the project root. + +The normal practice would be to copy ``phpunit.xml.dist`` to ``phpunit.xml`` +(which is git ignored), and to tailor it as you see fit. +For instance, you might wish to exclude database tests, or automatically generate +HTML code coverage reports. + +## Test Cases + +Every test needs a *test case*, or class that your tests extend. CodeIgniter 4 +provides a few that you may use directly: +* `CodeIgniter\Test\CIUnitTestCase` - for basic tests with no other service needs +* `CodeIgniter\Test\DatabaseTestTrait` - for tests that need database access + +Most of the time you will want to write your own test cases to hold functions and services +common to your test suites. + +## Creating Tests + +All tests go in the **tests/** directory. Each test file is a class that extends a +**Test Case** (see above) and contains methods for the individual tests. These method +names must start with the word "test" and should have descriptive names for precisely what +they are testing: +`testUserCanModifyFile()` `testOutputColorMatchesInput()` `testIsLoggedInFailsWithInvalidUser()` + +Writing tests is an art, and there are many resources available to help learn how. +Review the links above and always pay attention to your code coverage. + +### Database Tests + +Tests can include migrating, seeding, and testing against a mock or live1 database. +Be sure to modify the test case (or create your own) to point to your seed and migrations +and include any additional steps to be run before tests in the `setUp()` method. + +1 Note: If you are using database tests that require a live database connection +you will need to rename **phpunit.xml.dist** to **phpunit.xml**, uncomment the database +configuration lines and add your connection details. Prevent **phpunit.xml** from being +tracked in your repo by adding it to **.gitignore**. diff --git a/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php new file mode 100644 index 00000000..2bbdcfe5 --- /dev/null +++ b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -0,0 +1,37 @@ +forge->addField('id'); + $this->forge->addField([ + 'name' => ['type' => 'varchar', 'constraint' => 31], + 'uid' => ['type' => 'varchar', 'constraint' => 31], + 'class' => ['type' => 'varchar', 'constraint' => 63], + 'icon' => ['type' => 'varchar', 'constraint' => 31], + 'summary' => ['type' => 'varchar', 'constraint' => 255], + 'created_at' => ['type' => 'datetime', 'null' => true], + 'updated_at' => ['type' => 'datetime', 'null' => true], + 'deleted_at' => ['type' => 'datetime', 'null' => true], + ]); + + $this->forge->addKey('name'); + $this->forge->addKey('uid'); + $this->forge->addKey(['deleted_at', 'id']); + $this->forge->addKey('created_at'); + + $this->forge->createTable('factories'); + } + + public function down() + { + $this->forge->dropTable('factories'); + } +} diff --git a/tests/_support/Database/Seeds/ExampleSeeder.php b/tests/_support/Database/Seeds/ExampleSeeder.php new file mode 100644 index 00000000..f67bf8fb --- /dev/null +++ b/tests/_support/Database/Seeds/ExampleSeeder.php @@ -0,0 +1,41 @@ + 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Longer sample text for testing', + ], + [ + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Create widgets in your factory', + ], + [ + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', + 'summary' => 'Abandon all hope, ye who enter here', + ], + ]; + + $builder = $this->db->table('factories'); + + foreach ($factories as $factory) { + $builder->insert($factory); + } + } +} diff --git a/tests/_support/Libraries/ConfigReader.php b/tests/_support/Libraries/ConfigReader.php new file mode 100644 index 00000000..40d057ac --- /dev/null +++ b/tests/_support/Libraries/ConfigReader.php @@ -0,0 +1,17 @@ +findAll(); + + // Make sure the count is as expected + $this->assertCount(3, $objects); + } + + public function testSoftDeleteLeavesRow() + { + $model = new ExampleModel(); + $this->setPrivateProperty($model, 'useSoftDeletes', true); + $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); + + $object = $model->first(); + $model->delete($object->id); + + // The model should no longer find it + $this->assertNull($model->find($object->id)); + + // ... but it should still be in the database + $result = $model->builder()->where('id', $object->id)->get()->getResult(); + + $this->assertCount(1, $result); + } +} diff --git a/tests/session/ExampleSessionTest.php b/tests/session/ExampleSessionTest.php new file mode 100644 index 00000000..98fe7afa --- /dev/null +++ b/tests/session/ExampleSessionTest.php @@ -0,0 +1,18 @@ +set('logged_in', 123); + $this->assertSame(123, $session->get('logged_in')); + } +} diff --git a/tests/unit/HealthTest.php b/tests/unit/HealthTest.php new file mode 100644 index 00000000..ab3e2aa1 --- /dev/null +++ b/tests/unit/HealthTest.php @@ -0,0 +1,50 @@ +assertTrue(defined('APPPATH')); + } + + public function testBaseUrlHasBeenSet() + { + $validation = Services::validation(); + + $env = false; + + // Check the baseURL in .env + if (is_file(HOMEPATH . '.env')) { + $env = preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')) !== false; + } + + if ($env) { + // BaseURL in .env is a valid URL? + // phpunit.xml.dist sets app.baseURL in $_SERVER + // So if you set app.baseURL in .env, it takes precedence + $config = new App(); + $this->assertTrue( + $validation->check($config->baseURL, 'valid_url'), + 'baseURL "' . $config->baseURL . '" in .env is not valid URL' + ); + } + + // Get the baseURL in app/Config/App.php + // You can't use Config\App, because phpunit.xml.dist sets app.baseURL + $reader = new ConfigReader(); + + // BaseURL in app/Config/App.php is a valid URL? + $this->assertTrue( + $validation->check($reader->baseURL, 'valid_url'), + 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' + ); + } +}