Skip to content

Commit

Permalink
6.0-beta8
Browse files Browse the repository at this point in the history
  • Loading branch information
jnvsor committed Oct 27, 2024
1 parent b15c54d commit 5361a6c
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 243 deletions.
4 changes: 2 additions & 2 deletions _data/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
url: /settings/
text: Kint settings reference
-
url: /contrib/
text: Improving Kint
url: /internals/
text: Kint internals
-
url: /writing-plugins/
text: Writing plugins
Expand Down
9 changes: 5 additions & 4 deletions _includes/example_kint

Large diffs are not rendered by default.

22 changes: 13 additions & 9 deletions advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,33 +128,37 @@ These plugins are on in a default Kint installation.
* `ProfilePlugin`
Profiles your dump to identify classes, interfaces, instances, or properties causing performance issues.
* `ProxyPlugin`
Mostly used for tests, this is also useful if you don't want to make your own plugin class. It takes the array of types and bitmask of triggers the plugin should apply to, as well as a callback that should be run. Here's an example of using `ProxyPlugin` to make a simple `ToString` plugin:
This takes the array of types and bitmask of triggers the plugin should apply to, as well as a callback that should be run. The second argument is either a `ContextInterface` or an `AbstractValue` depending on the trigger.

This is mostly useful if you don't want to make your own plugin class. Here's an example of using `ProxyPlugin` to make a simple `ToString` plugin:

