This commit is contained in:
Markus
2022-04-28 09:40:10 +02:00
commit 795794f992
9586 changed files with 1146991 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use InvalidArgumentException;
use Kint\Utils;
use Kint\Zval\Value;
class ArrayLimitPlugin extends Plugin
{
/**
* Maximum size of arrays before limiting.
*
* @var int
*/
public static $trigger = 1000;
/**
* Maximum amount of items to show in a limited array.
*
* @var int
*/
public static $limit = 50;
/**
* Don't limit arrays with string keys.
*
* @var bool
*/
public static $numeric_only = true;
public function getTypes()
{
return ['array'];
}
public function getTriggers()
{
return Parser::TRIGGER_BEGIN;
}
public function parse(&$var, Value &$o, $trigger)
{
if (self::$limit >= 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);
}
}
}
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use ArrayObject;
use Kint\Zval\Value;
class ArrayObjectPlugin extends Plugin
{
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_BEGIN;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof ArrayObject) {
return;
}
$flags = $var->getFlags();
if (ArrayObject::STD_PROP_LIST === $flags) {
return;
}
$var->setFlags(ArrayObject::STD_PROP_LIST);
$o = $this->parser->parse($var, $o);
$var->setFlags($flags);
$this->parser->haltParse();
}
}

View File

@@ -0,0 +1,94 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
class Base64Plugin extends Plugin
{
/**
* The minimum length before a string will be considered for base64 decoding.
*
* @var int
*/
public static $min_length_hard = 16;
/**
* The minimum length before the base64 decoding will take precedence.
*
* @var int
*/
public static $min_length_soft = 50;
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (\strlen($var) < self::$min_length_hard || \strlen($var) % 4) {
return;
}
if (\preg_match('/^[A-Fa-f0-9]+$/', $var)) {
return;
}
if (!\preg_match('/^[A-Za-z0-9+\\/=]+$/', $var)) {
return;
}
$data = \base64_decode($var, true);
if (false === $data) {
return;
}
$base_obj = new Value();
$base_obj->depth = $o->depth + 1;
$base_obj->name = 'base64_decode('.$o->name.')';
if ($o->access_path) {
$base_obj->access_path = 'base64_decode('.$o->access_path.')';
}
$r = new Representation('Base64');
$r->contents = $this->parser->parse($data, $base_obj);
if (\strlen($var) > self::$min_length_soft) {
$o->addRepresentation($r, 0);
} else {
$o->addRepresentation($r);
}
}
}

View File

@@ -0,0 +1,49 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\BlobValue;
use Kint\Zval\Value;
class BinaryPlugin extends Plugin
{
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$o instanceof BlobValue || !\in_array($o->encoding, ['ASCII', 'UTF-8'], true)) {
$o->value->hints[] = 'binary';
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\InstanceValue;
use Kint\Zval\Value;
class BlacklistPlugin extends Plugin
{
/**
* List of classes and interfaces to blacklist.
*
* @var array
*/
public static $blacklist = [];
/**
* List of classes and interfaces to blacklist except when dumped directly.
*
* @var array
*/
public static $shallow_blacklist = ['Psr\\Container\\ContainerInterface'];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_BEGIN;
}
public function parse(&$var, Value &$o, $trigger)
{
foreach (self::$blacklist as $class) {
if ($var instanceof $class) {
return $this->blacklistValue($var, $o);
}
}
if ($o->depth <= 0) {
return;
}
foreach (self::$shallow_blacklist as $class) {
if ($var instanceof $class) {
return $this->blacklistValue($var, $o);
}
}
}
protected function blacklistValue(&$var, Value &$o)
{
$object = new InstanceValue();
$object->transplant($o);
$object->classname = \get_class($var);
$object->spl_object_hash = \spl_object_hash($var);
$object->clearRepresentations();
$object->value = null;
$object->size = null;
$object->hints[] = 'blacklist';
$o = $object;
$this->parser->haltParse();
}
}

View File

@@ -0,0 +1,113 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
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 = [];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
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 = [];
$reflection = new ReflectionClass($class);
foreach ($reflection->getMethods() as $method) {
$methods[] = new MethodValue($method);
}
\usort($methods, ['Kint\\Parser\\ClassMethodsPlugin', 'sort']);
self::$cache[$class] = $methods;
}
if (!empty(self::$cache[$class])) {
$rep = new Representation('Available methods', 'methods');
// Can't cache access paths
foreach (self::$cache[$class] as $m) {
$method = clone $m;
$method->depth = $o->depth + 1;
if (!$this->parser->childHasPath($o, $method)) {
$method->access_path = null;
} else {
$method->setAccessPathFrom($o);
}
if ($method->owner_class !== $class && $ds = $method->getRepresentation('docstring')) {
$ds = clone $ds;
$ds->class = $method->owner_class;
$method->replaceRepresentation($ds);
}
$rep->contents[] = $method;
}
$o->addRepresentation($rep);
}
}
private static function sort(MethodValue $a, MethodValue $b)
{
$sort = ((int) $a->static) - ((int) $b->static);
if ($sort) {
return $sort;
}
$sort = Value::sortByAccess($a, $b);
if ($sort) {
return $sort;
}
$sort = InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class);
if ($sort) {
return $sort;
}
return $a->startline - $b->startline;
}
}

View File

