├── resources
└── compiled
│ └── plain.css
├── LICENSE
├── src
├── Parser
│ ├── ConstructablePluginInterface.php
│ ├── PluginBeginInterface.php
│ ├── PluginInterface.php
│ ├── PluginCompleteInterface.php
│ ├── AbstractPlugin.php
│ ├── BinaryPlugin.php
│ ├── ArrayObjectPlugin.php
│ ├── DateTimePlugin.php
│ ├── ThrowablePlugin.php
│ ├── SplFileInfoPlugin.php
│ ├── FsPathPlugin.php
│ ├── ColorPlugin.php
│ ├── ToStringPlugin.php
│ ├── TimestampPlugin.php
│ ├── ProxyPlugin.php
│ ├── EnumPlugin.php
│ ├── StreamPlugin.php
│ ├── JsonPlugin.php
│ ├── BlacklistPlugin.php
│ ├── ClosurePlugin.php
│ ├── HtmlPlugin.php
│ ├── Base64Plugin.php
│ ├── ClassStringsPlugin.php
│ └── TablePlugin.php
├── Renderer
│ ├── ConstructableRendererInterface.php
│ ├── Rich
│ │ ├── PluginInterface.php
│ │ ├── ValuePluginInterface.php
│ │ ├── TabPluginInterface.php
│ │ ├── LockPlugin.php
│ │ ├── ProfilePlugin.php
│ │ ├── BinaryPlugin.php
│ │ ├── CallableDefinitionPlugin.php
│ │ ├── TraceFramePlugin.php
│ │ ├── SourcePlugin.php
│ │ ├── MicrotimePlugin.php
│ │ └── AbstractPlugin.php
│ ├── Text
│ │ ├── PluginInterface.php
│ │ ├── LockPlugin.php
│ │ ├── AbstractPlugin.php
│ │ └── SplFileInfoPlugin.php
│ ├── RendererInterface.php
│ ├── AssetRendererTrait.php
│ └── AbstractRenderer.php
├── Value
│ ├── ColorValue.php
│ ├── Context
│ │ ├── ArrayContext.php
│ │ ├── ClassConstContext.php
│ │ ├── StaticPropertyContext.php
│ │ ├── ContextInterface.php
│ │ ├── ClassOwnedContext.php
│ │ ├── DoubleAccessMemberContext.php
│ │ ├── BaseContext.php
│ │ ├── PropertyContext.php
│ │ └── ClassDeclaredContext.php
│ ├── UnknownValue.php
│ ├── VirtualValue.php
│ ├── UninitializedValue.php
│ ├── Representation
│ │ ├── RepresentationInterface.php
│ │ ├── TableRepresentation.php
│ │ ├── ProfileRepresentation.php
│ │ ├── BinaryRepresentation.php
│ │ ├── ValueRepresentation.php
│ │ ├── StringRepresentation.php
│ │ ├── AbstractRepresentation.php
│ │ └── ContainerRepresentation.php
│ ├── ClosedResourceValue.php
│ ├── ParameterHoldingTrait.php
│ ├── TraceValue.php
│ ├── DomNodeValue.php
│ ├── ResourceValue.php
│ ├── ThrowableValue.php
│ ├── DomNodeListValue.php
│ ├── MicrotimeValue.php
│ ├── ArrayValue.php
│ ├── DateTimeValue.php
│ ├── EnumValue.php
│ ├── StreamValue.php
│ ├── SimpleXMLElementValue.php
│ ├── FixedWidthValue.php
│ ├── DeclaredCallableBag.php
│ ├── SplFileInfoValue.php
│ ├── FunctionValue.php
│ ├── InstanceValue.php
│ ├── ParameterBag.php
│ └── StringValue.php
└── FacadeInterface.php
├── README.md
├── composer.json
├── init_helpers.php
└── init.php
/resources/compiled/plain.css:
--------------------------------------------------------------------------------
1 | .kint-plain{background:hsla(0,0%,100%,.9);white-space:pre;display:block;font-family:monospace;color:#222;line-height:normal}.kint-plain i{color:#d00;font-style:normal}.kint-plain u{color:#030;text-decoration:none;font-weight:bold}.kint-plain .kint-microtime-js .kint-microtime-lap{text-shadow:1px 0 #d00,0 1px #d00,-1px 0 #d00,0 -1px #d00;color:#fff;font-weight:bold}
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Jonathan Vollebregt (jnvsor@gmail.com), Rokas Šleinius (raveren@gmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/src/Parser/ConstructablePluginInterface.php:
--------------------------------------------------------------------------------
1 | ';
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/ValuePluginInterface.php:
--------------------------------------------------------------------------------
1 | parameters as $p) {
44 | $out[] = (string) $p;
45 | }
46 |
47 | return \implode(', ', $out);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Parser/AbstractPlugin.php:
--------------------------------------------------------------------------------
1 | parser = $parser;
37 | }
38 |
39 | public function setParser(Parser $p): void
40 | {
41 | $this->parser = $p;
42 | }
43 |
44 | protected function getParser(): Parser
45 | {
46 | return $this->parser;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Value/Representation/TableRepresentation.php:
--------------------------------------------------------------------------------
1 | $contents */
35 | public function __construct(array $contents, ?string $name = null)
36 | {
37 | parent::__construct('Table', $contents, $name, false);
38 | }
39 |
40 | public function getHint(): string
41 | {
42 | return 'table';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Value/TraceValue.php:
--------------------------------------------------------------------------------
1 | size > 0) {
45 | return parent::getDisplaySize();
46 | }
47 |
48 | return 'empty';
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Renderer/RendererInterface.php:
--------------------------------------------------------------------------------
1 | resource_type = $resource_type;
41 | }
42 |
43 | public function getDisplayType(): string
44 | {
45 | return $this->resource_type.' resource';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Value/Context/ClassConstContext.php:
--------------------------------------------------------------------------------
1 | owner_class.'::'.$this->name;
37 | }
38 |
39 | public function getOperator(): string
40 | {
41 | return '::';
42 | }
43 |
44 | public function getModifiers(): string
45 | {
46 | $final = $this->final ? 'final ' : '';
47 |
48 | return $final.$this->getAccess().' const';
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Value/Context/StaticPropertyContext.php:
--------------------------------------------------------------------------------
1 | owner_class.'::$'.$this->name;
37 | }
38 |
39 | public function getOperator(): string
40 | {
41 | return '::';
42 | }
43 |
44 | public function getModifiers(): string
45 | {
46 | $final = $this->final ? 'final ' : '';
47 |
48 | return $final.$this->getAccess().' static';
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Value/Representation/ProfileRepresentation.php:
--------------------------------------------------------------------------------
1 | complexity = $complexity;
41 | }
42 |
43 | public function getHint(): string
44 | {
45 | return 'profiling';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Value/Representation/BinaryRepresentation.php:
--------------------------------------------------------------------------------
1 | value = $value;
39 | }
40 |
41 | public function getHint(): string
42 | {
43 | return 'binary';
44 | }
45 |
46 | public function getValue(): string
47 | {
48 | return $this->value;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Value/Representation/ValueRepresentation.php:
--------------------------------------------------------------------------------
1 | value = $value;
41 | }
42 |
43 | public function getValue(): AbstractValue
44 | {
45 | return $this->value;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Value/ThrowableValue.php:
--------------------------------------------------------------------------------
1 | message = $throw->getMessage();
43 | }
44 |
45 | public function getDisplayValue(): string
46 | {
47 | return '"'.$this->message.'"';
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/FacadeInterface.php:
--------------------------------------------------------------------------------
1 | getHint()) {
37 | case 'blacklist':
38 | return $this->renderLockedHeader($v, 'BLACKLISTED');
39 | case 'recursion':
40 | return $this->renderLockedHeader($v, 'RECURSION');
41 | case 'depth_limit':
42 | return $this->renderLockedHeader($v, 'DEPTH LIMIT');
43 | case 'array_limit':
44 | return $this->renderLockedHeader($v, 'ARRAY LIMIT');
45 | }
46 |
47 | return null;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Value/DomNodeListValue.php:
--------------------------------------------------------------------------------
1 | length = $node->length;
46 | }
47 |
48 | public function getLength(): int
49 | {
50 | return $this->length;
51 | }
52 |
53 | public function getDisplaySize(): string
54 | {
55 | return (string) $this->length;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Parser/BinaryPlugin.php:
--------------------------------------------------------------------------------
1 | getEncoding()) {
49 | $v->addRepresentation(new BinaryRepresentation($v->getValue(), true), 0);
50 | }
51 |
52 | return $v;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Value/Context/ContextInterface.php:
--------------------------------------------------------------------------------
1 | getHint()) {
37 | case 'blacklist':
38 | return '
'.$this->renderLockedHeader($v, 'Blacklisted').'
';
39 | case 'recursion':
40 | return ''.$this->renderLockedHeader($v, 'Recursion').'
';
41 | case 'depth_limit':
42 | return ''.$this->renderLockedHeader($v, 'Depth Limit').'
';
43 | case 'array_limit':
44 | return ''.$this->renderLockedHeader($v, 'Array Limit').'
';
45 | }
46 |
47 | return null;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Value/Context/ClassOwnedContext.php:
--------------------------------------------------------------------------------
1 | owner_class = $owner_class;
42 | }
43 |
44 | public function getName(): string
45 | {
46 | return (string) $this->name;
47 | }
48 |
49 | public function getOperator(): string
50 | {
51 | return '->';
52 | }
53 |
54 | /** @psalm-param ?class-string $scope */
55 | public function isAccessible(?string $scope): bool
56 | {
57 | return __PHP_Incomplete_Class::class !== $this->owner_class;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Value/Representation/StringRepresentation.php:
--------------------------------------------------------------------------------
1 | value = $value;
50 | }
51 |
52 | /** @psalm-return non-empty-string */
53 | public function getValue(): string
54 | {
55 | return $this->value;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Renderer/Text/AbstractPlugin.php:
--------------------------------------------------------------------------------
1 | renderer = $r;
40 | }
41 |
42 | public function renderLockedHeader(AbstractValue $v, ?string $content = null): string
43 | {
44 | $out = '';
45 |
46 | if (0 === $v->getContext()->getDepth()) {
47 | $out .= $this->renderer->colorTitle($this->renderer->renderTitle($v)).PHP_EOL;
48 | }
49 |
50 | $out .= $this->renderer->renderHeader($v);
51 |
52 | if (null !== $content) {
53 | $out .= ' '.$this->renderer->colorValue($content);
54 | }
55 |
56 | $out .= PHP_EOL;
57 |
58 | return $out;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kint-php/kint",
3 | "description": "Kint - Advanced PHP dumper",
4 | "keywords": ["dump", "debug"],
5 | "type": "library",
6 | "homepage": "https://kint-php.github.io/kint/",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Jonathan Vollebregt",
11 | "homepage": "https://github.com/jnvsor"
12 | },
13 | {
14 | "name": "Contributors",
15 | "homepage": "https://github.com/kint-php/kint/graphs/contributors"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=7.4"
20 | },
21 | "require-dev": {
22 | "friendsofphp/php-cs-fixer": "^3",
23 | "phpunit/phpunit": "^9",
24 | "symfony/finder": ">=7",
25 | "seld/phar-utils": "^1",
26 | "vimeo/psalm": "^6"
27 | },
28 | "autoload": {
29 | "files": ["init.php"],
30 | "psr-4": {
31 | "Kint\\": "src/"
32 | }
33 | },
34 | "autoload-dev": {
35 | "psr-4": {
36 | "Kint\\Test\\": "tests/"
37 | }
38 | },
39 | "config": {
40 | "platform": {
41 | "php": "8.3"
42 | }
43 | },
44 | "scripts": {
45 | "clean": [
46 | "rm -rf resources/compiled/",
47 | "rm -rf build/"
48 | ],
49 | "format": [
50 | "@format:php",
51 | "@format:js",
52 | "@format:sass"
53 | ],
54 | "format:php": "php-cs-fixer fix",
55 | "format:js": "npm run format:js",
56 | "format:sass": "npm run format:sass",
57 | "build": [
58 | "@build:sass",
59 | "@build:js",
60 | "@build:php"
61 | ],
62 | "build:sass": "npm run build:sass",
63 | "build:js": "npm run build:js",
64 | "build:php": "php ./build.php",
65 | "analyze": [
66 | "@analyze:php",
67 | "@analyze:js"
68 | ],
69 | "analyze:php": "psalm --no-cache",
70 | "analyze:js": "npm run analyze:js"
71 | },
72 | "suggest": {
73 | "kint-php/kint-helpers": "Provides extra helper functions",
74 | "kint-php/kint-twig": "Provides d() and s() functions in twig templates"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Renderer/Text/SplFileInfoPlugin.php:
--------------------------------------------------------------------------------
1 | getRepresentation('splfileinfo');
38 |
39 | if (!$r instanceof SplFileInfoRepresentation) {
40 | return null;
41 | }
42 |
43 | $out = '';
44 |
45 | $c = $v->getContext();
46 |
47 | if (0 === $c->getDepth()) {
48 | $out .= $this->renderer->colorTitle($this->renderer->renderTitle($v)).PHP_EOL;
49 | }
50 |
51 | $out .= $this->renderer->renderHeader($v);
52 | if (null !== $v->getDisplayValue()) {
53 | $out .= ' =>';
54 | }
55 | $out .= ' '.$this->renderer->colorValue($this->renderer->escape($r->getValue())).PHP_EOL;
56 |
57 | return $out;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Value/MicrotimeValue.php:
--------------------------------------------------------------------------------
1 | context = $old->context;
38 | $this->type = $old->type;
39 | $this->flags = $old->flags;
40 | $this->representations = $old->representations;
41 | $this->wrapped = $old;
42 | }
43 |
44 | public function getHint(): string
45 | {
46 | return parent::getHint() ?? 'microtime';
47 | }
48 |
49 | public function getDisplaySize(): ?string
50 | {
51 | return $this->wrapped->getDisplaySize();
52 | }
53 |
54 | public function getDisplayValue(): ?string
55 | {
56 | return $this->wrapped->getDisplayValue();
57 | }
58 |
59 | public function getDisplayType(): string
60 | {
61 | return $this->wrapped->getDisplayType();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/ProfilePlugin.php:
--------------------------------------------------------------------------------
1 | ';
43 |
44 | $out .= 'Complexity: '.$r->complexity.PHP_EOL;
45 | if (isset($r->instance_counts)) {
46 | $out .= 'Instance repetitions: '.\var_export($r->instance_counts, true).PHP_EOL;
47 | }
48 | if (isset($r->instance_complexity)) {
49 | $out .= 'Instance complexity: '.\var_export($r->instance_complexity, true).PHP_EOL;
50 | }
51 |
52 | $out .= '';
53 |
54 | return $out;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Parser/ArrayObjectPlugin.php:
--------------------------------------------------------------------------------
1 | getFlags();
53 |
54 | if (ArrayObject::STD_PROP_LIST === $flags) {
55 | return null;
56 | }
57 |
58 | $parser = $this->getParser();
59 |
60 | $var->setFlags(ArrayObject::STD_PROP_LIST);
61 |
62 | $v = $parser->parse($var, $c);
63 |
64 | $var->setFlags($flags);
65 |
66 | return $v;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Value/Context/DoubleAccessMemberContext.php:
--------------------------------------------------------------------------------
1 | access) {
38 | case self::ACCESS_PUBLIC:
39 | if (self::ACCESS_PRIVATE === $this->access_set) {
40 | return 'private(set)';
41 | }
42 | if (self::ACCESS_PROTECTED === $this->access_set) {
43 | return 'protected(set)';
44 | }
45 |
46 | return 'public';
47 |
48 | case self::ACCESS_PROTECTED:
49 | if (self::ACCESS_PRIVATE === $this->access_set) {
50 | return 'protected private(set)';
51 | }
52 |
53 | return 'protected';
54 |
55 | case self::ACCESS_PRIVATE:
56 | return 'private';
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Value/ArrayValue.php:
--------------------------------------------------------------------------------
1 | size = $size;
48 | $this->contents = $contents;
49 | }
50 |
51 | public function getSize(): int
52 | {
53 | return $this->size;
54 | }
55 |
56 | /** @psalm-return AbstractValue[] */
57 | public function getContents()
58 | {
59 | return $this->contents;
60 | }
61 |
62 | public function getDisplaySize(): string
63 | {
64 | return (string) $this->size;
65 | }
66 |
67 | public function getDisplayChildren(): array
68 | {
69 | return $this->contents;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Value/DateTimeValue.php:
--------------------------------------------------------------------------------
1 | dt = clone $dt;
43 | }
44 |
45 | public function getHint(): string
46 | {
47 | return parent::getHint() ?? 'datetime';
48 | }
49 |
50 | public function getDisplayValue(): string
51 | {
52 | $stamp = $this->dt->format('Y-m-d H:i:s');
53 | if ((int) ($micro = $this->dt->format('u'))) {
54 | $stamp .= '.'.$micro;
55 | }
56 | $stamp .= $this->dt->format(' P');
57 |
58 | $tzn = $this->dt->getTimezone()->getName();
59 | if ('+' !== $tzn[0] && '-' !== $tzn[0]) {
60 | $stamp .= $this->dt->format(' T');
61 | }
62 |
63 | return $stamp;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Value/EnumValue.php:
--------------------------------------------------------------------------------
1 | enumval = $enumval;
44 | }
45 |
46 | public function getHint(): string
47 | {
48 | return parent::getHint() ?? 'enum';
49 | }
50 |
51 | public function getDisplayType(): string
52 | {
53 | return $this->classname.'::'.$this->enumval->name;
54 | }
55 |
56 | public function getDisplayValue(): ?string
57 | {
58 | if ($this->enumval instanceof BackedEnum) {
59 | if (\is_string($this->enumval->value)) {
60 | return '"'.$this->enumval->value.'"';
61 | }
62 |
63 | return (string) $this->enumval->value;
64 | }
65 |
66 | return null;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Value/Representation/AbstractRepresentation.php:
--------------------------------------------------------------------------------
1 | label = $label;
42 | /** @psalm-var string $name */
43 | $name = \preg_replace('/[^a-z0-9]+/', '_', \strtolower($name ?? $label));
44 | $this->name = $name;
45 | $this->implicit_label = $implicit_label;
46 | }
47 |
48 | public function getLabel(): string
49 | {
50 | return $this->label;
51 | }
52 |
53 | public function getName(): string
54 | {
55 | return $this->name;
56 | }
57 |
58 | public function labelIsImplicit(): bool
59 | {
60 | return $this->implicit_label;
61 | }
62 |
63 | public function getHint(): ?string
64 | {
65 | return null;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Value/Representation/ContainerRepresentation.php:
--------------------------------------------------------------------------------
1 |
39 | */
40 | protected array $contents;
41 |
42 | /** @psalm-param non-empty-array $contents */
43 | public function __construct(string $label, array $contents, ?string $name = null, bool $implicit_label = false)
44 | {
45 | if ([] === $contents) {
46 | throw new InvalidArgumentException("ContainerRepresentation can't take empty list");
47 | }
48 |
49 | parent::__construct($label, $name, $implicit_label);
50 | $this->contents = $contents;
51 | }
52 |
53 | /** @psalm-return non-empty-array */
54 | public function getContents(): array
55 | {
56 | return $this->contents;
57 | }
58 |
59 | public function getLabel(): string
60 | {
61 | return parent::getLabel().' ('.\count($this->contents).')';
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Parser/DateTimePlugin.php:
--------------------------------------------------------------------------------
1 | getContext(), $var);
56 | } catch (Error $e) {
57 | // Only happens if someone makes a DateTimeInterface with a private __clone
58 | return $v;
59 | }
60 |
61 | $dtv->setChildren($v->getChildren());
62 | $dtv->flags = $v->flags;
63 | $dtv->appendRepresentations($v->getRepresentations());
64 |
65 | return $dtv;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Parser/ThrowablePlugin.php:
--------------------------------------------------------------------------------
1 | getContext(), $var);
56 | $throw->setChildren($v->getChildren());
57 | $throw->flags = $v->flags;
58 | $throw->appendRepresentations($v->getRepresentations());
59 |
60 | try {
61 | $throw->addRepresentation(new SourceRepresentation($var->getFile(), $var->getLine(), null, true), 0);
62 | } catch (RuntimeException $e) {
63 | }
64 |
65 | return $throw;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/BinaryPlugin.php:
--------------------------------------------------------------------------------
1 | ';
48 |
49 | $lines = \str_split($r->getValue(), self::$line_length);
50 |
51 | foreach ($lines as $index => $line) {
52 | $out .= ((string) \sprintf('%08X', $index * self::$line_length)).":\t";
53 |
54 | $chunks = \str_split(\str_pad(\bin2hex($line), 2 * self::$line_length, ' '), 2 * self::$chunk_length);
55 |
56 | $out .= \implode(' ', $chunks);
57 | $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $line)."\n";
58 | }
59 |
60 | $out .= '';
61 |
62 | return $out;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/CallableDefinitionPlugin.php:
--------------------------------------------------------------------------------
1 | getContext();
48 |
49 | if ($c->inherited) {
50 | $docstring[] = 'Inherited from '.$this->renderer->escape($c->owner_class);
51 | }
52 | }
53 |
54 | $docstring[] = 'Defined in '.$this->renderer->escape(Utils::shortenPath($r->getFileName())).':'.$r->getLine();
55 |
56 | $docstring = ''.\implode("\n", $docstring).'';
57 |
58 | if (null !== ($trimmed = $r->getDocstringTrimmed())) {
59 | $docstring = $this->renderer->escape($trimmed)."\n\n".$docstring;
60 | }
61 |
62 | return ''.$docstring.'
';
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Parser/SplFileInfoPlugin.php:
--------------------------------------------------------------------------------
1 | getContext(), $var);
61 | $out->setChildren($v->getChildren());
62 | $out->flags = $v->flags;
63 | $out->addRepresentation(new SplFileInfoRepresentation(clone $var));
64 | $out->appendRepresentations($v->getRepresentations());
65 |
66 | return $out;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Value/Context/BaseContext.php:
--------------------------------------------------------------------------------
1 | name = $name;
51 | }
52 |
53 | public function getName()
54 | {
55 | return $this->name;
56 | }
57 |
58 | public function getDepth(): int
59 | {
60 | return $this->depth;
61 | }
62 |
63 | public function getOperator(): ?string
64 | {
65 | return null;
66 | }
67 |
68 | public function isRef(): bool
69 | {
70 | return $this->reference;
71 | }
72 |
73 | /** @psalm-param ?class-string $scope */
74 | public function isAccessible(?string $scope): bool
75 | {
76 | return true;
77 | }
78 |
79 | public function getAccessPath(): ?string
80 | {
81 | return $this->access_path;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Parser/FsPathPlugin.php:
--------------------------------------------------------------------------------
1 | 2048) {
52 | return $v;
53 | }
54 |
55 | if (!\preg_match('/[\\/\\'.DIRECTORY_SEPARATOR.']/', $var)) {
56 | return $v;
57 | }
58 |
59 | if (\preg_match('/[?<>"*|]/', $var)) {
60 | return $v;
61 | }
62 |
63 | try {
64 | if (!@\file_exists($var)) {
65 | return $v;
66 | }
67 | } catch (TypeError $e) {// @codeCoverageIgnore
68 | // Only possible in PHP 7
69 | return $v; // @codeCoverageIgnore
70 | }
71 |
72 | if (\in_array($var, self::$blacklist, true)) {
73 | return $v;
74 | }
75 |
76 | $v->addRepresentation(new SplFileInfoRepresentation(new SplFileInfo($var)), 0);
77 |
78 | return $v;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Value/StreamValue.php:
--------------------------------------------------------------------------------
1 | stream_meta = $stream_meta;
50 | $this->uri = $uri;
51 |
52 | if ($stream_meta) {
53 | $this->addRepresentation(new ContainerRepresentation('Stream', $stream_meta, null, true));
54 | }
55 | }
56 |
57 | public function getHint(): string
58 | {
59 | return parent::getHint() ?? 'stream';
60 | }
61 |
62 | public function getDisplayValue(): ?string
63 | {
64 | if (null === $this->uri) {
65 | return null;
66 | }
67 |
68 | if ('/' === $this->uri[0] && \stream_is_local($this->uri)) {
69 | return Utils::shortenPath($this->uri);
70 | }
71 |
72 | return $this->uri;
73 | }
74 |
75 | public function getDisplayChildren(): array
76 | {
77 | return $this->stream_meta;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Renderer/AssetRendererTrait.php:
--------------------------------------------------------------------------------
1 | } */
35 | private static array $assetCache = [];
36 |
37 | /** @psalm-api */
38 | public static function renderJs(): string
39 | {
40 | if (!isset(self::$assetCache['js'])) {
41 | self::$assetCache['js'] = \file_get_contents(KINT_DIR.'/resources/compiled/main.js');
42 | }
43 |
44 | return self::$assetCache['js'];
45 | }
46 |
47 | /** @psalm-api */
48 | public static function renderCss(): ?string
49 | {
50 | if (!isset(self::$theme)) {
51 | return null;
52 | }
53 |
54 | if (!isset(self::$assetCache['css'][self::$theme])) {
55 | if (\file_exists(KINT_DIR.'/resources/compiled/'.self::$theme)) {
56 | self::$assetCache['css'][self::$theme] = \file_get_contents(KINT_DIR.'/resources/compiled/'.self::$theme);
57 | } elseif (\file_exists(self::$theme)) {
58 | self::$assetCache['css'][self::$theme] = \file_get_contents(self::$theme);
59 | } else {
60 | self::$assetCache['css'][self::$theme] = false;
61 | }
62 | }
63 |
64 | if (false === self::$assetCache['css'][self::$theme]) {
65 | return null;
66 | }
67 |
68 | return self::$assetCache['css'][self::$theme];
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Value/Context/PropertyContext.php:
--------------------------------------------------------------------------------
1 | */
40 | public int $hooks = self::HOOK_NONE;
41 | public ?string $hook_set_type = null;
42 |
43 | public function getModifiers(): string
44 | {
45 | $out = $this->getAccess();
46 |
47 | if ($this->readonly) {
48 | $out .= ' readonly';
49 | }
50 |
51 | return $out;
52 | }
53 |
54 | public function getHooks(): ?string
55 | {
56 | if (self::HOOK_NONE === $this->hooks) {
57 | return null;
58 | }
59 |
60 | $out = '{ ';
61 | if ($this->hooks & self::HOOK_GET) {
62 | if ($this->hooks & self::HOOK_GET_REF) {
63 | $out .= '&';
64 | }
65 | $out .= 'get; ';
66 | }
67 | if ($this->hooks & self::HOOK_SET) {
68 | if ($this->hooks & self::HOOK_SET_TYPE && '' !== ($this->hook_set_type ?? '')) {
69 | $out .= 'set('.$this->hook_set_type.'); ';
70 | } else {
71 | $out .= 'set; ';
72 | }
73 | }
74 | $out .= '}';
75 |
76 | return $out;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/TraceFramePlugin.php:
--------------------------------------------------------------------------------
1 | getFile()) && null !== ($line = $v->getLine())) {
43 | $header = ''.$this->renderer->ideLink($file, $line).' ';
44 | } else {
45 | $header = 'PHP internal call ';
46 | }
47 |
48 | if ($callable = $v->getCallable()) {
49 | if ($callable instanceof MethodValue) {
50 | $function = $callable->getFullyQualifiedDisplayName();
51 | } else {
52 | $function = $callable->getDisplayName();
53 | }
54 |
55 | $function = $this->renderer->escape($function);
56 |
57 | if (null !== ($url = $callable->getPhpDocUrl())) {
58 | $function = ''.$function.'';
59 | }
60 |
61 | $header .= $function;
62 | }
63 |
64 | $children = $this->renderer->renderChildren($v);
65 | $header = $this->renderer->renderHeaderWrapper($v->getContext(), (bool) \strlen($children), $header);
66 |
67 | return ''.$header.$children.'
';
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Parser/ColorPlugin.php:
--------------------------------------------------------------------------------
1 | 32) {
51 | return $v;
52 | }
53 |
54 | if (!$v instanceof StringValue) {
55 | return $v;
56 | }
57 |
58 | $trimmed = \strtolower(\trim($var));
59 |
60 | if (!isset(ColorRepresentation::$color_map[$trimmed]) && !\preg_match('/^(?:(?:rgb|hsl)a?[^\\)]{6,}\\)|#[0-9a-f]{3,8})$/', $trimmed)) {
61 | return $v;
62 | }
63 |
64 | try {
65 | $rep = new ColorRepresentation($var);
66 | } catch (InvalidArgumentException $e) {
67 | return $v;
68 | }
69 |
70 | $out = new ColorValue($v->getContext(), $v->getValue(), $v->getEncoding());
71 | $out->flags = $v->flags;
72 | $out->appendRepresentations($v->getRepresentations());
73 | $out->removeRepresentation('contents');
74 | $out->addRepresentation($rep, 0);
75 |
76 | return $out;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Value/SimpleXMLElementValue.php:
--------------------------------------------------------------------------------
1 | $children */
39 | public function __construct(
40 | ContextInterface $context,
41 | SimpleXMLElement $element,
42 | array $children,
43 | ?string $text_content
44 | ) {
45 | parent::__construct($context, \get_class($element), \spl_object_hash($element), \spl_object_id($element));
46 |
47 | $this->children = $children;
48 | $this->text_content = $text_content;
49 | }
50 |
51 | public function getHint(): string
52 | {
53 | return parent::getHint() ?? 'simplexml_element';
54 | }
55 |
56 | public function getDisplaySize(): ?string
57 | {
58 | if ((bool) $this->children) {
59 | return (string) \count($this->children);
60 | }
61 |
62 | if (null !== $this->text_content) {
63 | return (string) \strlen($this->text_content);
64 | }
65 |
66 | return null;
67 | }
68 |
69 | public function getDisplayValue(): ?string
70 | {
71 | if ((bool) $this->children) {
72 | return parent::getDisplayValue();
73 | }
74 |
75 | if (null !== $this->text_content) {
76 | return '"'.$this->text_content.'"';
77 | }
78 |
79 | return null;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Value/FixedWidthValue.php:
--------------------------------------------------------------------------------
1 | value = $value;
53 | } else {
54 | throw new InvalidArgumentException('FixedWidthValue can only contain fixed width types, got '.$type);
55 | }
56 | }
57 |
58 | /**
59 | * @psalm-api
60 | *
61 | * @psalm-return FixedWidthType
62 | */
63 | public function getValue()
64 | {
65 | return $this->value;
66 | }
67 |
68 | public function getDisplaySize(): ?string
69 | {
70 | return null;
71 | }
72 |
73 | public function getDisplayValue(): ?string
74 | {
75 | if ('boolean' === $this->type) {
76 | return ((bool) $this->value) ? 'true' : 'false';
77 | }
78 |
79 | if ('integer' === $this->type || 'double' === $this->type) {
80 | return (string) $this->value;
81 | }
82 |
83 | return null;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/init_helpers.php:
--------------------------------------------------------------------------------
1 | render_spl_ids;
51 | }
52 |
53 | public function setCallInfo(array $info): void
54 | {
55 | $this->callee = $info['callee'] ?? null;
56 | $this->trace = $info['trace'] ?? [];
57 | }
58 |
59 | public function setStatics(array $statics): void
60 | {
61 | $this->show_trace = !empty($statics['display_called_from']);
62 | }
63 |
64 | public function filterParserPlugins(array $plugins): array
65 | {
66 | return $plugins;
67 | }
68 |
69 | public function preRender(): string
70 | {
71 | return '';
72 | }
73 |
74 | public function postRender(): string
75 | {
76 | return '';
77 | }
78 |
79 | public static function getFileLink(string $file, int $line): ?string
80 | {
81 | if (null === self::$file_link_format) {
82 | return null;
83 | }
84 |
85 | return \str_replace(['%f', '%l'], [$file, $line], self::$file_link_format);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Parser/ToStringPlugin.php:
--------------------------------------------------------------------------------
1 | hasMethod('__toString')) {
59 | return $v;
60 | }
61 |
62 | foreach (self::$blacklist as $class) {
63 | if ($var instanceof $class) {
64 | return $v;
65 | }
66 | }
67 |
68 | try {
69 | $string = (string) $var;
70 | } catch (Throwable $t) {
71 | return $v;
72 | }
73 |
74 | $c = $v->getContext();
75 |
76 | $base = new BaseContext($c->getName());
77 | $base->depth = $c->getDepth() + 1;
78 | if (null !== ($ap = $c->getAccessPath())) {
79 | $base->access_path = '(string) '.$ap;
80 | }
81 |
82 | $string = $this->getParser()->parse($string, $base);
83 |
84 | $v->addRepresentation(new ValueRepresentation('toString', $string));
85 |
86 | return $v;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Value/DeclaredCallableBag.php:
--------------------------------------------------------------------------------
1 | internal = $callable->isInternal();
60 | $t = $callable->getFileName();
61 | $this->filename = false === $t ? null : $t;
62 | $t = $callable->getStartLine();
63 | $this->startline = false === $t ? null : $t;
64 | $t = $callable->getEndLine();
65 | $this->endline = false === $t ? null : $t;
66 | $t = $callable->getDocComment();
67 | $this->docstring = false === $t ? null : $t;
68 | $this->return_reference = $callable->returnsReference();
69 |
70 | $rt = $callable->getReturnType();
71 | if ($rt) {
72 | $this->returntype = Utils::getTypeString($rt);
73 | }
74 |
75 | $parameters = [];
76 | foreach ($callable->getParameters() as $param) {
77 | $parameters[] = new ParameterBag($param);
78 | }
79 | $this->parameters = $parameters;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Parser/TimestampPlugin.php:
--------------------------------------------------------------------------------
1 | 10) {
73 | return $v;
74 | }
75 |
76 | if (!$v instanceof StringValue && !$v instanceof FixedWidthValue) {
77 | return $v;
78 | }
79 |
80 | if (!$dt = DateTimeImmutable::createFromFormat('U', (string) $var)) {
81 | return $v;
82 | }
83 |
84 | $v->removeRepresentation('contents');
85 | $v->addRepresentation(new StringRepresentation('Timestamp', $dt->format('c'), null, true));
86 |
87 | return $v;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Parser/ProxyPlugin.php:
--------------------------------------------------------------------------------
1 | types = $types;
54 | $this->triggers = $triggers;
55 | $this->callback = $callback;
56 | }
57 |
58 | public function setParser(Parser $p): void
59 | {
60 | $this->parser = $p;
61 | }
62 |
63 | public function getTypes(): array
64 | {
65 | return $this->types;
66 | }
67 |
68 | public function getTriggers(): int
69 | {
70 | return $this->triggers;
71 | }
72 |
73 | public function parseBegin(&$var, ContextInterface $c): ?AbstractValue
74 | {
75 | return \call_user_func_array($this->callback, [
76 | &$var,
77 | $c,
78 | Parser::TRIGGER_BEGIN,
79 | $this->parser,
80 | ]);
81 | }
82 |
83 | public function parseComplete(&$var, AbstractValue $v, int $trigger): AbstractValue
84 | {
85 | return \call_user_func_array($this->callback, [
86 | &$var,
87 | $v,
88 | $trigger,
89 | $this->parser,
90 | ]);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Parser/EnumPlugin.php:
--------------------------------------------------------------------------------
1 | getContext();
61 | $class = \get_class($var);
62 |
63 | if (!isset($this->cache[$class])) {
64 | $contents = [];
65 |
66 | foreach ($var->cases() as $case) {
67 | $base = new BaseContext($case->name);
68 | $base->access_path = '\\'.$class.'::'.$case->name;
69 | $base->depth = $c->getDepth() + 1;
70 | $contents[] = new EnumValue($base, $case);
71 | }
72 |
73 | /** @psalm-var non-empty-array $contents */
74 | $this->cache[$class] = new ContainerRepresentation('Enum values', $contents, 'enum');
75 | }
76 |
77 | $object = new EnumValue($c, $var);
78 | $object->flags = $v->flags;
79 | $object->appendRepresentations($v->getRepresentations());
80 | $object->addRepresentation($this->cache[$class], 0);
81 |
82 | return $object;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Parser/StreamPlugin.php:
--------------------------------------------------------------------------------
1 | getContext();
66 |
67 | $parser = $this->getParser();
68 | $parsed_meta = [];
69 | foreach ($meta as $key => $val) {
70 | $base = new ArrayContext($key);
71 | $base->depth = $c->getDepth() + 1;
72 |
73 | if (null !== ($ap = $c->getAccessPath())) {
74 | $base->access_path = 'stream_get_meta_data('.$ap.')['.\var_export($key, true).']';
75 | }
76 |
77 | $val = $parser->parse($val, $base);
78 | $val->flags |= AbstractValue::FLAG_GENERATED;
79 | $parsed_meta[] = $val;
80 | }
81 |
82 | $stream = new StreamValue($c, $parsed_meta, $meta['uri'] ?? null);
83 | $stream->flags = $v->flags;
84 | $stream->appendRepresentations($v->getRepresentations());
85 |
86 | return $stream;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Value/SplFileInfoValue.php:
--------------------------------------------------------------------------------
1 | path = $info->getPathname();
47 |
48 | try {
49 | // SplFileInfo::getRealPath will return cwd when path is ''
50 | if ('' !== $this->path && $info->getRealPath()) {
51 | $this->filesize = $info->getSize();
52 | }
53 | } catch (RuntimeException $e) {
54 | if (false === \strpos($e->getMessage(), ' open_basedir ')) {
55 | throw $e; // @codeCoverageIgnore
56 | }
57 | }
58 | }
59 |
60 | public function getHint(): string
61 | {
62 | return parent::getHint() ?? 'splfileinfo';
63 | }
64 |
65 | /** @psalm-api */
66 | public function getFileSize(): ?int
67 | {
68 | return $this->filesize;
69 | }
70 |
71 | public function getDisplaySize(): ?string
72 | {
73 | if (null === $this->filesize) {
74 | return null;
75 | }
76 |
77 | $size = Utils::getHumanReadableBytes($this->filesize);
78 |
79 | return $size['value'].$size['unit'];
80 | }
81 |
82 | public function getDisplayValue(): ?string
83 | {
84 | $shortpath = Utils::shortenPath($this->path);
85 |
86 | if ($shortpath !== $this->path) {
87 | return $shortpath;
88 | }
89 |
90 | return parent::getDisplayValue();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/init.php:
--------------------------------------------------------------------------------
1 | = 0);
43 | \define('KINT_PHP81', \version_compare(PHP_VERSION, '8.1') >= 0);
44 | \define('KINT_PHP82', \version_compare(PHP_VERSION, '8.2') >= 0);
45 | \define('KINT_PHP83', \version_compare(PHP_VERSION, '8.3') >= 0);
46 | \define('KINT_PHP84', \version_compare(PHP_VERSION, '8.4') >= 0);
47 | \define('KINT_PHP8412', \version_compare(PHP_VERSION, '8.4.12') >= 0);
48 | \define('KINT_PHP85', \version_compare(PHP_VERSION, '8.5') >= 0);
49 |
50 | // Dynamic default settings
51 | if (\strlen((string) \ini_get('xdebug.file_link_format')) > 0) {
52 | /** @psalm-var non-empty-string ini_get('xdebug.file_link_format') */
53 | AbstractRenderer::$file_link_format = \ini_get('xdebug.file_link_format');
54 | }
55 | if (isset($_SERVER['DOCUMENT_ROOT']) && false === \strpos($_SERVER['DOCUMENT_ROOT'], "\0")) {
56 | Utils::$path_aliases = [
57 | $_SERVER['DOCUMENT_ROOT'] => '',
58 | ];
59 |
60 | // Suppressed for unreadable document roots (related to open_basedir)
61 | if (false !== @\realpath($_SERVER['DOCUMENT_ROOT'])) {
62 | /** @psalm-suppress InvalidPropertyAssignmentValue */
63 | Utils::$path_aliases[\realpath($_SERVER['DOCUMENT_ROOT'])] = '';
64 | }
65 | }
66 |
67 | Utils::composerSkipFlags();
68 |
69 | if ((!\defined('KINT_SKIP_FACADE') || !KINT_SKIP_FACADE) && !\class_exists('Kint')) {
70 | \class_alias(Kint::class, 'Kint');
71 | }
72 |
73 | if (!\defined('KINT_SKIP_HELPERS') || !KINT_SKIP_HELPERS) {
74 | require_once __DIR__.'/init_helpers.php';
75 | }
76 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/SourcePlugin.php:
--------------------------------------------------------------------------------
1 | getSourceLines();
43 |
44 | // Trim empty lines from the start and end of the source
45 | foreach ($source as $linenum => $line) {
46 | if (\strlen(\trim($line)) || $linenum === $r->getLine()) {
47 | break;
48 | }
49 |
50 | unset($source[$linenum]);
51 | }
52 |
53 | foreach (\array_reverse($source, true) as $linenum => $line) {
54 | if (\strlen(\trim($line)) || $linenum === $r->getLine()) {
55 | break;
56 | }
57 |
58 | unset($source[$linenum]);
59 | }
60 |
61 | $output = '';
62 |
63 | foreach ($source as $linenum => $line) {
64 | if ($linenum === $r->getLine()) {
65 | $output .= ''.$this->renderer->escape($line)."\n".'
';
66 | } else {
67 | $output .= ''.$this->renderer->escape($line)."\n".'
';
68 | }
69 | }
70 |
71 | if ($output) {
72 | $data = '';
73 | if ($r->showFileName()) {
74 | $data = ' data-kint-filename="'.$this->renderer->escape($r->getFileName()).'"';
75 | }
76 |
77 | return '';
78 | }
79 |
80 | return null;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Parser/JsonPlugin.php:
--------------------------------------------------------------------------------
1 | getContext();
64 |
65 | $base = new BaseContext('JSON Decode');
66 | $base->depth = $c->getDepth();
67 |
68 | if (null !== ($ap = $c->getAccessPath())) {
69 | $base->access_path = 'json_decode('.$ap.', true)';
70 | }
71 |
72 | $json = $this->getParser()->parse($json, $base);
73 |
74 | if ($json instanceof ArrayValue && (~$json->flags & AbstractValue::FLAG_DEPTH_LIMIT) && $contents = $json->getContents()) {
75 | foreach ($contents as $value) {
76 | $value->flags |= AbstractValue::FLAG_GENERATED;
77 | }
78 | $v->addRepresentation(new ContainerRepresentation('Json', $contents), 0);
79 | } else {
80 | $json->flags |= AbstractValue::FLAG_GENERATED;
81 | $v->addRepresentation(new ValueRepresentation('Json', $json), 0);
82 | }
83 |
84 | return $v;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/MicrotimePlugin.php:
--------------------------------------------------------------------------------
1 | getDateTime())) {
40 | return null;
41 | }
42 |
43 | $out = $dt->format('Y-m-d H:i:s.u');
44 | if (null !== ($lap = $r->getLapTime())) {
45 | $out .= '
SINCE LAST CALL: '.\round($lap, 4).'s.';
46 | }
47 | if (null !== ($total = $r->getTotalTime())) {
48 | $out .= '
SINCE START: '.\round($total, 4).'s.';
49 | }
50 | if (null !== ($avg = $r->getAverageTime())) {
51 | $out .= '
AVERAGE DURATION: '.\round($avg, 4).'s.';
52 | }
53 |
54 | $bytes = Utils::getHumanReadableBytes($r->getMemoryUsage());
55 | $out .= '
MEMORY USAGE: '.$r->getMemoryUsage().' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')';
56 | $bytes = Utils::getHumanReadableBytes($r->getMemoryUsageReal());
57 | $out .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')';
58 |
59 | $bytes = Utils::getHumanReadableBytes($r->getMemoryPeakUsage());
60 | $out .= '
PEAK MEMORY USAGE: '.$r->getMemoryPeakUsage().' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')';
61 | $bytes = Utils::getHumanReadableBytes($r->getMemoryPeakUsageReal());
62 | $out .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')';
63 |
64 | return ''.$out.'
';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Parser/BlacklistPlugin.php:
--------------------------------------------------------------------------------
1 | blacklistValue($var, $c);
70 | }
71 | }
72 |
73 | if ($c->getDepth() <= 0) {
74 | return null;
75 | }
76 |
77 | foreach (self::$shallow_blacklist as $class) {
78 | if ($var instanceof $class) {
79 | return $this->blacklistValue($var, $c);
80 | }
81 | }
82 |
83 | return null;
84 | }
85 |
86 | /**
87 | * @param object &$var
88 | */
89 | protected function blacklistValue(&$var, ContextInterface $c): InstanceValue
90 | {
91 | $object = new InstanceValue($c, \get_class($var), \spl_object_hash($var), \spl_object_id($var));
92 | $object->flags |= AbstractValue::FLAG_BLACKLIST;
93 |
94 | return $object;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Parser/ClosurePlugin.php:
--------------------------------------------------------------------------------
1 | getContext();
57 |
58 | $object = new ClosureValue($c, $var);
59 | $object->flags = $v->flags;
60 | $object->appendRepresentations($v->getRepresentations());
61 |
62 | $object->removeRepresentation('properties');
63 |
64 | $closure = new ReflectionFunction($var);
65 |
66 | $statics = [];
67 |
68 | if ($v = $closure->getClosureThis()) {
69 | $statics = ['this' => $v];
70 | }
71 |
72 | $statics = $statics + $closure->getStaticVariables();
73 |
74 | $cdepth = $c->getDepth();
75 |
76 | if (\count($statics)) {
77 | $statics_parsed = [];
78 |
79 | $parser = $this->getParser();
80 |
81 | foreach ($statics as $name => $_) {
82 | $base = new BaseContext('$'.$name);
83 | $base->depth = $cdepth + 1;
84 | $base->reference = null !== ReflectionReference::fromArrayElement($statics, $name);
85 | $statics_parsed[$name] = $parser->parse($statics[$name], $base);
86 | }
87 |
88 | $object->addRepresentation(new ContainerRepresentation('Uses', $statics_parsed), 0);
89 | }
90 |
91 | return $object;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/Parser/HtmlPlugin.php:
--------------------------------------------------------------------------------
1 | ' !== \strtolower((string) \substr($var, 0, 15))) {
56 | return $v;
57 | }
58 |
59 | try {
60 | $html = HTMLDocument::createFromString($var, LIBXML_NOERROR);
61 | } catch (DOMException $e) { // @codeCoverageIgnore
62 | return $v; // @codeCoverageIgnore
63 | }
64 |
65 | $c = $v->getContext();
66 |
67 | $base = new BaseContext('childNodes');
68 | $base->depth = $c->getDepth();
69 |
70 | if (null !== ($ap = $c->getAccessPath())) {
71 | $base->access_path = '\\Dom\\HTMLDocument::createFromString('.$ap.')->childNodes';
72 | }
73 |
74 | $out = $this->getParser()->parse($html->childNodes, $base);
75 | $iter = $out->getRepresentation('iterator');
76 |
77 | if ($out->flags & AbstractValue::FLAG_DEPTH_LIMIT) {
78 | $out->flags |= AbstractValue::FLAG_GENERATED;
79 | $v->addRepresentation(new ValueRepresentation('HTML', $out), 0);
80 | } elseif ($iter instanceof ContainerRepresentation) {
81 | $v->addRepresentation(new ContainerRepresentation('HTML', $iter->getContents()), 0);
82 | }
83 |
84 | return $v;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Value/FunctionValue.php:
--------------------------------------------------------------------------------
1 | callable_bag = $bag;
45 |
46 | if ($this->callable_bag->internal) {
47 | $this->definition_rep = null;
48 |
49 | return;
50 | }
51 |
52 | /**
53 | * @psalm-var string $this->callable_bag->filename
54 | * @psalm-var int $this->callable_bag->startline
55 | * Psalm issue #11121
56 | */
57 | $this->definition_rep = new CallableDefinitionRepresentation(
58 | $this->callable_bag->filename,
59 | $this->callable_bag->startline,
60 | $this->callable_bag->docstring
61 | );
62 | $this->addRepresentation($this->definition_rep);
63 | }
64 |
65 | public function getCallableBag(): DeclaredCallableBag
66 | {
67 | return $this->callable_bag;
68 | }
69 |
70 | /** @psalm-api */
71 | public function getDefinitionRepresentation(): ?CallableDefinitionRepresentation
72 | {
73 | return $this->definition_rep;
74 | }
75 |
76 | public function getDisplayName(): string
77 | {
78 | return $this->context->getName().'('.$this->callable_bag->getParams().')';
79 | }
80 |
81 | public function getDisplayValue(): ?string
82 | {
83 | if ($this->definition_rep instanceof CallableDefinitionRepresentation) {
84 | return $this->definition_rep->getDocstringFirstLine();
85 | }
86 |
87 | return parent::getDisplayValue();
88 | }
89 |
90 | public function getPhpDocUrl(): ?string
91 | {
92 | if (!$this->callable_bag->internal) {
93 | return null;
94 | }
95 |
96 | return 'https://www.php.net/function.'.\str_replace('_', '-', \strtolower((string) $this->context->getName()));
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/Parser/Base64Plugin.php:
--------------------------------------------------------------------------------
1 | getContext();
78 |
79 | $base = new BaseContext('base64_decode('.$c->getName().')');
80 | $base->depth = $c->getDepth() + 1;
81 |
82 | if (null !== ($ap = $c->getAccessPath())) {
83 | $base->access_path = 'base64_decode('.$ap.')';
84 | }
85 |
86 | $data = $this->getParser()->parse($data, $base);
87 | $data->flags |= AbstractValue::FLAG_GENERATED;
88 |
89 | if (!$data instanceof StringValue || false === $data->getEncoding()) {
90 | return $v;
91 | }
92 |
93 | $r = new ValueRepresentation('Base64', $data);
94 |
95 | if (\strlen($var) > self::$min_length_soft) {
96 | $v->addRepresentation($r, 0);
97 | } else {
98 | $v->addRepresentation($r);
99 | }
100 |
101 | return $v;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Value/InstanceValue.php:
--------------------------------------------------------------------------------
1 |
49 | */
50 | protected ?array $children = null;
51 |
52 | /** @psalm-param class-string $classname */
53 | public function __construct(
54 | ContextInterface $context,
55 | string $classname,
56 | string $spl_object_hash,
57 | int $spl_object_id
58 | ) {
59 | parent::__construct($context, 'object');
60 | $this->classname = $classname;
61 | $this->spl_object_hash = $spl_object_hash;
62 | $this->spl_object_id = $spl_object_id;
63 | }
64 |
65 | /** @psalm-return class-string */
66 | public function getClassName(): string
67 | {
68 | return $this->classname;
69 | }
70 |
71 | public function getSplObjectHash(): string
72 | {
73 | return $this->spl_object_hash;
74 | }
75 |
76 | public function getSplObjectId(): int
77 | {
78 | return $this->spl_object_id;
79 | }
80 |
81 | /** @psalm-param null|list $children */
82 | public function setChildren(?array $children): void
83 | {
84 | $this->children = $children;
85 | }
86 |
87 | /** @psalm-return null|list */
88 | public function getChildren(): ?array
89 | {
90 | return $this->children;
91 | }
92 |
93 | public function getDisplayType(): string
94 | {
95 | return $this->classname;
96 | }
97 |
98 | public function getDisplaySize(): ?string
99 | {
100 | if (null === $this->children) {
101 | return null;
102 | }
103 |
104 | return (string) \count($this->children);
105 | }
106 |
107 | public function getDisplayChildren(): array
108 | {
109 | return $this->children ?? [];
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Parser/ClassStringsPlugin.php:
--------------------------------------------------------------------------------
1 | methods_plugin = new ClassMethodsPlugin($parser);
47 | $this->statics_plugin = new ClassStaticsPlugin($parser);
48 | }
49 |
50 | public function setParser(Parser $p): void
51 | {
52 | parent::setParser($p);
53 |
54 | $this->methods_plugin->setParser($p);
55 | $this->statics_plugin->setParser($p);
56 | }
57 |
58 | public function getTypes(): array
59 | {
60 | return ['string'];
61 | }
62 |
63 | public function getTriggers(): int
64 | {
65 | return Parser::TRIGGER_SUCCESS;
66 | }
67 |
68 | public function parseComplete(&$var, AbstractValue $v, int $trigger): AbstractValue
69 | {
70 | $c = $v->getContext();
71 |
72 | if ($c->getDepth() > 0) {
73 | return $v;
74 | }
75 |
76 | if (!\class_exists($var, true)) {
77 | return $v;
78 | }
79 |
80 | if (\in_array($var, self::$blacklist, true)) {
81 | return $v;
82 | }
83 |
84 | $r = new ReflectionClass($var);
85 |
86 | $fakeC = new BaseContext($c->getName());
87 | $fakeC->access_path = null;
88 | $fakeV = new InstanceValue($fakeC, $r->getName(), 'badhash', -1);
89 | $fakeVar = null;
90 |
91 | $fakeV = $this->methods_plugin->parseComplete($fakeVar, $fakeV, Parser::TRIGGER_SUCCESS);
92 | $fakeV = $this->statics_plugin->parseComplete($fakeVar, $fakeV, Parser::TRIGGER_SUCCESS);
93 |
94 | foreach (['methods', 'static_methods', 'statics', 'constants'] as $rep) {
95 | if ($rep = $fakeV->getRepresentation($rep)) {
96 | $v->addRepresentation($rep);
97 | }
98 | }
99 |
100 | return $v;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Value/ParameterBag.php:
--------------------------------------------------------------------------------
1 | name = $param->getName();
49 | $this->position = $param->getPosition();
50 | $this->ref = $param->isPassedByReference();
51 |
52 | $this->type_hint = ($type = $param->getType()) ? Utils::getTypeString($type) : null;
53 |
54 | if ($param->isDefaultValueAvailable()) {
55 | $default = $param->getDefaultValue();
56 | switch (\gettype($default)) {
57 | case 'NULL':
58 | $this->default = 'null';
59 | break;
60 | case 'boolean':
61 | $this->default = $default ? 'true' : 'false';
62 | break;
63 | case 'array':
64 | $this->default = \count($default) ? 'array(...)' : 'array()';
65 | break;
66 | case 'double':
67 | case 'integer':
68 | case 'string':
69 | $this->default = \var_export($default, true);
70 | break;
71 | case 'object':
72 | $this->default = 'object('.\get_class($default).')';
73 | break;
74 | default:
75 | $this->default = \gettype($default);
76 | break;
77 | }
78 | } else {
79 | $this->default = null;
80 | }
81 | }
82 |
83 | public function __toString()
84 | {
85 | $type = $this->type_hint;
86 | if (null !== $type) {
87 | $type .= ' ';
88 | }
89 |
90 | $default = $this->default;
91 | if (null !== $default) {
92 | $default = ' = '.$default;
93 | }
94 |
95 | $ref = $this->ref ? '&' : '';
96 |
97 | return $type.$ref.'$'.$this->name.$default;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Value/StringValue.php:
--------------------------------------------------------------------------------
1 | value = $value;
56 | $this->encoding = $encoding;
57 | $this->length = \strlen($value);
58 | }
59 |
60 | public function getValue(): string
61 | {
62 | return $this->value;
63 | }
64 |
65 | public function getValueUtf8(): string
66 | {
67 | if (false === $this->encoding) {
68 | throw new DomainException('StringValue with no encoding can\'t be converted to UTF-8');
69 | }
70 |
71 | if ('ASCII' === $this->encoding || 'UTF-8' === $this->encoding) {
72 | return $this->value;
73 | }
74 |
75 | /** @psalm-var string $encoded */
76 | $encoded = \mb_convert_encoding($this->value, 'UTF-8', $this->encoding);
77 |
78 | return $encoded;
79 | }
80 |
81 | /** @psalm-api */
82 | public function getLength(): int
83 | {
84 | return $this->length;
85 | }
86 |
87 | /** @psalm-return Encoding */
88 | public function getEncoding()
89 | {
90 | return $this->encoding;
91 | }
92 |
93 | public function getDisplayType(): string
94 | {
95 | if (false === $this->encoding) {
96 | return 'binary '.$this->type;
97 | }
98 |
99 | if ('ASCII' === $this->encoding) {
100 | return $this->type;
101 | }
102 |
103 | return $this->encoding.' '.$this->type;
104 | }
105 |
106 | public function getDisplaySize(): string
107 | {
108 | return (string) $this->length;
109 | }
110 |
111 | public function getDisplayValue(): string
112 | {
113 | return '"'.$this->value.'"';
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/Value/Context/ClassDeclaredContext.php:
--------------------------------------------------------------------------------
1 | access = $access;
52 | }
53 |
54 | abstract public function getModifiers(): string;
55 |
56 | /** @psalm-param ?class-string $scope */
57 | public function isAccessible(?string $scope): bool
58 | {
59 | if (__PHP_Incomplete_Class::class === $this->owner_class) {
60 | return false;
61 | }
62 |
63 | if (self::ACCESS_PUBLIC === $this->access) {
64 | return true;
65 | }
66 |
67 | if (null === $scope) {
68 | return false;
69 | }
70 |
71 | if (self::ACCESS_PRIVATE === $this->access) {
72 | return $scope === $this->owner_class;
73 | }
74 |
75 | if (KINT_PHP8412 && null !== $this->proto_class) {
76 | if (\is_a($scope, $this->proto_class, true)) {
77 | return true;
78 | }
79 |
80 | if (\is_a($this->proto_class, $scope, true)) {
81 | return true;
82 | }
83 | } else {
84 | if (\is_a($scope, $this->owner_class, true)) {
85 | return true;
86 | }
87 |
88 | if (\is_a($this->owner_class, $scope, true)) {
89 | return true;
90 | }
91 | }
92 |
93 | return false;
94 | }
95 |
96 | protected function getAccess(): string
97 | {
98 | switch ($this->access) {
99 | case self::ACCESS_PUBLIC:
100 | return 'public';
101 | case self::ACCESS_PROTECTED:
102 | return 'protected';
103 | case self::ACCESS_PRIVATE:
104 | return 'private';
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Renderer/Rich/AbstractPlugin.php:
--------------------------------------------------------------------------------
1 | renderer = $r;
43 | }
44 |
45 | /**
46 | * @param string $content The replacement for the getValueShort contents
47 | */
48 | public function renderLockedHeader(AbstractValue $v, string $content): string
49 | {
50 | $header = '';
51 |
52 | $c = $v->getContext();
53 |
54 | if (RichRenderer::$access_paths && $c->getDepth() > 0 && null !== ($ap = $c->getAccessPath())) {
55 | $header .= '⇄';
56 | }
57 |
58 | $header .= '';
59 |
60 | if ($c instanceof ClassDeclaredContext) {
61 | $header .= ''.$c->getModifiers().' ';
62 | }
63 |
64 | $header .= ''.$this->renderer->escape($v->getDisplayName()).' ';
65 |
66 | if ($c instanceof PropertyContext && null !== ($s = $c->getHooks())) {
67 | $header .= ''.$this->renderer->escape($s).' ';
68 | }
69 |
70 | if (null !== ($s = $c->getOperator())) {
71 | $header .= $this->renderer->escape($s, 'ASCII').' ';
72 | }
73 |
74 | $s = $v->getDisplayType();
75 |
76 | if (RichRenderer::$escape_types) {
77 | $s = $this->renderer->escape($s);
78 | }
79 |
80 | if ($c->isRef()) {
81 | $s = '&'.$s;
82 | }
83 |
84 | $header .= ''.$s.'';
85 |
86 | if ($v instanceof InstanceValue && $this->renderer->shouldRenderObjectIds()) {
87 | $header .= '#'.$v->getSplObjectId();
88 | }
89 |
90 | $header .= ' ';
91 |
92 | if (null !== ($s = $v->getDisplaySize())) {
93 | if (RichRenderer::$escape_types) {
94 | $s = $this->renderer->escape($s);
95 | }
96 | $header .= '('.$s.') ';
97 | }
98 |
99 | $header .= $content;
100 |
101 | if (!empty($ap)) {
102 | $header .= ''.$this->renderer->escape($ap).'
';
103 | }
104 |
105 | return $header.'';
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Parser/TablePlugin.php:
--------------------------------------------------------------------------------
1 | self::$max_width) {
76 | return $v;
77 | }
78 |
79 | $keys = \array_keys($elem);
80 | } elseif (\array_keys($elem) !== $keys) {
81 | return $v;
82 | }
83 | }
84 |
85 | $children = $v->getContents();
86 |
87 | if (!$children) {
88 | return $v;
89 | }
90 |
91 | // Ensure none of the child arrays are recursion or depth limit. We
92 | // don't care if their children are since they are the table cells
93 | foreach ($children as $childarray) {
94 | if (!$childarray instanceof ArrayValue || empty($childarray->getContents())) {
95 | return $v;
96 | }
97 | }
98 |
99 | $v->addRepresentation(new TableRepresentation($children), 0);
100 |
101 | return $v;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------