<pre class="prettyprint linenums"><?php
use Kint\Zval\Value;
use Kint\Zval\Representation\Representation;
use Kint\Value\AbstractValue;
use Kint\Value\Representation\StringRepresentation;
use Kint\Parser\Parser;
use Kint\Parser\ProxyPlugin;
use Throwable;
$plugin = new ProxyPlugin(
['object'],
Parser::TRIGGER_SUCCESS,
function (&$var, Value &$o, int $trigger, Parser $parser): void {
function (&$var, AbstractValue $v, int $trigger, Parser $parser): AbstractValue {
$reflection = new ReflectionClass($var);
if (!$reflection->hasMethod('__toString')) {
return;
return $v;
}

$r = new Representation('toString');
try {
$r->contents = (string) $var;
$string = (string) $var;
} catch (Throwable $t) {
return;
return $v;
}

$o->addRepresentation($r);
$r = new StringRepresentation('toString', $string);
$v->addRepresentation($r);

return $v;
}
);

Expand Down
128 changes: 0 additions & 128 deletions contrib.md

This file was deleted.

Binary file modified images/intro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/plugin-after.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/plugin-before.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/plugin-binary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/plugin-microtime.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion index.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ Let's take a look at this data with Kint
* `-d($var)` will attempt to `ob_clean` the previous output and flush after printing
* Add heavy classes to the blacklist to improve performance:
`Kint\Parser\BlacklistPlugin::$shallow_blacklist[] = SomeLargeClass::class;`
* To put dumps in a toolbar at the bottom of the page set `Kint\Renderer\RichRenderer::$folder = true;`
* To change display theme, use `Kint\Renderer\RichRenderer::$theme = 'theme.css';`. You can pass the absolute path to a CSS file, or use one of the built in themes:
* `original.css` (default)
* `solarized.css`
Expand Down
118 changes: 118 additions & 0 deletions internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
permalink: /internals/
title: Kint internals
---

<div id="leftmenu" class="col-sm-4 col-md-3 hidden-xs">
<ul class="nav nav-list side-navigation" data-spy="affix" data-offset-top="{{ site.affix_offset }}">
<li><a href="#overview">Overview</a></li>
<li><a href="#parser">Parser</a></li>
<li><a href="#value">Values</a></li>
<li><a href="#renderer">Renderer</a></li>
<li><a href="#guidelines">Contributor guidelines</a></li>
<li><a href="{{ site.baseurl }}/writing-plugins/">Writing plugins &raquo;</a></li>
</ul>
</div>
<div class="col-sm-8 col-md-9" markdown="1">

# Kint internals

<section id="overview" markdown="1">

## Overview

Kint is typically used as an install-and-forget dumping tool but has plenty of options for customization and to be used as a library.

For both contributing to Kint and for customizing behavior a certain familiarity with Kint's internals is required. This page provides a brief overview of what goes on under the hood.

First, a `Kint\Value\Context\ContextInterface` is passed into `Kint\Parser` along with a PHP value. The parser then creates a `Kint\Value\AbstractValue` to represent the value and returns it.

Once the `AbstractValue` has been built it's passed to a `Kint\Renderer\RendererInterface` which produces a string output.

Creating the initial `ContextInterface` (Which includes the input value's name among other things) and sticking all of this together is handled by the `Kint\Kint` facade (which is aliased to `\Kint`)

</section>
<section id="parser" markdown="1">

## Parser

The parser receives an input value and a `ContextInterface` as parameters. It calls `gettype()` to get the first piece of information about the input data.

The parser loops through its `Kint\Parser\PluginBeginInterface` plugins and if one of them returns an `AbstractValue` this is the value returned.

If not, it switches on the type and calls one of various specialized parsing routines. In the case of arrays and objects this will result in recursive parsing of child values. Since references are a thing the parser has to detect recursive data structures to prevent infinite recursion.

After the basic parse is done and the `AbstractValue` has been created the parser loops through its `PluginCompleteInterface` plugins which can each alter the value and returns the final result.

</section>
<section id="value" markdown="1">

## Values

Values all must inherit from `AbstractValue`. All values have a string `$type` and an integer `$flags` which contains a bitmask of states common to all values (Such as when a value is blacklisted or reaches the depth limit)

Depending on the type of data a value may have more properties. A `StringValue` has a string, an encoding, and a length. Meanwhile an `ArrayValue` has a size and a list of child `AbstractValue`

Once the parser receives a parameter you no longer have information from the parent scope: what it was called, if it was a child of an array, if it was a private property, or if it was a reference. This is passed into the parser from the parent scope as a `ContextInterface` and stored in `$context`

Lastly, `$representations` stores a list of `Kint\Value\Representation\RepresentationInterface` attached to the value, which allows the rich renderer to have multiple tabs showing different representations of the same data.

</section>
<section id="renderer" markdown="1">

## Renderer

The renderer takes values produced by the parser and outputs a string. The exact process varies depending on the renderer. It could print out text or it could print out HTML. It could store the dumped data in a database or email it to the ISS.

### RichRenderer

On its own the `Kint\Renderer\RichRenderer` only renders 3 types of representation: `StringRepresentation`, `ValueRepresentation` and `ContainerRepresentation`.

It has two sets of plugins: A list of `Kint\Renderer\Rich\ValuePluginInterface` for custom rendering of values, and a list of `TabPluginInterface` for custom rendering of representations in a value.

### TextRenderer

The `TextRenderer` ignores representations entirely and provides the most succinct explanation possible. For scalar values it will show the value, for arrays it will show the children, and for objects it will show the "Children".

An objects children are typically the properties but plugins can overwrite them in certain cases. For instance, if an object has no properties the `IteratorPlugin` will set the iterator contents to be the children.

`TextRenderer` has a list of `Kint\Renderer\Text\PluginInterface` which can alter the rendering of values, and a whitelist of parser plugins to stop all of the plugins from running on every dump.

The `CliRenderer` and `PlainRenderer` extend `TextRenderer` and provide additional features like colors.

</section>
<section id="guidelines" markdown="1">

## Contributor guidelines

You can see <a href="https://github.com/kint-php/kint/blob/master/CONTRIBUTING.md" target="_blank">a full list of contributor guidelines</a> in the repository.

Since the parser takes PHP data by reference, and since input data can contain references itself, you can very easily break your application by accidentally altering data inside the dump. Be **very careful** not to alter user data.

### Setting up a dev environment

For developing on core Kint you'll need two things:

1. Composer (PHP)
2. Npm (NodeJS)

If you don't have composer <a href="https://getcomposer.org/" target="_blank">do yourself a favor and learn it</a>. If you don't have npm that's understandable.

In any case, Kint uses composer and npm for development tools. Composer calls npm under the assumption that it's in your `$PATH`.

If all of these are installed simply run `composer install` and all your dependencies will be installed automatically.

### Format and Build

* Static analysis can find bugs in code when even unit tests don't. You should always run `composer analyze` before a commit and fix any errors.
* Tests have to pass. You should always run `./vendor/bin/phpunit tests` before a commit and fix any errors.
* Since code style is a good thing you should always run `composer format` before a commit to fix any inconsistent code style.
* Since we deliver reproducibly compiled JS/CSS/PHAR files in our repo you should always run `composer build` before a commit to rebuild the files and commit them.

If you fail any of these steps CI will complain.

</section>

<h2><a href="{{ site.baseurl }}/writing-plugins/">Writing plugins &raquo;</a></h2>

</div>
Loading

0 comments on commit 5361a6c

Please sign in to comment.