@@ -0,0 +1,128 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\InstanceValue;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
use ReflectionClass;
use ReflectionProperty;
class ClassStaticsPlugin extends Plugin
{
private static $cache = [];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
$class = \get_class($var);
$reflection = new ReflectionClass($class);
// 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 = [];
foreach ($reflection->getConstants() as $name => $val) {
$const = Value::blank($name, '\\'.$class.'::'.$name);
$const->const = true;
$const->depth = $o->depth + 1;
$const->owner_class = $class;
$const->operator = Value::OPERATOR_STATIC;
$const = $this->parser->parse($val, $const);
$consts[] = $const;
}
self::$cache[$class] = $consts;
}
$statics = new Representation('Static class properties', 'statics');
$statics->contents = self::$cache[$class];
foreach ($reflection->getProperties(ReflectionProperty::IS_STATIC) as $static) {
$prop = new Value();
$prop->name = '$'.$static->getName();
$prop->depth = $o->depth + 1;
$prop->static = true;
$prop->operator = Value::OPERATOR_STATIC;
$prop->owner_class = $static->getDeclaringClass()->name;
$prop->access = Value::ACCESS_PUBLIC;
if ($static->isProtected()) {
$prop->access = Value::ACCESS_PROTECTED;
} elseif ($static->isPrivate()) {
$prop->access = Value::ACCESS_PRIVATE;
}
if ($this->parser->childHasPath($o, $prop)) {
$prop->access_path = '\\'.$prop->owner_class.'::'.$prop->name;
}
$static->setAccessible(true);
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, ['Kint\\Parser\\ClassStaticsPlugin', 'sort']);
$o->addRepresentation($statics);
}
private static function sort(Value $a, Value $b)
{
$sort = ((int) $a->const) - ((int) $b->const);
if ($sort) {
return $sort;
}
$sort = Value::sortByAccess($a, $b);
if ($sort) {
return $sort;
}
return InstanceValue::sortByHierarchy($a->owner_class, $b->owner_class);
}
}

View File

@@ -0,0 +1,94 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Closure;
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 ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof Closure) {
return;
}
$object = new ClosureValue();
$object->transplant($o);
$o = $object;
$object->removeRepresentation('properties');
$closure = new ReflectionFunction($var);
$o->filename = $closure->getFileName();
$o->startline = $closure->getStartLine();
foreach ($closure->getParameters() as $param) {
$o->parameters[] = new ParameterValue($param);
}
$p = new Representation('Parameters');
$p->contents = &$o->parameters;
$o->addRepresentation($p, 0);
$statics = [];
if ($v = $closure->getClosureThis()) {
$statics = ['this' => $v];
}
if (\count($statics = $statics + $closure->getStaticVariables())) {
$statics_parsed = [];
foreach ($statics as $name => &$static) {
$obj = Value::blank('$'.$name);
$obj->depth = $o->depth + 1;
$statics_parsed[$name] = $this->parser->parse($static, $obj);
if (null === $statics_parsed[$name]->value) {
$statics_parsed[$name]->access_path = null;
}
}
$r = new Representation('Uses');
$r->contents = $statics_parsed;
$o->addRepresentation($r, 0);
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\ColorRepresentation;
use Kint\Zval\Value;
class ColorPlugin extends Plugin
{
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (\strlen($var) > 32) {
return;
}
$trimmed = \strtolower(\trim($var));
if (!isset(ColorRepresentation::$color_map[$trimmed]) && !\preg_match('/^(?:(?:rgb|hsl)[^\\)]{6,}\\)|#[0-9a-fA-F]{3,8})$/', $trimmed)) {
return;
}
$rep = new ColorRepresentation($var);
if ($rep->variant) {
$o->removeRepresentation($o->value);
$o->addRepresentation($rep, 0);
$o->hints[] = 'color';
}
}
}

View File

