mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-06 09:38:23 +01:00
Merge pull request #18244 from Hystepik/develop#3
Fix php debug bar for php 8.0
This commit is contained in:
@@ -35,7 +35,7 @@
|
|||||||
"nnnick/chartjs" : "^2.9",
|
"nnnick/chartjs" : "^2.9",
|
||||||
"stripe/stripe-php" : "6.43.1",
|
"stripe/stripe-php" : "6.43.1",
|
||||||
"maximebf/debugbar" : "1.15.1",
|
"maximebf/debugbar" : "1.15.1",
|
||||||
"symfony/var-dumper" : "3"
|
"symfony/var-dumper" : "3.2"
|
||||||
},
|
},
|
||||||
"require-dev" : {
|
"require-dev" : {
|
||||||
"php-parallel-lint/php-parallel-lint" : "^0",
|
"php-parallel-lint/php-parallel-lint" : "^0",
|
||||||
|
|||||||
4
composer.lock
generated
4
composer.lock
generated
@@ -591,7 +591,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v3.0.0",
|
"version": "v3.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
@@ -616,7 +616,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "3.0-dev"
|
"dev-master": "3.2-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|||||||
@@ -48,7 +48,16 @@ class AmqpCaster
|
|||||||
{
|
{
|
||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
// BC layer in the ampq lib
|
$a += array(
|
||||||
|
$prefix.'is_connected' => $c->isConnected(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Recent version of the extension already expose private properties
|
||||||
|
if (isset($a["\x00AMQPConnection\x00login"])) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BC layer in the amqp lib
|
||||||
if (method_exists($c, 'getReadTimeout')) {
|
if (method_exists($c, 'getReadTimeout')) {
|
||||||
$timeout = $c->getReadTimeout();
|
$timeout = $c->getReadTimeout();
|
||||||
} else {
|
} else {
|
||||||
@@ -56,13 +65,13 @@ class AmqpCaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'isConnected' => $c->isConnected(),
|
$prefix.'is_connected' => $c->isConnected(),
|
||||||
$prefix.'login' => $c->getLogin(),
|
$prefix.'login' => $c->getLogin(),
|
||||||
$prefix.'password' => $c->getPassword(),
|
$prefix.'password' => $c->getPassword(),
|
||||||
$prefix.'host' => $c->getHost(),
|
$prefix.'host' => $c->getHost(),
|
||||||
$prefix.'port' => $c->getPort(),
|
|
||||||
$prefix.'vhost' => $c->getVhost(),
|
$prefix.'vhost' => $c->getVhost(),
|
||||||
$prefix.'readTimeout' => $timeout,
|
$prefix.'port' => $c->getPort(),
|
||||||
|
$prefix.'read_timeout' => $timeout,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -73,11 +82,19 @@ class AmqpCaster
|
|||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'isConnected' => $c->isConnected(),
|
$prefix.'is_connected' => $c->isConnected(),
|
||||||
$prefix.'channelId' => $c->getChannelId(),
|
$prefix.'channel_id' => $c->getChannelId(),
|
||||||
$prefix.'prefetchSize' => $c->getPrefetchSize(),
|
);
|
||||||
$prefix.'prefetchCount' => $c->getPrefetchCount(),
|
|
||||||
|
// Recent version of the extension already expose private properties
|
||||||
|
if (isset($a["\x00AMQPChannel\x00connection"])) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a += array(
|
||||||
$prefix.'connection' => $c->getConnection(),
|
$prefix.'connection' => $c->getConnection(),
|
||||||
|
$prefix.'prefetch_size' => $c->getPrefetchSize(),
|
||||||
|
$prefix.'prefetch_count' => $c->getPrefetchCount(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -88,11 +105,19 @@ class AmqpCaster
|
|||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'name' => $c->getName(),
|
|
||||||
$prefix.'flags' => self::extractFlags($c->getFlags()),
|
$prefix.'flags' => self::extractFlags($c->getFlags()),
|
||||||
$prefix.'arguments' => $c->getArguments(),
|
);
|
||||||
|
|
||||||
|
// Recent version of the extension already expose private properties
|
||||||
|
if (isset($a["\x00AMQPQueue\x00name"])) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a += array(
|
||||||
$prefix.'connection' => $c->getConnection(),
|
$prefix.'connection' => $c->getConnection(),
|
||||||
$prefix.'channel' => $c->getChannel(),
|
$prefix.'channel' => $c->getChannel(),
|
||||||
|
$prefix.'name' => $c->getName(),
|
||||||
|
$prefix.'arguments' => $c->getArguments(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -103,12 +128,24 @@ class AmqpCaster
|
|||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'name' => $c->getName(),
|
|
||||||
$prefix.'flags' => self::extractFlags($c->getFlags()),
|
$prefix.'flags' => self::extractFlags($c->getFlags()),
|
||||||
$prefix.'type' => isset(self::$exchangeTypes[$c->getType()]) ? new ConstStub(self::$exchangeTypes[$c->getType()], $c->getType()) : $c->getType(),
|
);
|
||||||
$prefix.'arguments' => $c->getArguments(),
|
|
||||||
$prefix.'channel' => $c->getChannel(),
|
$type = isset(self::$exchangeTypes[$c->getType()]) ? new ConstStub(self::$exchangeTypes[$c->getType()], $c->getType()) : $c->getType();
|
||||||
|
|
||||||
|
// Recent version of the extension already expose private properties
|
||||||
|
if (isset($a["\x00AMQPExchange\x00name"])) {
|
||||||
|
$a["\x00AMQPExchange\x00type"] = $type;
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a += array(
|
||||||
$prefix.'connection' => $c->getConnection(),
|
$prefix.'connection' => $c->getConnection(),
|
||||||
|
$prefix.'channel' => $c->getChannel(),
|
||||||
|
$prefix.'name' => $c->getName(),
|
||||||
|
$prefix.'type' => $type,
|
||||||
|
$prefix.'arguments' => $c->getArguments(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -118,28 +155,37 @@ class AmqpCaster
|
|||||||
{
|
{
|
||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
|
$deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode());
|
||||||
|
|
||||||
|
// Recent version of the extension already expose private properties
|
||||||
|
if (isset($a["\x00AMQPEnvelope\x00body"])) {
|
||||||
|
$a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode;
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
|
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
|
||||||
$a += array($prefix.'body' => $c->getBody());
|
$a += array($prefix.'body' => $c->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'routingKey' => $c->getRoutingKey(),
|
$prefix.'delivery_tag' => $c->getDeliveryTag(),
|
||||||
$prefix.'deliveryTag' => $c->getDeliveryTag(),
|
$prefix.'is_redelivery' => $c->isRedelivery(),
|
||||||
$prefix.'deliveryMode' => new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()),
|
$prefix.'exchange_name' => $c->getExchangeName(),
|
||||||
$prefix.'exchangeName' => $c->getExchangeName(),
|
$prefix.'routing_key' => $c->getRoutingKey(),
|
||||||
$prefix.'isRedelivery' => $c->isRedelivery(),
|
$prefix.'content_type' => $c->getContentType(),
|
||||||
$prefix.'contentType' => $c->getContentType(),
|
$prefix.'content_encoding' => $c->getContentEncoding(),
|
||||||
$prefix.'contentEncoding' => $c->getContentEncoding(),
|
|
||||||
$prefix.'type' => $c->getType(),
|
|
||||||
$prefix.'timestamp' => $c->getTimestamp(),
|
|
||||||
$prefix.'priority' => $c->getPriority(),
|
|
||||||
$prefix.'expiration' => $c->getExpiration(),
|
|
||||||
$prefix.'userId' => $c->getUserId(),
|
|
||||||
$prefix.'appId' => $c->getAppId(),
|
|
||||||
$prefix.'messageId' => $c->getMessageId(),
|
|
||||||
$prefix.'replyTo' => $c->getReplyTo(),
|
|
||||||
$prefix.'correlationId' => $c->getCorrelationId(),
|
|
||||||
$prefix.'headers' => $c->getHeaders(),
|
$prefix.'headers' => $c->getHeaders(),
|
||||||
|
$prefix.'delivery_mode' => $deliveryMode,
|
||||||
|
$prefix.'priority' => $c->getPriority(),
|
||||||
|
$prefix.'correlation_id' => $c->getCorrelationId(),
|
||||||
|
$prefix.'reply_to' => $c->getReplyTo(),
|
||||||
|
$prefix.'expiration' => $c->getExpiration(),
|
||||||
|
$prefix.'message_id' => $c->getMessageId(),
|
||||||
|
$prefix.'timestamp' => $c->getTimeStamp(),
|
||||||
|
$prefix.'type' => $c->getType(),
|
||||||
|
$prefix.'user_id' => $c->getUserId(),
|
||||||
|
$prefix.'app_id' => $c->getAppId(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
|
|||||||
80
htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php
Normal file
80
htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a list of function arguments.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class ArgsStub extends EnumStub
|
||||||
|
{
|
||||||
|
private static $parameters = array();
|
||||||
|
|
||||||
|
public function __construct(array $args, $function, $class)
|
||||||
|
{
|
||||||
|
list($variadic, $params) = self::getParameters($function, $class);
|
||||||
|
|
||||||
|
$values = array();
|
||||||
|
foreach ($args as $k => $v) {
|
||||||
|
$values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
|
||||||
|
}
|
||||||
|
if (null === $params) {
|
||||||
|
parent::__construct($values, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (count($values) < count($params)) {
|
||||||
|
$params = array_slice($params, 0, count($values));
|
||||||
|
} elseif (count($values) > count($params)) {
|
||||||
|
$values[] = new EnumStub(array_splice($values, count($params)), false);
|
||||||
|
$params[] = $variadic;
|
||||||
|
}
|
||||||
|
if (array('...') === $params) {
|
||||||
|
$this->dumpKeys = false;
|
||||||
|
$this->value = $values[0]->value;
|
||||||
|
} else {
|
||||||
|
$this->value = array_combine($params, $values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getParameters($function, $class)
|
||||||
|
{
|
||||||
|
if (isset(self::$parameters[$k = $class.'::'.$function])) {
|
||||||
|
return self::$parameters[$k];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function);
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
return array(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
$variadic = '...';
|
||||||
|
$params = array();
|
||||||
|
foreach ($r->getParameters() as $v) {
|
||||||
|
$k = '$'.$v->name;
|
||||||
|
if ($v->isPassedByReference()) {
|
||||||
|
$k = '&'.$k;
|
||||||
|
}
|
||||||
|
if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
|
||||||
|
$variadic .= $k;
|
||||||
|
} else {
|
||||||
|
$params[] = $k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$parameters[$k] = array($variadic, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Caster;
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for filtering out properties in casters.
|
* Helper for filtering out properties in casters.
|
||||||
*
|
*
|
||||||
@@ -36,29 +38,39 @@ class Caster
|
|||||||
/**
|
/**
|
||||||
* Casts objects to arrays and adds the dynamic property prefix.
|
* Casts objects to arrays and adds the dynamic property prefix.
|
||||||
*
|
*
|
||||||
* @param object $obj The object to cast.
|
* @param object $obj The object to cast
|
||||||
* @param \ReflectionClass $reflector The class reflector to use for inspecting the object definition.
|
* @param \ReflectionClass $reflector The class reflector to use for inspecting the object definition
|
||||||
*
|
*
|
||||||
* @return array The array-cast of the object, with prefixed dynamic properties.
|
* @return array The array-cast of the object, with prefixed dynamic properties
|
||||||
*/
|
*/
|
||||||
public static function castObject($obj, \ReflectionClass $reflector)
|
public static function castObject($obj, \ReflectionClass $reflector)
|
||||||
{
|
{
|
||||||
if ($reflector->hasMethod('__debugInfo')) {
|
if ($reflector->hasMethod('__debugInfo')) {
|
||||||
$a = $obj->__debugInfo();
|
$a = $obj->__debugInfo();
|
||||||
|
} elseif ($obj instanceof \Closure) {
|
||||||
|
$a = array();
|
||||||
} else {
|
} else {
|
||||||
$a = (array) $obj;
|
$a = (array) $obj;
|
||||||
}
|
}
|
||||||
|
if ($obj instanceof \__PHP_Incomplete_Class) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
if ($a) {
|
if ($a) {
|
||||||
|
$combine = false;
|
||||||
$p = array_keys($a);
|
$p = array_keys($a);
|
||||||
foreach ($p as $i => $k) {
|
foreach ($p as $i => $k) {
|
||||||
if (!isset($k[0]) || ("\0" !== $k[0] && !$reflector->hasProperty($k))) {
|
if (isset($k[0]) ? "\0" !== $k[0] && !$reflector->hasProperty($k) : \PHP_VERSION_ID >= 70200) {
|
||||||
|
$combine = true;
|
||||||
$p[$i] = self::PREFIX_DYNAMIC.$k;
|
$p[$i] = self::PREFIX_DYNAMIC.$k;
|
||||||
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) {
|
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) {
|
||||||
|
$combine = true;
|
||||||
$p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0");
|
$p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$a = array_combine($p, $a);
|
if ($combine) {
|
||||||
|
$a = array_combine($p, $a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -70,14 +82,17 @@ class Caster
|
|||||||
* By default, a single match in the $filter bit field filters properties out, following an "or" logic.
|
* By default, a single match in the $filter bit field filters properties out, following an "or" logic.
|
||||||
* When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
|
* When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
|
||||||
*
|
*
|
||||||
* @param array $a The array containing the properties to filter.
|
* @param array $a The array containing the properties to filter
|
||||||
* @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out.
|
* @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out
|
||||||
* @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set.
|
* @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set
|
||||||
|
* @param int &$count Set to the number of removed properties
|
||||||
*
|
*
|
||||||
* @return array The filtered array
|
* @return array The filtered array
|
||||||
*/
|
*/
|
||||||
public static function filter(array $a, $filter, array $listedProperties = array())
|
public static function filter(array $a, $filter, array $listedProperties = array(), &$count = 0)
|
||||||
{
|
{
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
foreach ($a as $k => $v) {
|
foreach ($a as $k => $v) {
|
||||||
$type = self::EXCLUDE_STRICT & $filter;
|
$type = self::EXCLUDE_STRICT & $filter;
|
||||||
|
|
||||||
@@ -108,9 +123,20 @@ class Caster
|
|||||||
|
|
||||||
if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
|
if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
|
||||||
unset($a[$k]);
|
unset($a[$k]);
|
||||||
|
++$count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, $isNested)
|
||||||
|
{
|
||||||
|
if (isset($a['__PHP_Incomplete_Class_Name'])) {
|
||||||
|
$stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')';
|
||||||
|
unset($a['__PHP_Incomplete_Class_Name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
87
htdocs/includes/symfony/var-dumper/Caster/ClassStub.php
Normal file
87
htdocs/includes/symfony/var-dumper/Caster/ClassStub.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a PHP class identifier.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class ClassStub extends ConstStub
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string A PHP identifier, e.g. a class, method, interface, etc. name
|
||||||
|
* @param callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
|
||||||
|
*/
|
||||||
|
public function __construct($identifier, $callable = null)
|
||||||
|
{
|
||||||
|
$this->value = $identifier;
|
||||||
|
|
||||||
|
if (0 < $i = strrpos($identifier, '\\')) {
|
||||||
|
$this->attr['ellipsis'] = strlen($identifier) - $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (null !== $callable) {
|
||||||
|
if ($callable instanceof \Closure) {
|
||||||
|
$r = new \ReflectionFunction($callable);
|
||||||
|
} elseif (is_object($callable)) {
|
||||||
|
$r = array($callable, '__invoke');
|
||||||
|
} elseif (is_array($callable)) {
|
||||||
|
$r = $callable;
|
||||||
|
} elseif (false !== $i = strpos($callable, '::')) {
|
||||||
|
$r = array(substr($callable, 0, $i), substr($callable, 2 + $i));
|
||||||
|
} else {
|
||||||
|
$r = new \ReflectionFunction($callable);
|
||||||
|
}
|
||||||
|
} elseif (false !== $i = strpos($identifier, '::')) {
|
||||||
|
$r = array(substr($identifier, 0, $i), substr($identifier, 2 + $i));
|
||||||
|
} else {
|
||||||
|
$r = new \ReflectionClass($identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($r)) {
|
||||||
|
try {
|
||||||
|
$r = new \ReflectionMethod($r[0], $r[1]);
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
$r = new \ReflectionClass($r[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($f = $r->getFileName()) {
|
||||||
|
$this->attr['file'] = $f;
|
||||||
|
$this->attr['line'] = $r->getStartLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function wrapCallable($callable)
|
||||||
|
{
|
||||||
|
if (is_object($callable) || !is_callable($callable)) {
|
||||||
|
return $callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($callable)) {
|
||||||
|
$callable = new static($callable);
|
||||||
|
} elseif (is_string($callable[0])) {
|
||||||
|
$callable[0] = new static($callable[0]);
|
||||||
|
} else {
|
||||||
|
$callable[1] = new static($callable[1], $callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $callable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,4 +25,9 @@ class ConstStub extends Stub
|
|||||||
$this->class = $name;
|
$this->class = $name;
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return (string) $this->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,12 @@ class CutStub extends Stub
|
|||||||
|
|
||||||
case 'resource':
|
case 'resource':
|
||||||
case 'unknown type':
|
case 'unknown type':
|
||||||
|
case 'resource (closed)':
|
||||||
$this->type = self::TYPE_RESOURCE;
|
$this->type = self::TYPE_RESOURCE;
|
||||||
$this->handle = (int) $value;
|
$this->handle = (int) $value;
|
||||||
$this->class = @get_resource_type($value);
|
if ('Unknown' === $this->class = @get_resource_type($value)) {
|
||||||
|
$this->class = 'Closed';
|
||||||
|
}
|
||||||
$this->cut = -1;
|
$this->cut = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class DOMCaster
|
|||||||
'namespaceURI' => $dom->namespaceURI,
|
'namespaceURI' => $dom->namespaceURI,
|
||||||
'prefix' => $dom->prefix,
|
'prefix' => $dom->prefix,
|
||||||
'localName' => $dom->localName,
|
'localName' => $dom->localName,
|
||||||
'baseURI' => $dom->baseURI,
|
'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI,
|
||||||
'textContent' => new CutStub($dom->textContent),
|
'textContent' => new CutStub($dom->textContent),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ class DOMCaster
|
|||||||
'version' => $dom->version,
|
'version' => $dom->version,
|
||||||
'xmlVersion' => $dom->xmlVersion,
|
'xmlVersion' => $dom->xmlVersion,
|
||||||
'strictErrorChecking' => $dom->strictErrorChecking,
|
'strictErrorChecking' => $dom->strictErrorChecking,
|
||||||
'documentURI' => $dom->documentURI,
|
'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,
|
||||||
'config' => $dom->config,
|
'config' => $dom->config,
|
||||||
'formatOutput' => $dom->formatOutput,
|
'formatOutput' => $dom->formatOutput,
|
||||||
'validateOnParse' => $dom->validateOnParse,
|
'validateOnParse' => $dom->validateOnParse,
|
||||||
@@ -237,7 +237,7 @@ class DOMCaster
|
|||||||
'columnNumber' => $dom->columnNumber,
|
'columnNumber' => $dom->columnNumber,
|
||||||
'offset' => $dom->offset,
|
'offset' => $dom->offset,
|
||||||
'relatedNode' => $dom->relatedNode,
|
'relatedNode' => $dom->relatedNode,
|
||||||
'uri' => $dom->uri,
|
'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||||||
*/
|
*/
|
||||||
class EnumStub extends Stub
|
class EnumStub extends Stub
|
||||||
{
|
{
|
||||||
public function __construct(array $values)
|
public $dumpKeys = true;
|
||||||
|
|
||||||
|
public function __construct(array $values, $dumpKeys = true)
|
||||||
{
|
{
|
||||||
$this->value = $values;
|
$this->value = $values;
|
||||||
|
$this->dumpKeys = $dumpKeys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class ExceptionCaster
|
|||||||
E_STRICT => 'E_STRICT',
|
E_STRICT => 'E_STRICT',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static $framesCache = array();
|
||||||
|
|
||||||
public static function castError(\Error $e, array $a, Stub $stub, $isNested, $filter = 0)
|
public static function castError(\Error $e, array $a, Stub $stub, $isNested, $filter = 0)
|
||||||
{
|
{
|
||||||
return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter);
|
return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter);
|
||||||
@@ -65,13 +67,9 @@ class ExceptionCaster
|
|||||||
$prefix = Caster::PREFIX_PROTECTED;
|
$prefix = Caster::PREFIX_PROTECTED;
|
||||||
$xPrefix = "\0Exception\0";
|
$xPrefix = "\0Exception\0";
|
||||||
|
|
||||||
if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace'])) {
|
if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace']) && $a[$xPrefix.'previous'] instanceof \Exception) {
|
||||||
$b = (array) $a[$xPrefix.'previous'];
|
$b = (array) $a[$xPrefix.'previous'];
|
||||||
array_unshift($b[$xPrefix.'trace'], array(
|
self::traceUnshift($b[$xPrefix.'trace'], get_class($a[$xPrefix.'previous']), $b[$prefix.'file'], $b[$prefix.'line']);
|
||||||
'function' => 'new '.get_class($a[$xPrefix.'previous']),
|
|
||||||
'file' => $b[$prefix.'file'],
|
|
||||||
'line' => $b[$prefix.'line'],
|
|
||||||
));
|
|
||||||
$a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -1 - count($a[$xPrefix.'trace']->value));
|
$a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -1 - count($a[$xPrefix.'trace']->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +86,7 @@ class ExceptionCaster
|
|||||||
$stub->class = '';
|
$stub->class = '';
|
||||||
$stub->handle = 0;
|
$stub->handle = 0;
|
||||||
$frames = $trace->value;
|
$frames = $trace->value;
|
||||||
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
$a = array();
|
$a = array();
|
||||||
$j = count($frames);
|
$j = count($frames);
|
||||||
@@ -97,34 +96,38 @@ class ExceptionCaster
|
|||||||
if (!isset($trace->value[$i])) {
|
if (!isset($trace->value[$i])) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
$lastCall = isset($frames[$i]['function']) ? ' ==> '.(isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
|
$lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
|
||||||
|
$frames[] = array('function' => '');
|
||||||
|
|
||||||
for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
|
for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
|
||||||
$call = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[$i]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '???';
|
$f = $frames[$i];
|
||||||
|
$call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'].'()' : '???';
|
||||||
|
|
||||||
$a[Caster::PREFIX_VIRTUAL.$j.'. '.$call.$lastCall] = new FrameStub(
|
$label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall;
|
||||||
|
$frame = new FrameStub(
|
||||||
array(
|
array(
|
||||||
'object' => isset($frames[$i]['object']) ? $frames[$i]['object'] : null,
|
'object' => isset($f['object']) ? $f['object'] : null,
|
||||||
'class' => isset($frames[$i]['class']) ? $frames[$i]['class'] : null,
|
'class' => isset($f['class']) ? $f['class'] : null,
|
||||||
'type' => isset($frames[$i]['type']) ? $frames[$i]['type'] : null,
|
'type' => isset($f['type']) ? $f['type'] : null,
|
||||||
'function' => isset($frames[$i]['function']) ? $frames[$i]['function'] : null,
|
'function' => isset($f['function']) ? $f['function'] : null,
|
||||||
) + $frames[$i - 1],
|
) + $frames[$i - 1],
|
||||||
$trace->keepArgs,
|
false,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
$f = self::castFrameStub($frame, array(), $frame, true);
|
||||||
|
if (isset($f[$prefix.'src'])) {
|
||||||
|
foreach ($f[$prefix.'src']->value as $label => $frame) {
|
||||||
|
$label = substr_replace($label, "title=Stack level $j.&", 2, 0);
|
||||||
|
}
|
||||||
|
$f = $frames[$i - 1];
|
||||||
|
if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {
|
||||||
|
$frame->value['arguments'] = new ArgsStub($f['args'], isset($f['function']) ? $f['function'] : null, isset($f['class']) ? $f['class'] : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$a[$label] = $frame;
|
||||||
|
|
||||||
$lastCall = ' ==> '.$call;
|
$lastCall = $call;
|
||||||
}
|
}
|
||||||
$a[Caster::PREFIX_VIRTUAL.$j.'. {main}'.$lastCall] = new FrameStub(
|
|
||||||
array(
|
|
||||||
'object' => null,
|
|
||||||
'class' => null,
|
|
||||||
'type' => null,
|
|
||||||
'function' => '{main}',
|
|
||||||
) + $frames[$i - 1],
|
|
||||||
$trace->keepArgs,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
if (null !== $trace->sliceLength) {
|
if (null !== $trace->sliceLength) {
|
||||||
$a = array_slice($a, 0, $trace->sliceLength, true);
|
$a = array_slice($a, 0, $trace->sliceLength, true);
|
||||||
}
|
}
|
||||||
@@ -141,30 +144,52 @@ class ExceptionCaster
|
|||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
if (isset($f['file'], $f['line'])) {
|
if (isset($f['file'], $f['line'])) {
|
||||||
if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) {
|
$cacheKey = $f;
|
||||||
$f['file'] = substr($f['file'], 0, -strlen($match[0]));
|
unset($cacheKey['object'], $cacheKey['args']);
|
||||||
$f['line'] = (int) $match[1];
|
$cacheKey[] = self::$srcContext;
|
||||||
}
|
$cacheKey = implode('-', $cacheKey);
|
||||||
if (file_exists($f['file']) && 0 <= self::$srcContext) {
|
|
||||||
$src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
|
|
||||||
|
|
||||||
if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) {
|
if (isset(self::$framesCache[$cacheKey])) {
|
||||||
$template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem()));
|
$a[$prefix.'src'] = self::$framesCache[$cacheKey];
|
||||||
|
} else {
|
||||||
|
if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) {
|
||||||
|
$f['file'] = substr($f['file'], 0, -strlen($match[0]));
|
||||||
|
$f['line'] = (int) $match[1];
|
||||||
|
}
|
||||||
|
$caller = isset($f['function']) ? sprintf('in %s() on line %d', (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'], $f['line']) : null;
|
||||||
|
$src = $f['line'];
|
||||||
|
$srcKey = $f['file'];
|
||||||
|
$ellipsis = explode(DIRECTORY_SEPARATOR, $srcKey);
|
||||||
|
$ellipsis = 3 < count($ellipsis) ? 2 + strlen(implode(array_slice($ellipsis, -2))) : 0;
|
||||||
|
|
||||||
try {
|
if (file_exists($f['file']) && 0 <= self::$srcContext) {
|
||||||
$templateName = $template->getTemplateName();
|
if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
|
||||||
$templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
|
$template = isset($f['object']) ? $f['object'] : unserialize(sprintf('O:%d:"%s":0:{}', strlen($f['class']), $f['class']));
|
||||||
|
|
||||||
|
$ellipsis = 0;
|
||||||
|
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
|
||||||
$templateInfo = $template->getDebugInfo();
|
$templateInfo = $template->getDebugInfo();
|
||||||
if (isset($templateInfo[$f['line']])) {
|
if (isset($templateInfo[$f['line']])) {
|
||||||
$src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
|
if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
|
||||||
|
$templatePath = null;
|
||||||
|
}
|
||||||
|
if ($templateSrc) {
|
||||||
|
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, $caller, 'twig', $templatePath);
|
||||||
|
$srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($srcKey == $f['file']) {
|
||||||
|
$src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, $caller, 'php', $f['file']);
|
||||||
|
$srcKey .= ':'.$f['line'];
|
||||||
|
if ($ellipsis) {
|
||||||
|
$ellipsis += 1 + strlen($f['line']);
|
||||||
}
|
}
|
||||||
} catch (\Twig_Error_Loader $e) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
$srcAttr = $ellipsis ? 'ellipsis='.$ellipsis : '';
|
||||||
$src[$f['file']] = $f['line'];
|
self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(array("\0~$srcAttr\0$srcKey" => $src));
|
||||||
}
|
}
|
||||||
$a[$prefix.'src'] = new EnumStub($src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);
|
unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);
|
||||||
@@ -176,8 +201,8 @@ class ExceptionCaster
|
|||||||
unset($a[$k]);
|
unset($a[$k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($frame->keepArgs && isset($f['args'])) {
|
if ($frame->keepArgs && !empty($f['args'])) {
|
||||||
$a[$prefix.'args'] = $f['args'];
|
$a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
@@ -193,46 +218,81 @@ class ExceptionCaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
|
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
|
||||||
array_unshift($trace, array(
|
if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
|
||||||
'function' => $xClass ? 'new '.$xClass : null,
|
self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);
|
||||||
'file' => $a[Caster::PREFIX_PROTECTED.'file'],
|
}
|
||||||
'line' => $a[Caster::PREFIX_PROTECTED.'line'],
|
$a[$xPrefix.'trace'] = new TraceStub($trace, self::$traceArgs);
|
||||||
));
|
|
||||||
$a[$xPrefix.'trace'] = new TraceStub($trace);
|
|
||||||
}
|
}
|
||||||
if (empty($a[$xPrefix.'previous'])) {
|
if (empty($a[$xPrefix.'previous'])) {
|
||||||
unset($a[$xPrefix.'previous']);
|
unset($a[$xPrefix.'previous']);
|
||||||
}
|
}
|
||||||
unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']);
|
unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']);
|
||||||
|
|
||||||
|
if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
|
||||||
|
$a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);
|
||||||
|
}
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function extractSource(array $srcArray, $line, $srcContext)
|
private static function traceUnshift(&$trace, $class, $file, $line)
|
||||||
{
|
{
|
||||||
|
if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
array_unshift($trace, array(
|
||||||
|
'function' => $class ? 'new '.$class : null,
|
||||||
|
'file' => $file,
|
||||||
|
'line' => $line,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function extractSource($srcLines, $line, $srcContext, $title, $lang, $file = null)
|
||||||
|
{
|
||||||
|
$srcLines = explode("\n", $srcLines);
|
||||||
$src = array();
|
$src = array();
|
||||||
|
|
||||||
for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {
|
for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {
|
||||||
$src[] = (isset($srcArray[$i]) ? $srcArray[$i] : '')."\n";
|
$src[] = (isset($srcLines[$i]) ? $srcLines[$i] : '')."\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$srcLines = array();
|
||||||
$ltrim = 0;
|
$ltrim = 0;
|
||||||
while (' ' === $src[0][$ltrim] || "\t" === $src[0][$ltrim]) {
|
do {
|
||||||
$i = $srcContext << 1;
|
$pad = null;
|
||||||
while ($i > 0 && $src[0][$ltrim] === $src[$i][$ltrim]) {
|
for ($i = $srcContext << 1; $i >= 0; --$i) {
|
||||||
--$i;
|
if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) {
|
||||||
}
|
if (null === $pad) {
|
||||||
if ($i) {
|
$pad = $c;
|
||||||
break;
|
}
|
||||||
|
if ((' ' !== $c && "\t" !== $c) || $pad !== $c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++$ltrim;
|
++$ltrim;
|
||||||
}
|
} while (0 > $i && null !== $pad);
|
||||||
if ($ltrim) {
|
|
||||||
foreach ($src as $i => $line) {
|
--$ltrim;
|
||||||
$src[$i] = substr($line, $ltrim);
|
|
||||||
|
foreach ($src as $i => $c) {
|
||||||
|
if ($ltrim) {
|
||||||
|
$c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
|
||||||
}
|
}
|
||||||
|
$c = substr($c, 0, -1);
|
||||||
|
if ($i !== $srcContext) {
|
||||||
|
$c = new ConstStub('default', $c);
|
||||||
|
} else {
|
||||||
|
$c = new ConstStub($c, $title);
|
||||||
|
if (null !== $file) {
|
||||||
|
$c->attr['file'] = $file;
|
||||||
|
$c->attr['line'] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$c->attr['lang'] = $lang;
|
||||||
|
$srcLines[sprintf("\0~%d\0", $i + $line - $srcContext)] = $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode('', $src);
|
return new EnumStub($srcLines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
htdocs/includes/symfony/var-dumper/Caster/LinkStub.php
Normal file
51
htdocs/includes/symfony/var-dumper/Caster/LinkStub.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a file or a URL.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class LinkStub extends ConstStub
|
||||||
|
{
|
||||||
|
public function __construct($label, $line = 0, $href = null)
|
||||||
|
{
|
||||||
|
$this->value = $label;
|
||||||
|
|
||||||
|
if (null === $href) {
|
||||||
|
$href = $label;
|
||||||
|
}
|
||||||
|
if (is_string($href)) {
|
||||||
|
if (0 === strpos($href, 'file://')) {
|
||||||
|
if ($href === $label) {
|
||||||
|
$label = substr($label, 7);
|
||||||
|
}
|
||||||
|
$href = substr($href, 7);
|
||||||
|
} elseif (false !== strpos($href, '://')) {
|
||||||
|
$this->attr['href'] = $href;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file_exists($href)) {
|
||||||
|
if ($line) {
|
||||||
|
$this->attr['line'] = $line;
|
||||||
|
}
|
||||||
|
$this->attr['file'] = realpath($href) ?: $href;
|
||||||
|
|
||||||
|
if ($this->attr['file'] === $label && 3 < count($ellipsis = explode(DIRECTORY_SEPARATOR, $href))) {
|
||||||
|
$this->attr['ellipsis'] = 2 + strlen(implode(array_slice($ellipsis, -2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,6 +77,12 @@ class PdoCaster
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isset($attr[$k = 'STATEMENT_CLASS'][1])) {
|
||||||
|
if ($attr[$k][1]) {
|
||||||
|
$attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]);
|
||||||
|
}
|
||||||
|
$attr[$k][0] = new ClassStub($attr[$k][0]);
|
||||||
|
}
|
||||||
|
|
||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
$a += array(
|
$a += array(
|
||||||
|
|||||||
77
htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php
Normal file
77
htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts Redis class from ext-redis to array representation.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class RedisCaster
|
||||||
|
{
|
||||||
|
private static $serializer = array(
|
||||||
|
\Redis::SERIALIZER_NONE => 'NONE',
|
||||||
|
\Redis::SERIALIZER_PHP => 'PHP',
|
||||||
|
2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function castRedis(\Redis $c, array $a, Stub $stub, $isNested)
|
||||||
|
{
|
||||||
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
|
if (defined('HHVM_VERSION_ID')) {
|
||||||
|
if (isset($a[Caster::PREFIX_PROTECTED.'serializer'])) {
|
||||||
|
$ser = $a[Caster::PREFIX_PROTECTED.'serializer'];
|
||||||
|
$a[Caster::PREFIX_PROTECTED.'serializer'] = isset(self::$serializer[$ser]) ? new ConstStub(self::$serializer[$ser], $ser) : $ser;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$connected = $c->isConnected()) {
|
||||||
|
return $a + array(
|
||||||
|
$prefix.'isConnected' => $connected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ser = $c->getOption(\Redis::OPT_SERIALIZER);
|
||||||
|
$retry = defined('Redis::OPT_SCAN') ? $c->getOption(\Redis::OPT_SCAN) : 0;
|
||||||
|
|
||||||
|
return $a + array(
|
||||||
|
$prefix.'isConnected' => $connected,
|
||||||
|
$prefix.'host' => $c->getHost(),
|
||||||
|
$prefix.'port' => $c->getPort(),
|
||||||
|
$prefix.'auth' => $c->getAuth(),
|
||||||
|
$prefix.'dbNum' => $c->getDbNum(),
|
||||||
|
$prefix.'timeout' => $c->getTimeout(),
|
||||||
|
$prefix.'persistentId' => $c->getPersistentID(),
|
||||||
|
$prefix.'options' => new EnumStub(array(
|
||||||
|
'READ_TIMEOUT' => $c->getOption(\Redis::OPT_READ_TIMEOUT),
|
||||||
|
'SERIALIZER' => isset(self::$serializer[$ser]) ? new ConstStub(self::$serializer[$ser], $ser) : $ser,
|
||||||
|
'PREFIX' => $c->getOption(\Redis::OPT_PREFIX),
|
||||||
|
'SCAN' => new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, $isNested)
|
||||||
|
{
|
||||||
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
|
return $a + array(
|
||||||
|
$prefix.'hosts' => $c->_hosts(),
|
||||||
|
$prefix.'function' => ClassStub::wrapCallable($c->_function()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,19 +53,32 @@ class ReflectionCaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($f = $c->getFileName()) {
|
if ($f = $c->getFileName()) {
|
||||||
$a[$prefix.'file'] = $f;
|
$a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
|
||||||
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
|
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefix = Caster::PREFIX_DYNAMIC;
|
$prefix = Caster::PREFIX_DYNAMIC;
|
||||||
unset($a['name'], $a[$prefix.'0'], $a[$prefix.'this'], $a[$prefix.'parameter'], $a[Caster::PREFIX_VIRTUAL.'extra']);
|
unset($a['name'], $a[$prefix.'this'], $a[$prefix.'parameter'], $a[Caster::PREFIX_VIRTUAL.'extra']);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function castGenerator(\Generator $c, array $a, Stub $stub, $isNested)
|
public static function castGenerator(\Generator $c, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
return class_exists('ReflectionGenerator', false) ? self::castReflectionGenerator(new \ReflectionGenerator($c), $a, $stub, $isNested) : $a;
|
if (!class_exists('ReflectionGenerator', false)) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot create ReflectionGenerator based on a terminated Generator
|
||||||
|
try {
|
||||||
|
$reflectionGenerator = new \ReflectionGenerator($c);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$a[Caster::PREFIX_VIRTUAL.'closed'] = true;
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function castType(\ReflectionType $c, array $a, Stub $stub, $isNested)
|
public static function castType(\ReflectionType $c, array $a, Stub $stub, $isNested)
|
||||||
@@ -73,7 +86,7 @@ class ReflectionCaster
|
|||||||
$prefix = Caster::PREFIX_VIRTUAL;
|
$prefix = Caster::PREFIX_VIRTUAL;
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'type' => $c->__toString(),
|
$prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : $c->__toString(),
|
||||||
$prefix.'allowsNull' => $c->allowsNull(),
|
$prefix.'allowsNull' => $c->allowsNull(),
|
||||||
$prefix.'isBuiltin' => $c->isBuiltin(),
|
$prefix.'isBuiltin' => $c->isBuiltin(),
|
||||||
);
|
);
|
||||||
@@ -88,31 +101,33 @@ class ReflectionCaster
|
|||||||
if ($c->getThis()) {
|
if ($c->getThis()) {
|
||||||
$a[$prefix.'this'] = new CutStub($c->getThis());
|
$a[$prefix.'this'] = new CutStub($c->getThis());
|
||||||
}
|
}
|
||||||
$x = $c->getFunction();
|
$function = $c->getFunction();
|
||||||
$frame = array(
|
$frame = array(
|
||||||
'class' => isset($x->class) ? $x->class : null,
|
'class' => isset($function->class) ? $function->class : null,
|
||||||
'type' => isset($x->class) ? ($x->isStatic() ? '::' : '->') : null,
|
'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,
|
||||||
'function' => $x->name,
|
'function' => $function->name,
|
||||||
'file' => $c->getExecutingFile(),
|
'file' => $c->getExecutingFile(),
|
||||||
'line' => $c->getExecutingLine(),
|
'line' => $c->getExecutingLine(),
|
||||||
);
|
);
|
||||||
if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) {
|
if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) {
|
||||||
$x = new \ReflectionGenerator($c->getExecutingGenerator());
|
$function = new \ReflectionGenerator($c->getExecutingGenerator());
|
||||||
array_unshift($trace, array(
|
array_unshift($trace, array(
|
||||||
'function' => 'yield',
|
'function' => 'yield',
|
||||||
'file' => $x->getExecutingFile(),
|
'file' => $function->getExecutingFile(),
|
||||||
'line' => $x->getExecutingLine() - 1,
|
'line' => $function->getExecutingLine() - 1,
|
||||||
));
|
));
|
||||||
$trace[] = $frame;
|
$trace[] = $frame;
|
||||||
$a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);
|
$a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);
|
||||||
} else {
|
} else {
|
||||||
$x = new FrameStub($frame, false, true);
|
$function = new FrameStub($frame, false, true);
|
||||||
$x = ExceptionCaster::castFrameStub($x, array(), $x, true);
|
$function = ExceptionCaster::castFrameStub($function, array(), $function, true);
|
||||||
$a[$prefix.'executing'] = new EnumStub(array(
|
$a[$prefix.'executing'] = new EnumStub(array(
|
||||||
$frame['class'].$frame['type'].$frame['function'].'()' => $x[$prefix.'src'],
|
$frame['class'].$frame['type'].$frame['function'].'()' => $function[$prefix.'src'],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$a[Caster::PREFIX_VIRTUAL.'closed'] = false;
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +172,12 @@ class ReflectionCaster
|
|||||||
));
|
));
|
||||||
|
|
||||||
if (isset($a[$prefix.'returnType'])) {
|
if (isset($a[$prefix.'returnType'])) {
|
||||||
$a[$prefix.'returnType'] = (string) $a[$prefix.'returnType'];
|
$v = $a[$prefix.'returnType'];
|
||||||
|
$v = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString();
|
||||||
|
$a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() ? '?'.$v : $v, array(class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', ''));
|
||||||
|
}
|
||||||
|
if (isset($a[$prefix.'class'])) {
|
||||||
|
$a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);
|
||||||
}
|
}
|
||||||
if (isset($a[$prefix.'this'])) {
|
if (isset($a[$prefix.'this'])) {
|
||||||
$a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
|
$a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
|
||||||
@@ -165,12 +185,12 @@ class ReflectionCaster
|
|||||||
|
|
||||||
foreach ($c->getParameters() as $v) {
|
foreach ($c->getParameters() as $v) {
|
||||||
$k = '$'.$v->name;
|
$k = '$'.$v->name;
|
||||||
if ($v->isPassedByReference()) {
|
|
||||||
$k = '&'.$k;
|
|
||||||
}
|
|
||||||
if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
|
if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
|
||||||
$k = '...'.$k;
|
$k = '...'.$k;
|
||||||
}
|
}
|
||||||
|
if ($v->isPassedByReference()) {
|
||||||
|
$k = '&'.$k;
|
||||||
|
}
|
||||||
$a[$prefix.'parameters'][$k] = $v;
|
$a[$prefix.'parameters'][$k] = $v;
|
||||||
}
|
}
|
||||||
if (isset($a[$prefix.'parameters'])) {
|
if (isset($a[$prefix.'parameters'])) {
|
||||||
@@ -213,24 +233,22 @@ class ReflectionCaster
|
|||||||
'position' => 'getPosition',
|
'position' => 'getPosition',
|
||||||
'isVariadic' => 'isVariadic',
|
'isVariadic' => 'isVariadic',
|
||||||
'byReference' => 'isPassedByReference',
|
'byReference' => 'isPassedByReference',
|
||||||
|
'allowsNull' => 'allowsNull',
|
||||||
));
|
));
|
||||||
|
|
||||||
try {
|
if (method_exists($c, 'getType')) {
|
||||||
if (method_exists($c, 'hasType')) {
|
if ($v = $c->getType()) {
|
||||||
if ($c->hasType()) {
|
$a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString();
|
||||||
$a[$prefix.'typeHint'] = $c->getType()->__toString();
|
|
||||||
}
|
|
||||||
} elseif ($c->isArray()) {
|
|
||||||
$a[$prefix.'typeHint'] = 'array';
|
|
||||||
} elseif (method_exists($c, 'isCallable') && $c->isCallable()) {
|
|
||||||
$a[$prefix.'typeHint'] = 'callable';
|
|
||||||
} elseif ($v = $c->getClass()) {
|
|
||||||
$a[$prefix.'typeHint'] = $v->name;
|
|
||||||
}
|
|
||||||
} catch (\ReflectionException $e) {
|
|
||||||
if (preg_match('/^Class ([^ ]++) does not exist$/', $e->getMessage(), $m)) {
|
|
||||||
$a[$prefix.'typeHint'] = $m[1];
|
|
||||||
}
|
}
|
||||||
|
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $c, $v)) {
|
||||||
|
$a[$prefix.'typeHint'] = $v[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($a[$prefix.'typeHint'])) {
|
||||||
|
$v = $a[$prefix.'typeHint'];
|
||||||
|
$a[$prefix.'typeHint'] = new ClassStub($v, array(class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', ''));
|
||||||
|
} else {
|
||||||
|
unset($a[$prefix.'allowsNull']);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -238,9 +256,13 @@ class ReflectionCaster
|
|||||||
if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) {
|
if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) {
|
||||||
$a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
|
$a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
|
||||||
}
|
}
|
||||||
|
if (null === $v) {
|
||||||
|
unset($a[$prefix.'allowsNull']);
|
||||||
|
}
|
||||||
} catch (\ReflectionException $e) {
|
} catch (\ReflectionException $e) {
|
||||||
if (isset($a[$prefix.'typeHint']) && $c->allowsNull()) {
|
if (isset($a[$prefix.'typeHint']) && $c->allowsNull() && !class_exists('ReflectionNamedType', false)) {
|
||||||
$a[$prefix.'default'] = null;
|
$a[$prefix.'default'] = null;
|
||||||
|
unset($a[$prefix.'allowsNull']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +310,7 @@ class ReflectionCaster
|
|||||||
$x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : array();
|
$x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : array();
|
||||||
|
|
||||||
if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
|
if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
|
||||||
$x['file'] = $m;
|
$x['file'] = new LinkStub($m, $c->getStartLine());
|
||||||
$x['line'] = $c->getStartLine().' to '.$c->getEndLine();
|
$x['line'] = $c->getStartLine().' to '.$c->getEndLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,12 +40,17 @@ class ResourceCaster
|
|||||||
|
|
||||||
public static function castStream($stream, array $a, Stub $stub, $isNested)
|
public static function castStream($stream, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
return stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
|
$a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
|
||||||
|
if (isset($a['uri'])) {
|
||||||
|
$a['uri'] = new LinkStub($a['uri']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function castStreamContext($stream, array $a, Stub $stub, $isNested)
|
public static function castStreamContext($stream, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
return stream_context_get_params($stream);
|
return @stream_context_get_params($stream) ?: $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function castGd($gd, array $a, Stub $stub, $isNested)
|
public static function castGd($gd, array $a, Stub $stub, $isNested)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class SplCaster
|
|||||||
$b = array(
|
$b = array(
|
||||||
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
|
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
|
||||||
$prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
|
$prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
|
||||||
$prefix.'iteratorClass' => $c->getIteratorClass(),
|
$prefix.'iteratorClass' => new ClassStub($c->getIteratorClass()),
|
||||||
$prefix.'storage' => $c->getArrayCopy(),
|
$prefix.'storage' => $c->getArrayCopy(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class SplCaster
|
|||||||
$c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
|
$c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
|
||||||
|
|
||||||
$a += array(
|
$a += array(
|
||||||
$prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_KEEP) ? 'IT_MODE_KEEP' : 'IT_MODE_DELETE'), $mode),
|
$prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode),
|
||||||
$prefix.'dllist' => iterator_to_array($c),
|
$prefix.'dllist' => iterator_to_array($c),
|
||||||
);
|
);
|
||||||
$c->setIteratorMode($mode);
|
$c->setIteratorMode($mode);
|
||||||
@@ -115,6 +115,10 @@ class SplCaster
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($a[$prefix.'realPath'])) {
|
||||||
|
$a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($a[$prefix.'perms'])) {
|
if (isset($a[$prefix.'perms'])) {
|
||||||
$a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
|
$a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
|
||||||
}
|
}
|
||||||
@@ -180,7 +184,7 @@ class SplCaster
|
|||||||
$storage = array();
|
$storage = array();
|
||||||
unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967
|
unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967
|
||||||
|
|
||||||
foreach ($c as $obj) {
|
foreach (clone $c as $obj) {
|
||||||
$storage[spl_object_hash($obj)] = array(
|
$storage[spl_object_hash($obj)] = array(
|
||||||
'object' => $obj,
|
'object' => $obj,
|
||||||
'info' => $c->getInfo(),
|
'info' => $c->getInfo(),
|
||||||
|
|||||||
@@ -28,9 +28,17 @@ class StubCaster
|
|||||||
$stub->value = $c->value;
|
$stub->value = $c->value;
|
||||||
$stub->handle = $c->handle;
|
$stub->handle = $c->handle;
|
||||||
$stub->cut = $c->cut;
|
$stub->cut = $c->cut;
|
||||||
|
$stub->attr = $c->attr;
|
||||||
|
|
||||||
return array();
|
if (Stub::TYPE_REF === $c->type && !$c->class && is_string($c->value) && !preg_match('//u', $c->value)) {
|
||||||
|
$stub->type = Stub::TYPE_STRING;
|
||||||
|
$stub->class = Stub::STRING_BINARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, $isNested)
|
public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, $isNested)
|
||||||
@@ -52,15 +60,17 @@ class StubCaster
|
|||||||
public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
|
public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
if ($isNested) {
|
if ($isNested) {
|
||||||
$stub->class = '';
|
$stub->class = $c->dumpKeys ? '' : null;
|
||||||
$stub->handle = 0;
|
$stub->handle = 0;
|
||||||
$stub->value = null;
|
$stub->value = null;
|
||||||
|
$stub->cut = $c->cut;
|
||||||
|
$stub->attr = $c->attr;
|
||||||
|
|
||||||
$a = array();
|
$a = array();
|
||||||
|
|
||||||
if ($c->value) {
|
if ($c->value) {
|
||||||
foreach (array_keys($c->value) as $k) {
|
foreach (array_keys($c->value) as $k) {
|
||||||
$keys[] = Caster::PREFIX_VIRTUAL.$k;
|
$keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k;
|
||||||
}
|
}
|
||||||
// Preserve references with array_combine()
|
// Preserve references with array_combine()
|
||||||
$a = array_combine($keys, $c->value);
|
$a = array_combine($keys, $c->value);
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts XmlReader class to array representation.
|
||||||
|
*
|
||||||
|
* @author Baptiste Clavié <clavie.b@gmail.com>
|
||||||
|
*/
|
||||||
|
class XmlReaderCaster
|
||||||
|
{
|
||||||
|
private static $nodeTypes = array(
|
||||||
|
\XmlReader::NONE => 'NONE',
|
||||||
|
\XmlReader::ELEMENT => 'ELEMENT',
|
||||||
|
\XmlReader::ATTRIBUTE => 'ATTRIBUTE',
|
||||||
|
\XmlReader::TEXT => 'TEXT',
|
||||||
|
\XmlReader::CDATA => 'CDATA',
|
||||||
|
\XmlReader::ENTITY_REF => 'ENTITY_REF',
|
||||||
|
\XmlReader::ENTITY => 'ENTITY',
|
||||||
|
\XmlReader::PI => 'PI (Processing Instruction)',
|
||||||
|
\XmlReader::COMMENT => 'COMMENT',
|
||||||
|
\XmlReader::DOC => 'DOC',
|
||||||
|
\XmlReader::DOC_TYPE => 'DOC_TYPE',
|
||||||
|
\XmlReader::DOC_FRAGMENT => 'DOC_FRAGMENT',
|
||||||
|
\XmlReader::NOTATION => 'NOTATION',
|
||||||
|
\XmlReader::WHITESPACE => 'WHITESPACE',
|
||||||
|
\XmlReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',
|
||||||
|
\XmlReader::END_ELEMENT => 'END_ELEMENT',
|
||||||
|
\XmlReader::END_ENTITY => 'END_ENTITY',
|
||||||
|
\XmlReader::XML_DECLARATION => 'XML_DECLARATION',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function castXmlReader(\XmlReader $reader, array $a, Stub $stub, $isNested)
|
||||||
|
{
|
||||||
|
$props = Caster::PREFIX_VIRTUAL.'parserProperties';
|
||||||
|
$info = array(
|
||||||
|
'localName' => $reader->localName,
|
||||||
|
'prefix' => $reader->prefix,
|
||||||
|
'nodeType' => new ConstStub(self::$nodeTypes[$reader->nodeType], $reader->nodeType),
|
||||||
|
'depth' => $reader->depth,
|
||||||
|
'isDefault' => $reader->isDefault,
|
||||||
|
'isEmptyElement' => \XmlReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement,
|
||||||
|
'xmlLang' => $reader->xmlLang,
|
||||||
|
'attributeCount' => $reader->attributeCount,
|
||||||
|
'value' => $reader->value,
|
||||||
|
'namespaceURI' => $reader->namespaceURI,
|
||||||
|
'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,
|
||||||
|
$props => array(
|
||||||
|
'LOADDTD' => $reader->getParserProperty(\XmlReader::LOADDTD),
|
||||||
|
'DEFAULTATTRS' => $reader->getParserProperty(\XmlReader::DEFAULTATTRS),
|
||||||
|
'VALIDATE' => $reader->getParserProperty(\XmlReader::VALIDATE),
|
||||||
|
'SUBST_ENTITIES' => $reader->getParserProperty(\XmlReader::SUBST_ENTITIES),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, array(), $count)) {
|
||||||
|
$info[$props] = new EnumStub($info[$props]);
|
||||||
|
$info[$props]->cut = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = Caster::filter($info, Caster::EXCLUDE_EMPTY, array(), $count);
|
||||||
|
// +2 because hasValue and hasAttributes are always filtered
|
||||||
|
$stub->cut += $count + 2;
|
||||||
|
|
||||||
|
return $a + $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
|
|||||||
abstract class AbstractCloner implements ClonerInterface
|
abstract class AbstractCloner implements ClonerInterface
|
||||||
{
|
{
|
||||||
public static $defaultCasters = array(
|
public static $defaultCasters = array(
|
||||||
|
'__PHP_Incomplete_Class' => 'Symfony\Component\VarDumper\Caster\Caster::castPhpIncompleteClass',
|
||||||
|
|
||||||
'Symfony\Component\VarDumper\Caster\CutStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
'Symfony\Component\VarDumper\Caster\CutStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
||||||
'Symfony\Component\VarDumper\Caster\CutArrayStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castCutArray',
|
'Symfony\Component\VarDumper\Caster\CutArrayStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castCutArray',
|
||||||
'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
||||||
@@ -67,6 +69,8 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
|
'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
|
||||||
'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
|
'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
|
||||||
|
|
||||||
|
'XmlReader' => 'Symfony\Component\VarDumper\Caster\XmlReaderCaster::castXmlReader',
|
||||||
|
|
||||||
'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
|
'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
|
||||||
'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
|
'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
|
||||||
'Error' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castError',
|
'Error' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castError',
|
||||||
@@ -100,6 +104,9 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
|
|
||||||
'MongoCursorInterface' => 'Symfony\Component\VarDumper\Caster\MongoCaster::castCursor',
|
'MongoCursorInterface' => 'Symfony\Component\VarDumper\Caster\MongoCaster::castCursor',
|
||||||
|
|
||||||
|
'Redis' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedis',
|
||||||
|
'RedisArray' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedisArray',
|
||||||
|
|
||||||
':curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
|
':curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
|
||||||
':dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
':dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||||
':dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
':dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||||
@@ -111,6 +118,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
':pgsql result' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castResult',
|
':pgsql result' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castResult',
|
||||||
':process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
|
':process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
|
||||||
':stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
':stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
||||||
|
':persistent stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
||||||
':stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
|
':stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
|
||||||
':xml' => 'Symfony\Component\VarDumper\Caster\XmlResourceCaster::castXml',
|
':xml' => 'Symfony\Component\VarDumper\Caster\XmlResourceCaster::castXml',
|
||||||
);
|
);
|
||||||
@@ -125,7 +133,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
private $filter = 0;
|
private $filter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable[]|null $casters A map of casters.
|
* @param callable[]|null $casters A map of casters
|
||||||
*
|
*
|
||||||
* @see addCasters
|
* @see addCasters
|
||||||
*/
|
*/
|
||||||
@@ -146,7 +154,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
* Resource types are to be prefixed with a `:`,
|
* Resource types are to be prefixed with a `:`,
|
||||||
* see e.g. static::$defaultCasters.
|
* see e.g. static::$defaultCasters.
|
||||||
*
|
*
|
||||||
* @param callable[] $casters A map of casters.
|
* @param callable[] $casters A map of casters
|
||||||
*/
|
*/
|
||||||
public function addCasters(array $casters)
|
public function addCasters(array $casters)
|
||||||
{
|
{
|
||||||
@@ -178,10 +186,10 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
/**
|
/**
|
||||||
* Clones a PHP variable.
|
* Clones a PHP variable.
|
||||||
*
|
*
|
||||||
* @param mixed $var Any PHP variable.
|
* @param mixed $var Any PHP variable
|
||||||
* @param int $filter A bit field of Caster::EXCLUDE_* constants.
|
* @param int $filter A bit field of Caster::EXCLUDE_* constants
|
||||||
*
|
*
|
||||||
* @return Data The cloned variable represented by a Data object.
|
* @return Data The cloned variable represented by a Data object
|
||||||
*/
|
*/
|
||||||
public function cloneVar($var, $filter = 0)
|
public function cloneVar($var, $filter = 0)
|
||||||
{
|
{
|
||||||
@@ -216,19 +224,19 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
/**
|
/**
|
||||||
* Effectively clones the PHP variable.
|
* Effectively clones the PHP variable.
|
||||||
*
|
*
|
||||||
* @param mixed $var Any PHP variable.
|
* @param mixed $var Any PHP variable
|
||||||
*
|
*
|
||||||
* @return array The cloned variable represented in an array.
|
* @return array The cloned variable represented in an array
|
||||||
*/
|
*/
|
||||||
abstract protected function doClone($var);
|
abstract protected function doClone($var);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Casts an object to an array representation.
|
* Casts an object to an array representation.
|
||||||
*
|
*
|
||||||
* @param Stub $stub The Stub for the casted object.
|
* @param Stub $stub The Stub for the casted object
|
||||||
* @param bool $isNested True if the object is nested in the dumped structure.
|
* @param bool $isNested True if the object is nested in the dumped structure
|
||||||
*
|
*
|
||||||
* @return array The object casted as array.
|
* @return array The object casted as array
|
||||||
*/
|
*/
|
||||||
protected function castObject(Stub $stub, $isNested)
|
protected function castObject(Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
@@ -245,14 +253,15 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
new \ReflectionClass($class),
|
new \ReflectionClass($class),
|
||||||
array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
|
array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
|
||||||
);
|
);
|
||||||
|
$classInfo[1] = array_map('strtolower', $classInfo[1]);
|
||||||
|
|
||||||
$this->classInfo[$class] = $classInfo;
|
$this->classInfo[$class] = $classInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = $this->callCaster('Symfony\Component\VarDumper\Caster\Caster::castObject', $obj, $classInfo[0], null, $isNested);
|
$a = Caster::castObject($obj, $classInfo[0]);
|
||||||
|
|
||||||
foreach ($classInfo[1] as $p) {
|
foreach ($classInfo[1] as $p) {
|
||||||
if (!empty($this->casters[$p = strtolower($p)])) {
|
if (!empty($this->casters[$p])) {
|
||||||
foreach ($this->casters[$p] as $p) {
|
foreach ($this->casters[$p] as $p) {
|
||||||
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
|
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
|
||||||
}
|
}
|
||||||
@@ -265,10 +274,10 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
/**
|
/**
|
||||||
* Casts a resource to an array representation.
|
* Casts a resource to an array representation.
|
||||||
*
|
*
|
||||||
* @param Stub $stub The Stub for the casted resource.
|
* @param Stub $stub The Stub for the casted resource
|
||||||
* @param bool $isNested True if the object is nested in the dumped structure.
|
* @param bool $isNested True if the object is nested in the dumped structure
|
||||||
*
|
*
|
||||||
* @return array The resource casted as array.
|
* @return array The resource casted as array
|
||||||
*/
|
*/
|
||||||
protected function castResource(Stub $stub, $isNested)
|
protected function castResource(Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
@@ -288,13 +297,13 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
/**
|
/**
|
||||||
* Calls a custom caster.
|
* Calls a custom caster.
|
||||||
*
|
*
|
||||||
* @param callable $callback The caster.
|
* @param callable $callback The caster
|
||||||
* @param object|resource $obj The object/resource being casted.
|
* @param object|resource $obj The object/resource being casted
|
||||||
* @param array $a The result of the previous cast for chained casters.
|
* @param array $a The result of the previous cast for chained casters
|
||||||
* @param Stub $stub The Stub for the casted object/resource.
|
* @param Stub $stub The Stub for the casted object/resource
|
||||||
* @param bool $isNested True if $obj is nested in the dumped structure.
|
* @param bool $isNested True if $obj is nested in the dumped structure
|
||||||
*
|
*
|
||||||
* @return array The casted object/resource.
|
* @return array The casted object/resource
|
||||||
*/
|
*/
|
||||||
private function callCaster($callback, $obj, $a, $stub, $isNested)
|
private function callCaster($callback, $obj, $a, $stub, $isNested)
|
||||||
{
|
{
|
||||||
@@ -305,7 +314,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
$a = $cast;
|
$a = $cast;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$a[(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠'] = new ThrowingCasterException($e);
|
$a = array((Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)) + $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ interface ClonerInterface
|
|||||||
/**
|
/**
|
||||||
* Clones a PHP variable.
|
* Clones a PHP variable.
|
||||||
*
|
*
|
||||||
* @param mixed $var Any PHP variable.
|
* @param mixed $var Any PHP variable
|
||||||
*
|
*
|
||||||
* @return Data The cloned variable represented by a Data object.
|
* @return Data The cloned variable represented by a Data object
|
||||||
*/
|
*/
|
||||||
public function cloneVar($var);
|
public function cloneVar($var);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,4 +38,5 @@ class Cursor
|
|||||||
public $hashLength = 0;
|
public $hashLength = 0;
|
||||||
public $hashCut = 0;
|
public $hashCut = 0;
|
||||||
public $stop = false;
|
public $stop = false;
|
||||||
|
public $attr = array();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,18 +11,22 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Cloner;
|
namespace Symfony\Component\VarDumper\Cloner;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Caster\Caster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class Data
|
class Data
|
||||||
{
|
{
|
||||||
private $data;
|
private $data;
|
||||||
|
private $position = 0;
|
||||||
|
private $key = 0;
|
||||||
private $maxDepth = 20;
|
private $maxDepth = 20;
|
||||||
private $maxItemsPerDepth = -1;
|
private $maxItemsPerDepth = -1;
|
||||||
private $useRefHandles = -1;
|
private $useRefHandles = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $data A array as returned by ClonerInterface::cloneVar().
|
* @param array $data A array as returned by ClonerInterface::cloneVar()
|
||||||
*/
|
*/
|
||||||
public function __construct(array $data)
|
public function __construct(array $data)
|
||||||
{
|
{
|
||||||
@@ -30,7 +34,7 @@ class Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array The raw data structure.
|
* @return array The raw data structure
|
||||||
*/
|
*/
|
||||||
public function getRawData()
|
public function getRawData()
|
||||||
{
|
{
|
||||||
@@ -40,9 +44,9 @@ class Data
|
|||||||
/**
|
/**
|
||||||
* Returns a depth limited clone of $this.
|
* Returns a depth limited clone of $this.
|
||||||
*
|
*
|
||||||
* @param int $maxDepth The max dumped depth level.
|
* @param int $maxDepth The max dumped depth level
|
||||||
*
|
*
|
||||||
* @return self A clone of $this.
|
* @return self A clone of $this
|
||||||
*/
|
*/
|
||||||
public function withMaxDepth($maxDepth)
|
public function withMaxDepth($maxDepth)
|
||||||
{
|
{
|
||||||
@@ -53,11 +57,11 @@ class Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Limits the numbers of elements per depth level.
|
* Limits the number of elements per depth level.
|
||||||
*
|
*
|
||||||
* @param int $maxItemsPerDepth The max number of items dumped per depth level.
|
* @param int $maxItemsPerDepth The max number of items dumped per depth level
|
||||||
*
|
*
|
||||||
* @return self A clone of $this.
|
* @return self A clone of $this
|
||||||
*/
|
*/
|
||||||
public function withMaxItemsPerDepth($maxItemsPerDepth)
|
public function withMaxItemsPerDepth($maxItemsPerDepth)
|
||||||
{
|
{
|
||||||
@@ -70,9 +74,9 @@ class Data
|
|||||||
/**
|
/**
|
||||||
* Enables/disables objects' identifiers tracking.
|
* Enables/disables objects' identifiers tracking.
|
||||||
*
|
*
|
||||||
* @param bool $useRefHandles False to hide global ref. handles.
|
* @param bool $useRefHandles False to hide global ref. handles
|
||||||
*
|
*
|
||||||
* @return self A clone of $this.
|
* @return self A clone of $this
|
||||||
*/
|
*/
|
||||||
public function withRefHandles($useRefHandles)
|
public function withRefHandles($useRefHandles)
|
||||||
{
|
{
|
||||||
@@ -82,22 +86,66 @@ class Data
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeks to a specific key in nested data structures.
|
||||||
|
*
|
||||||
|
* @param string|int $key The key to seek to
|
||||||
|
*
|
||||||
|
* @return self|null A clone of $this of null if the key is not set
|
||||||
|
*/
|
||||||
|
public function seek($key)
|
||||||
|
{
|
||||||
|
$item = $this->data[$this->position][$this->key];
|
||||||
|
|
||||||
|
if (!$item instanceof Stub || !$item->position) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$keys = array($key);
|
||||||
|
|
||||||
|
switch ($item->type) {
|
||||||
|
case Stub::TYPE_OBJECT:
|
||||||
|
$keys[] = Caster::PREFIX_DYNAMIC.$key;
|
||||||
|
$keys[] = Caster::PREFIX_PROTECTED.$key;
|
||||||
|
$keys[] = Caster::PREFIX_VIRTUAL.$key;
|
||||||
|
$keys[] = "\0$item->class\0$key";
|
||||||
|
case Stub::TYPE_ARRAY:
|
||||||
|
case Stub::TYPE_RESOURCE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = null;
|
||||||
|
$children = $this->data[$item->position];
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (isset($children[$key]) || array_key_exists($key, $children)) {
|
||||||
|
$data = clone $this;
|
||||||
|
$data->key = $key;
|
||||||
|
$data->position = $item->position;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps data with a DumperInterface dumper.
|
* Dumps data with a DumperInterface dumper.
|
||||||
*/
|
*/
|
||||||
public function dump(DumperInterface $dumper)
|
public function dump(DumperInterface $dumper)
|
||||||
{
|
{
|
||||||
$refs = array(0);
|
$refs = array(0);
|
||||||
$this->dumpItem($dumper, new Cursor(), $refs, $this->data[0][0]);
|
$this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Depth-first dumping of items.
|
* Depth-first dumping of items.
|
||||||
*
|
*
|
||||||
* @param DumperInterface $dumper The dumper being used for dumping.
|
* @param DumperInterface $dumper The dumper being used for dumping
|
||||||
* @param Cursor $cursor A cursor used for tracking dumper state position.
|
* @param Cursor $cursor A cursor used for tracking dumper state position
|
||||||
* @param array &$refs A map of all references discovered while dumping.
|
* @param array &$refs A map of all references discovered while dumping
|
||||||
* @param mixed $item A Stub object or the original value being dumped.
|
* @param mixed $item A Stub object or the original value being dumped
|
||||||
*/
|
*/
|
||||||
private function dumpItem($dumper, $cursor, &$refs, $item)
|
private function dumpItem($dumper, $cursor, &$refs, $item)
|
||||||
{
|
{
|
||||||
@@ -107,6 +155,7 @@ class Data
|
|||||||
$firstSeen = true;
|
$firstSeen = true;
|
||||||
|
|
||||||
if (!$item instanceof Stub) {
|
if (!$item instanceof Stub) {
|
||||||
|
$cursor->attr = array();
|
||||||
$type = gettype($item);
|
$type = gettype($item);
|
||||||
} elseif (Stub::TYPE_REF === $item->type) {
|
} elseif (Stub::TYPE_REF === $item->type) {
|
||||||
if ($item->handle) {
|
if ($item->handle) {
|
||||||
@@ -119,6 +168,7 @@ class Data
|
|||||||
$cursor->hardRefHandle = $this->useRefHandles & $item->handle;
|
$cursor->hardRefHandle = $this->useRefHandles & $item->handle;
|
||||||
$cursor->hardRefCount = $item->refCount;
|
$cursor->hardRefCount = $item->refCount;
|
||||||
}
|
}
|
||||||
|
$cursor->attr = $item->attr;
|
||||||
$type = $item->class ?: gettype($item->value);
|
$type = $item->class ?: gettype($item->value);
|
||||||
$item = $item->value;
|
$item = $item->value;
|
||||||
}
|
}
|
||||||
@@ -133,6 +183,7 @@ class Data
|
|||||||
}
|
}
|
||||||
$cursor->softRefHandle = $this->useRefHandles & $item->handle;
|
$cursor->softRefHandle = $this->useRefHandles & $item->handle;
|
||||||
$cursor->softRefCount = $item->refCount;
|
$cursor->softRefCount = $item->refCount;
|
||||||
|
$cursor->attr = $item->attr;
|
||||||
$cut = $item->cut;
|
$cut = $item->cut;
|
||||||
|
|
||||||
if ($item->position && $firstSeen) {
|
if ($item->position && $firstSeen) {
|
||||||
@@ -162,7 +213,7 @@ class Data
|
|||||||
$withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
|
$withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
|
||||||
$dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
|
$dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
|
||||||
if ($withChildren) {
|
if ($withChildren) {
|
||||||
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type);
|
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
|
||||||
} elseif ($children && 0 <= $cut) {
|
} elseif ($children && 0 <= $cut) {
|
||||||
$cut += count($children);
|
$cut += count($children);
|
||||||
}
|
}
|
||||||
@@ -186,15 +237,16 @@ class Data
|
|||||||
* Dumps children of hash structures.
|
* Dumps children of hash structures.
|
||||||
*
|
*
|
||||||
* @param DumperInterface $dumper
|
* @param DumperInterface $dumper
|
||||||
* @param Cursor $parentCursor The cursor of the parent hash.
|
* @param Cursor $parentCursor The cursor of the parent hash
|
||||||
* @param array &$refs A map of all references discovered while dumping.
|
* @param array &$refs A map of all references discovered while dumping
|
||||||
* @param array $children The children to dump.
|
* @param array $children The children to dump
|
||||||
* @param int $hashCut The number of items removed from the original hash.
|
* @param int $hashCut The number of items removed from the original hash
|
||||||
* @param string $hashType A Cursor::HASH_* const.
|
* @param string $hashType A Cursor::HASH_* const
|
||||||
|
* @param bool $dumpKeys Whether keys should be dumped or not
|
||||||
*
|
*
|
||||||
* @return int The final number of removed items.
|
* @return int The final number of removed items
|
||||||
*/
|
*/
|
||||||
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType)
|
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType, $dumpKeys)
|
||||||
{
|
{
|
||||||
$cursor = clone $parentCursor;
|
$cursor = clone $parentCursor;
|
||||||
++$cursor->depth;
|
++$cursor->depth;
|
||||||
@@ -204,7 +256,7 @@ class Data
|
|||||||
$cursor->hashCut = $hashCut;
|
$cursor->hashCut = $hashCut;
|
||||||
foreach ($children as $key => $child) {
|
foreach ($children as $key => $child) {
|
||||||
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
|
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
|
||||||
$cursor->hashKey = $key;
|
$cursor->hashKey = $dumpKeys ? $key : null;
|
||||||
$this->dumpItem($dumper, $cursor, $refs, $child);
|
$this->dumpItem($dumper, $cursor, $refs, $child);
|
||||||
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
|
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
|
||||||
$parentCursor->stop = true;
|
$parentCursor->stop = true;
|
||||||
|
|||||||
@@ -21,40 +21,40 @@ interface DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Dumps a scalar value.
|
* Dumps a scalar value.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
* @param string $type The PHP type of the value being dumped.
|
* @param string $type The PHP type of the value being dumped
|
||||||
* @param scalar $value The scalar value being dumped.
|
* @param scalar $value The scalar value being dumped
|
||||||
*/
|
*/
|
||||||
public function dumpScalar(Cursor $cursor, $type, $value);
|
public function dumpScalar(Cursor $cursor, $type, $value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps a string.
|
* Dumps a string.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
* @param string $str The string being dumped.
|
* @param string $str The string being dumped
|
||||||
* @param bool $bin Whether $str is UTF-8 or binary encoded.
|
* @param bool $bin Whether $str is UTF-8 or binary encoded
|
||||||
* @param int $cut The number of characters $str has been cut by.
|
* @param int $cut The number of characters $str has been cut by
|
||||||
*/
|
*/
|
||||||
public function dumpString(Cursor $cursor, $str, $bin, $cut);
|
public function dumpString(Cursor $cursor, $str, $bin, $cut);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps while entering an hash.
|
* Dumps while entering an hash.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
* @param int $type A Cursor::HASH_* const for the type of hash.
|
* @param int $type A Cursor::HASH_* const for the type of hash
|
||||||
* @param string $class The object class, resource type or array count.
|
* @param string $class The object class, resource type or array count
|
||||||
* @param bool $hasChild When the dump of the hash has child item.
|
* @param bool $hasChild When the dump of the hash has child item
|
||||||
*/
|
*/
|
||||||
public function enterHash(Cursor $cursor, $type, $class, $hasChild);
|
public function enterHash(Cursor $cursor, $type, $class, $hasChild);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps while leaving an hash.
|
* Dumps while leaving an hash.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
* @param int $type A Cursor::HASH_* const for the type of hash.
|
* @param int $type A Cursor::HASH_* const for the type of hash
|
||||||
* @param string $class The object class, resource type or array count.
|
* @param string $class The object class, resource type or array count
|
||||||
* @param bool $hasChild When the dump of the hash has child item.
|
* @param bool $hasChild When the dump of the hash has child item
|
||||||
* @param int $cut The number of items the hash has been cut by.
|
* @param int $cut The number of items the hash has been cut by
|
||||||
*/
|
*/
|
||||||
public function leaveHash(Cursor $cursor, $type, $class, $hasChild, $cut);
|
public function leaveHash(Cursor $cursor, $type, $class, $hasChild, $cut);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,5 @@ class Stub
|
|||||||
public $handle = 0;
|
public $handle = 0;
|
||||||
public $refCount = 0;
|
public $refCount = 0;
|
||||||
public $position = 0;
|
public $position = 0;
|
||||||
|
public $attr = array();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ class VarCloner extends AbstractCloner
|
|||||||
protected function doClone($var)
|
protected function doClone($var)
|
||||||
{
|
{
|
||||||
$useExt = $this->useExt;
|
$useExt = $this->useExt;
|
||||||
$i = 0; // Current iteration position in $queue
|
|
||||||
$len = 1; // Length of $queue
|
$len = 1; // Length of $queue
|
||||||
$pos = 0; // Number of cloned items past the first level
|
$pos = 0; // Number of cloned items past the first level
|
||||||
$refs = 0; // Hard references counter
|
$refsCounter = 0; // Hard references counter
|
||||||
$queue = array(array($var)); // This breadth-first queue is the return value
|
$queue = array(array($var)); // This breadth-first queue is the return value
|
||||||
$arrayRefs = array(); // Map of queue indexes to stub array objects
|
$arrayRefs = array(); // Map of queue indexes to stub array objects
|
||||||
$hardRefs = array(); // Map of original zval hashes to stub objects
|
$hardRefs = array(); // Map of original zval hashes to stub objects
|
||||||
@@ -60,27 +59,32 @@ class VarCloner extends AbstractCloner
|
|||||||
for ($i = 0; $i < $len; ++$i) {
|
for ($i = 0; $i < $len; ++$i) {
|
||||||
$indexed = true; // Whether the currently iterated array is numerically indexed or not
|
$indexed = true; // Whether the currently iterated array is numerically indexed or not
|
||||||
$j = -1; // Position in the currently iterated array
|
$j = -1; // Position in the currently iterated array
|
||||||
$step = $queue[$i]; // Copy of the currently iterated array used for hard references detection
|
$fromObjCast = array_keys($queue[$i]);
|
||||||
foreach ($step as $k => $v) {
|
$fromObjCast = array_keys(array_flip($fromObjCast)) !== $fromObjCast;
|
||||||
|
$refs = $vals = $fromObjCast ? array_values($queue[$i]) : $queue[$i];
|
||||||
|
foreach ($queue[$i] as $k => $v) {
|
||||||
// $k is the original key
|
// $k is the original key
|
||||||
// $v is the original value or a stub object in case of hard references
|
// $v is the original value or a stub object in case of hard references
|
||||||
if ($indexed && $k !== ++$j) {
|
if ($k !== ++$j) {
|
||||||
$indexed = false;
|
$indexed = false;
|
||||||
}
|
}
|
||||||
|
if ($fromObjCast) {
|
||||||
|
$k = $j;
|
||||||
|
}
|
||||||
if ($useExt) {
|
if ($useExt) {
|
||||||
$zval = symfony_zval_info($k, $step);
|
$zval = symfony_zval_info($k, $refs);
|
||||||
} else {
|
} else {
|
||||||
$step[$k] = $cookie;
|
$refs[$k] = $cookie;
|
||||||
if ($zval['zval_isref'] = $queue[$i][$k] === $cookie) {
|
if ($zval['zval_isref'] = $vals[$k] === $cookie) {
|
||||||
$zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null;
|
$zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null;
|
||||||
}
|
}
|
||||||
$zval['type'] = gettype($v);
|
$zval['type'] = gettype($v);
|
||||||
}
|
}
|
||||||
if ($zval['zval_isref']) {
|
if ($zval['zval_isref']) {
|
||||||
$queue[$i][$k] = &$stub; // Break hard references to make $queue completely
|
$vals[$k] = &$stub; // Break hard references to make $queue completely
|
||||||
unset($stub); // independent from the original structure
|
unset($stub); // independent from the original structure
|
||||||
if (isset($hardRefs[$zval['zval_hash']])) {
|
if (isset($hardRefs[$zval['zval_hash']])) {
|
||||||
$queue[$i][$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($step[$k] = $v);
|
$vals[$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($refs[$k] = $v);
|
||||||
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
|
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
|
||||||
++$v->value->refCount;
|
++$v->value->refCount;
|
||||||
}
|
}
|
||||||
@@ -102,12 +106,12 @@ class VarCloner extends AbstractCloner
|
|||||||
} else {
|
} else {
|
||||||
$stub->value = $v;
|
$stub->value = $v;
|
||||||
}
|
}
|
||||||
} elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = iconv_strlen($v, 'UTF-8') - $maxString) {
|
} elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
|
||||||
$stub = new Stub();
|
$stub = new Stub();
|
||||||
$stub->type = Stub::TYPE_STRING;
|
$stub->type = Stub::TYPE_STRING;
|
||||||
$stub->class = Stub::STRING_UTF8;
|
$stub->class = Stub::STRING_UTF8;
|
||||||
$stub->cut = $cut;
|
$stub->cut = $cut;
|
||||||
$stub->value = iconv_substr($v, 0, $maxString, 'UTF-8');
|
$stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -178,10 +182,13 @@ class VarCloner extends AbstractCloner
|
|||||||
|
|
||||||
case 'resource':
|
case 'resource':
|
||||||
case 'unknown type':
|
case 'unknown type':
|
||||||
|
case 'resource (closed)':
|
||||||
if (empty($resRefs[$h = (int) $v])) {
|
if (empty($resRefs[$h = (int) $v])) {
|
||||||
$stub = new Stub();
|
$stub = new Stub();
|
||||||
$stub->type = Stub::TYPE_RESOURCE;
|
$stub->type = Stub::TYPE_RESOURCE;
|
||||||
$stub->class = $zval['resource_type'] ?: get_resource_type($v);
|
if ('Unknown' === $stub->class = $zval['resource_type'] ?: @get_resource_type($v)) {
|
||||||
|
$stub->class = 'Closed';
|
||||||
|
}
|
||||||
$stub->value = $v;
|
$stub->value = $v;
|
||||||
$stub->handle = $h;
|
$stub->handle = $h;
|
||||||
$a = $this->castResource($stub, 0 < $i);
|
$a = $this->castResource($stub, 0 < $i);
|
||||||
@@ -204,18 +211,18 @@ class VarCloner extends AbstractCloner
|
|||||||
if (isset($stub)) {
|
if (isset($stub)) {
|
||||||
if ($zval['zval_isref']) {
|
if ($zval['zval_isref']) {
|
||||||
if ($useExt) {
|
if ($useExt) {
|
||||||
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
|
$vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
|
||||||
$v->value = $stub;
|
$v->value = $stub;
|
||||||
} else {
|
} else {
|
||||||
$step[$k] = new Stub();
|
$refs[$k] = new Stub();
|
||||||
$step[$k]->value = $stub;
|
$refs[$k]->value = $stub;
|
||||||
$h = spl_object_hash($step[$k]);
|
$h = spl_object_hash($refs[$k]);
|
||||||
$queue[$i][$k] = $hardRefs[$h] = &$step[$k];
|
$vals[$k] = $hardRefs[$h] = &$refs[$k];
|
||||||
$values[$h] = $v;
|
$values[$h] = $v;
|
||||||
}
|
}
|
||||||
$queue[$i][$k]->handle = ++$refs;
|
$vals[$k]->handle = ++$refsCounter;
|
||||||
} else {
|
} else {
|
||||||
$queue[$i][$k] = $stub;
|
$vals[$k] = $stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($a) {
|
if ($a) {
|
||||||
@@ -243,19 +250,38 @@ class VarCloner extends AbstractCloner
|
|||||||
$stub = $a = null;
|
$stub = $a = null;
|
||||||
} elseif ($zval['zval_isref']) {
|
} elseif ($zval['zval_isref']) {
|
||||||
if ($useExt) {
|
if ($useExt) {
|
||||||
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = new Stub();
|
$vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub();
|
||||||
$queue[$i][$k]->value = $v;
|
$vals[$k]->value = $v;
|
||||||
} else {
|
} else {
|
||||||
$step[$k] = $queue[$i][$k] = new Stub();
|
$refs[$k] = $vals[$k] = new Stub();
|
||||||
$step[$k]->value = $v;
|
$refs[$k]->value = $v;
|
||||||
$h = spl_object_hash($step[$k]);
|
$h = spl_object_hash($refs[$k]);
|
||||||
$hardRefs[$h] = &$step[$k];
|
$hardRefs[$h] = &$refs[$k];
|
||||||
$values[$h] = $v;
|
$values[$h] = $v;
|
||||||
}
|
}
|
||||||
$queue[$i][$k]->handle = ++$refs;
|
$vals[$k]->handle = ++$refsCounter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($fromObjCast) {
|
||||||
|
$refs = $vals;
|
||||||
|
$vals = array();
|
||||||
|
$j = -1;
|
||||||
|
foreach ($queue[$i] as $k => $v) {
|
||||||
|
foreach (array($k => $v) as $a => $v) {
|
||||||
|
}
|
||||||
|
if ($a !== $k) {
|
||||||
|
$vals = (object) $vals;
|
||||||
|
$vals->{$k} = $refs[++$j];
|
||||||
|
$vals = (array) $vals;
|
||||||
|
} else {
|
||||||
|
$vals[$k] = $refs[++$j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$queue[$i] = $vals;
|
||||||
|
|
||||||
if (isset($arrayRefs[$i])) {
|
if (isset($arrayRefs[$i])) {
|
||||||
if ($indexed) {
|
if ($indexed) {
|
||||||
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
|
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
|
||||||
@@ -291,7 +317,7 @@ class VarCloner extends AbstractCloner
|
|||||||
if (!empty($frame['line'])) {
|
if (!empty($frame['line'])) {
|
||||||
ob_start();
|
ob_start();
|
||||||
debug_zval_dump($obj);
|
debug_zval_dump($obj);
|
||||||
self::$hashMask = substr(ob_get_clean(), 17);
|
self::$hashMask = (int) substr(ob_get_clean(), 17);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ use Symfony\Component\VarDumper\Cloner\DumperInterface;
|
|||||||
*/
|
*/
|
||||||
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||||
{
|
{
|
||||||
|
const DUMP_LIGHT_ARRAY = 1;
|
||||||
|
const DUMP_STRING_LENGTH = 2;
|
||||||
|
|
||||||
public static $defaultOutput = 'php://output';
|
public static $defaultOutput = 'php://output';
|
||||||
|
|
||||||
protected $line = '';
|
protected $line = '';
|
||||||
@@ -28,18 +31,21 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
protected $outputStream;
|
protected $outputStream;
|
||||||
protected $decimalPoint; // This is locale dependent
|
protected $decimalPoint; // This is locale dependent
|
||||||
protected $indentPad = ' ';
|
protected $indentPad = ' ';
|
||||||
|
protected $flags;
|
||||||
|
|
||||||
private $charset;
|
private $charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput.
|
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput
|
||||||
* @param string $charset The default character encoding to use for non-UTF8 strings.
|
* @param string $charset The default character encoding to use for non-UTF8 strings
|
||||||
|
* @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation
|
||||||
*/
|
*/
|
||||||
public function __construct($output = null, $charset = null)
|
public function __construct($output = null, $charset = null, $flags = 0)
|
||||||
{
|
{
|
||||||
|
$this->flags = (int) $flags;
|
||||||
$this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
|
$this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
|
||||||
$this->decimalPoint = (string) 0.5;
|
$this->decimalPoint = localeconv();
|
||||||
$this->decimalPoint = $this->decimalPoint[1];
|
$this->decimalPoint = $this->decimalPoint['decimal_point'];
|
||||||
$this->setOutput($output ?: static::$defaultOutput);
|
$this->setOutput($output ?: static::$defaultOutput);
|
||||||
if (!$output && is_string(static::$defaultOutput)) {
|
if (!$output && is_string(static::$defaultOutput)) {
|
||||||
static::$defaultOutput = $this->outputStream;
|
static::$defaultOutput = $this->outputStream;
|
||||||
@@ -49,9 +55,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Sets the output destination of the dumps.
|
* Sets the output destination of the dumps.
|
||||||
*
|
*
|
||||||
* @param callable|resource|string $output A line dumper callable, an opened stream or an output path.
|
* @param callable|resource|string $output A line dumper callable, an opened stream or an output path
|
||||||
*
|
*
|
||||||
* @return callable|resource|string The previous output destination.
|
* @return callable|resource|string The previous output destination
|
||||||
*/
|
*/
|
||||||
public function setOutput($output)
|
public function setOutput($output)
|
||||||
{
|
{
|
||||||
@@ -74,9 +80,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Sets the default character encoding to use for non-UTF8 strings.
|
* Sets the default character encoding to use for non-UTF8 strings.
|
||||||
*
|
*
|
||||||
* @param string $charset The default character encoding to use for non-UTF8 strings.
|
* @param string $charset The default character encoding to use for non-UTF8 strings
|
||||||
*
|
*
|
||||||
* @return string The previous charset.
|
* @return string The previous charset
|
||||||
*/
|
*/
|
||||||
public function setCharset($charset)
|
public function setCharset($charset)
|
||||||
{
|
{
|
||||||
@@ -93,9 +99,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Sets the indentation pad string.
|
* Sets the indentation pad string.
|
||||||
*
|
*
|
||||||
* @param string $pad A string the will be prepended to dumped lines, repeated by nesting level.
|
* @param string $pad A string the will be prepended to dumped lines, repeated by nesting level
|
||||||
*
|
*
|
||||||
* @return string The indent pad.
|
* @return string The indent pad
|
||||||
*/
|
*/
|
||||||
public function setIndentPad($pad)
|
public function setIndentPad($pad)
|
||||||
{
|
{
|
||||||
@@ -108,33 +114,43 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Dumps a Data object.
|
* Dumps a Data object.
|
||||||
*
|
*
|
||||||
* @param Data $data A Data object.
|
* @param Data $data A Data object
|
||||||
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path.
|
* @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump
|
||||||
|
*
|
||||||
|
* @return string|null The dump as string when $output is true
|
||||||
*/
|
*/
|
||||||
public function dump(Data $data, $output = null)
|
public function dump(Data $data, $output = null)
|
||||||
{
|
{
|
||||||
$exception = null;
|
$this->decimalPoint = localeconv();
|
||||||
|
$this->decimalPoint = $this->decimalPoint['decimal_point'];
|
||||||
|
|
||||||
|
if ($returnDump = true === $output) {
|
||||||
|
$output = fopen('php://memory', 'r+b');
|
||||||
|
}
|
||||||
if ($output) {
|
if ($output) {
|
||||||
$prevOutput = $this->setOutput($output);
|
$prevOutput = $this->setOutput($output);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$data->dump($this);
|
$data->dump($this);
|
||||||
$this->dumpLine(-1);
|
$this->dumpLine(-1);
|
||||||
} catch (\Exception $exception) {
|
|
||||||
// Re-thrown below
|
if ($returnDump) {
|
||||||
}
|
$result = stream_get_contents($output, -1, 0);
|
||||||
if ($output) {
|
fclose($output);
|
||||||
$this->setOutput($prevOutput);
|
|
||||||
}
|
return $result;
|
||||||
if (null !== $exception) {
|
}
|
||||||
throw $exception;
|
} finally {
|
||||||
|
if ($output) {
|
||||||
|
$this->setOutput($prevOutput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps the current line.
|
* Dumps the current line.
|
||||||
*
|
*
|
||||||
* @param int $depth The recursive depth in the dumped structure for the line being dumped.
|
* @param int $depth The recursive depth in the dumped structure for the line being dumped
|
||||||
*/
|
*/
|
||||||
protected function dumpLine($depth)
|
protected function dumpLine($depth)
|
||||||
{
|
{
|
||||||
@@ -145,8 +161,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Generic line dumper callback.
|
* Generic line dumper callback.
|
||||||
*
|
*
|
||||||
* @param string $line The line to write.
|
* @param string $line The line to write
|
||||||
* @param int $depth The recursive depth in the dumped structure.
|
* @param int $depth The recursive depth in the dumped structure
|
||||||
|
* @param string $indentPad The line indent pad
|
||||||
*/
|
*/
|
||||||
protected function echoLine($line, $depth, $indentPad)
|
protected function echoLine($line, $depth, $indentPad)
|
||||||
{
|
{
|
||||||
@@ -158,12 +175,20 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
/**
|
/**
|
||||||
* Converts a non-UTF-8 string to UTF-8.
|
* Converts a non-UTF-8 string to UTF-8.
|
||||||
*
|
*
|
||||||
* @param string $s The non-UTF-8 string to convert.
|
* @param string $s The non-UTF-8 string to convert
|
||||||
*
|
*
|
||||||
* @return string The string converted to UTF-8.
|
* @return string The string converted to UTF-8
|
||||||
*/
|
*/
|
||||||
protected function utf8Encode($s)
|
protected function utf8Encode($s)
|
||||||
{
|
{
|
||||||
|
if (preg_match('//u', $s)) {
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('iconv')) {
|
||||||
|
throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.');
|
||||||
|
}
|
||||||
|
|
||||||
if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
|
if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ class CliDumper extends AbstractDumper
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __construct($output = null, $charset = null)
|
public function __construct($output = null, $charset = null, $flags = 0)
|
||||||
{
|
{
|
||||||
parent::__construct($output, $charset);
|
parent::__construct($output, $charset, $flags);
|
||||||
|
|
||||||
if ('\\' === DIRECTORY_SEPARATOR && false !== @getenv('ANSICON')) {
|
if ('\\' === DIRECTORY_SEPARATOR && 'ON' !== @getenv('ConEmuANSI') && 'xterm' !== @getenv('TERM')) {
|
||||||
// Use only the base 16 xterm colors when using ANSICON
|
// Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI
|
||||||
$this->setStyles(array(
|
$this->setStyles(array(
|
||||||
'default' => '31',
|
'default' => '31',
|
||||||
'num' => '1;34',
|
'num' => '1;34',
|
||||||
@@ -97,7 +97,7 @@ class CliDumper extends AbstractDumper
|
|||||||
/**
|
/**
|
||||||
* Configures styles.
|
* Configures styles.
|
||||||
*
|
*
|
||||||
* @param array $styles A map of style names to style definitions.
|
* @param array $styles A map of style names to style definitions
|
||||||
*/
|
*/
|
||||||
public function setStyles(array $styles)
|
public function setStyles(array $styles)
|
||||||
{
|
{
|
||||||
@@ -112,9 +112,13 @@ class CliDumper extends AbstractDumper
|
|||||||
$this->dumpKey($cursor);
|
$this->dumpKey($cursor);
|
||||||
|
|
||||||
$style = 'const';
|
$style = 'const';
|
||||||
$attr = array();
|
$attr = $cursor->attr;
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
case 'default':
|
||||||
|
$style = 'default';
|
||||||
|
break;
|
||||||
|
|
||||||
case 'integer':
|
case 'integer':
|
||||||
$style = 'num';
|
$style = 'num';
|
||||||
break;
|
break;
|
||||||
@@ -123,9 +127,9 @@ class CliDumper extends AbstractDumper
|
|||||||
$style = 'num';
|
$style = 'num';
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case INF === $value: $value = 'INF'; break;
|
case INF === $value: $value = 'INF'; break;
|
||||||
case -INF === $value: $value = '-INF'; break;
|
case -INF === $value: $value = '-INF'; break;
|
||||||
case is_nan($value): $value = 'NAN'; break;
|
case is_nan($value): $value = 'NAN'; break;
|
||||||
default:
|
default:
|
||||||
$value = (string) $value;
|
$value = (string) $value;
|
||||||
if (false === strpos($value, $this->decimalPoint)) {
|
if (false === strpos($value, $this->decimalPoint)) {
|
||||||
@@ -144,8 +148,8 @@ class CliDumper extends AbstractDumper
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$attr['value'] = isset($value[0]) && !preg_match('//u', $value) ? $this->utf8Encode($value) : $value;
|
$attr += array('value' => $this->utf8Encode($value));
|
||||||
$value = isset($type[0]) && !preg_match('//u', $type) ? $this->utf8Encode($type) : $type;
|
$value = $this->utf8Encode($type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +164,7 @@ class CliDumper extends AbstractDumper
|
|||||||
public function dumpString(Cursor $cursor, $str, $bin, $cut)
|
public function dumpString(Cursor $cursor, $str, $bin, $cut)
|
||||||
{
|
{
|
||||||
$this->dumpKey($cursor);
|
$this->dumpKey($cursor);
|
||||||
|
$attr = $cursor->attr;
|
||||||
|
|
||||||
if ($bin) {
|
if ($bin) {
|
||||||
$str = $this->utf8Encode($str);
|
$str = $this->utf8Encode($str);
|
||||||
@@ -168,8 +173,8 @@ class CliDumper extends AbstractDumper
|
|||||||
$this->line .= '""';
|
$this->line .= '""';
|
||||||
$this->dumpLine($cursor->depth, true);
|
$this->dumpLine($cursor->depth, true);
|
||||||
} else {
|
} else {
|
||||||
$attr = array(
|
$attr += array(
|
||||||
'length' => 0 <= $cut ? iconv_strlen($str, 'UTF-8') + $cut : 0,
|
'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,
|
||||||
'binary' => $bin,
|
'binary' => $bin,
|
||||||
);
|
);
|
||||||
$str = explode("\n", $str);
|
$str = explode("\n", $str);
|
||||||
@@ -180,6 +185,9 @@ class CliDumper extends AbstractDumper
|
|||||||
$m = count($str) - 1;
|
$m = count($str) - 1;
|
||||||
$i = $lineCut = 0;
|
$i = $lineCut = 0;
|
||||||
|
|
||||||
|
if (self::DUMP_STRING_LENGTH & $this->flags) {
|
||||||
|
$this->line .= '('.$attr['length'].') ';
|
||||||
|
}
|
||||||
if ($bin) {
|
if ($bin) {
|
||||||
$this->line .= 'b';
|
$this->line .= 'b';
|
||||||
}
|
}
|
||||||
@@ -195,8 +203,8 @@ class CliDumper extends AbstractDumper
|
|||||||
if ($i < $m) {
|
if ($i < $m) {
|
||||||
$str .= "\n";
|
$str .= "\n";
|
||||||
}
|
}
|
||||||
if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = iconv_strlen($str, 'UTF-8')) {
|
if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {
|
||||||
$str = iconv_substr($str, 0, $this->maxStringWidth, 'UTF-8');
|
$str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');
|
||||||
$lineCut = $len - $this->maxStringWidth;
|
$lineCut = $len - $this->maxStringWidth;
|
||||||
}
|
}
|
||||||
if ($m && 0 < $cursor->depth) {
|
if ($m && 0 < $cursor->depth) {
|
||||||
@@ -241,15 +249,13 @@ class CliDumper extends AbstractDumper
|
|||||||
{
|
{
|
||||||
$this->dumpKey($cursor);
|
$this->dumpKey($cursor);
|
||||||
|
|
||||||
if (!preg_match('//u', $class)) {
|
$class = $this->utf8Encode($class);
|
||||||
$class = $this->utf8Encode($class);
|
|
||||||
}
|
|
||||||
if (Cursor::HASH_OBJECT === $type) {
|
if (Cursor::HASH_OBJECT === $type) {
|
||||||
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{';
|
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{';
|
||||||
} elseif (Cursor::HASH_RESOURCE === $type) {
|
} elseif (Cursor::HASH_RESOURCE === $type) {
|
||||||
$prefix = $this->style('note', $class.' resource').($hasChild ? ' {' : ' ');
|
$prefix = $this->style('note', $class.' resource').($hasChild ? ' {' : ' ');
|
||||||
} else {
|
} else {
|
||||||
$prefix = $class ? $this->style('note', 'array:'.$class).' [' : '[';
|
$prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cursor->softRefCount || 0 < $cursor->softRefHandle) {
|
if ($cursor->softRefCount || 0 < $cursor->softRefHandle) {
|
||||||
@@ -280,9 +286,9 @@ class CliDumper extends AbstractDumper
|
|||||||
/**
|
/**
|
||||||
* Dumps an ellipsis for cut children.
|
* Dumps an ellipsis for cut children.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
* @param bool $hasChild When the dump of the hash has child item.
|
* @param bool $hasChild When the dump of the hash has child item
|
||||||
* @param int $cut The number of items the hash has been cut by.
|
* @param int $cut The number of items the hash has been cut by
|
||||||
*/
|
*/
|
||||||
protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut)
|
protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut)
|
||||||
{
|
{
|
||||||
@@ -300,7 +306,7 @@ class CliDumper extends AbstractDumper
|
|||||||
/**
|
/**
|
||||||
* Dumps a key in a hash structure.
|
* Dumps a key in a hash structure.
|
||||||
*
|
*
|
||||||
* @param Cursor $cursor The Cursor position in the dump.
|
* @param Cursor $cursor The Cursor position in the dump
|
||||||
*/
|
*/
|
||||||
protected function dumpKey(Cursor $cursor)
|
protected function dumpKey(Cursor $cursor)
|
||||||
{
|
{
|
||||||
@@ -314,6 +320,9 @@ class CliDumper extends AbstractDumper
|
|||||||
switch ($cursor->hashType) {
|
switch ($cursor->hashType) {
|
||||||
default:
|
default:
|
||||||
case Cursor::HASH_INDEXED:
|
case Cursor::HASH_INDEXED:
|
||||||
|
if (self::DUMP_LIGHT_ARRAY & $this->flags) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
$style = 'index';
|
$style = 'index';
|
||||||
case Cursor::HASH_ASSOC:
|
case Cursor::HASH_ASSOC:
|
||||||
if (is_int($key)) {
|
if (is_int($key)) {
|
||||||
@@ -332,13 +341,17 @@ class CliDumper extends AbstractDumper
|
|||||||
} elseif (0 < strpos($key, "\0", 1)) {
|
} elseif (0 < strpos($key, "\0", 1)) {
|
||||||
$key = explode("\0", substr($key, 1), 2);
|
$key = explode("\0", substr($key, 1), 2);
|
||||||
|
|
||||||
switch ($key[0]) {
|
switch ($key[0][0]) {
|
||||||
case '+': // User inserted keys
|
case '+': // User inserted keys
|
||||||
$attr['dynamic'] = true;
|
$attr['dynamic'] = true;
|
||||||
$this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
|
$this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
|
||||||
break 2;
|
break 2;
|
||||||
case '~':
|
case '~':
|
||||||
$style = 'meta';
|
$style = 'meta';
|
||||||
|
if (isset($key[0][1])) {
|
||||||
|
parse_str(substr($key[0], 1), $attr);
|
||||||
|
$attr += array('binary' => $cursor->hashKeyIsBinary);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
$style = 'protected';
|
$style = 'protected';
|
||||||
@@ -368,11 +381,11 @@ class CliDumper extends AbstractDumper
|
|||||||
/**
|
/**
|
||||||
* Decorates a value with some style.
|
* Decorates a value with some style.
|
||||||
*
|
*
|
||||||
* @param string $style The type of style being applied.
|
* @param string $style The type of style being applied
|
||||||
* @param string $value The value being styled.
|
* @param string $value The value being styled
|
||||||
* @param array $attr Optional context information.
|
* @param array $attr Optional context information
|
||||||
*
|
*
|
||||||
* @return string The value with style decoration.
|
* @return string The value with style decoration
|
||||||
*/
|
*/
|
||||||
protected function style($style, $value, $attr = array())
|
protected function style($style, $value, $attr = array())
|
||||||
{
|
{
|
||||||
@@ -412,7 +425,7 @@ class CliDumper extends AbstractDumper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool Tells if the current output stream supports ANSI colors or not.
|
* @return bool Tells if the current output stream supports ANSI colors or not
|
||||||
*/
|
*/
|
||||||
protected function supportsColors()
|
protected function supportsColors()
|
||||||
{
|
{
|
||||||
@@ -446,7 +459,12 @@ class CliDumper extends AbstractDumper
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||||
static::$defaultColors = @(false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'));
|
static::$defaultColors = @(
|
||||||
|
'10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
|
||||||
|
|| false !== getenv('ANSICON')
|
||||||
|
|| 'ON' === getenv('ConEmuANSI')
|
||||||
|
|| 'xterm' === getenv('TERM')
|
||||||
|
);
|
||||||
} elseif (function_exists('posix_isatty')) {
|
} elseif (function_exists('posix_isatty')) {
|
||||||
$h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null);
|
$h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null);
|
||||||
$h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream;
|
$h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interface DataDumperInterface
|
|||||||
/**
|
/**
|
||||||
* Dumps a Data object.
|
* Dumps a Data object.
|
||||||
*
|
*
|
||||||
* @param Data $data A Data object.
|
* @param Data $data A Data object
|
||||||
*/
|
*/
|
||||||
public function dump(Data $data);
|
public function dump(Data $data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ class HtmlDumper extends CliDumper
|
|||||||
|
|
||||||
protected $dumpHeader;
|
protected $dumpHeader;
|
||||||
protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
|
protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
|
||||||
protected $dumpSuffix = '</pre><script>Sfdump("%s")</script>';
|
protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';
|
||||||
protected $dumpId = 'sf-dump';
|
protected $dumpId = 'sf-dump';
|
||||||
protected $colors = true;
|
protected $colors = true;
|
||||||
protected $headerIsDumped = false;
|
protected $headerIsDumped = false;
|
||||||
protected $lastDepth = -1;
|
protected $lastDepth = -1;
|
||||||
protected $styles = array(
|
protected $styles = array(
|
||||||
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:100000; word-break: normal',
|
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: normal',
|
||||||
'num' => 'font-weight:bold; color:#1299DA',
|
'num' => 'font-weight:bold; color:#1299DA',
|
||||||
'const' => 'font-weight:bold',
|
'const' => 'font-weight:bold',
|
||||||
'str' => 'font-weight:bold; color:#56DB3A',
|
'str' => 'font-weight:bold; color:#56DB3A',
|
||||||
@@ -43,27 +43,24 @@ class HtmlDumper extends CliDumper
|
|||||||
'meta' => 'color:#B729D9',
|
'meta' => 'color:#B729D9',
|
||||||
'key' => 'color:#56DB3A',
|
'key' => 'color:#56DB3A',
|
||||||
'index' => 'color:#1299DA',
|
'index' => 'color:#1299DA',
|
||||||
|
'ellipsis' => 'color:#FF8400',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private $displayOptions = array(
|
||||||
|
'maxDepth' => 1,
|
||||||
|
'maxStringLength' => 160,
|
||||||
|
'fileLinkFormat' => null,
|
||||||
|
);
|
||||||
|
private $extraDisplayOptions = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __construct($output = null, $charset = null)
|
public function __construct($output = null, $charset = null, $flags = 0)
|
||||||
{
|
{
|
||||||
AbstractDumper::__construct($output, $charset);
|
AbstractDumper::__construct($output, $charset, $flags);
|
||||||
$this->dumpId = 'sf-dump-'.mt_rand();
|
$this->dumpId = 'sf-dump-'.mt_rand();
|
||||||
}
|
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function setOutput($output)
|
|
||||||
{
|
|
||||||
if ($output !== $prev = parent::setOutput($output)) {
|
|
||||||
$this->headerIsDumped = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $prev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,10 +72,21 @@ class HtmlDumper extends CliDumper
|
|||||||
$this->styles = $styles + $this->styles;
|
$this->styles = $styles + $this->styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures display options.
|
||||||
|
*
|
||||||
|
* @param array $displayOptions A map of display options to customize the behavior
|
||||||
|
*/
|
||||||
|
public function setDisplayOptions(array $displayOptions)
|
||||||
|
{
|
||||||
|
$this->headerIsDumped = false;
|
||||||
|
$this->displayOptions = $displayOptions + $this->displayOptions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an HTML header that will be dumped once in the output stream.
|
* Sets an HTML header that will be dumped once in the output stream.
|
||||||
*
|
*
|
||||||
* @param string $header An HTML string.
|
* @param string $header An HTML string
|
||||||
*/
|
*/
|
||||||
public function setDumpHeader($header)
|
public function setDumpHeader($header)
|
||||||
{
|
{
|
||||||
@@ -88,8 +96,8 @@ class HtmlDumper extends CliDumper
|
|||||||
/**
|
/**
|
||||||
* Sets an HTML prefix and suffix that will encapse every single dump.
|
* Sets an HTML prefix and suffix that will encapse every single dump.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prepended HTML string.
|
* @param string $prefix The prepended HTML string
|
||||||
* @param string $suffix The appended HTML string.
|
* @param string $suffix The appended HTML string
|
||||||
*/
|
*/
|
||||||
public function setDumpBoundaries($prefix, $suffix)
|
public function setDumpBoundaries($prefix, $suffix)
|
||||||
{
|
{
|
||||||
@@ -100,10 +108,13 @@ class HtmlDumper extends CliDumper
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function dump(Data $data, $output = null)
|
public function dump(Data $data, $output = null, array $extraDisplayOptions = array())
|
||||||
{
|
{
|
||||||
parent::dump($data, $output);
|
$this->extraDisplayOptions = $extraDisplayOptions;
|
||||||
|
$result = parent::dump($data, $output);
|
||||||
$this->dumpId = 'sf-dump-'.mt_rand();
|
$this->dumpId = 'sf-dump-'.mt_rand();
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,13 +122,13 @@ class HtmlDumper extends CliDumper
|
|||||||
*/
|
*/
|
||||||
protected function getDumpHeader()
|
protected function getDumpHeader()
|
||||||
{
|
{
|
||||||
$this->headerIsDumped = true;
|
$this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
|
||||||
|
|
||||||
if (null !== $this->dumpHeader) {
|
if (null !== $this->dumpHeader) {
|
||||||
return $this->dumpHeader;
|
return $this->dumpHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
$line = <<<'EOHTML'
|
$line = str_replace('{$options}', json_encode($this->displayOptions, JSON_FORCE_OBJECT), <<<'EOHTML'
|
||||||
<script>
|
<script>
|
||||||
Sfdump = window.Sfdump || (function (doc) {
|
Sfdump = window.Sfdump || (function (doc) {
|
||||||
|
|
||||||
@@ -173,15 +184,30 @@ function toggle(a, recursive) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
return function (root) {
|
return function (root, x) {
|
||||||
root = doc.getElementById(root);
|
root = doc.getElementById(root);
|
||||||
|
|
||||||
|
var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
|
||||||
|
options = {$options},
|
||||||
|
elt = root.getElementsByTagName('A'),
|
||||||
|
len = elt.length,
|
||||||
|
i = 0, s, h,
|
||||||
|
t = [];
|
||||||
|
|
||||||
|
while (i < len) t.push(elt[i++]);
|
||||||
|
|
||||||
|
for (i in x) {
|
||||||
|
options[i] = x[i];
|
||||||
|
}
|
||||||
|
|
||||||
function a(e, f) {
|
function a(e, f) {
|
||||||
addEventListener(root, e, function (e) {
|
addEventListener(root, e, function (e) {
|
||||||
if ('A' == e.target.tagName) {
|
if ('A' == e.target.tagName) {
|
||||||
f(e.target, e);
|
f(e.target, e);
|
||||||
} else if ('A' == e.target.parentNode.tagName) {
|
} else if ('A' == e.target.parentNode.tagName) {
|
||||||
f(e.target.parentNode, e);
|
f(e.target.parentNode, e);
|
||||||
|
} else if (e.target.nextElementSibling && 'A' == e.target.nextElementSibling.tagName) {
|
||||||
|
f(e.target.nextElementSibling, e, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -193,15 +219,17 @@ return function (root) {
|
|||||||
refStyle.innerHTML = '';
|
refStyle.innerHTML = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
a('mouseover', function (a) {
|
a('mouseover', function (a, e, c) {
|
||||||
if (a = idRx.exec(a.className)) {
|
if (c) {
|
||||||
|
e.target.style.cursor = "pointer";
|
||||||
|
} else if (a = idRx.exec(a.className)) {
|
||||||
try {
|
try {
|
||||||
refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';
|
refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
a('click', function (a, e) {
|
a('click', function (a, e, c) {
|
||||||
if (/\bsf-dump-toggle\b/.test(a.className)) {
|
if (/\bsf-dump-toggle\b/.test(a.className)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!toggle(a, isCtrlKey(e))) {
|
if (!toggle(a, isCtrlKey(e))) {
|
||||||
@@ -222,7 +250,8 @@ return function (root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.getSelection) {
|
if (c) {
|
||||||
|
} else if (doc.getSelection) {
|
||||||
try {
|
try {
|
||||||
doc.getSelection().removeAllRanges();
|
doc.getSelection().removeAllRanges();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -231,31 +260,24 @@ return function (root) {
|
|||||||
} else {
|
} else {
|
||||||
doc.selection.empty();
|
doc.selection.empty();
|
||||||
}
|
}
|
||||||
|
} else if (/\bsf-dump-str-toggle\b/.test(a.className)) {
|
||||||
|
e.preventDefault();
|
||||||
|
e = a.parentNode.parentNode;
|
||||||
|
e.className = e.className.replace(/sf-dump-str-(expand|collapse)/, a.parentNode.className);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
|
|
||||||
elt = root.getElementsByTagName('A'),
|
|
||||||
len = elt.length,
|
|
||||||
i = 0,
|
|
||||||
t = [];
|
|
||||||
|
|
||||||
while (i < len) t.push(elt[i++]);
|
|
||||||
|
|
||||||
elt = root.getElementsByTagName('SAMP');
|
elt = root.getElementsByTagName('SAMP');
|
||||||
len = elt.length;
|
len = elt.length;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
while (i < len) t.push(elt[i++]);
|
while (i < len) t.push(elt[i++]);
|
||||||
|
|
||||||
root = t;
|
|
||||||
len = t.length;
|
len = t.length;
|
||||||
i = t = 0;
|
|
||||||
|
|
||||||
while (i < len) {
|
for (i = 0; i < len; ++i) {
|
||||||
elt = root[i];
|
elt = t[i];
|
||||||
if ("SAMP" == elt.tagName) {
|
if ('SAMP' == elt.tagName) {
|
||||||
elt.className = "sf-dump-expanded";
|
elt.className = 'sf-dump-expanded';
|
||||||
a = elt.previousSibling || {};
|
a = elt.previousSibling || {};
|
||||||
if ('A' != a.tagName) {
|
if ('A' != a.tagName) {
|
||||||
a = doc.createElement('A');
|
a = doc.createElement('A');
|
||||||
@@ -267,19 +289,24 @@ return function (root) {
|
|||||||
a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
|
a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
|
||||||
a.innerHTML += '<span>▼</span>';
|
a.innerHTML += '<span>▼</span>';
|
||||||
a.className += ' sf-dump-toggle';
|
a.className += ' sf-dump-toggle';
|
||||||
|
x = 1;
|
||||||
if ('sf-dump' != elt.parentNode.className) {
|
if ('sf-dump' != elt.parentNode.className) {
|
||||||
|
x += elt.parentNode.getAttribute('data-depth')/1;
|
||||||
|
}
|
||||||
|
elt.setAttribute('data-depth', x);
|
||||||
|
if (x > options.maxDepth) {
|
||||||
toggle(a);
|
toggle(a);
|
||||||
}
|
}
|
||||||
} else if ("sf-dump-ref" == elt.className && (a = elt.getAttribute('href'))) {
|
} else if ('sf-dump-ref' == elt.className && (a = elt.getAttribute('href'))) {
|
||||||
a = a.substr(1);
|
a = a.substr(1);
|
||||||
elt.className += ' '+a;
|
elt.className += ' '+a;
|
||||||
|
|
||||||
if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
|
if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
|
||||||
a = a != elt.nextSibling.id && doc.getElementById(a);
|
a = a != elt.nextSibling.id && doc.getElementById(a);
|
||||||
try {
|
try {
|
||||||
t = a.nextSibling;
|
s = a.nextSibling;
|
||||||
elt.appendChild(a);
|
elt.appendChild(a);
|
||||||
t.parentNode.insertBefore(a, t);
|
s.parentNode.insertBefore(a, s);
|
||||||
if (/^[@#]/.test(elt.innerHTML)) {
|
if (/^[@#]/.test(elt.innerHTML)) {
|
||||||
elt.innerHTML += ' <span>▶</span>';
|
elt.innerHTML += ' <span>▶</span>';
|
||||||
} else {
|
} else {
|
||||||
@@ -295,13 +322,38 @@ return function (root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++i;
|
}
|
||||||
|
|
||||||
|
if (0 >= options.maxStringLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
elt = root.querySelectorAll('.sf-dump-str');
|
||||||
|
len = elt.length;
|
||||||
|
i = 0;
|
||||||
|
t = [];
|
||||||
|
|
||||||
|
while (i < len) t.push(elt[i++]);
|
||||||
|
len = t.length;
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
elt = t[i];
|
||||||
|
s = elt.innerText || elt.textContent;
|
||||||
|
x = s.length - options.maxStringLength;
|
||||||
|
if (0 < x) {
|
||||||
|
h = elt.innerHTML;
|
||||||
|
elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);
|
||||||
|
elt.className += ' sf-dump-str-collapse';
|
||||||
|
elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+
|
||||||
|
'<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})(document);
|
})(document);
|
||||||
</script>
|
</script><style>
|
||||||
<style>
|
|
||||||
pre.sf-dump {
|
pre.sf-dump {
|
||||||
display: block;
|
display: block;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
@@ -323,11 +375,33 @@ pre.sf-dump a {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
EOHTML;
|
pre.sf-dump .sf-dump-ellipsis {
|
||||||
|
display: inline-block;
|
||||||
|
overflow: visible;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 5em;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
pre.sf-dump code {
|
||||||
|
display:inline;
|
||||||
|
padding:0;
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
.sf-dump-str-collapse .sf-dump-str-collapse {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.sf-dump-str-expand .sf-dump-str-expand {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
EOHTML
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($this->styles as $class => $style) {
|
foreach ($this->styles as $class => $style) {
|
||||||
$line .= 'pre.sf-dump'.('default' !== $class ? ' .sf-dump-'.$class : '').'{'.$style.'}';
|
$line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
||||||
@@ -374,7 +448,7 @@ EOHTML;
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$v = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
$v = esc($value);
|
||||||
|
|
||||||
if ('ref' === $style) {
|
if ('ref' === $style) {
|
||||||
if (empty($attr['count'])) {
|
if (empty($attr['count'])) {
|
||||||
@@ -385,41 +459,47 @@ EOHTML;
|
|||||||
return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
|
return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('const' === $style && array_key_exists('value', $attr)) {
|
if ('const' === $style && isset($attr['value'])) {
|
||||||
$style .= sprintf(' title="%s"', htmlspecialchars(json_encode($attr['value']), ENT_QUOTES, 'UTF-8'));
|
$style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
|
||||||
} elseif ('public' === $style) {
|
} elseif ('public' === $style) {
|
||||||
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
|
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
|
||||||
} elseif ('str' === $style && 1 < $attr['length']) {
|
} elseif ('str' === $style && 1 < $attr['length']) {
|
||||||
$style .= sprintf(' title="%s%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
|
$style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
|
||||||
} elseif ('note' === $style && false !== $c = strrpos($v, '\\')) {
|
} elseif ('note' === $style && false !== $c = strrpos($v, '\\')) {
|
||||||
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $v, $style, substr($v, $c + 1));
|
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $v, $style, substr($v, $c + 1));
|
||||||
} elseif ('protected' === $style) {
|
} elseif ('protected' === $style) {
|
||||||
$style .= ' title="Protected property"';
|
$style .= ' title="Protected property"';
|
||||||
|
} elseif ('meta' === $style && isset($attr['title'])) {
|
||||||
|
$style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title'])));
|
||||||
} elseif ('private' === $style) {
|
} elseif ('private' === $style) {
|
||||||
$style .= sprintf(' title="Private property defined in class: `%s`"', $attr['class']);
|
$style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class'])));
|
||||||
|
}
|
||||||
|
$map = static::$controlCharsMap;
|
||||||
|
|
||||||
|
if (isset($attr['ellipsis'])) {
|
||||||
|
$label = esc(substr($value, -$attr['ellipsis']));
|
||||||
|
$style = str_replace(' title="', " title=\"$v\n", $style);
|
||||||
|
$v = sprintf('<span class=sf-dump-ellipsis>%s</span>%s', substr($v, 0, -strlen($label)), $label);
|
||||||
}
|
}
|
||||||
|
|
||||||
$map = static::$controlCharsMap;
|
$v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
|
||||||
$style = "<span class=sf-dump-{$style}>";
|
$s = '<span class=sf-dump-default>';
|
||||||
$v = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $style) {
|
|
||||||
$s = '</span>';
|
|
||||||
$c = $c[$i = 0];
|
$c = $c[$i = 0];
|
||||||
do {
|
do {
|
||||||
$s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', ord($c[$i]));
|
$s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', ord($c[$i]));
|
||||||
} while (isset($c[++$i]));
|
} while (isset($c[++$i]));
|
||||||
|
|
||||||
return $s.$style;
|
return $s.'</span>';
|
||||||
}, $v, -1, $cchrCount);
|
}, $v).'</span>';
|
||||||
|
|
||||||
if ($cchrCount && '<' === $v[0]) {
|
if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) {
|
||||||
$v = substr($v, 7);
|
$attr['href'] = $href;
|
||||||
} else {
|
|
||||||
$v = $style.$v;
|
|
||||||
}
|
}
|
||||||
if ($cchrCount && '>' === substr($v, -1)) {
|
if (isset($attr['href'])) {
|
||||||
$v = substr($v, 0, -strlen($style));
|
$v = sprintf('<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $v);
|
||||||
} else {
|
}
|
||||||
$v .= '</span>';
|
if (isset($attr['lang'])) {
|
||||||
|
$v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $v;
|
return $v;
|
||||||
@@ -433,12 +513,17 @@ EOHTML;
|
|||||||
if (-1 === $this->lastDepth) {
|
if (-1 === $this->lastDepth) {
|
||||||
$this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;
|
$this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;
|
||||||
}
|
}
|
||||||
if (!$this->headerIsDumped) {
|
if ($this->headerIsDumped !== (null !== $this->outputStream ? $this->outputStream : $this->lineDumper)) {
|
||||||
$this->line = $this->getDumpHeader().$this->line;
|
$this->line = $this->getDumpHeader().$this->line;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 === $depth) {
|
if (-1 === $depth) {
|
||||||
$this->line .= sprintf($this->dumpSuffix, $this->dumpId);
|
$args = array('"'.$this->dumpId.'"');
|
||||||
|
if ($this->extraDisplayOptions) {
|
||||||
|
$args[] = json_encode($this->extraDisplayOptions, JSON_FORCE_OBJECT);
|
||||||
|
}
|
||||||
|
// Replace is for BC
|
||||||
|
$this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args));
|
||||||
}
|
}
|
||||||
$this->lastDepth = $depth;
|
$this->lastDepth = $depth;
|
||||||
|
|
||||||
@@ -449,4 +534,20 @@ EOHTML;
|
|||||||
}
|
}
|
||||||
AbstractDumper::dumpLine($depth);
|
AbstractDumper::dumpLine($depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getSourceLink($file, $line)
|
||||||
|
{
|
||||||
|
$options = $this->extraDisplayOptions + $this->displayOptions;
|
||||||
|
|
||||||
|
if ($fmt = $options['fileLinkFormat']) {
|
||||||
|
return is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function esc($str)
|
||||||
|
{
|
||||||
|
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2014-2015 Fabien Potencier
|
Copyright (c) 2014-2017 Fabien Potencier
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
Symfony mechanism for exploring and dumping PHP variables
|
VarDumper Component
|
||||||
=========================================================
|
===================
|
||||||
|
|
||||||
This component provides a mechanism that allows exploring then dumping
|
The VarDumper component provides mechanisms for walking through any arbitrary
|
||||||
any PHP variable.
|
PHP variable. Built on top, it provides a better `dump()` function that you
|
||||||
|
can use instead of `var_dump`.
|
||||||
|
|
||||||
It handles scalars, objects and resources properly, taking hard and soft
|
Resources
|
||||||
references into account. More than being immune to infinite recursion
|
---------
|
||||||
problems, it allows dumping where references link to each other.
|
|
||||||
It explores recursive structures using a breadth-first algorithm.
|
|
||||||
|
|
||||||
The component exposes all the parts involved in the different steps of
|
* [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)
|
||||||
cloning then dumping a PHP variable, while applying size limits and having
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
specialized output formats and methods.
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||||
|
|||||||
@@ -29,17 +29,20 @@ trait VarDumperTestTrait
|
|||||||
$this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message);
|
$this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDump($data)
|
protected function getDump($data, $key = null)
|
||||||
{
|
{
|
||||||
$h = fopen('php://memory', 'r+b');
|
$flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0;
|
||||||
|
$flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0;
|
||||||
|
|
||||||
$cloner = new VarCloner();
|
$cloner = new VarCloner();
|
||||||
$cloner->setMaxItems(-1);
|
$cloner->setMaxItems(-1);
|
||||||
$dumper = new CliDumper($h);
|
$dumper = new CliDumper(null, null, $flags);
|
||||||
$dumper->setColors(false);
|
$dumper->setColors(false);
|
||||||
$dumper->dump($cloner->cloneVar($data)->withRefHandles(false));
|
$data = $cloner->cloneVar($data)->withRefHandles(false);
|
||||||
$data = stream_get_contents($h, -1, 0);
|
if (null !== $key && null === $data = $data->seek($key)) {
|
||||||
fclose($h);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return rtrim($data);
|
return rtrim($dumper->dump($data, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,14 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests\Caster;
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Caster\Caster;
|
use Symfony\Component\VarDumper\Caster\Caster;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class CasterTest extends \PHPUnit_Framework_TestCase
|
class CasterTest extends TestCase
|
||||||
{
|
{
|
||||||
use VarDumperTestTrait;
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
|
||||||
|
use Symfony\Component\VarDumper\Caster\FrameStub;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
|
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
|
class ExceptionCasterTest extends TestCase
|
||||||
|
{
|
||||||
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
private function getTestException($msg, &$ref = null)
|
||||||
|
{
|
||||||
|
return new \Exception(''.$msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
ExceptionCaster::$srcContext = 1;
|
||||||
|
ExceptionCaster::$traceArgs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultSettings()
|
||||||
|
{
|
||||||
|
$ref = array('foo');
|
||||||
|
$e = $this->getTestException('foo', $ref);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
Exception {
|
||||||
|
#message: "foo"
|
||||||
|
#code: 0
|
||||||
|
#file: "%sExceptionCasterTest.php"
|
||||||
|
#line: 27
|
||||||
|
-trace: {
|
||||||
|
%sExceptionCasterTest.php:27: {
|
||||||
|
: {
|
||||||
|
: return new \Exception(''.$msg);
|
||||||
|
: }
|
||||||
|
}
|
||||||
|
%sExceptionCasterTest.php:%d: {
|
||||||
|
: $ref = array('foo');
|
||||||
|
: $e = $this->getTestException('foo', $ref);
|
||||||
|
:
|
||||||
|
arguments: {
|
||||||
|
$msg: "foo"
|
||||||
|
&$ref: array:1 [ …1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||||
|
$this->assertSame(array('foo'), $ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSeek()
|
||||||
|
{
|
||||||
|
$e = $this->getTestException(2);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
{
|
||||||
|
%sExceptionCasterTest.php:27: {
|
||||||
|
: {
|
||||||
|
: return new \Exception(''.$msg);
|
||||||
|
: }
|
||||||
|
}
|
||||||
|
%sExceptionCasterTest.php:%d: {
|
||||||
|
: {
|
||||||
|
: $e = $this->getTestException(2);
|
||||||
|
:
|
||||||
|
arguments: {
|
||||||
|
$msg: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $this->getDump($e, 'trace'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoArgs()
|
||||||
|
{
|
||||||
|
$e = $this->getTestException(1);
|
||||||
|
ExceptionCaster::$traceArgs = false;
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
Exception {
|
||||||
|
#message: "1"
|
||||||
|
#code: 0
|
||||||
|
#file: "%sExceptionCasterTest.php"
|
||||||
|
#line: 27
|
||||||
|
-trace: {
|
||||||
|
%sExceptionCasterTest.php:27: {
|
||||||
|
: {
|
||||||
|
: return new \Exception(''.$msg);
|
||||||
|
: }
|
||||||
|
}
|
||||||
|
%sExceptionCasterTest.php:%d: {
|
||||||
|
: {
|
||||||
|
: $e = $this->getTestException(1);
|
||||||
|
: ExceptionCaster::$traceArgs = false;
|
||||||
|
}
|
||||||
|
%A
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoSrcContext()
|
||||||
|
{
|
||||||
|
$e = $this->getTestException(1);
|
||||||
|
ExceptionCaster::$srcContext = -1;
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
Exception {
|
||||||
|
#message: "1"
|
||||||
|
#code: 0
|
||||||
|
#file: "%sExceptionCasterTest.php"
|
||||||
|
#line: 27
|
||||||
|
-trace: {
|
||||||
|
%sExceptionCasterTest.php: 27
|
||||||
|
%sExceptionCasterTest.php: %d
|
||||||
|
%A
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHtmlDump()
|
||||||
|
{
|
||||||
|
$e = $this->getTestException(1);
|
||||||
|
ExceptionCaster::$srcContext = -1;
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$cloner->setMaxItems(1);
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$dump = $dumper->dump($cloner->cloneVar($e)->withRefHandles(false), true);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
<foo></foo><bar><span class=sf-dump-note>Exception</span> {<samp>
|
||||||
|
#<span class=sf-dump-protected title="Protected property">message</span>: "<span class=sf-dump-str>1</span>"
|
||||||
|
#<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span>
|
||||||
|
#<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%sExceptionCasterTest.php
|
||||||
|
%d characters"><span class=sf-dump-ellipsis>%sTests</span>%eCaster%eExceptionCasterTest.php</span>"
|
||||||
|
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>27</span>
|
||||||
|
-<span class=sf-dump-private title="Private property defined in class: `Exception`">trace</span>: {<samp>
|
||||||
|
<span class=sf-dump-meta title="%sExceptionCasterTest.php
|
||||||
|
Stack level %d."><span class=sf-dump-ellipsis>%sVarDumper%eTests</span>%eCaster%eExceptionCasterTest.php</span>: <span class=sf-dump-num>27</span>
|
||||||
|
…%d
|
||||||
|
</samp>}
|
||||||
|
</samp>}
|
||||||
|
</bar>
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function Twig\Template::getSourceContext
|
||||||
|
*/
|
||||||
|
public function testFrameWithTwig()
|
||||||
|
{
|
||||||
|
require_once dirname(__DIR__).'/Fixtures/Twig.php';
|
||||||
|
|
||||||
|
$f = array(
|
||||||
|
new FrameStub(array(
|
||||||
|
'file' => dirname(__DIR__).'/Fixtures/Twig.php',
|
||||||
|
'line' => 20,
|
||||||
|
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
|
||||||
|
)),
|
||||||
|
new FrameStub(array(
|
||||||
|
'file' => dirname(__DIR__).'/Fixtures/Twig.php',
|
||||||
|
'line' => 21,
|
||||||
|
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
|
||||||
|
'object' => new \__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
array:2 [
|
||||||
|
0 => {
|
||||||
|
class: "__TwigTemplate_VarDumperFixture_u75a09"
|
||||||
|
src: {
|
||||||
|
%sTwig.php:1: {
|
||||||
|
:
|
||||||
|
: foo bar
|
||||||
|
: twig source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
class: "__TwigTemplate_VarDumperFixture_u75a09"
|
||||||
|
object: __TwigTemplate_VarDumperFixture_u75a09 {
|
||||||
|
%A
|
||||||
|
}
|
||||||
|
src: {
|
||||||
|
%sExceptionCasterTest.php:2: {
|
||||||
|
: foo bar
|
||||||
|
: twig source
|
||||||
|
:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,14 +11,18 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests\Caster;
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Caster\PdoCaster;
|
use Symfony\Component\VarDumper\Caster\PdoCaster;
|
||||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class PdoCasterTest extends \PHPUnit_Framework_TestCase
|
class PdoCasterTest extends TestCase
|
||||||
{
|
{
|
||||||
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @requires extension pdo_sqlite
|
* @requires extension pdo_sqlite
|
||||||
*/
|
*/
|
||||||
@@ -36,22 +40,25 @@ class PdoCasterTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame('NATURAL', $attr['CASE']->class);
|
$this->assertSame('NATURAL', $attr['CASE']->class);
|
||||||
$this->assertSame('BOTH', $attr['DEFAULT_FETCH_MODE']->class);
|
$this->assertSame('BOTH', $attr['DEFAULT_FETCH_MODE']->class);
|
||||||
|
|
||||||
$xCast = array(
|
$xDump = <<<'EODUMP'
|
||||||
"\0~\0inTransaction" => $pdo->inTransaction(),
|
array:2 [
|
||||||
"\0~\0attributes" => array(
|
"\x00~\x00inTransaction" => false
|
||||||
'CASE' => $attr['CASE'],
|
"\x00~\x00attributes" => array:9 [
|
||||||
'ERRMODE' => $attr['ERRMODE'],
|
"CASE" => NATURAL
|
||||||
'PERSISTENT' => false,
|
"ERRMODE" => SILENT
|
||||||
'DRIVER_NAME' => 'sqlite',
|
"PERSISTENT" => false
|
||||||
'ORACLE_NULLS' => $attr['ORACLE_NULLS'],
|
"DRIVER_NAME" => "sqlite"
|
||||||
'CLIENT_VERSION' => $pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION),
|
"ORACLE_NULLS" => NATURAL
|
||||||
'SERVER_VERSION' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION),
|
"CLIENT_VERSION" => "%s"
|
||||||
'STATEMENT_CLASS' => array('PDOStatement'),
|
"SERVER_VERSION" => "%s"
|
||||||
'DEFAULT_FETCH_MODE' => $attr['DEFAULT_FETCH_MODE'],
|
"STATEMENT_CLASS" => array:%d [
|
||||||
),
|
0 => "PDOStatement"%A
|
||||||
);
|
]
|
||||||
unset($cast["\0~\0attributes"]['STATEMENT_CLASS'][1]);
|
"DEFAULT_FETCH_MODE" => BOTH
|
||||||
|
]
|
||||||
|
]
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
$this->assertSame($xCast, $cast);
|
$this->assertDumpMatchesFormat($xDump, $cast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
* @requires extension redis
|
||||||
|
*/
|
||||||
|
class RedisCasterTest extends TestCase
|
||||||
|
{
|
||||||
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
public function testNotConnected()
|
||||||
|
{
|
||||||
|
$redis = new \Redis();
|
||||||
|
|
||||||
|
if (defined('HHVM_VERSION_ID')) {
|
||||||
|
$xCast = <<<'EODUMP'
|
||||||
|
Redis {
|
||||||
|
#host: ""
|
||||||
|
%A
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
} else {
|
||||||
|
$xCast = <<<'EODUMP'
|
||||||
|
Redis {
|
||||||
|
isConnected: false
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($xCast, $redis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConnected()
|
||||||
|
{
|
||||||
|
$redis = new \Redis();
|
||||||
|
if (!@$redis->connect('127.0.0.1')) {
|
||||||
|
$e = error_get_last();
|
||||||
|
self::markTestSkipped($e['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined('HHVM_VERSION_ID')) {
|
||||||
|
$xCast = <<<'EODUMP'
|
||||||
|
Redis {
|
||||||
|
#host: "127.0.0.1"
|
||||||
|
%A
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
} else {
|
||||||
|
$xCast = <<<'EODUMP'
|
||||||
|
Redis {
|
||||||
|
+"socket": Redis Socket Buffer resource
|
||||||
|
isConnected: true
|
||||||
|
host: "127.0.0.1"
|
||||||
|
port: 6379
|
||||||
|
auth: null
|
||||||
|
dbNum: 0
|
||||||
|
timeout: 0.0
|
||||||
|
persistentId: null
|
||||||
|
options: {
|
||||||
|
READ_TIMEOUT: 0.0
|
||||||
|
SERIALIZER: NONE
|
||||||
|
PREFIX: null
|
||||||
|
SCAN: NORETRY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($xCast, $redis);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,13 +11,15 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests\Caster;
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
|
use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
|
||||||
|
use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class ReflectionCasterTest extends \PHPUnit_Framework_TestCase
|
class ReflectionCasterTest extends TestCase
|
||||||
{
|
{
|
||||||
use VarDumperTestTrait;
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ ReflectionClass {
|
|||||||
"export" => ReflectionMethod {
|
"export" => ReflectionMethod {
|
||||||
+name: "export"
|
+name: "export"
|
||||||
+class: "ReflectionClass"
|
+class: "ReflectionClass"
|
||||||
parameters: {
|
%A parameters: {
|
||||||
$%s: ReflectionParameter {
|
$%s: ReflectionParameter {
|
||||||
%A position: 0
|
%A position: 0
|
||||||
%A
|
%A
|
||||||
@@ -75,7 +77,7 @@ Closure {
|
|||||||
\$b: & 123
|
\$b: & 123
|
||||||
}
|
}
|
||||||
file: "%sReflectionCasterTest.php"
|
file: "%sReflectionCasterTest.php"
|
||||||
line: "65 to 65"
|
line: "67 to 67"
|
||||||
}
|
}
|
||||||
EOTXT
|
EOTXT
|
||||||
, $var
|
, $var
|
||||||
@@ -91,7 +93,7 @@ EOTXT
|
|||||||
ReflectionParameter {
|
ReflectionParameter {
|
||||||
+name: "arg1"
|
+name: "arg1"
|
||||||
position: 0
|
position: 0
|
||||||
typeHint: "Symfony\Component\VarDumper\Tests\Caster\NotExistingClass"
|
typeHint: "Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass"
|
||||||
default: null
|
default: null
|
||||||
}
|
}
|
||||||
EOTXT
|
EOTXT
|
||||||
@@ -146,83 +148,88 @@ EOTXT
|
|||||||
*/
|
*/
|
||||||
public function testGenerator()
|
public function testGenerator()
|
||||||
{
|
{
|
||||||
$g = new GeneratorDemo();
|
if (extension_loaded('xdebug')) {
|
||||||
$g = $g->baz();
|
$this->markTestSkipped('xdebug is active');
|
||||||
$r = new \ReflectionGenerator($g);
|
}
|
||||||
|
|
||||||
$xDump = <<<'EODUMP'
|
$generator = new GeneratorDemo();
|
||||||
|
$generator = $generator->baz();
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
Generator {
|
Generator {
|
||||||
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
||||||
executing: {
|
executing: {
|
||||||
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): {
|
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): {
|
||||||
%sGeneratorDemo.php:14: """
|
%sGeneratorDemo.php:14: {
|
||||||
{\n
|
: {
|
||||||
yield from bar();\n
|
: yield from bar();
|
||||||
}\n
|
: }
|
||||||
"""
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
closed: false
|
||||||
}
|
}
|
||||||
EODUMP;
|
EODUMP;
|
||||||
|
|
||||||
$this->assertDumpMatchesFormat($xDump, $g);
|
$this->assertDumpMatchesFormat($expectedDump, $generator);
|
||||||
|
|
||||||
foreach ($g as $v) {
|
foreach ($generator as $v) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$xDump = <<<'EODUMP'
|
$expectedDump = <<<'EODUMP'
|
||||||
array:2 [
|
array:2 [
|
||||||
0 => ReflectionGenerator {
|
0 => ReflectionGenerator {
|
||||||
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
||||||
trace: {
|
trace: {
|
||||||
3. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() ==> yield(): {
|
%sGeneratorDemo.php:9: {
|
||||||
src: {
|
: {
|
||||||
%sGeneratorDemo.php:9: """
|
: yield 1;
|
||||||
{\n
|
: }
|
||||||
yield 1;\n
|
|
||||||
}\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
2. Symfony\Component\VarDumper\Tests\Fixtures\bar() ==> Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
|
%sGeneratorDemo.php:20: {
|
||||||
src: {
|
: {
|
||||||
%sGeneratorDemo.php:20: """
|
: yield from GeneratorDemo::foo();
|
||||||
{\n
|
: }
|
||||||
yield from GeneratorDemo::foo();\n
|
|
||||||
}\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
1. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() ==> Symfony\Component\VarDumper\Tests\Fixtures\bar(): {
|
%sGeneratorDemo.php:14: {
|
||||||
src: {
|
: {
|
||||||
%sGeneratorDemo.php:14: """
|
: yield from bar();
|
||||||
{\n
|
: }
|
||||||
yield from bar();\n
|
|
||||||
}\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
closed: false
|
||||||
}
|
}
|
||||||
1 => Generator {
|
1 => Generator {
|
||||||
executing: {
|
executing: {
|
||||||
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
|
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
|
||||||
%sGeneratorDemo.php:10: """
|
%sGeneratorDemo.php:10: {
|
||||||
yield 1;\n
|
: yield 1;
|
||||||
}\n
|
: }
|
||||||
\n
|
:
|
||||||
"""
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
closed: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
EODUMP;
|
EODUMP;
|
||||||
|
|
||||||
$this->assertDumpMatchesFormat($xDump, array($r, $r->getExecutingGenerator()));
|
$r = new \ReflectionGenerator($generator);
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, array($r, $r->getExecutingGenerator()));
|
||||||
|
|
||||||
|
foreach ($generator as $v) {
|
||||||
|
}
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
Generator {
|
||||||
|
closed: true
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $generator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reflectionParameterFixture(NotExistingClass $arg1 = null, $arg2)
|
function reflectionParameterFixture(NotLoadableClass $arg1 = null, $arg2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests\Caster;
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||||
*/
|
*/
|
||||||
class SplCasterTest extends \PHPUnit_Framework_TestCase
|
class SplCasterTest extends TestCase
|
||||||
{
|
{
|
||||||
use VarDumperTestTrait;
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
@@ -57,12 +58,6 @@ SplFileInfo {
|
|||||||
pathname: "https://google.com/about"
|
pathname: "https://google.com/about"
|
||||||
extension: ""
|
extension: ""
|
||||||
realPath: false
|
realPath: false
|
||||||
writable: false
|
|
||||||
readable: false
|
|
||||||
executable: false
|
|
||||||
file: false
|
|
||||||
dir: false
|
|
||||||
link: false
|
|
||||||
%A}
|
%A}
|
||||||
EOTXT
|
EOTXT
|
||||||
),
|
),
|
||||||
@@ -102,10 +97,10 @@ SplFileObject {
|
|||||||
file: true
|
file: true
|
||||||
dir: false
|
dir: false
|
||||||
link: false
|
link: false
|
||||||
%AcsvControl: array:2 [
|
%AcsvControl: array:%d [
|
||||||
0 => ","
|
0 => ","
|
||||||
1 => """
|
1 => """
|
||||||
]
|
%A]
|
||||||
flags: DROP_NEW_LINE|SKIP_EMPTY
|
flags: DROP_NEW_LINE|SKIP_EMPTY
|
||||||
maxLineLen: 0
|
maxLineLen: 0
|
||||||
fstat: array:26 [
|
fstat: array:26 [
|
||||||
@@ -123,4 +118,30 @@ SplFileObject {
|
|||||||
EOTXT;
|
EOTXT;
|
||||||
$this->assertDumpMatchesFormat($dump, $var);
|
$this->assertDumpMatchesFormat($dump, $var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideCastSplDoublyLinkedList
|
||||||
|
*/
|
||||||
|
public function testCastSplDoublyLinkedList($modeValue, $modeDump)
|
||||||
|
{
|
||||||
|
$var = new \SplDoublyLinkedList();
|
||||||
|
$var->setIteratorMode($modeValue);
|
||||||
|
$dump = <<<EOTXT
|
||||||
|
SplDoublyLinkedList {
|
||||||
|
%Amode: $modeDump
|
||||||
|
dllist: []
|
||||||
|
}
|
||||||
|
EOTXT;
|
||||||
|
$this->assertDumpMatchesFormat($dump, $var);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideCastSplDoublyLinkedList()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(\SplDoublyLinkedList::IT_MODE_FIFO, 'IT_MODE_FIFO | IT_MODE_KEEP'),
|
||||||
|
array(\SplDoublyLinkedList::IT_MODE_LIFO, 'IT_MODE_LIFO | IT_MODE_KEEP'),
|
||||||
|
array(\SplDoublyLinkedList::IT_MODE_FIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_FIFO | IT_MODE_DELETE'),
|
||||||
|
array(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\Caster\ArgsStub;
|
||||||
|
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||||
|
use Symfony\Component\VarDumper\Caster\LinkStub;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
|
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
use Symfony\Component\VarDumper\Tests\Fixtures\FooInterface;
|
||||||
|
|
||||||
|
class StubCasterTest extends TestCase
|
||||||
|
{
|
||||||
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
public function testArgsStubWithDefaults($foo = 234, $bar = 456)
|
||||||
|
{
|
||||||
|
$args = array(new ArgsStub(array(123), __FUNCTION__, __CLASS__));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
array:1 [
|
||||||
|
0 => {
|
||||||
|
$foo: 123
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArgsStubWithExtraArgs($foo = 234)
|
||||||
|
{
|
||||||
|
$args = array(new ArgsStub(array(123, 456), __FUNCTION__, __CLASS__));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
array:1 [
|
||||||
|
0 => {
|
||||||
|
$foo: 123
|
||||||
|
...: {
|
||||||
|
456
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArgsStubNoParamWithExtraArgs()
|
||||||
|
{
|
||||||
|
$args = array(new ArgsStub(array(123), __FUNCTION__, __CLASS__));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
array:1 [
|
||||||
|
0 => {
|
||||||
|
123
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArgsStubWithClosure()
|
||||||
|
{
|
||||||
|
$args = array(new ArgsStub(array(123), '{closure}', null));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
array:1 [
|
||||||
|
0 => {
|
||||||
|
123
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLinkStub()
|
||||||
|
{
|
||||||
|
$var = array(new LinkStub(__CLASS__, 0, __FILE__));
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$dumper->setDisplayOptions(array('fileLinkFormat' => '%f:%l'));
|
||||||
|
$dump = $dumper->dump($cloner->cloneVar($var), true);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
|
||||||
|
<span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:0" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="55 characters">Symfony\Component\VarDumper\Tests\Caster\StubCasterTest</span></a>"
|
||||||
|
</samp>]
|
||||||
|
</bar>
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClassStub()
|
||||||
|
{
|
||||||
|
$var = array(new ClassStub('hello', array(FooInterface::class, 'foo')));
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$dump = $dumper->dump($cloner->cloneVar($var), true, array('fileLinkFormat' => '%f:%l'));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
|
||||||
|
<span class=sf-dump-index>0</span> => "<a href="%sFooInterface.php:10" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="5 characters">hello</span></a>"
|
||||||
|
</samp>]
|
||||||
|
</bar>
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClassStubWithNotExistingClass()
|
||||||
|
{
|
||||||
|
$var = array(new ClassStub(NotExisting::class));
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$dump = $dumper->dump($cloner->cloneVar($var), true);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
|
||||||
|
<span class=sf-dump-index>0</span> => "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\Caster\NotExisting
|
||||||
|
52 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests\Caster</span>\NotExisting</span>"
|
||||||
|
</samp>]
|
||||||
|
</bar>
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClassStubWithNotExistingMethod()
|
||||||
|
{
|
||||||
|
$var = array(new ClassStub('hello', array(FooInterface::class, 'missing')));
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$dump = $dumper->dump($cloner->cloneVar($var), true, array('fileLinkFormat' => '%f:%l'));
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
|
||||||
|
<span class=sf-dump-index>0</span> => "<a href="%sFooInterface.php:5" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="5 characters">hello</span></a>"
|
||||||
|
</samp>]
|
||||||
|
</bar>
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertStringMatchesFormat($expectedDump, $dump);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Baptiste Clavié <clavie.b@gmail.com>
|
||||||
|
*/
|
||||||
|
class XmlReaderCasterTest extends TestCase
|
||||||
|
{
|
||||||
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
/** @var \XmlReader */
|
||||||
|
private $reader;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->reader = new \XmlReader();
|
||||||
|
$this->reader->open(__DIR__.'/../Fixtures/xml_reader.xml');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->reader->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testParserProperty()
|
||||||
|
{
|
||||||
|
$this->reader->setParserProperty(\XMLReader::SUBST_ENTITIES, true);
|
||||||
|
|
||||||
|
$expectedDump = <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+nodeType: NONE
|
||||||
|
parserProperties: {
|
||||||
|
SUBST_ENTITIES: true
|
||||||
|
…3
|
||||||
|
}
|
||||||
|
…12
|
||||||
|
}
|
||||||
|
EODUMP;
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $this->reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideNodes
|
||||||
|
*/
|
||||||
|
public function testNodes($seek, $expectedDump)
|
||||||
|
{
|
||||||
|
while ($seek--) {
|
||||||
|
$this->reader->read();
|
||||||
|
}
|
||||||
|
$this->assertDumpMatchesFormat($expectedDump, $this->reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideNodes()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(0, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+nodeType: NONE
|
||||||
|
…13
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(1, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "foo"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…11
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(2, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "#text"
|
||||||
|
+nodeType: SIGNIFICANT_WHITESPACE
|
||||||
|
+depth: 1
|
||||||
|
+value: """
|
||||||
|
\n
|
||||||
|
|
||||||
|
"""
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(3, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…10
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(4, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: END_ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…10
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(6, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+isEmptyElement: true
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(9, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "#text"
|
||||||
|
+nodeType: TEXT
|
||||||
|
+depth: 2
|
||||||
|
+value: "With text"
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(12, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+attributeCount: 2
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(13, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: END_ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…10
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(15, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "bar"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+depth: 1
|
||||||
|
+attributeCount: 1
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(16, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "#text"
|
||||||
|
+nodeType: SIGNIFICANT_WHITESPACE
|
||||||
|
+depth: 2
|
||||||
|
+value: """
|
||||||
|
\n
|
||||||
|
|
||||||
|
"""
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(17, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "baz"
|
||||||
|
+prefix: "baz"
|
||||||
|
+nodeType: ELEMENT
|
||||||
|
+depth: 2
|
||||||
|
+namespaceURI: "http://symfony.com"
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…8
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(18, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "baz"
|
||||||
|
+prefix: "baz"
|
||||||
|
+nodeType: END_ELEMENT
|
||||||
|
+depth: 2
|
||||||
|
+namespaceURI: "http://symfony.com"
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…8
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(19, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "#text"
|
||||||
|
+nodeType: SIGNIFICANT_WHITESPACE
|
||||||
|
+depth: 2
|
||||||
|
+value: """
|
||||||
|
\n
|
||||||
|
|
||||||
|
"""
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(21, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "#text"
|
||||||
|
+nodeType: SIGNIFICANT_WHITESPACE
|
||||||
|
+depth: 1
|
||||||
|
+value: "\n"
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…9
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
array(22, <<<'EODUMP'
|
||||||
|
XMLReader {
|
||||||
|
+localName: "foo"
|
||||||
|
+nodeType: END_ELEMENT
|
||||||
|
+baseURI: "%sxml_reader.xml"
|
||||||
|
…11
|
||||||
|
}
|
||||||
|
EODUMP
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,14 +11,17 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests;
|
namespace Symfony\Component\VarDumper\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
use Twig\Environment;
|
||||||
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class CliDumperTest extends \PHPUnit_Framework_TestCase
|
class CliDumperTest extends TestCase
|
||||||
{
|
{
|
||||||
use VarDumperTestTrait;
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
@@ -62,15 +65,12 @@ array:24 [
|
|||||||
7 => b"é\\x00"
|
7 => b"é\\x00"
|
||||||
"[]" => []
|
"[]" => []
|
||||||
"res" => stream resource {@{$res}
|
"res" => stream resource {@{$res}
|
||||||
wrapper_type: "plainfile"
|
%A wrapper_type: "plainfile"
|
||||||
stream_type: "STDIO"
|
stream_type: "STDIO"
|
||||||
mode: "r"
|
mode: "r"
|
||||||
unread_bytes: 0
|
unread_bytes: 0
|
||||||
seekable: true
|
seekable: true
|
||||||
timed_out: false
|
%A options: []
|
||||||
blocked: true
|
|
||||||
eof: false
|
|
||||||
options: []
|
|
||||||
}
|
}
|
||||||
"obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d
|
"obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d
|
||||||
+foo: "foo"
|
+foo: "foo"
|
||||||
@@ -118,7 +118,7 @@ EOTXT
|
|||||||
$var = xml_parser_create();
|
$var = xml_parser_create();
|
||||||
|
|
||||||
$this->assertDumpMatchesFormat(
|
$this->assertDumpMatchesFormat(
|
||||||
<<<EOTXT
|
<<<'EOTXT'
|
||||||
xml resource {
|
xml resource {
|
||||||
current_byte_index: %i
|
current_byte_index: %i
|
||||||
current_column_number: %i
|
current_column_number: %i
|
||||||
@@ -131,6 +131,72 @@ EOTXT
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testJsonCast()
|
||||||
|
{
|
||||||
|
$var = (array) json_decode('{"0":{},"1":null}');
|
||||||
|
foreach ($var as &$v) {
|
||||||
|
}
|
||||||
|
$var[] = &$v;
|
||||||
|
$var[''] = 2;
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID >= 70200) {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
array:4 [
|
||||||
|
0 => {}
|
||||||
|
1 => &1 null
|
||||||
|
2 => &1 null
|
||||||
|
"" => 2
|
||||||
|
]
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
array:4 [
|
||||||
|
"0" => {}
|
||||||
|
"1" => &1 null
|
||||||
|
0 => &1 null
|
||||||
|
"" => 2
|
||||||
|
]
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testObjectCast()
|
||||||
|
{
|
||||||
|
$var = (object) array(1 => 1);
|
||||||
|
$var->{1} = 2;
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID >= 70200) {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
{
|
||||||
|
+"1": 2
|
||||||
|
}
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
{
|
||||||
|
+1: 1
|
||||||
|
+"1": 2
|
||||||
|
}
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testClosedResource()
|
public function testClosedResource()
|
||||||
{
|
{
|
||||||
if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {
|
if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {
|
||||||
@@ -152,7 +218,7 @@ EOTXT
|
|||||||
|
|
||||||
$this->assertStringMatchesFormat(
|
$this->assertStringMatchesFormat(
|
||||||
<<<EOTXT
|
<<<EOTXT
|
||||||
Unknown resource @{$res}
|
Closed resource @{$res}
|
||||||
|
|
||||||
EOTXT
|
EOTXT
|
||||||
,
|
,
|
||||||
@@ -160,12 +226,47 @@ EOTXT
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFlags()
|
||||||
|
{
|
||||||
|
putenv('DUMP_LIGHT_ARRAY=1');
|
||||||
|
putenv('DUMP_STRING_LENGTH=1');
|
||||||
|
|
||||||
|
$var = array(
|
||||||
|
range(1, 3),
|
||||||
|
array('foo', 2 => 'bar'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertDumpEquals(
|
||||||
|
<<<EOTXT
|
||||||
|
[
|
||||||
|
[
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
]
|
||||||
|
[
|
||||||
|
0 => (3) "foo"
|
||||||
|
2 => (3) "bar"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
|
||||||
|
putenv('DUMP_LIGHT_ARRAY=');
|
||||||
|
putenv('DUMP_STRING_LENGTH=');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function Twig\Template::getSourceContext
|
||||||
|
*/
|
||||||
public function testThrowingCaster()
|
public function testThrowingCaster()
|
||||||
{
|
{
|
||||||
$out = fopen('php://memory', 'r+b');
|
$out = fopen('php://memory', 'r+b');
|
||||||
|
|
||||||
require_once __DIR__.'/Fixtures/Twig.php';
|
require_once __DIR__.'/Fixtures/Twig.php';
|
||||||
$twig = new \__TwigTemplate_VarDumperFixture_u75a09(new \Twig_Environment(new \Twig_Loader_Filesystem()));
|
$twig = new \__TwigTemplate_VarDumperFixture_u75a09(new Environment(new FilesystemLoader()));
|
||||||
|
|
||||||
$dumper = new CliDumper();
|
$dumper = new CliDumper();
|
||||||
$dumper->setColors(false);
|
$dumper->setColors(false);
|
||||||
@@ -181,96 +282,56 @@ EOTXT
|
|||||||
':stream' => eval('return function () use ($twig) {
|
':stream' => eval('return function () use ($twig) {
|
||||||
try {
|
try {
|
||||||
$twig->render(array());
|
$twig->render(array());
|
||||||
} catch (\Twig_Error_Runtime $e) {
|
} catch (\Twig\Error\RuntimeError $e) {
|
||||||
throw $e->getPrevious();
|
throw $e->getPrevious();
|
||||||
}
|
}
|
||||||
};'),
|
};'),
|
||||||
));
|
));
|
||||||
$line = __LINE__ - 2;
|
|
||||||
$ref = (int) $out;
|
$ref = (int) $out;
|
||||||
|
|
||||||
$data = $cloner->cloneVar($out);
|
$data = $cloner->cloneVar($out);
|
||||||
$dumper->dump($data, $out);
|
$dumper->dump($data, $out);
|
||||||
rewind($out);
|
$out = stream_get_contents($out, -1, 0);
|
||||||
$out = stream_get_contents($out);
|
|
||||||
|
|
||||||
if (method_exists($twig, 'getSource')) {
|
|
||||||
$twig = <<<EOTXT
|
|
||||||
foo.twig:2: """
|
|
||||||
foo bar\\n
|
|
||||||
twig source\\n
|
|
||||||
\\n
|
|
||||||
"""
|
|
||||||
|
|
||||||
EOTXT;
|
|
||||||
} else {
|
|
||||||
$twig = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$r = defined('HHVM_VERSION') ? '' : '#%d';
|
$r = defined('HHVM_VERSION') ? '' : '#%d';
|
||||||
$this->assertStringMatchesFormat(
|
$this->assertStringMatchesFormat(
|
||||||
<<<EOTXT
|
<<<EOTXT
|
||||||
stream resource {@{$ref}
|
stream resource {@{$ref}
|
||||||
wrapper_type: "PHP"
|
⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
|
||||||
|
#message: "Unexpected Exception thrown from a caster: Foobar"
|
||||||
|
-trace: {
|
||||||
|
%sTwig.php:2: {
|
||||||
|
: foo bar
|
||||||
|
: twig source
|
||||||
|
:
|
||||||
|
}
|
||||||
|
%sTemplate.php:%d: {
|
||||||
|
: try {
|
||||||
|
: \$this->doDisplay(\$context, \$blocks);
|
||||||
|
: } catch (Twig%sError \$e) {
|
||||||
|
}
|
||||||
|
%sTemplate.php:%d: {
|
||||||
|
: {
|
||||||
|
: \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));
|
||||||
|
: }
|
||||||
|
}
|
||||||
|
%sTemplate.php:%d: {
|
||||||
|
: try {
|
||||||
|
: \$this->display(\$context);
|
||||||
|
: } catch (%s \$e) {
|
||||||
|
}
|
||||||
|
%sCliDumperTest.php:%d: {
|
||||||
|
%A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%Awrapper_type: "PHP"
|
||||||
stream_type: "MEMORY"
|
stream_type: "MEMORY"
|
||||||
mode: "%s+b"
|
mode: "%s+b"
|
||||||
unread_bytes: 0
|
unread_bytes: 0
|
||||||
seekable: true
|
seekable: true
|
||||||
uri: "php://memory"
|
uri: "php://memory"
|
||||||
timed_out: false
|
%Aoptions: []
|
||||||
blocked: true
|
|
||||||
eof: false
|
|
||||||
options: []
|
|
||||||
⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
|
|
||||||
#message: "Unexpected Exception thrown from a caster: Foobar"
|
|
||||||
-trace: {
|
|
||||||
%d. __TwigTemplate_VarDumperFixture_u75a09->doDisplay() ==> new Exception(): {
|
|
||||||
src: {
|
|
||||||
%sTwig.php:19: """
|
|
||||||
// line 2\\n
|
|
||||||
throw new \Exception('Foobar');\\n
|
|
||||||
}\\n
|
|
||||||
"""
|
|
||||||
{$twig} }
|
|
||||||
}
|
|
||||||
%d. Twig_Template->displayWithErrorHandling() ==> __TwigTemplate_VarDumperFixture_u75a09->doDisplay(): {
|
|
||||||
src: {
|
|
||||||
%sTemplate.php:%d: """
|
|
||||||
try {\\n
|
|
||||||
\$this->doDisplay(\$context, \$blocks);\\n
|
|
||||||
} catch (Twig_Error \$e) {\\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%d. Twig_Template->display() ==> Twig_Template->displayWithErrorHandling(): {
|
|
||||||
src: {
|
|
||||||
%sTemplate.php:%d: """
|
|
||||||
{\\n
|
|
||||||
\$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));\\n
|
|
||||||
}\\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%d. Twig_Template->render() ==> Twig_Template->display(): {
|
|
||||||
src: {
|
|
||||||
%sTemplate.php:%d: """
|
|
||||||
try {\\n
|
|
||||||
\$this->display(\$context);\\n
|
|
||||||
} catch (Exception \$e) {\\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%d. %slosure%s() ==> Twig_Template->render(): {
|
|
||||||
src: {
|
|
||||||
%sCliDumperTest.php:{$line}: """
|
|
||||||
}\\n
|
|
||||||
};'),\\n
|
|
||||||
));\\n
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EOTXT
|
EOTXT
|
||||||
@@ -288,11 +349,8 @@ EOTXT
|
|||||||
$dumper->setColors(false);
|
$dumper->setColors(false);
|
||||||
$cloner = new VarCloner();
|
$cloner = new VarCloner();
|
||||||
|
|
||||||
$out = fopen('php://memory', 'r+b');
|
|
||||||
$data = $cloner->cloneVar($var);
|
$data = $cloner->cloneVar($var);
|
||||||
$dumper->dump($data, $out);
|
$out = $dumper->dump($data, true);
|
||||||
rewind($out);
|
|
||||||
$out = stream_get_contents($out);
|
|
||||||
|
|
||||||
$r = defined('HHVM_VERSION') ? '' : '#%d';
|
$r = defined('HHVM_VERSION') ? '' : '#%d';
|
||||||
$this->assertStringMatchesFormat(
|
$this->assertStringMatchesFormat(
|
||||||
@@ -318,7 +376,7 @@ EOTXT
|
|||||||
$var = $this->getSpecialVars();
|
$var = $this->getSpecialVars();
|
||||||
|
|
||||||
$this->assertDumpEquals(
|
$this->assertDumpEquals(
|
||||||
<<<EOTXT
|
<<<'EOTXT'
|
||||||
array:3 [
|
array:3 [
|
||||||
0 => array:1 [
|
0 => array:1 [
|
||||||
0 => &1 array:1 [
|
0 => &1 array:1 [
|
||||||
@@ -364,7 +422,7 @@ EOTXT
|
|||||||
$dumper->dump($data);
|
$dumper->dump($data);
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
<<<EOTXT
|
<<<'EOTXT'
|
||||||
array:2 [
|
array:2 [
|
||||||
1 => array:1 [
|
1 => array:1 [
|
||||||
"GLOBALS" => &1 array:1 [
|
"GLOBALS" => &1 array:1 [
|
||||||
@@ -386,7 +444,7 @@ EOTXT
|
|||||||
*/
|
*/
|
||||||
public function testBuggyRefs()
|
public function testBuggyRefs()
|
||||||
{
|
{
|
||||||
if (PHP_VERSION_ID >= 50600) {
|
if (\PHP_VERSION_ID >= 50600) {
|
||||||
$this->markTestSkipped('PHP 5.6 fixed refs counting');
|
$this->markTestSkipped('PHP 5.6 fixed refs counting');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +464,7 @@ EOTXT
|
|||||||
});
|
});
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
<<<EOTXT
|
<<<'EOTXT'
|
||||||
array:1 [
|
array:1 [
|
||||||
0 => array:1 [
|
0 => array:1 [
|
||||||
0 => array:1 [
|
0 => array:1 [
|
||||||
@@ -421,6 +479,21 @@ EOTXT
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testIncompleteClass()
|
||||||
|
{
|
||||||
|
$unserializeCallbackHandler = ini_set('unserialize_callback_func', null);
|
||||||
|
$var = unserialize('O:8:"Foo\Buzz":0:{}');
|
||||||
|
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
|
||||||
|
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<EOTXT
|
||||||
|
__PHP_Incomplete_Class(Foo\Buzz) {}
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private function getSpecialVars()
|
private function getSpecialVars()
|
||||||
{
|
{
|
||||||
foreach (array_keys($GLOBALS) as $var) {
|
foreach (array_keys($GLOBALS) as $var) {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Fixtures;
|
||||||
|
|
||||||
|
interface FooInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Hello.
|
||||||
|
*/
|
||||||
|
public function foo();
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Fixtures;
|
||||||
|
|
||||||
|
class NotLoadableClass extends NotLoadableClass
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* foo.twig */
|
/* foo.twig */
|
||||||
class __TwigTemplate_VarDumperFixture_u75a09 extends Twig_Template
|
class __TwigTemplate_VarDumperFixture_u75a09 extends Twig\Template
|
||||||
{
|
{
|
||||||
public function __construct(Twig_Environment $env)
|
private $path;
|
||||||
|
|
||||||
|
public function __construct(Twig\Environment $env = null, $path = null)
|
||||||
{
|
{
|
||||||
parent::__construct($env);
|
if (null !== $env) {
|
||||||
|
parent::__construct($env);
|
||||||
|
}
|
||||||
$this->parent = false;
|
$this->parent = false;
|
||||||
|
$this->blocks = array();
|
||||||
$this->blocks = array(
|
$this->path = $path;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function doDisplay(array $context, array $blocks = array())
|
protected function doDisplay(array $context, array $blocks = array())
|
||||||
@@ -26,9 +28,11 @@ class __TwigTemplate_VarDumperFixture_u75a09 extends Twig_Template
|
|||||||
|
|
||||||
public function getDebugInfo()
|
public function getDebugInfo()
|
||||||
{
|
{
|
||||||
return array (19 => 2);
|
return array(20 => 1, 21 => 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceContext()
|
||||||
|
{
|
||||||
|
return new Twig\Source(" foo bar\n twig source\n\n", 'foo.twig', $this->path ?: __FILE__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* foo bar*/
|
|
||||||
/* twig source*/
|
|
||||||
/* */
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<foo>
|
||||||
|
<bar></bar>
|
||||||
|
<bar />
|
||||||
|
<bar>With text</bar>
|
||||||
|
<bar foo="bar" baz="fubar"></bar>
|
||||||
|
<bar xmlns:baz="http://symfony.com">
|
||||||
|
<baz:baz></baz:baz>
|
||||||
|
</bar>
|
||||||
|
</foo>
|
||||||
@@ -11,13 +11,14 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests;
|
namespace Symfony\Component\VarDumper\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
class HtmlDumperTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testGet()
|
public function testGet()
|
||||||
{
|
{
|
||||||
@@ -59,26 +60,24 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
|||||||
<span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>
|
<span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>
|
||||||
<span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>
|
<span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>
|
||||||
<span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>
|
<span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>
|
||||||
"<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&%s;j&%s;</span>\\n"
|
"<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&%s;j&%s;<span class=sf-dump-default>\\n</span></span>"
|
||||||
<span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&%s;</span>\\x00"
|
<span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&%s;<span class=sf-dump-default>\\x00</span></span>"
|
||||||
"<span class=sf-dump-key>[]</span>" => []
|
"<span class=sf-dump-key>[]</span>" => []
|
||||||
"<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
|
"<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
|
||||||
<span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
|
%A <span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
|
||||||
<span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str title="5 characters">STDIO</span>"
|
<span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str title="5 characters">STDIO</span>"
|
||||||
<span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
|
<span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
|
||||||
<span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
|
<span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
|
||||||
<span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
|
<span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
|
||||||
<span class=sf-dump-meta>timed_out</span>: <span class=sf-dump-const>false</span>
|
%A <span class=sf-dump-meta>options</span>: []
|
||||||
<span class=sf-dump-meta>blocked</span>: <span class=sf-dump-const>true</span>
|
|
||||||
<span class=sf-dump-meta>eof</span>: <span class=sf-dump-const>false</span>
|
|
||||||
<span class=sf-dump-meta>options</span>: []
|
|
||||||
</samp>}
|
</samp>}
|
||||||
"<span class=sf-dump-key>obj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a><samp id={$dumpId}-ref2%d>
|
"<span class=sf-dump-key>obj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a><samp id={$dumpId}-ref2%d>
|
||||||
+<span class=sf-dump-public title="Public property">foo</span>: "<span class=sf-dump-str title="3 characters">foo</span>"
|
+<span class=sf-dump-public title="Public property">foo</span>: "<span class=sf-dump-str title="3 characters">foo</span>"
|
||||||
+"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
|
+"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
|
||||||
</samp>}
|
</samp>}
|
||||||
"<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {{$r}<samp>
|
"<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {{$r}<samp>
|
||||||
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="48 characters">Symfony\Component\VarDumper\Tests\HtmlDumperTest</span>"
|
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\HtmlDumperTest
|
||||||
|
48 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests</span>\HtmlDumperTest</span>"
|
||||||
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
|
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
|
||||||
<span class=sf-dump-meta>parameters</span>: {<samp>
|
<span class=sf-dump-meta>parameters</span>: {<samp>
|
||||||
<span class=sf-dump-meta>\$a</span>: {}
|
<span class=sf-dump-meta>\$a</span>: {}
|
||||||
@@ -87,7 +86,8 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
|||||||
<span class=sf-dump-meta>default</span>: <span class=sf-dump-const>null</span>
|
<span class=sf-dump-meta>default</span>: <span class=sf-dump-const>null</span>
|
||||||
</samp>}
|
</samp>}
|
||||||
</samp>}
|
</samp>}
|
||||||
<span class=sf-dump-meta>file</span>: "<span class=sf-dump-str title="%d characters">{$var['file']}</span>"
|
<span class=sf-dump-meta>file</span>: "<span class=sf-dump-str title="{$var['file']}
|
||||||
|
%d characters"><span class=sf-dump-ellipsis>%sTests</span>%eFixtures%edumb-var.php</span>"
|
||||||
<span class=sf-dump-meta>line</span>: "<span class=sf-dump-str title="%d characters">{$var['line']} to {$var['line']}</span>"
|
<span class=sf-dump-meta>line</span>: "<span class=sf-dump-str title="%d characters">{$var['line']} to {$var['line']}</span>"
|
||||||
</samp>}
|
</samp>}
|
||||||
"<span class=sf-dump-key>line</span>" => <span class=sf-dump-num>{$var['line']}</span>
|
"<span class=sf-dump-key>line</span>" => <span class=sf-dump-num>{$var['line']}</span>
|
||||||
@@ -123,19 +123,41 @@ EOTXT
|
|||||||
$cloner = new VarCloner();
|
$cloner = new VarCloner();
|
||||||
|
|
||||||
$data = $cloner->cloneVar($var);
|
$data = $cloner->cloneVar($var);
|
||||||
$out = fopen('php://memory', 'r+b');
|
$out = $dumper->dump($data, true);
|
||||||
$dumper->dump($data, $out);
|
|
||||||
rewind($out);
|
|
||||||
$out = stream_get_contents($out);
|
|
||||||
|
|
||||||
$this->assertStringMatchesFormat(
|
$this->assertStringMatchesFormat(
|
||||||
<<<EOTXT
|
<<<'EOTXT'
|
||||||
<foo></foo><bar>b"<span class=sf-dump-str title="7 binary or non-UTF-8 characters">Словарь</span>"
|
<foo></foo><bar>b"<span class=sf-dump-str title="7 binary or non-UTF-8 characters">Словарь</span>"
|
||||||
</bar>
|
</bar>
|
||||||
|
|
||||||
EOTXT
|
EOTXT
|
||||||
,
|
,
|
||||||
|
$out
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAppend()
|
||||||
|
{
|
||||||
|
$out = fopen('php://memory', 'r+b');
|
||||||
|
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
|
||||||
|
$dumper->dump($cloner->cloneVar(123), $out);
|
||||||
|
$dumper->dump($cloner->cloneVar(456), $out);
|
||||||
|
|
||||||
|
$out = stream_get_contents($out, -1, 0);
|
||||||
|
|
||||||
|
$this->assertSame(<<<'EOTXT'
|
||||||
|
<foo></foo><bar><span class=sf-dump-num>123</span>
|
||||||
|
</bar>
|
||||||
|
<bar><span class=sf-dump-num>456</span>
|
||||||
|
</bar>
|
||||||
|
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
$out
|
$out
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests\Test;
|
namespace Symfony\Component\VarDumper\Tests\Test;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
|
|
||||||
class VarDumperTestTraitTest extends \PHPUnit_Framework_TestCase
|
class VarDumperTestTraitTest extends TestCase
|
||||||
{
|
{
|
||||||
use VarDumperTestTrait;
|
use VarDumperTestTrait;
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Tests;
|
namespace Symfony\Component\VarDumper\Tests;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class VarClonerTest extends \PHPUnit_Framework_TestCase
|
class VarClonerTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testMaxIntBoundary()
|
public function testMaxIntBoundary()
|
||||||
{
|
{
|
||||||
@@ -41,6 +42,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
[handle] => 0
|
[handle] => 0
|
||||||
[refCount] => 0
|
[refCount] => 0
|
||||||
[position] => 1
|
[position] => 1
|
||||||
|
[attr] => Array
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -52,6 +57,8 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
[position:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
|
[key:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
||||||
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
@@ -84,6 +91,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
[handle] => %i
|
[handle] => %i
|
||||||
[refCount] => 0
|
[refCount] => 0
|
||||||
[position] => 1
|
[position] => 1
|
||||||
|
[attr] => Array
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -99,6 +110,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
[handle] => %i
|
[handle] => %i
|
||||||
[refCount] => 0
|
[refCount] => 0
|
||||||
[position] => 2
|
[position] => 2
|
||||||
|
[attr] => Array
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
[\000+\0002] => Symfony\Component\VarDumper\Cloner\Stub Object
|
[\000+\0002] => Symfony\Component\VarDumper\Cloner\Stub Object
|
||||||
@@ -110,6 +125,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
[handle] => %i
|
[handle] => %i
|
||||||
[refCount] => 0
|
[refCount] => 0
|
||||||
[position] => 3
|
[position] => 3
|
||||||
|
[attr] => Array
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -126,6 +145,8 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
[position:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
|
[key:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
||||||
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
@@ -135,6 +156,86 @@ EOTXT;
|
|||||||
$this->assertStringMatchesFormat($expected, print_r($clone, true));
|
$this->assertStringMatchesFormat($expected, print_r($clone, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testJsonCast()
|
||||||
|
{
|
||||||
|
if (ini_get('xdebug.overload_var_dump') == 2) {
|
||||||
|
$this->markTestSkipped('xdebug is active');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = (array) json_decode('{"1":{}}');
|
||||||
|
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$clone = $cloner->cloneVar($data);
|
||||||
|
|
||||||
|
$expected = <<<'EOTXT'
|
||||||
|
object(Symfony\Component\VarDumper\Cloner\Data)#%i (6) {
|
||||||
|
["data":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
array(2) {
|
||||||
|
[0]=>
|
||||||
|
array(1) {
|
||||||
|
[0]=>
|
||||||
|
object(Symfony\Component\VarDumper\Cloner\Stub)#%i (8) {
|
||||||
|
["type"]=>
|
||||||
|
string(5) "array"
|
||||||
|
["class"]=>
|
||||||
|
string(5) "assoc"
|
||||||
|
["value"]=>
|
||||||
|
int(1)
|
||||||
|
["cut"]=>
|
||||||
|
int(0)
|
||||||
|
["handle"]=>
|
||||||
|
int(0)
|
||||||
|
["refCount"]=>
|
||||||
|
int(0)
|
||||||
|
["position"]=>
|
||||||
|
int(1)
|
||||||
|
["attr"]=>
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1]=>
|
||||||
|
array(1) {
|
||||||
|
["1"]=>
|
||||||
|
object(Symfony\Component\VarDumper\Cloner\Stub)#%i (8) {
|
||||||
|
["type"]=>
|
||||||
|
string(6) "object"
|
||||||
|
["class"]=>
|
||||||
|
string(8) "stdClass"
|
||||||
|
["value"]=>
|
||||||
|
NULL
|
||||||
|
["cut"]=>
|
||||||
|
int(0)
|
||||||
|
["handle"]=>
|
||||||
|
int(%i)
|
||||||
|
["refCount"]=>
|
||||||
|
int(0)
|
||||||
|
["position"]=>
|
||||||
|
int(0)
|
||||||
|
["attr"]=>
|
||||||
|
array(0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
["position":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
int(0)
|
||||||
|
["key":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
int(0)
|
||||||
|
["maxDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
int(20)
|
||||||
|
["maxItemsPerDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
int(-1)
|
||||||
|
["useRefHandles":"Symfony\Component\VarDumper\Cloner\Data":private]=>
|
||||||
|
int(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
EOTXT;
|
||||||
|
ob_start();
|
||||||
|
var_dump($clone);
|
||||||
|
$this->assertStringMatchesFormat(\PHP_VERSION_ID >= 70200 ? str_replace('"1"', '1', $expected) : $expected, ob_get_clean());
|
||||||
|
}
|
||||||
|
|
||||||
public function testCaster()
|
public function testCaster()
|
||||||
{
|
{
|
||||||
$cloner = new VarCloner(array(
|
$cloner = new VarCloner(array(
|
||||||
@@ -165,6 +266,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
[handle] => %i
|
[handle] => %i
|
||||||
[refCount] => 0
|
[refCount] => 0
|
||||||
[position] => 1
|
[position] => 1
|
||||||
|
[attr] => Array
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -176,6 +281,8 @@ Symfony\Component\VarDumper\Cloner\Data Object
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
[position:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
|
[key:Symfony\Component\VarDumper\Cloner\Data:private] => 0
|
||||||
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
|
||||||
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
|
||||||
|
|||||||
@@ -20,9 +20,14 @@
|
|||||||
"symfony/polyfill-mbstring": "~1.0"
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"twig/twig": "~1.20|~2.0"
|
"ext-iconv": "*",
|
||||||
|
"twig/twig": "~1.34|~2.4"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
"ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
|
||||||
"ext-symfony_debug": ""
|
"ext-symfony_debug": ""
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -35,7 +40,7 @@
|
|||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "3.0-dev"
|
"dev-master": "3.2-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,13 @@
|
|||||||
backupGlobals="false"
|
backupGlobals="false"
|
||||||
colors="true"
|
colors="true"
|
||||||
bootstrap="vendor/autoload.php"
|
bootstrap="vendor/autoload.php"
|
||||||
|
failOnRisky="true"
|
||||||
|
failOnWarning="true"
|
||||||
>
|
>
|
||||||
<php>
|
<php>
|
||||||
<ini name="error_reporting" value="-1" />
|
<ini name="error_reporting" value="-1" />
|
||||||
|
<env name="DUMP_LIGHT_ARRAY" value="" />
|
||||||
|
<env name="DUMP_STRING_LENGTH" value="" />
|
||||||
</php>
|
</php>
|
||||||
|
|
||||||
<testsuites>
|
<testsuites>
|
||||||
|
|||||||
Reference in New Issue
Block a user