@@ -0,0 +1,337 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use DOMNamedNodeMap;
use DOMNode;
use DOMNodeList;
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
* way to see inside the DOMNode without print_r, and the only way to see mixed
* text and node inside XML (SimpleXMLElement will strip out the text).
*/
class DOMDocumentPlugin extends Plugin
{
/**
* List of properties to skip parsing.
*
* The properties of a DOMNode can do a *lot* of damage to debuggers. The
* DOMNode contains not one, not two, not three, not four, not 5, not 6,
* not 7 but 8 different ways to recurse into itself:
* * firstChild
* * lastChild
* * previousSibling
* * nextSibling
* * ownerDocument
* * parentNode
* * childNodes
* * attributes
*
* All of this combined: the tiny SVGs used as the caret in Kint are already
* enough to make parsing and rendering take over a second, and send memory
* usage over 128 megs. So we blacklist every field we don't strictly need
* and hope that that's good enough.
*
* In retrospect - this is probably why print_r does the same
*
* @var array
*/
public static $blacklist = [
'parentNode' => 'DOMNode',
'firstChild' => 'DOMNode',
'lastChild' => 'DOMNode',
'previousSibling' => 'DOMNode',
'nextSibling' => 'DOMNode',
'ownerDocument' => 'DOMDocument',
];
/**
* Show all properties and methods.
*
* @var bool
*/
public static $verbose = false;
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$o instanceof InstanceValue) {
return;
}
if ($var instanceof DOMNamedNodeMap || $var instanceof DOMNodeList) {
return $this->parseList($var, $o, $trigger);
}
if ($var instanceof DOMNode) {
return $this->parseNode($var, $o);
}
}
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
// 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) {
return;
}
$o->size = $var->length;
if (0 === $o->size) {
$o->replaceRepresentation(new Representation('Iterator'));
$o->size = null;
return;
}
// 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 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 = [$b];
$o->replaceRepresentation($r, 0);
return;
}
$r = new Representation('Iterator');
$o->replaceRepresentation($r, 0);
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) {
// 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).')';
}
}
$r->contents[] = $this->parser->parse($item, $base_obj);
}
}
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 = [
'nodeValue',
'childNodes',
'attributes',
];
if (self::$verbose) {
$known_properties = [
'nodeName',
'nodeValue',
'nodeType',
'parentNode',
'childNodes',
'firstChild',
'lastChild',
'previousSibling',
'nextSibling',
'attributes',
'ownerDocument',
'namespaceURI',
'prefix',
'localName',
'baseURI',
'textContent',
];
}
$childNodes = null;
$attributes = null;
$rep = $o->value;
foreach ($known_properties as $prop) {
$prop_obj = $this->parseProperty($o, $prop, $var);
$rep->contents[] = $prop_obj;
if ('childNodes' === $prop) {
$childNodes = $prop_obj->getRepresentation('iterator');
} elseif ('attributes' === $prop) {
$attributes = $prop_obj->getRepresentation('iterator');
}
}
if (!self::$verbose) {
$o->removeRepresentation('methods');
$o->removeRepresentation('properties');
}
// Attributes and comments and text nodes don't
// need children or attributes of their own
if (\in_array($o->classname, ['DOMAttr', 'DOMText', 'DOMComment'], true)) {
$o = self::textualNodeToString($o);
return;
}
// Set the attributes
if ($attributes) {
$a = new Representation('Attributes');
foreach ($attributes->contents as $attribute) {
$a->contents[] = $attribute;
}
$o->addRepresentation($a, 0);
}
// Set the children
if ($childNodes) {
$c = new Representation('Children');
if (1 === \count($childNodes->contents) && ($node = \reset($childNodes->contents)) && \in_array('depth_limit', $node->hints, true)) {
$n = new InstanceValue();
$n->transplant($node);
$n->name = 'childNodes';
$n->classname = 'DOMNodeList';
$c->contents = [$n];
} else {
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;
}
}
$o->addRepresentation($c, 0);
}
if ($childNodes) {
$o->size = \count($childNodes->contents);
}
if (!$o->size) {
$o->size = null;
}
}
protected function parseProperty(InstanceValue $o, $prop, &$var)
{
// Duplicating (And slightly optimizing) the Parser::parseObject() code here
$base_obj = new Value();
$base_obj->depth = $o->depth + 1;
$base_obj->owner_class = $o->classname;
$base_obj->name = $prop;
$base_obj->operator = Value::OPERATOR_OBJECT;
$base_obj->access = Value::ACCESS_PUBLIC;
if (null !== $o->access_path) {
$base_obj->access_path = $o->access_path;
if (\preg_match('/^[A-Za-z0-9_]+$/', $base_obj->name)) {
$base_obj->access_path .= '->'.$base_obj->name;
} else {
$base_obj->access_path .= '->{'.\var_export($base_obj->name, true).'}';
}
}
if (!isset($var->{$prop})) {
$base_obj->type = 'null';
} elseif (isset(self::$blacklist[$prop])) {
$b = new InstanceValue();
$b->transplant($base_obj);
$base_obj = $b;
$base_obj->hints[] = 'blacklist';
$base_obj->classname = self::$blacklist[$prop];
} elseif ('attributes' === $prop) {
// 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);
}
return $base_obj;
}
protected static function textualNodeToString(InstanceValue $o)
{
if (empty($o->value) || empty($o->value->contents) || empty($o->classname)) {
return;
}
if (!\in_array($o->classname, ['DOMText', 'DOMAttr', 'DOMComment'], true)) {
return;
}
foreach ($o->value->contents as $property) {
if ('nodeValue' === $property->name) {
$ret = clone $property;
$ret->name = $o->name;
return $ret;
}
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use DateTime;
use Kint\Zval\DateTimeValue;
use Kint\Zval\Value;
class DateTimePlugin extends Plugin
{
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof DateTime) {
return;
}
$object = new DateTimeValue($var);
$object->transplant($o);
$o = $object;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\SplFileInfoRepresentation;
use Kint\Zval\Value;
use SplFileInfo;
class FsPathPlugin extends Plugin
{
public static $blacklist = ['/', '.'];
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (\strlen($var) > 2048) {
return;
}
if (!\preg_match('/[\\/\\'.DIRECTORY_SEPARATOR.']/', $var)) {
return;
}
if (\preg_match('/[?<>"*|]/', $var)) {
return;
}
if (!@\file_exists($var)) {
return;
}
if (\in_array($var, self::$blacklist, true)) {
return;
}
$r = new SplFileInfoRepresentation(new SplFileInfo($var));
$r->hints[] = 'fspath';
$o->addRepresentation($r, 0);
}
}

View File

@@ -0,0 +1,105 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
use Traversable;
class IteratorPlugin extends Plugin
{
/**
* List of classes and interfaces to blacklist.
*
* Certain classes (Such as PDOStatement) irreversibly lose information
* when traversed. Others are just huge. Either way, put them in here
* and you won't have to worry about them being parsed.
*
* @var array
*/
public static $blacklist = [
'DOMNamedNodeMap',
'DOMNodeList',
'mysqli_result',
'PDOStatement',
'SplFileObject',
];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof Traversable) {
return;
}
foreach (self::$blacklist as $class) {
if ($var instanceof $class) {
$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 = [$b];
$o->addRepresentation($r);
return;
}
}
$data = \iterator_to_array($var);
$base_obj = new Value();
$base_obj->depth = $o->depth;
if ($o->access_path) {
$base_obj->access_path = 'iterator_to_array('.$o->access_path.')';
}
$r = new Representation('Iterator');
$r->contents = $this->parser->parse($data, $base_obj);
$r->contents = $r->contents->value->contents;
$primary = $o->getRepresentations();
$primary = \reset($primary);
if ($primary && $primary === $o->value && [] === $primary->contents) {
$o->addRepresentation($r, 0);
} else {
$o->addRepresentation($r);
}
}
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
class JsonPlugin extends Plugin
{
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!isset($var[0]) || ('{' !== $var[0] && '[' !== $var[0])) {
return;
}
$json = \json_decode($var, true);
if (!$json) {
return;
}
$json = (array) $json;
$base_obj = new Value();
$base_obj->depth = $o->depth;
if ($o->access_path) {
$base_obj->access_path = 'json_decode('.$o->access_path.', true)';
}
$r = new Representation('Json');
$r->contents = $this->parser->parse($json, $base_obj);
if (!\in_array('depth_limit', $r->contents->hints, true)) {
$r->contents = $r->contents->value->contents;
}
$o->addRepresentation($r, 0);
}
}

View File

@@ -0,0 +1,105 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\MicrotimeRepresentation;
use Kint\Zval\Value;
class MicrotimePlugin extends Plugin
{
private static $last = null;
private static $start = null;
private static $times = 0;
private static $group = 0;
public function getTypes()
{
return ['string', 'double'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (0 !== $o->depth) {
return;
}
if (\is_string($var)) {
if ('microtime()' !== $o->name || !\preg_match('/^0\\.[0-9]{8} [0-9]{10}$/', $var)) {
return;
}
$usec = (int) \substr($var, 2, 6);
$sec = (int) \substr($var, 11, 10);
} else {
if ('microtime(...)' !== $o->name) {
return;
}
$sec = \floor($var);
$usec = $var - $sec;
$usec = \floor($usec * 1000000);
}
$time = $sec + ($usec / 1000000);
if (null !== self::$last) {
$last_time = self::$last[0] + (self::$last[1] / 1000000);
$lap = $time - $last_time;
++self::$times;
} else {
$lap = null;
self::$start = $time;
}
self::$last = [$sec, $usec];
if (null !== $lap) {
$total = $time - self::$start;
$r = new MicrotimeRepresentation($sec, $usec, self::$group, $lap, $total, self::$times);
} else {
$r = new MicrotimeRepresentation($sec, $usec, self::$group);
}
$r->contents = $var;
$r->implicit_label = true;
$o->removeRepresentation($o->value);
$o->addRepresentation($r);
$o->hints[] = 'microtime';
}
public static function clean()
{
self::$last = null;
self::$start = null;
self::$times = 0;
++self::$group;
}
}

View File

@@ -0,0 +1,189 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Value;
use Mysqli;
use ReflectionClass;
use Throwable;
/**
* Adds support for Mysqli object parsing.
*
* Due to the way mysqli is implemented in PHP, this will cause
* warnings on certain Mysqli objects if screaming is enabled.
*/
class MysqliPlugin extends Plugin
{
// These 'properties' are actually globals
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 = [
'client_info' => true,
'errno' => true,
'error' => true,
];
// These are only readable on connected mysqli objects
protected $connected_readable = [
'affected_rows' => true,
'error_list' => true,
'field_count' => true,
'host_info' => true,
'info' => true,
'insert_id' => true,
'server_info' => true,
'server_version' => true,
'sqlstate' => true,
'protocol_version' => true,
'thread_id' => true,
'warning_count' => true,
];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_COMPLETE;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof Mysqli) {
return;
}
try {
$connected = \is_string(@$var->sqlstate);
} catch (Throwable $t) {
$connected = false;
}
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) {
if (isset($this->connected_readable[$obj->name])) {
if (!$connected) {
continue;
}
} elseif (isset($this->empty_readable[$obj->name])) {
// No failed connections after PHP 8.1
if (!$connected && !$empty) { // @codeCoverageIgnore
continue; // @codeCoverageIgnore
}
} elseif (!isset($this->always_readable[$obj->name])) {
continue;
}
if ('null' !== $obj->type) {
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 = Value::blank($obj->name, $obj->access_path);
$base->depth = $obj->depth;
$base->owner_class = $obj->owner_class;
$base->operator = $obj->operator;
$base->access = $obj->access;
$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);
}
}
}

623
system/ThirdParty/Kint/Parser/Parser.php vendored Normal file
View File

@@ -0,0 +1,623 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use DomainException;
use Exception;
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;
class Parser
{
/**
* Plugin triggers.
*
* These are constants indicating trigger points for plugins
*
* BEGIN: Before normal parsing
* SUCCESS: After successful parsing
* RECURSION: After parsing cancelled by recursion
* DEPTH_LIMIT: After parsing cancelled by depth limit
* COMPLETE: SUCCESS | RECURSION | DEPTH_LIMIT
*
* While a plugin's getTriggers may return any of these
*/
const TRIGGER_NONE = 0;
const TRIGGER_BEGIN = 1;
const TRIGGER_SUCCESS = 2;
const TRIGGER_RECURSION = 4;
const TRIGGER_DEPTH_LIMIT = 8;
const TRIGGER_COMPLETE = 14;
protected $caller_class;
protected $depth_limit = 0;
protected $marker;
protected $object_hashes = [];
protected $parse_break = false;
protected $plugins = [];
/**
* @param int $depth_limit Maximum depth to parse data
* @param null|string $caller Caller class name
*/
public function __construct($depth_limit = 0, $caller = null)
{
$this->marker = \uniqid("kint\0", true);
$this->depth_limit = $depth_limit;
$this->caller_class = $caller;
}
/**
* Set the caller class.
*
* @param null|string $caller Caller class name
*/
public function setCallerClass($caller = null)
{
$this->noRecurseCall();
$this->caller_class = $caller;
}
public function getCallerClass()
{
return $this->caller_class;
}
/**
* Set the depth limit.
*
* @param int $depth_limit Maximum depth to parse data
*/
public function setDepthLimit($depth_limit = 0)
{
$this->noRecurseCall();
$this->depth_limit = $depth_limit;
}
public function getDepthLimit()
{
return $this->depth_limit;
}
/**
* Parses a variable into a Kint object structure.
*
* @param mixed $var The input variable
* @param Value $o The base object
*
* @return Value
*/
public function parse(&$var, Value $o)
{
$o->type = \strtolower(\gettype($var));
if (!$this->applyPlugins($var, $o, self::TRIGGER_BEGIN)) {
return $o;
}
switch ($o->type) {
case 'array':
return $this->parseArray($var, $o);
case 'boolean':
case 'double':
case 'integer':
case 'null':
return $this->parseGeneric($var, $o);
case 'object':
return $this->parseObject($var, $o);
case 'resource':
return $this->parseResource($var, $o);
case 'string':
return $this->parseString($var, $o);
case 'unknown type':
case 'resource (closed)':
default:
return $this->parseResourceClosed($var, $o);
}
}
public function addPlugin(Plugin $p)
{
if (!$types = $p->getTypes()) {
return false;
}
if (!$triggers = $p->getTriggers()) {
return false;
}
$p->setParser($this);
foreach ($types as $type) {
if (!isset($this->plugins[$type])) {
$this->plugins[$type] = [
self::TRIGGER_BEGIN => [],
self::TRIGGER_SUCCESS => [],
self::TRIGGER_RECURSION => [],
self::TRIGGER_DEPTH_LIMIT => [],
];
}
foreach ($this->plugins[$type] as $trigger => &$pool) {
if ($triggers & $trigger) {
$pool[] = $p;
}
}
}
return true;
}
public function clearPlugins()
{
$this->plugins = [];
}
public function haltParse()
{
$this->parse_break = true;
}
public function childHasPath(InstanceValue $parent, Value $child)
{
if ('object' === $parent->type && (null !== $parent->access_path || $child->static || $child->const)) {
if (Value::ACCESS_PUBLIC === $child->access) {
return true;
}
if (Value::ACCESS_PRIVATE === $child->access && $this->caller_class) {
if ($this->caller_class === $child->owner_class) {
return true;
}
} elseif (Value::ACCESS_PROTECTED === $child->access && $this->caller_class) {
if ($this->caller_class === $child->owner_class) {
return true;
}
if (\is_subclass_of($this->caller_class, $child->owner_class)) {
return true;
}
if (\is_subclass_of($child->owner_class, $this->caller_class)) {
return true;
}
}
}
return false;
}
/**
* Returns an array without the recursion marker in it.
*
* DO NOT pass an array that has had it's marker removed back
* into the parser, it will result in an extra recursion
*
* @param array $array Array potentially containing a recursion marker
*
* @return array Array with recursion marker removed
*/
public function getCleanArray(array $array)
{
unset($array[$this->marker]);
return $array;
}
protected function noRecurseCall()
{
$bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
$caller_frame = [
'function' => __FUNCTION__,
];
while (isset($bt[0]['object']) && $bt[0]['object'] === $this) {
$caller_frame = \array_shift($bt);
}
foreach ($bt as $frame) {
if (isset($frame['object']) && $frame['object'] === $this) {
throw new DomainException(__CLASS__.'::'.$caller_frame['function'].' cannot be called from inside a parse');
}
}
}
private function parseGeneric(&$var, Value $o)
{
$rep = new Representation('Contents');
$rep->contents = $var;
$rep->implicit_label = true;
$o->addRepresentation($rep);
$o->value = $rep;
$this->applyPlugins($var, $o, self::TRIGGER_SUCCESS);
return $o;
}
/**
* Parses a string into a Kint BlobValue structure.
*
* @param string $var The input variable
* @param Value $o The base object
*
* @return Value
*/
private function parseString(&$var, Value $o)
{
$string = new BlobValue();
$string->transplant($o);
$string->encoding = BlobValue::detectEncoding($var);
$string->size = \strlen($var);
$rep = new Representation('Contents');
$rep->contents = $var;
$rep->implicit_label = true;
$string->addRepresentation($rep);
$string->value = $rep;
$this->applyPlugins($var, $string, self::TRIGGER_SUCCESS);
return $string;
}
/**
* Parses an array into a Kint object structure.
*
* @param array $var The input variable
* @param Value $o The base object
*
* @return Value
*/
private function parseArray(array &$var, Value $o)
{
$array = new Value();
$array->transplant($o);
$array->size = \count($var);
if (isset($var[$this->marker])) {
--$array->size;
$array->hints[] = 'recursion';
$this->applyPlugins($var, $array, self::TRIGGER_RECURSION);
return $array;
}
$rep = new Representation('Contents');
$rep->implicit_label = true;
$array->addRepresentation($rep);
$array->value = $rep;
if (!$array->size) {
$this->applyPlugins($var, $array, self::TRIGGER_SUCCESS);
return $array;
}
if ($this->depth_limit && $o->depth >= $this->depth_limit) {
$array->hints[] = 'depth_limit';
$this->applyPlugins($var, $array, self::TRIGGER_DEPTH_LIMIT);
return $array;
}
$copy = \array_values($var);
// It's really really hard to access numeric string keys in arrays,
// and it's really really hard to access integer properties in
// objects, so we just use array_values and index by counter to get
// at it reliably for reference testing. This also affects access
// paths since it's pretty much impossible to access these things
// without complicated stuff you should never need to do.
$i = 0;
// Set the marker for recursion
$var[$this->marker] = $array->depth;
$refmarker = new stdClass();
foreach ($var as $key => &$val) {
if ($key === $this->marker) {
continue;
}
$child = new Value();
$child->name = $key;
$child->depth = $array->depth + 1;
$child->access = Value::ACCESS_NONE;
$child->operator = Value::OPERATOR_ARRAY;
if (null !== $array->access_path) {
if (\is_string($key) && (string) (int) $key === $key) {
$child->access_path = 'array_values('.$array->access_path.')['.$i.']'; // @codeCoverageIgnore
} else {
$child->access_path = $array->access_path.'['.\var_export($key, true).']';
}
}
$stash = $val;
$copy[$i] = $refmarker;
if ($val === $refmarker) {
$child->reference = true;
$val = $stash;
}
$rep->contents[] = $this->parse($val, $child);
++$i;
}
$this->applyPlugins($var, $array, self::TRIGGER_SUCCESS);
unset($var[$this->marker]);
return $array;
}
/**
* Parses an object into a Kint InstanceValue structure.
*
* @param object $var The input variable
* @param Value $o The base object
*
* @return Value
*/
private function parseObject(&$var, Value $o)
{
$hash = \spl_object_hash($var);
$values = (array) $var;
$object = new InstanceValue();
$object->transplant($o);
$object->classname = \get_class($var);
$object->spl_object_hash = $hash;
$object->size = \count($values);
if (isset($this->object_hashes[$hash])) {
$object->hints[] = 'recursion';
$this->applyPlugins($var, $object, self::TRIGGER_RECURSION);
return $object;
}
$this->object_hashes[$hash] = $object;
if ($this->depth_limit && $o->depth >= $this->depth_limit) {
$object->hints[] = 'depth_limit';
$this->applyPlugins($var, $object, self::TRIGGER_DEPTH_LIMIT);
unset($this->object_hashes[$hash]);
return $object;
}
$reflector = new ReflectionObject($var);
if ($reflector->isUserDefined()) {
$object->filename = $reflector->getFileName();
$object->startline = $reflector->getStartLine();
}
$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;
// Reflection will not show parent classes private properties, and if a
// property was unset it will happly trigger a notice looking for it.
foreach ($values as $key => &$val) {
// Casting object to array:
// private properties show in the form "\0$owner_class_name\0$property_name";
// protected properties show in the form "\0*\0$property_name";
// public properties show in the form "$property_name";
// http://www.php.net/manual/en/language.types.array.php#language.types.array.casting
$child = new Value();
$child->depth = $object->depth + 1;
$child->owner_class = $object->classname;
$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 = Value::ACCESS_PROTECTED;
} else {
$child->access = Value::ACCESS_PRIVATE;
$child->owner_class = $split_key[1];
}
} elseif (KINT_PHP72) {
$child->name = (string) $key;
} else {
$child->name = $key; // @codeCoverageIgnore
}
if ($this->childHasPath($object, $child)) {
$child->access_path = $object->access_path;
if (!KINT_PHP72 && \is_int($child->name)) {
$child->access_path = 'array_values((array) '.$child->access_path.')['.$i.']'; // @codeCoverageIgnore
} elseif (\preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $child->name)) {
$child->access_path .= '->'.$child->name;
} else {
$child->access_path .= '->{'.\var_export((string) $child->name, true).'}';
}
}
$stash = $val;
$copy[$i] = $refmarker;
if ($val === $refmarker) {
$child->reference = true;
$val = $stash;
}
$rep->contents[] = $this->parse($val, $child);
++$i;
}
$object->addRepresentation($rep);
$object->value = $rep;
$this->applyPlugins($var, $object, self::TRIGGER_SUCCESS);
unset($this->object_hashes[$hash]);
return $object;
}
/**
* Parses a resource into a Kint ResourceValue structure.
*
* @param resource $var The input variable
* @param Value $o The base object
*
* @return Value
*/
private function parseResource(&$var, Value $o)
{
$resource = new ResourceValue();
$resource->transplant($o);
$resource->resource_type = \get_resource_type($var);
$this->applyPlugins($var, $resource, self::TRIGGER_SUCCESS);
return $resource;
}
/**
* Parses a closed resource into a Kint object structure.
*
* @param mixed $var The input variable
* @param Value $o The base object
*
* @return Value
*/
private function parseResourceClosed(&$var, Value $o)
{
$o->type = 'resource (closed)';
$this->applyPlugins($var, $o, self::TRIGGER_SUCCESS);
return $o;
}
/**
* Applies plugins for an object type.
*
* @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, Value &$o, $trigger)
{
$break_stash = $this->parse_break;
/** @var bool Psalm bug workaround */
$this->parse_break = false;
$plugins = [];
if (isset($this->plugins[$o->type][$trigger])) {
$plugins = $this->plugins[$o->type][$trigger];
}
foreach ($plugins as $plugin) {
try {
$plugin->parse($var, $o, $trigger);
} catch (Exception $e) {
\trigger_error(
'An exception ('.\get_class($e).') was thrown in '.$e->getFile().' on line '.$e->getLine().' while executing Kint Parser Plugin "'.\get_class($plugin).'". Error message: '.$e->getMessage(),
E_USER_WARNING
);
}
if ($this->parse_break) {
$this->parse_break = $break_stash;
return false;
}
}
$this->parse_break = $break_stash;
return true;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Value;
abstract class Plugin
{
protected $parser;
public function setParser(Parser $p)
{
$this->parser = $p;
}
/**
* An array of types (As returned by gettype) for all data this plugin can operate on.
*
* @return array List of types
*/
public function getTypes()
{
return [];
}
public function getTriggers()
{
return Parser::TRIGGER_NONE;
}
abstract public function parse(&$var, Value &$o, $trigger);
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use InvalidArgumentException;
use Kint\Zval\Value;
class ProxyPlugin extends Plugin
{
protected $types;
protected $triggers;
protected $callback;
public function __construct(array $types, $triggers, $callback)
{
if (!\is_int($triggers)) {
throw new InvalidArgumentException('ProxyPlugin triggers must be an int bitmask');
}
if (!\is_callable($callback)) {
throw new InvalidArgumentException('ProxyPlugin callback must be callable');
}
$this->types = $types;
$this->triggers = $triggers;
$this->callback = $callback;
}
public function getTypes()
{
return $this->types;
}
public function getTriggers()
{
return $this->triggers;
}
public function parse(&$var, Value &$o, $trigger)
{
return \call_user_func_array($this->callback, [&$var, &$o, $trigger, $this->parser]);
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
class SerializePlugin extends Plugin
{
/**
* Disables automatic unserialization on arrays and objects.
*
* As the PHP manual notes:
*
* > Unserialization can result in code being loaded and executed due to
* > object instantiation and autoloading, and a malicious user may be able
* > to exploit this.
*
* The natural way to stop that from happening is to just refuse to unserialize
* stuff by default. Which is what we're doing for anything that's not scalar.
*
* @var bool
*/
public static $safe_mode = true;
public static $options = [true];
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
$trimmed = \rtrim($var);
if ('N;' !== $trimmed && !\preg_match('/^(?:[COabis]:\\d+[:;]|d:\\d+(?:\\.\\d+);)/', $trimmed)) {
return;
}
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
$data = @\unserialize($trimmed, self::$options);
} else {
$data = @\unserialize($trimmed);
}
if (false === $data && 'b:0;' !== \substr($trimmed, 0, 4)) {
return;
}
}
$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 === [true]) {
$base_obj->access_path .= ')';
} elseif (self::$options === [false]) {
$base_obj->access_path .= ', false)';
} else {
$base_obj->access_path .= ', Serialize::$options)';
}
}
$r = new Representation('Serialized');
if (isset($data)) {
$r->contents = $this->parser->parse($data, $base_obj);
} else {
$base_obj->hints[] = 'blacklist';
$r->contents = $base_obj;
}
$o->addRepresentation($r, 0);
}
}

View File

@@ -0,0 +1,217 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\BlobValue;
use Kint\Zval\Representation\Representation;
use Kint\Zval\SimpleXMLElementValue;
use Kint\Zval\Value;
use SimpleXMLElement;
class SimpleXMLElementPlugin extends Plugin
{
/**
* Show all properties and methods.
*
* @var bool
*/
public static $verbose = false;
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof SimpleXMLElement) {
return;
}
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 Value();
$base_obj->depth = $x->depth;
if ($x->access_path) {
$base_obj->access_path = '(string) '.$x->access_path;
}
// 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;
}
$attribs = [];
foreach ($namespaces as $nsAlias => $nsUrl) {
if ($nsAttribs = $var->attributes($nsUrl)) {
$cleanAttribs = [];
foreach ($nsAttribs as $name => $attrib) {
$cleanAttribs[(string) $name] = $attrib;
}
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);
// 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;
}
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)->';
}
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 (isset($nsap[$obj->access_path])) {
++$nsap[$obj->access_path];
$obj->access_path .= '['.$nsap[$obj->access_path].']';
} else {
$nsap[$obj->access_path] = 0;
}
}
$value = $this->parser->parse($child, $obj);
if ($value->access_path && 'string' === $value->type) {
$value->access_path = '(string) '.$value->access_path;
}
$c->contents[] = $value;
}
}
}
$x->size = \count($c->contents);
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 ($srep || $svalrep) {
$x->setIsStringValue(true);
$x->value = $srep ?: $svalrep;
if ($srep) {
$x->replaceRepresentation($x->value, 0);
}
}
$reps = \array_reverse($s->getRepresentations());
foreach ($reps as $rep) {
$x->addRepresentation($rep, 0);
}
}
}
$o = $x;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\SplFileInfoRepresentation;
use Kint\Zval\Value;
use SplFileInfo;
use SplFileObject;
class SplFileInfoPlugin extends Plugin
{
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_COMPLETE;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof SplFileInfo || $var instanceof SplFileObject) {
return;
}
$r = new SplFileInfoRepresentation(clone $var);
$o->addRepresentation($r, 0);
$o->size = $r->getSize();
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Value;
use SplObjectStorage;
class SplObjectStoragePlugin extends Plugin
{
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_COMPLETE;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof SplObjectStorage || !($r = $o->getRepresentation('iterator'))) {
return;
}
$r = $o->getRepresentation('iterator');
if ($r) {
$o->size = !\is_array($r->contents) ? null : \count($r->contents);
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
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 ['resource'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$o instanceof ResourceValue || 'stream' !== $o->resource_type) {
return;
}
// 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 Value();
$base_obj->depth = $o->depth;
if ($o->access_path) {
$base_obj->access_path = 'stream_get_meta_data('.$o->access_path.')';
}
$rep->contents = $this->parser->parse($meta, $base_obj);
if (!\in_array('depth_limit', $rep->contents->hints, true)) {
$rep->contents = $rep->contents->value->contents;
}
$o->addRepresentation($rep, 0);
$o->value = $rep;
$stream = new StreamValue($meta);
$stream->transplant($o);
$o = $stream;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
class TablePlugin extends Plugin
{
public function getTypes()
{
return ['array'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (empty($o->value->contents)) {
return;
}
$array = $this->parser->getCleanArray($var);
if (\count($array) < 2) {
return;
}
// Ensure this is an array of arrays and that all child arrays have the
// same keys. We don't care about their children - if there's another
// "table" inside we'll just make another one down the value tab
$keys = null;
foreach ($array as $elem) {
if (!\is_array($elem) || \count($elem) < 2) {
return;
}
if (null === $keys) {
$keys = \array_keys($elem);
} elseif (\array_keys($elem) !== $keys) {
return;
}
}
// Ensure none of the child arrays are recursion or depth limit. We
// don't care if their children are since they are the table cells
foreach ($o->value->contents as $childarray) {
if (empty($childarray->value->contents)) {
return;
}
}
// Objects by reference for the win! We can do a copy-paste of the value
// representation contents and just slap a new hint on there and hey
// presto we have our table representation with no extra memory used!
$table = new Representation('Table');
$table->contents = $o->value->contents;
$table->hints[] = 'table';
$o->addRepresentation($table, 0);
}
}

View File

@@ -0,0 +1,60 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Exception;
use Kint\Zval\Representation\SourceRepresentation;
use Kint\Zval\ThrowableValue;
use Kint\Zval\Value;
use Throwable;
class ThrowablePlugin extends Plugin
{
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (!$var instanceof Exception && (!KINT_PHP70 || !$var instanceof Throwable)) {
return;
}
$throw = new ThrowableValue($var);
$throw->transplant($o);
$r = new SourceRepresentation($var->getFile(), $var->getLine());
$r->showfilename = true;
$throw->addRepresentation($r, 0);
$o = $throw;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Value;
class TimestampPlugin extends Plugin
{
public static $blacklist = [
2147483648,
2147483647,
1073741824,
1073741823,
];
public function getTypes()
{
return ['string', 'integer'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if (\is_string($var) && !\ctype_digit($var)) {
return;
}
if (\in_array($var, self::$blacklist, true)) {
return;
}
$len = \strlen((string) $var);
// Guess for anything between March 1973 and November 2286
if (9 === $len || 10 === $len) {
// If it's an int or string that's this short it probably has no other meaning
// Additionally it's highly unlikely the shortValue will be clipped for length
// If you're writing a plugin that interferes with this, just put your
// parser plugin further down the list so that it gets loaded afterwards.
$o->value->label = 'Timestamp';
$o->value->hints[] = 'timestamp';
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
use ReflectionClass;
class ToStringPlugin extends Plugin
{
public static $blacklist = [
'SimpleXMLElement',
'SplFileObject',
];
public function getTypes()
{
return ['object'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
$reflection = new ReflectionClass($var);
if (!$reflection->hasMethod('__toString')) {
return;
}
foreach (self::$blacklist as $class) {
if ($var instanceof $class) {
return;
}
}
$r = new Representation('toString');
$r->contents = (string) $var;
$o->addRepresentation($r);
}
}

View File

@@ -0,0 +1,120 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use Kint\Utils;
use Kint\Zval\TraceFrameValue;
use Kint\Zval\TraceValue;
use Kint\Zval\Value;
class TracePlugin extends Plugin
{
public static $blacklist = ['spl_autoload_call'];
public static $path_blacklist = [];
public function getTypes()
{
return ['array'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
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 TraceValue();
$traceobj->transplant($o);
$rep = $traceobj->value;
$old_trace = $rep->contents;
Utils::normalizeAliases(self::$blacklist);
$path_blacklist = self::normalizePaths(self::$path_blacklist);
$rep->contents = [];
foreach ($old_trace as $frame) {
$index = $frame->name;
if (!isset($trace[$index]['function'])) {
// Something's very very wrong here, but it's probably a plugin's fault
continue;
}
if (Utils::traceFrameIsListed($trace[$index], self::$blacklist)) {
continue;
}
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);
$rep->contents = \array_values($rep->contents);
$traceobj->clearRepresentations();
$traceobj->addRepresentation($rep);
$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;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/*
* 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.
*/
namespace Kint\Parser;
use DOMDocument;
use Exception;
use Kint\Zval\Representation\Representation;
use Kint\Zval\Value;
class XmlPlugin extends Plugin
{
/**
* Which method to parse the variable with.
*
* DOMDocument provides more information including the text between nodes,
* however it's memory usage is very high and it takes longer to parse and
* render. Plus it's a pain to work with. So SimpleXML is the default.
*
* @var string
*/
public static $parse_method = 'SimpleXML';
public function getTypes()
{
return ['string'];
}
public function getTriggers()
{
return Parser::TRIGGER_SUCCESS;
}
public function parse(&$var, Value &$o, $trigger)
{
if ('<?xml' !== \substr($var, 0, 5)) {
return;
}
if (!\method_exists(\get_class($this), 'xmlTo'.self::$parse_method)) {
return;
}
$xml = \call_user_func([\get_class($this), 'xmlTo'.self::$parse_method], $var, $o->access_path);
if (empty($xml)) {
return;
}
list($xml, $access_path, $name) = $xml;
$base_obj = new Value();
$base_obj->depth = $o->depth + 1;
$base_obj->name = $name;
$base_obj->access_path = $access_path;
$r = new Representation('XML');
$r->contents = $this->parser->parse($xml, $base_obj);
$o->addRepresentation($r, 0);
}
protected static function xmlToSimpleXML($var, $parent_path)
{
try {
$errors = \libxml_use_internal_errors(true);
$xml = \simplexml_load_string($var);
\libxml_use_internal_errors($errors);
} catch (Exception $e) {
if (isset($errors)) {
\libxml_use_internal_errors($errors);
}
return;
}
if (false === $xml) {
return;
}
if (null === $parent_path) {
$access_path = null;
} else {
$access_path = 'simplexml_load_string('.$parent_path.')';
}
$name = $xml->getName();
return [$xml, $access_path, $name];
}
/**
* Get the DOMDocument info.
*
* The documentation of DOMDocument::loadXML() states that while you can
* call it statically, it will give an E_STRICT warning. On my system it
* actually gives an E_DEPRECATED warning, but it works so we'll just add
* an error-silencing '@' to the access path.
*
* If it errors loading then we wouldn't have gotten this far in the first place.
*
* @param string $var The XML string
* @param null|string $parent_path The path to the parent, in this case the XML string
*
* @return null|array The root element DOMNode, the access path, and the root element name
*/
protected static function xmlToDOMDocument($var, $parent_path)
{
// There's no way to check validity in DOMDocument without making errors. For shame!
if (!self::xmlToSimpleXML($var, $parent_path)) {
return null;
}
$xml = new DOMDocument();
$xml->loadXML($var);
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 = '(function($s){$x = new \\DomDocument(); $x->loadXML($s); return $x;})('.$parent_path.')->'.$access_path;
}
$name = isset($xml->nodeName) ? $xml->nodeName : null;
return [$xml, $access_path, $name];
}
}