diff --git a/composer.json b/composer.json index 130fda34945..8d82f530df8 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "nnnick/chartjs" : "^2.9", "stripe/stripe-php" : "6.43.1", "maximebf/debugbar" : "1.15.1", - "symfony/var-dumper" : "3" + "symfony/var-dumper" : "3.2" }, "require-dev" : { "php-parallel-lint/php-parallel-lint" : "^0", diff --git a/composer.lock b/composer.lock index 3e867f8f186..5f761cb63fe 100644 --- a/composer.lock +++ b/composer.lock @@ -591,7 +591,7 @@ }, { "name": "symfony/var-dumper", - "version": "v3.0.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", @@ -616,7 +616,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { diff --git a/htdocs/includes/symfony/var-dumper/Caster/AmqpCaster.php b/htdocs/includes/symfony/var-dumper/Caster/AmqpCaster.php index 4e9b351c181..655262f4065 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/AmqpCaster.php +++ b/htdocs/includes/symfony/var-dumper/Caster/AmqpCaster.php @@ -48,7 +48,16 @@ class AmqpCaster { $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')) { $timeout = $c->getReadTimeout(); } else { @@ -56,13 +65,13 @@ class AmqpCaster } $a += array( - $prefix.'isConnected' => $c->isConnected(), + $prefix.'is_connected' => $c->isConnected(), $prefix.'login' => $c->getLogin(), $prefix.'password' => $c->getPassword(), $prefix.'host' => $c->getHost(), - $prefix.'port' => $c->getPort(), $prefix.'vhost' => $c->getVhost(), - $prefix.'readTimeout' => $timeout, + $prefix.'port' => $c->getPort(), + $prefix.'read_timeout' => $timeout, ); return $a; @@ -73,11 +82,19 @@ class AmqpCaster $prefix = Caster::PREFIX_VIRTUAL; $a += array( - $prefix.'isConnected' => $c->isConnected(), - $prefix.'channelId' => $c->getChannelId(), - $prefix.'prefetchSize' => $c->getPrefetchSize(), - $prefix.'prefetchCount' => $c->getPrefetchCount(), + $prefix.'is_connected' => $c->isConnected(), + $prefix.'channel_id' => $c->getChannelId(), + ); + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPChannel\x00connection"])) { + return $a; + } + + $a += array( $prefix.'connection' => $c->getConnection(), + $prefix.'prefetch_size' => $c->getPrefetchSize(), + $prefix.'prefetch_count' => $c->getPrefetchCount(), ); return $a; @@ -88,11 +105,19 @@ class AmqpCaster $prefix = Caster::PREFIX_VIRTUAL; $a += array( - $prefix.'name' => $c->getName(), $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.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'arguments' => $c->getArguments(), ); return $a; @@ -103,12 +128,24 @@ class AmqpCaster $prefix = Caster::PREFIX_VIRTUAL; $a += array( - $prefix.'name' => $c->getName(), $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.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'type' => $type, + $prefix.'arguments' => $c->getArguments(), ); return $a; @@ -118,28 +155,37 @@ class AmqpCaster { $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)) { $a += array($prefix.'body' => $c->getBody()); } $a += array( - $prefix.'routingKey' => $c->getRoutingKey(), - $prefix.'deliveryTag' => $c->getDeliveryTag(), - $prefix.'deliveryMode' => new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()), - $prefix.'exchangeName' => $c->getExchangeName(), - $prefix.'isRedelivery' => $c->isRedelivery(), - $prefix.'contentType' => $c->getContentType(), - $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.'delivery_tag' => $c->getDeliveryTag(), + $prefix.'is_redelivery' => $c->isRedelivery(), + $prefix.'exchange_name' => $c->getExchangeName(), + $prefix.'routing_key' => $c->getRoutingKey(), + $prefix.'content_type' => $c->getContentType(), + $prefix.'content_encoding' => $c->getContentEncoding(), $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; diff --git a/htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php b/htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php new file mode 100644 index 00000000000..6675caa0478 --- /dev/null +++ b/htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php @@ -0,0 +1,80 @@ + + * + * 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
+ */ +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); + } +} diff --git a/htdocs/includes/symfony/var-dumper/Caster/Caster.php b/htdocs/includes/symfony/var-dumper/Caster/Caster.php index 23e72e87701..7c7fe00ece4 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/Caster.php +++ b/htdocs/includes/symfony/var-dumper/Caster/Caster.php @@ -11,6 +11,8 @@ namespace Symfony\Component\VarDumper\Caster; +use Symfony\Component\VarDumper\Cloner\Stub; + /** * Helper for filtering out properties in casters. * @@ -36,29 +38,39 @@ class Caster /** * Casts objects to arrays and adds the dynamic property prefix. * - * @param object $obj The object to cast. - * @param \ReflectionClass $reflector The class reflector to use for inspecting the object definition. + * @param object $obj The object to cast + * @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) { if ($reflector->hasMethod('__debugInfo')) { $a = $obj->__debugInfo(); + } elseif ($obj instanceof \Closure) { + $a = array(); } else { $a = (array) $obj; } + if ($obj instanceof \__PHP_Incomplete_Class) { + return $a; + } if ($a) { + $combine = false; $p = array_keys($a); 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; } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { + $combine = true; $p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0"); } } - $a = array_combine($p, $a); + if ($combine) { + $a = array_combine($p, $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. * 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 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 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 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 */ - 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) { $type = self::EXCLUDE_STRICT & $filter; @@ -108,9 +123,20 @@ class Caster if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { unset($a[$k]); + ++$count; } } 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; + } } diff --git a/htdocs/includes/symfony/var-dumper/Caster/ClassStub.php b/htdocs/includes/symfony/var-dumper/Caster/ClassStub.php new file mode 100644 index 00000000000..59efecda9eb --- /dev/null +++ b/htdocs/includes/symfony/var-dumper/Caster/ClassStub.php @@ -0,0 +1,87 @@ + + * + * 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
+ */ +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; + } +} diff --git a/htdocs/includes/symfony/var-dumper/Caster/ConstStub.php b/htdocs/includes/symfony/var-dumper/Caster/ConstStub.php index f20e03cdf0d..26c0010b66a 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/ConstStub.php +++ b/htdocs/includes/symfony/var-dumper/Caster/ConstStub.php @@ -25,4 +25,9 @@ class ConstStub extends Stub $this->class = $name; $this->value = $value; } + + public function __toString() + { + return (string) $this->value; + } } diff --git a/htdocs/includes/symfony/var-dumper/Caster/CutStub.php b/htdocs/includes/symfony/var-dumper/Caster/CutStub.php index 8781f5cf3c6..61140eb361d 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/CutStub.php +++ b/htdocs/includes/symfony/var-dumper/Caster/CutStub.php @@ -39,9 +39,12 @@ class CutStub extends Stub case 'resource': case 'unknown type': + case 'resource (closed)': $this->type = self::TYPE_RESOURCE; $this->handle = (int) $value; - $this->class = @get_resource_type($value); + if ('Unknown' === $this->class = @get_resource_type($value)) { + $this->class = 'Closed'; + } $this->cut = -1; break; diff --git a/htdocs/includes/symfony/var-dumper/Caster/DOMCaster.php b/htdocs/includes/symfony/var-dumper/Caster/DOMCaster.php index e04cf9534b3..3a99865370c 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/DOMCaster.php +++ b/htdocs/includes/symfony/var-dumper/Caster/DOMCaster.php @@ -107,7 +107,7 @@ class DOMCaster 'namespaceURI' => $dom->namespaceURI, 'prefix' => $dom->prefix, 'localName' => $dom->localName, - 'baseURI' => $dom->baseURI, + 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, 'textContent' => new CutStub($dom->textContent), ); @@ -144,7 +144,7 @@ class DOMCaster 'version' => $dom->version, 'xmlVersion' => $dom->xmlVersion, 'strictErrorChecking' => $dom->strictErrorChecking, - 'documentURI' => $dom->documentURI, + 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, 'config' => $dom->config, 'formatOutput' => $dom->formatOutput, 'validateOnParse' => $dom->validateOnParse, @@ -237,7 +237,7 @@ class DOMCaster 'columnNumber' => $dom->columnNumber, 'offset' => $dom->offset, 'relatedNode' => $dom->relatedNode, - 'uri' => $dom->uri, + 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, ); return $a; diff --git a/htdocs/includes/symfony/var-dumper/Caster/EnumStub.php b/htdocs/includes/symfony/var-dumper/Caster/EnumStub.php index 67bb2e16390..3cee23eac20 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/EnumStub.php +++ b/htdocs/includes/symfony/var-dumper/Caster/EnumStub.php @@ -20,8 +20,11 @@ use Symfony\Component\VarDumper\Cloner\Stub; */ class EnumStub extends Stub { - public function __construct(array $values) + public $dumpKeys = true; + + public function __construct(array $values, $dumpKeys = true) { $this->value = $values; + $this->dumpKeys = $dumpKeys; } } diff --git a/htdocs/includes/symfony/var-dumper/Caster/ExceptionCaster.php b/htdocs/includes/symfony/var-dumper/Caster/ExceptionCaster.php index a5a8773e859..8c84137e646 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/ExceptionCaster.php +++ b/htdocs/includes/symfony/var-dumper/Caster/ExceptionCaster.php @@ -41,6 +41,8 @@ class ExceptionCaster E_STRICT => 'E_STRICT', ); + private static $framesCache = array(); + public static function castError(\Error $e, array $a, Stub $stub, $isNested, $filter = 0) { return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); @@ -65,13 +67,9 @@ class ExceptionCaster $prefix = Caster::PREFIX_PROTECTED; $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']; - array_unshift($b[$xPrefix.'trace'], array( - 'function' => 'new '.get_class($a[$xPrefix.'previous']), - 'file' => $b[$prefix.'file'], - 'line' => $b[$prefix.'line'], - )); + self::traceUnshift($b[$xPrefix.'trace'], get_class($a[$xPrefix.'previous']), $b[$prefix.'file'], $b[$prefix.'line']); $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->handle = 0; $frames = $trace->value; + $prefix = Caster::PREFIX_VIRTUAL; $a = array(); $j = count($frames); @@ -97,34 +96,38 @@ class ExceptionCaster if (!isset($trace->value[$i])) { 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) { - $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( - 'object' => isset($frames[$i]['object']) ? $frames[$i]['object'] : null, - 'class' => isset($frames[$i]['class']) ? $frames[$i]['class'] : null, - 'type' => isset($frames[$i]['type']) ? $frames[$i]['type'] : null, - 'function' => isset($frames[$i]['function']) ? $frames[$i]['function'] : null, + 'object' => isset($f['object']) ? $f['object'] : null, + 'class' => isset($f['class']) ? $f['class'] : null, + 'type' => isset($f['type']) ? $f['type'] : null, + 'function' => isset($f['function']) ? $f['function'] : null, ) + $frames[$i - 1], - $trace->keepArgs, + false, 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) { $a = array_slice($a, 0, $trace->sliceLength, true); } @@ -141,30 +144,52 @@ class ExceptionCaster $prefix = Caster::PREFIX_VIRTUAL; if (isset($f['file'], $f['line'])) { - 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]; - } - 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); + $cacheKey = $f; + unset($cacheKey['object'], $cacheKey['args']); + $cacheKey[] = self::$srcContext; + $cacheKey = implode('-', $cacheKey); - if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) { - $template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem())); + if (isset(self::$framesCache[$cacheKey])) { + $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 { - $templateName = $template->getTemplateName(); - $templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName)); + if (file_exists($f['file']) && 0 <= self::$srcContext) { + if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { + $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(); 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 { - $src[$f['file']] = $f['line']; + $srcAttr = $ellipsis ? 'ellipsis='.$ellipsis : ''; + 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']); @@ -176,8 +201,8 @@ class ExceptionCaster unset($a[$k]); } } - if ($frame->keepArgs && isset($f['args'])) { - $a[$prefix.'args'] = $f['args']; + if ($frame->keepArgs && !empty($f['args'])) { + $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); } return $a; @@ -193,46 +218,81 @@ class ExceptionCaster } if (!($filter & Caster::EXCLUDE_VERBOSE)) { - array_unshift($trace, array( - 'function' => $xClass ? 'new '.$xClass : null, - 'file' => $a[Caster::PREFIX_PROTECTED.'file'], - 'line' => $a[Caster::PREFIX_PROTECTED.'line'], - )); - $a[$xPrefix.'trace'] = new TraceStub($trace); + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); + } + $a[$xPrefix.'trace'] = new TraceStub($trace, self::$traceArgs); } if (empty($a[$xPrefix.'previous'])) { unset($a[$xPrefix.'previous']); } 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; } - 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(); 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; - while (' ' === $src[0][$ltrim] || "\t" === $src[0][$ltrim]) { - $i = $srcContext << 1; - while ($i > 0 && $src[0][$ltrim] === $src[$i][$ltrim]) { - --$i; - } - if ($i) { - break; + do { + $pad = null; + for ($i = $srcContext << 1; $i >= 0; --$i) { + if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { + if (null === $pad) { + $pad = $c; + } + if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { + break; + } + } } ++$ltrim; - } - if ($ltrim) { - foreach ($src as $i => $line) { - $src[$i] = substr($line, $ltrim); + } while (0 > $i && null !== $pad); + + --$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); } } diff --git a/htdocs/includes/symfony/var-dumper/Caster/LinkStub.php b/htdocs/includes/symfony/var-dumper/Caster/LinkStub.php new file mode 100644 index 00000000000..ea39c5b08ee --- /dev/null +++ b/htdocs/includes/symfony/var-dumper/Caster/LinkStub.php @@ -0,0 +1,51 @@ + + * + * 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
+ */ +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))); + } + } + } + } +} diff --git a/htdocs/includes/symfony/var-dumper/Caster/PdoCaster.php b/htdocs/includes/symfony/var-dumper/Caster/PdoCaster.php index e60b9275fd8..b8667824773 100644 --- a/htdocs/includes/symfony/var-dumper/Caster/PdoCaster.php +++ b/htdocs/includes/symfony/var-dumper/Caster/PdoCaster.php @@ -77,6 +77,12 @@ class PdoCaster } 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; $a += array( diff --git a/htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php b/htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php new file mode 100644 index 00000000000..07a3a1b0911 --- /dev/null +++ b/htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php @@ -0,0 +1,77 @@ + + * + * 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
+ */
+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()),
+ );
+ }
+}
diff --git a/htdocs/includes/symfony/var-dumper/Caster/ReflectionCaster.php b/htdocs/includes/symfony/var-dumper/Caster/ReflectionCaster.php
index 936e11982ee..dcb5a2f29ca 100644
--- a/htdocs/includes/symfony/var-dumper/Caster/ReflectionCaster.php
+++ b/htdocs/includes/symfony/var-dumper/Caster/ReflectionCaster.php
@@ -53,19 +53,32 @@ class ReflectionCaster
}
if ($f = $c->getFileName()) {
- $a[$prefix.'file'] = $f;
+ $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
}
$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;
}
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)
@@ -73,7 +86,7 @@ class ReflectionCaster
$prefix = Caster::PREFIX_VIRTUAL;
$a += array(
- $prefix.'type' => $c->__toString(),
+ $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : $c->__toString(),
$prefix.'allowsNull' => $c->allowsNull(),
$prefix.'isBuiltin' => $c->isBuiltin(),
);
@@ -88,31 +101,33 @@ class ReflectionCaster
if ($c->getThis()) {
$a[$prefix.'this'] = new CutStub($c->getThis());
}
- $x = $c->getFunction();
+ $function = $c->getFunction();
$frame = array(
- 'class' => isset($x->class) ? $x->class : null,
- 'type' => isset($x->class) ? ($x->isStatic() ? '::' : '->') : null,
- 'function' => $x->name,
+ 'class' => isset($function->class) ? $function->class : null,
+ 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,
+ 'function' => $function->name,
'file' => $c->getExecutingFile(),
'line' => $c->getExecutingLine(),
);
if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) {
- $x = new \ReflectionGenerator($c->getExecutingGenerator());
+ $function = new \ReflectionGenerator($c->getExecutingGenerator());
array_unshift($trace, array(
'function' => 'yield',
- 'file' => $x->getExecutingFile(),
- 'line' => $x->getExecutingLine() - 1,
+ 'file' => $function->getExecutingFile(),
+ 'line' => $function->getExecutingLine() - 1,
));
$trace[] = $frame;
$a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);
} else {
- $x = new FrameStub($frame, false, true);
- $x = ExceptionCaster::castFrameStub($x, array(), $x, true);
+ $function = new FrameStub($frame, false, true);
+ $function = ExceptionCaster::castFrameStub($function, array(), $function, true);
$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;
}
@@ -157,7 +172,12 @@ class ReflectionCaster
));
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'])) {
$a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
@@ -165,12 +185,12 @@ class ReflectionCaster
foreach ($c->getParameters() as $v) {
$k = '$'.$v->name;
- if ($v->isPassedByReference()) {
- $k = '&'.$k;
- }
if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
$k = '...'.$k;
}
+ if ($v->isPassedByReference()) {
+ $k = '&'.$k;
+ }
$a[$prefix.'parameters'][$k] = $v;
}
if (isset($a[$prefix.'parameters'])) {
@@ -213,24 +233,22 @@ class ReflectionCaster
'position' => 'getPosition',
'isVariadic' => 'isVariadic',
'byReference' => 'isPassedByReference',
+ 'allowsNull' => 'allowsNull',
));
- try {
- if (method_exists($c, 'hasType')) {
- if ($c->hasType()) {
- $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];
+ if (method_exists($c, 'getType')) {
+ if ($v = $c->getType()) {
+ $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString();
}
+ } 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 {
@@ -238,9 +256,13 @@ class ReflectionCaster
if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) {
$a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
}
+ if (null === $v) {
+ unset($a[$prefix.'allowsNull']);
+ }
} 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;
+ unset($a[$prefix.'allowsNull']);
}
}
@@ -288,7 +310,7 @@ class ReflectionCaster
$x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : array();
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();
}
diff --git a/htdocs/includes/symfony/var-dumper/Caster/ResourceCaster.php b/htdocs/includes/symfony/var-dumper/Caster/ResourceCaster.php
index 903641f69c6..3cdb27c3087 100644
--- a/htdocs/includes/symfony/var-dumper/Caster/ResourceCaster.php
+++ b/htdocs/includes/symfony/var-dumper/Caster/ResourceCaster.php
@@ -40,12 +40,17 @@ class ResourceCaster
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)
{
- return stream_context_get_params($stream);
+ return @stream_context_get_params($stream) ?: $a;
}
public static function castGd($gd, array $a, Stub $stub, $isNested)
diff --git a/htdocs/includes/symfony/var-dumper/Caster/SplCaster.php b/htdocs/includes/symfony/var-dumper/Caster/SplCaster.php
index 97f21463821..4f23efa52d2 100644
--- a/htdocs/includes/symfony/var-dumper/Caster/SplCaster.php
+++ b/htdocs/includes/symfony/var-dumper/Caster/SplCaster.php
@@ -36,7 +36,7 @@ class SplCaster
$b = array(
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
$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(),
);
@@ -71,7 +71,7 @@ class SplCaster
$c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
$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),
);
$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'])) {
$a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
}
@@ -180,7 +184,7 @@ class SplCaster
$storage = array();
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(
'object' => $obj,
'info' => $c->getInfo(),
diff --git a/htdocs/includes/symfony/var-dumper/Caster/StubCaster.php b/htdocs/includes/symfony/var-dumper/Caster/StubCaster.php
index ebad5ba9844..2ec096c5a8c 100644
--- a/htdocs/includes/symfony/var-dumper/Caster/StubCaster.php
+++ b/htdocs/includes/symfony/var-dumper/Caster/StubCaster.php
@@ -28,9 +28,17 @@ class StubCaster
$stub->value = $c->value;
$stub->handle = $c->handle;
$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)
@@ -52,15 +60,17 @@ class StubCaster
public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
{
if ($isNested) {
- $stub->class = '';
+ $stub->class = $c->dumpKeys ? '' : null;
$stub->handle = 0;
$stub->value = null;
+ $stub->cut = $c->cut;
+ $stub->attr = $c->attr;
$a = array();
if ($c->value) {
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()
$a = array_combine($keys, $c->value);
diff --git a/htdocs/includes/symfony/var-dumper/Caster/XmlReaderCaster.php b/htdocs/includes/symfony/var-dumper/Caster/XmlReaderCaster.php
new file mode 100644
index 00000000000..c371009a17a
--- /dev/null
+++ b/htdocs/includes/symfony/var-dumper/Caster/XmlReaderCaster.php
@@ -0,0 +1,77 @@
+
+ *
+ * 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é
*/
class Data
{
private $data;
+ private $position = 0;
+ private $key = 0;
private $maxDepth = 20;
private $maxItemsPerDepth = -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)
{
@@ -30,7 +34,7 @@ class Data
}
/**
- * @return array The raw data structure.
+ * @return array The raw data structure
*/
public function getRawData()
{
@@ -40,9 +44,9 @@ class Data
/**
* 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)
{
@@ -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)
{
@@ -70,9 +74,9 @@ class Data
/**
* 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)
{
@@ -82,22 +86,66 @@ class 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.
*/
public function dump(DumperInterface $dumper)
{
$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.
*
- * @param DumperInterface $dumper The dumper being used for dumping.
- * @param Cursor $cursor A cursor used for tracking dumper state position.
- * @param array &$refs A map of all references discovered while dumping.
- * @param mixed $item A Stub object or the original value being dumped.
+ * @param DumperInterface $dumper The dumper being used for dumping
+ * @param Cursor $cursor A cursor used for tracking dumper state position
+ * @param array &$refs A map of all references discovered while dumping
+ * @param mixed $item A Stub object or the original value being dumped
*/
private function dumpItem($dumper, $cursor, &$refs, $item)
{
@@ -107,6 +155,7 @@ class Data
$firstSeen = true;
if (!$item instanceof Stub) {
+ $cursor->attr = array();
$type = gettype($item);
} elseif (Stub::TYPE_REF === $item->type) {
if ($item->handle) {
@@ -119,6 +168,7 @@ class Data
$cursor->hardRefHandle = $this->useRefHandles & $item->handle;
$cursor->hardRefCount = $item->refCount;
}
+ $cursor->attr = $item->attr;
$type = $item->class ?: gettype($item->value);
$item = $item->value;
}
@@ -133,6 +183,7 @@ class Data
}
$cursor->softRefHandle = $this->useRefHandles & $item->handle;
$cursor->softRefCount = $item->refCount;
+ $cursor->attr = $item->attr;
$cut = $item->cut;
if ($item->position && $firstSeen) {
@@ -162,7 +213,7 @@ class Data
$withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
$dumper->enterHash($cursor, $item->type, $item->class, $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) {
$cut += count($children);
}
@@ -186,15 +237,16 @@ class Data
* Dumps children of hash structures.
*
* @param DumperInterface $dumper
- * @param Cursor $parentCursor The cursor of the parent hash.
- * @param array &$refs A map of all references discovered while dumping.
- * @param array $children The children to dump.
- * @param int $hashCut The number of items removed from the original hash.
- * @param string $hashType A Cursor::HASH_* const.
+ * @param Cursor $parentCursor The cursor of the parent hash
+ * @param array &$refs A map of all references discovered while dumping
+ * @param array $children The children to dump
+ * @param int $hashCut The number of items removed from the original hash
+ * @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->depth;
@@ -204,7 +256,7 @@ class Data
$cursor->hashCut = $hashCut;
foreach ($children as $key => $child) {
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
- $cursor->hashKey = $key;
+ $cursor->hashKey = $dumpKeys ? $key : null;
$this->dumpItem($dumper, $cursor, $refs, $child);
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
$parentCursor->stop = true;
diff --git a/htdocs/includes/symfony/var-dumper/Cloner/DumperInterface.php b/htdocs/includes/symfony/var-dumper/Cloner/DumperInterface.php
index eba23d42297..cb7981694f9 100644
--- a/htdocs/includes/symfony/var-dumper/Cloner/DumperInterface.php
+++ b/htdocs/includes/symfony/var-dumper/Cloner/DumperInterface.php
@@ -21,40 +21,40 @@ interface DumperInterface
/**
* Dumps a scalar value.
*
- * @param Cursor $cursor The Cursor position in the dump.
- * @param string $type The PHP type of the value being dumped.
- * @param scalar $value The scalar value being dumped.
+ * @param Cursor $cursor The Cursor position in the dump
+ * @param string $type The PHP type of the value being dumped
+ * @param scalar $value The scalar value being dumped
*/
public function dumpScalar(Cursor $cursor, $type, $value);
/**
* Dumps a string.
*
- * @param Cursor $cursor The Cursor position in the dump.
- * @param string $str The string being dumped.
- * @param bool $bin Whether $str is UTF-8 or binary encoded.
- * @param int $cut The number of characters $str has been cut by.
+ * @param Cursor $cursor The Cursor position in the dump
+ * @param string $str The string being dumped
+ * @param bool $bin Whether $str is UTF-8 or binary encoded
+ * @param int $cut The number of characters $str has been cut by
*/
public function dumpString(Cursor $cursor, $str, $bin, $cut);
/**
* Dumps while entering an hash.
*
- * @param Cursor $cursor The Cursor position in the dump.
- * @param int $type A Cursor::HASH_* const for the type of hash.
- * @param string $class The object class, resource type or array count.
- * @param bool $hasChild When the dump of the hash has child item.
+ * @param Cursor $cursor The Cursor position in the dump
+ * @param int $type A Cursor::HASH_* const for the type of hash
+ * @param string $class The object class, resource type or array count
+ * @param bool $hasChild When the dump of the hash has child item
*/
public function enterHash(Cursor $cursor, $type, $class, $hasChild);
/**
* Dumps while leaving an hash.
*
- * @param Cursor $cursor The Cursor position in the dump.
- * @param int $type A Cursor::HASH_* const for the type of hash.
- * @param string $class The object class, resource type or array count.
- * @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 Cursor $cursor The Cursor position in the dump
+ * @param int $type A Cursor::HASH_* const for the type of hash
+ * @param string $class The object class, resource type or array count
+ * @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
*/
public function leaveHash(Cursor $cursor, $type, $class, $hasChild, $cut);
}
diff --git a/htdocs/includes/symfony/var-dumper/Cloner/Stub.php b/htdocs/includes/symfony/var-dumper/Cloner/Stub.php
index f58a57a7276..313c591fc83 100644
--- a/htdocs/includes/symfony/var-dumper/Cloner/Stub.php
+++ b/htdocs/includes/symfony/var-dumper/Cloner/Stub.php
@@ -37,4 +37,5 @@ class Stub
public $handle = 0;
public $refCount = 0;
public $position = 0;
+ public $attr = array();
}
diff --git a/htdocs/includes/symfony/var-dumper/Cloner/VarCloner.php b/htdocs/includes/symfony/var-dumper/Cloner/VarCloner.php
index 98d6e9e51c1..6a3b451bda7 100644
--- a/htdocs/includes/symfony/var-dumper/Cloner/VarCloner.php
+++ b/htdocs/includes/symfony/var-dumper/Cloner/VarCloner.php
@@ -25,10 +25,9 @@ class VarCloner extends AbstractCloner
protected function doClone($var)
{
$useExt = $this->useExt;
- $i = 0; // Current iteration position in $queue
$len = 1; // Length of $queue
$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
$arrayRefs = array(); // Map of queue indexes to stub array 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) {
$indexed = true; // Whether the currently iterated array is numerically indexed or not
$j = -1; // Position in the currently iterated array
- $step = $queue[$i]; // Copy of the currently iterated array used for hard references detection
- foreach ($step as $k => $v) {
+ $fromObjCast = array_keys($queue[$i]);
+ $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
// $v is the original value or a stub object in case of hard references
- if ($indexed && $k !== ++$j) {
+ if ($k !== ++$j) {
$indexed = false;
}
+ if ($fromObjCast) {
+ $k = $j;
+ }
if ($useExt) {
- $zval = symfony_zval_info($k, $step);
+ $zval = symfony_zval_info($k, $refs);
} else {
- $step[$k] = $cookie;
- if ($zval['zval_isref'] = $queue[$i][$k] === $cookie) {
+ $refs[$k] = $cookie;
+ if ($zval['zval_isref'] = $vals[$k] === $cookie) {
$zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null;
}
$zval['type'] = gettype($v);
}
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
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)) {
++$v->value->refCount;
}
@@ -102,12 +106,12 @@ class VarCloner extends AbstractCloner
} else {
$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->type = Stub::TYPE_STRING;
$stub->class = Stub::STRING_UTF8;
$stub->cut = $cut;
- $stub->value = iconv_substr($v, 0, $maxString, 'UTF-8');
+ $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
}
break;
@@ -178,10 +182,13 @@ class VarCloner extends AbstractCloner
case 'resource':
case 'unknown type':
+ case 'resource (closed)':
if (empty($resRefs[$h = (int) $v])) {
$stub = new Stub();
$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->handle = $h;
$a = $this->castResource($stub, 0 < $i);
@@ -204,18 +211,18 @@ class VarCloner extends AbstractCloner
if (isset($stub)) {
if ($zval['zval_isref']) {
if ($useExt) {
- $queue[$i][$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
+ $vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
$v->value = $stub;
} else {
- $step[$k] = new Stub();
- $step[$k]->value = $stub;
- $h = spl_object_hash($step[$k]);
- $queue[$i][$k] = $hardRefs[$h] = &$step[$k];
+ $refs[$k] = new Stub();
+ $refs[$k]->value = $stub;
+ $h = spl_object_hash($refs[$k]);
+ $vals[$k] = $hardRefs[$h] = &$refs[$k];
$values[$h] = $v;
}
- $queue[$i][$k]->handle = ++$refs;
+ $vals[$k]->handle = ++$refsCounter;
} else {
- $queue[$i][$k] = $stub;
+ $vals[$k] = $stub;
}
if ($a) {
@@ -243,19 +250,38 @@ class VarCloner extends AbstractCloner
$stub = $a = null;
} elseif ($zval['zval_isref']) {
if ($useExt) {
- $queue[$i][$k] = $hardRefs[$zval['zval_hash']] = new Stub();
- $queue[$i][$k]->value = $v;
+ $vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub();
+ $vals[$k]->value = $v;
} else {
- $step[$k] = $queue[$i][$k] = new Stub();
- $step[$k]->value = $v;
- $h = spl_object_hash($step[$k]);
- $hardRefs[$h] = &$step[$k];
+ $refs[$k] = $vals[$k] = new Stub();
+ $refs[$k]->value = $v;
+ $h = spl_object_hash($refs[$k]);
+ $hardRefs[$h] = &$refs[$k];
$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 ($indexed) {
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
@@ -291,7 +317,7 @@ class VarCloner extends AbstractCloner
if (!empty($frame['line'])) {
ob_start();
debug_zval_dump($obj);
- self::$hashMask = substr(ob_get_clean(), 17);
+ self::$hashMask = (int) substr(ob_get_clean(), 17);
}
}
diff --git a/htdocs/includes/symfony/var-dumper/Dumper/AbstractDumper.php b/htdocs/includes/symfony/var-dumper/Dumper/AbstractDumper.php
index f8b9c107779..12f835b1ffa 100644
--- a/htdocs/includes/symfony/var-dumper/Dumper/AbstractDumper.php
+++ b/htdocs/includes/symfony/var-dumper/Dumper/AbstractDumper.php
@@ -21,6 +21,9 @@ use Symfony\Component\VarDumper\Cloner\DumperInterface;
*/
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
{
+ const DUMP_LIGHT_ARRAY = 1;
+ const DUMP_STRING_LENGTH = 2;
+
public static $defaultOutput = 'php://output';
protected $line = '';
@@ -28,18 +31,21 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
protected $outputStream;
protected $decimalPoint; // This is locale dependent
protected $indentPad = ' ';
+ protected $flags;
private $charset;
/**
- * @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 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 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->decimalPoint = (string) 0.5;
- $this->decimalPoint = $this->decimalPoint[1];
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
$this->setOutput($output ?: static::$defaultOutput);
if (!$output && is_string(static::$defaultOutput)) {
static::$defaultOutput = $this->outputStream;
@@ -49,9 +55,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
/**
* 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)
{
@@ -74,9 +80,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
/**
* 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)
{
@@ -93,9 +99,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
/**
* 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)
{
@@ -108,33 +114,43 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
/**
* Dumps 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 Data $data A Data object
+ * @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)
{
- $exception = null;
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
+
+ if ($returnDump = true === $output) {
+ $output = fopen('php://memory', 'r+b');
+ }
if ($output) {
$prevOutput = $this->setOutput($output);
}
try {
$data->dump($this);
$this->dumpLine(-1);
- } catch (\Exception $exception) {
- // Re-thrown below
- }
- if ($output) {
- $this->setOutput($prevOutput);
- }
- if (null !== $exception) {
- throw $exception;
+
+ if ($returnDump) {
+ $result = stream_get_contents($output, -1, 0);
+ fclose($output);
+
+ return $result;
+ }
+ } finally {
+ if ($output) {
+ $this->setOutput($prevOutput);
+ }
}
}
/**
* 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)
{
@@ -145,8 +161,9 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
/**
* Generic line dumper callback.
*
- * @param string $line The line to write.
- * @param int $depth The recursive depth in the dumped structure.
+ * @param string $line The line to write
+ * @param int $depth The recursive depth in the dumped structure
+ * @param string $indentPad The line indent pad
*/
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.
*
- * @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)
{
+ 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)) {
return $c;
}
diff --git a/htdocs/includes/symfony/var-dumper/Dumper/CliDumper.php b/htdocs/includes/symfony/var-dumper/Dumper/CliDumper.php
index bca2abcb3d0..540f9245fdf 100644
--- a/htdocs/includes/symfony/var-dumper/Dumper/CliDumper.php
+++ b/htdocs/includes/symfony/var-dumper/Dumper/CliDumper.php
@@ -54,12 +54,12 @@ class CliDumper extends AbstractDumper
/**
* {@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')) {
- // Use only the base 16 xterm colors when using ANSICON
+ if ('\\' === DIRECTORY_SEPARATOR && 'ON' !== @getenv('ConEmuANSI') && 'xterm' !== @getenv('TERM')) {
+ // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI
$this->setStyles(array(
'default' => '31',
'num' => '1;34',
@@ -97,7 +97,7 @@ class CliDumper extends AbstractDumper
/**
* 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)
{
@@ -112,9 +112,13 @@ class CliDumper extends AbstractDumper
$this->dumpKey($cursor);
$style = 'const';
- $attr = array();
+ $attr = $cursor->attr;
switch ($type) {
+ case 'default':
+ $style = 'default';
+ break;
+
case 'integer':
$style = 'num';
break;
@@ -123,9 +127,9 @@ class CliDumper extends AbstractDumper
$style = 'num';
switch (true) {
- 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:
$value = (string) $value;
if (false === strpos($value, $this->decimalPoint)) {
@@ -144,8 +148,8 @@ class CliDumper extends AbstractDumper
break;
default:
- $attr['value'] = isset($value[0]) && !preg_match('//u', $value) ? $this->utf8Encode($value) : $value;
- $value = isset($type[0]) && !preg_match('//u', $type) ? $this->utf8Encode($type) : $type;
+ $attr += array('value' => $this->utf8Encode($value));
+ $value = $this->utf8Encode($type);
break;
}
@@ -160,6 +164,7 @@ class CliDumper extends AbstractDumper
public function dumpString(Cursor $cursor, $str, $bin, $cut)
{
$this->dumpKey($cursor);
+ $attr = $cursor->attr;
if ($bin) {
$str = $this->utf8Encode($str);
@@ -168,8 +173,8 @@ class CliDumper extends AbstractDumper
$this->line .= '""';
$this->dumpLine($cursor->depth, true);
} else {
- $attr = array(
- 'length' => 0 <= $cut ? iconv_strlen($str, 'UTF-8') + $cut : 0,
+ $attr += array(
+ 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,
'binary' => $bin,
);
$str = explode("\n", $str);
@@ -180,6 +185,9 @@ class CliDumper extends AbstractDumper
$m = count($str) - 1;
$i = $lineCut = 0;
+ if (self::DUMP_STRING_LENGTH & $this->flags) {
+ $this->line .= '('.$attr['length'].') ';
+ }
if ($bin) {
$this->line .= 'b';
}
@@ -195,8 +203,8 @@ class CliDumper extends AbstractDumper
if ($i < $m) {
$str .= "\n";
}
- if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = iconv_strlen($str, 'UTF-8')) {
- $str = iconv_substr($str, 0, $this->maxStringWidth, 'UTF-8');
+ if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {
+ $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');
$lineCut = $len - $this->maxStringWidth;
}
if ($m && 0 < $cursor->depth) {
@@ -241,15 +249,13 @@ class CliDumper extends AbstractDumper
{
$this->dumpKey($cursor);
- if (!preg_match('//u', $class)) {
- $class = $this->utf8Encode($class);
- }
+ $class = $this->utf8Encode($class);
if (Cursor::HASH_OBJECT === $type) {
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{';
} elseif (Cursor::HASH_RESOURCE === $type) {
$prefix = $this->style('note', $class.' resource').($hasChild ? ' {' : ' ');
} 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) {
@@ -280,9 +286,9 @@ class CliDumper extends AbstractDumper
/**
* Dumps an ellipsis for cut children.
*
- * @param Cursor $cursor The Cursor position in the dump.
- * @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 Cursor $cursor The Cursor position in the dump
+ * @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
*/
protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut)
{
@@ -300,7 +306,7 @@ class CliDumper extends AbstractDumper
/**
* 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)
{
@@ -314,6 +320,9 @@ class CliDumper extends AbstractDumper
switch ($cursor->hashType) {
default:
case Cursor::HASH_INDEXED:
+ if (self::DUMP_LIGHT_ARRAY & $this->flags) {
+ break;
+ }
$style = 'index';
case Cursor::HASH_ASSOC:
if (is_int($key)) {
@@ -332,13 +341,17 @@ class CliDumper extends AbstractDumper
} elseif (0 < strpos($key, "\0", 1)) {
$key = explode("\0", substr($key, 1), 2);
- switch ($key[0]) {
+ switch ($key[0][0]) {
case '+': // User inserted keys
$attr['dynamic'] = true;
$this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
break 2;
case '~':
$style = 'meta';
+ if (isset($key[0][1])) {
+ parse_str(substr($key[0], 1), $attr);
+ $attr += array('binary' => $cursor->hashKeyIsBinary);
+ }
break;
case '*':
$style = 'protected';
@@ -368,11 +381,11 @@ class CliDumper extends AbstractDumper
/**
* Decorates a value with some style.
*
- * @param string $style The type of style being applied.
- * @param string $value The value being styled.
- * @param array $attr Optional context information.
+ * @param string $style The type of style being applied
+ * @param string $value The value being styled
+ * @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())
{
@@ -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()
{
@@ -446,7 +459,12 @@ class CliDumper extends AbstractDumper
}
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')) {
$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;
diff --git a/htdocs/includes/symfony/var-dumper/Dumper/DataDumperInterface.php b/htdocs/includes/symfony/var-dumper/Dumper/DataDumperInterface.php
index ee6060cebf6..2c3d9db850d 100644
--- a/htdocs/includes/symfony/var-dumper/Dumper/DataDumperInterface.php
+++ b/htdocs/includes/symfony/var-dumper/Dumper/DataDumperInterface.php
@@ -23,7 +23,7 @@ interface DataDumperInterface
/**
* Dumps a Data object.
*
- * @param Data $data A Data object.
+ * @param Data $data A Data object
*/
public function dump(Data $data);
}
diff --git a/htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php b/htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php
index 28af8e4cb22..cc0b1ce179c 100644
--- a/htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php
+++ b/htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php
@@ -25,13 +25,13 @@ class HtmlDumper extends CliDumper
protected $dumpHeader;
protected $dumpPrefix = '
*/
-class CasterTest extends \PHPUnit_Framework_TestCase
+class CasterTest extends TestCase
{
use VarDumperTestTrait;
diff --git a/htdocs/includes/symfony/var-dumper/Tests/Caster/ExceptionCasterTest.php b/htdocs/includes/symfony/var-dumper/Tests/Caster/ExceptionCasterTest.php
new file mode 100644
index 00000000000..e0fb177b4bb
--- /dev/null
+++ b/htdocs/includes/symfony/var-dumper/Tests/Caster/ExceptionCasterTest.php
@@ -0,0 +1,225 @@
+
+ *
+ * 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('
*/
-class PdoCasterTest extends \PHPUnit_Framework_TestCase
+class PdoCasterTest extends TestCase
{
+ use VarDumperTestTrait;
+
/**
* @requires extension pdo_sqlite
*/
@@ -36,22 +40,25 @@ class PdoCasterTest extends \PHPUnit_Framework_TestCase
$this->assertSame('NATURAL', $attr['CASE']->class);
$this->assertSame('BOTH', $attr['DEFAULT_FETCH_MODE']->class);
- $xCast = array(
- "\0~\0inTransaction" => $pdo->inTransaction(),
- "\0~\0attributes" => array(
- 'CASE' => $attr['CASE'],
- 'ERRMODE' => $attr['ERRMODE'],
- 'PERSISTENT' => false,
- 'DRIVER_NAME' => 'sqlite',
- 'ORACLE_NULLS' => $attr['ORACLE_NULLS'],
- 'CLIENT_VERSION' => $pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION),
- 'SERVER_VERSION' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION),
- 'STATEMENT_CLASS' => array('PDOStatement'),
- 'DEFAULT_FETCH_MODE' => $attr['DEFAULT_FETCH_MODE'],
- ),
- );
- unset($cast["\0~\0attributes"]['STATEMENT_CLASS'][1]);
+ $xDump = <<<'EODUMP'
+array:2 [
+ "\x00~\x00inTransaction" => false
+ "\x00~\x00attributes" => array:9 [
+ "CASE" => NATURAL
+ "ERRMODE" => SILENT
+ "PERSISTENT" => false
+ "DRIVER_NAME" => "sqlite"
+ "ORACLE_NULLS" => NATURAL
+ "CLIENT_VERSION" => "%s"
+ "SERVER_VERSION" => "%s"
+ "STATEMENT_CLASS" => array:%d [
+ 0 => "PDOStatement"%A
+ ]
+ "DEFAULT_FETCH_MODE" => BOTH
+ ]
+]
+EODUMP;
- $this->assertSame($xCast, $cast);
+ $this->assertDumpMatchesFormat($xDump, $cast);
}
}
diff --git a/htdocs/includes/symfony/var-dumper/Tests/Caster/RedisCasterTest.php b/htdocs/includes/symfony/var-dumper/Tests/Caster/RedisCasterTest.php
new file mode 100644
index 00000000000..af038192f5c
--- /dev/null
+++ b/htdocs/includes/symfony/var-dumper/Tests/Caster/RedisCasterTest.php
@@ -0,0 +1,85 @@
+
+ *
+ * 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
+ * @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);
+ }
+}
diff --git a/htdocs/includes/symfony/var-dumper/Tests/Caster/ReflectionCasterTest.php b/htdocs/includes/symfony/var-dumper/Tests/Caster/ReflectionCasterTest.php
index 0d7147fbcd2..5495a78e40f 100644
--- a/htdocs/includes/symfony/var-dumper/Tests/Caster/ReflectionCasterTest.php
+++ b/htdocs/includes/symfony/var-dumper/Tests/Caster/ReflectionCasterTest.php
@@ -11,13 +11,15 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
+use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass;
/**
* @author Nicolas Grekas
*/
-class ReflectionCasterTest extends \PHPUnit_Framework_TestCase
+class ReflectionCasterTest extends TestCase
{
use VarDumperTestTrait;
@@ -49,7 +51,7 @@ ReflectionClass {
"export" => ReflectionMethod {
+name: "export"
+class: "ReflectionClass"
- parameters: {
+%A parameters: {
$%s: ReflectionParameter {
%A position: 0
%A
@@ -75,7 +77,7 @@ Closure {
\$b: & 123
}
file: "%sReflectionCasterTest.php"
- line: "65 to 65"
+ line: "67 to 67"
}
EOTXT
, $var
@@ -91,7 +93,7 @@ EOTXT
ReflectionParameter {
+name: "arg1"
position: 0
- typeHint: "Symfony\Component\VarDumper\Tests\Caster\NotExistingClass"
+ typeHint: "Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass"
default: null
}
EOTXT
@@ -146,83 +148,88 @@ EOTXT
*/
public function testGenerator()
{
- $g = new GeneratorDemo();
- $g = $g->baz();
- $r = new \ReflectionGenerator($g);
+ if (extension_loaded('xdebug')) {
+ $this->markTestSkipped('xdebug is active');
+ }
- $xDump = <<<'EODUMP'
+ $generator = new GeneratorDemo();
+ $generator = $generator->baz();
+
+ $expectedDump = <<<'EODUMP'
Generator {
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
executing: {
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): {
- %sGeneratorDemo.php:14: """
- {\n
- yield from bar();\n
- }\n
- """
+ %sGeneratorDemo.php:14: {
+ : {
+ : yield from bar();
+ : }
+ }
}
}
+ closed: false
}
EODUMP;
- $this->assertDumpMatchesFormat($xDump, $g);
+ $this->assertDumpMatchesFormat($expectedDump, $generator);
- foreach ($g as $v) {
+ foreach ($generator as $v) {
break;
}
- $xDump = <<<'EODUMP'
+ $expectedDump = <<<'EODUMP'
array:2 [
0 => ReflectionGenerator {
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
trace: {
- 3. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() ==> yield(): {
- src: {
- %sGeneratorDemo.php:9: """
- {\n
- yield 1;\n
- }\n
- """
- }
+ %sGeneratorDemo.php:9: {
+ : {
+ : yield 1;
+ : }
}
- 2. Symfony\Component\VarDumper\Tests\Fixtures\bar() ==> Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
- src: {
- %sGeneratorDemo.php:20: """
- {\n
- yield from GeneratorDemo::foo();\n
- }\n
- """
- }
+ %sGeneratorDemo.php:20: {
+ : {
+ : yield from GeneratorDemo::foo();
+ : }
}
- 1. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() ==> Symfony\Component\VarDumper\Tests\Fixtures\bar(): {
- src: {
- %sGeneratorDemo.php:14: """
- {\n
- yield from bar();\n
- }\n
- """
- }
+ %sGeneratorDemo.php:14: {
+ : {
+ : yield from bar();
+ : }
}
}
+ closed: false
}
1 => Generator {
executing: {
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
- %sGeneratorDemo.php:10: """
- yield 1;\n
- }\n
- \n
- """
+ %sGeneratorDemo.php:10: {
+ : yield 1;
+ : }
+ :
+ }
}
}
+ closed: false
}
]
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)
{
}
diff --git a/htdocs/includes/symfony/var-dumper/Tests/Caster/SplCasterTest.php b/htdocs/includes/symfony/var-dumper/Tests/Caster/SplCasterTest.php
index 5d71e8d379d..e2181d90b5b 100644
--- a/htdocs/includes/symfony/var-dumper/Tests/Caster/SplCasterTest.php
+++ b/htdocs/includes/symfony/var-dumper/Tests/Caster/SplCasterTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
/**
* @author Grégoire Pineau
*/
-class CliDumperTest extends \PHPUnit_Framework_TestCase
+class CliDumperTest extends TestCase
{
use VarDumperTestTrait;
@@ -62,15 +65,12 @@ array:24 [
7 => b"é\\x00"
"[]" => []
"res" => stream resource {@{$res}
- wrapper_type: "plainfile"
+%A wrapper_type: "plainfile"
stream_type: "STDIO"
mode: "r"
unread_bytes: 0
seekable: true
- timed_out: false
- blocked: true
- eof: false
- options: []
+%A options: []
}
"obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d
+foo: "foo"
@@ -118,7 +118,7 @@ EOTXT
$var = xml_parser_create();
$this->assertDumpMatchesFormat(
- <<
*/
-class HtmlDumperTest extends \PHPUnit_Framework_TestCase
+class HtmlDumperTest extends TestCase
{
public function testGet()
{
@@ -59,26 +60,24 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
4 => INF
5 => -INF
6 => {$intMax}
- "str" => "d&%s;j&%s;\\n"
- 7 => b"&%s;\\x00"
+ "str" => "d&%s;j&%s;\\n"
+ 7 => b"&%s;\\x00"
"[]" => []
"res" => stream resource @{$res}
- : "plainfile"
+%A : "plainfile"
: "STDIO"
: "r"
: 0
: true
- : false
- : true
- : false
- : []
+%A : []
}
"obj" => DumbFoo {#%d
+foo: "foo"
+"bar": "bar"
}
"closure" => Closure {{$r}
- : "Symfony\Component\VarDumper\Tests\HtmlDumperTest"
+ : "Symfony\Component\VarDumper\Tests\HtmlDumperTest"
: HtmlDumperTest {{$r} &%s;}
: {
: {}
@@ -87,7 +86,8 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
: null
}
}
- : "{$var['file']}"
+ : "%sTests%eFixtures%edumb-var.php"
: "{$var['line']} to {$var['line']}"
}
"line" => {$var['line']}
@@ -123,19 +123,41 @@ EOTXT
$cloner = new VarCloner();
$data = $cloner->cloneVar($var);
- $out = fopen('php://memory', 'r+b');
- $dumper->dump($data, $out);
- rewind($out);
- $out = stream_get_contents($out);
+ $out = $dumper->dump($data, true);
$this->assertStringMatchesFormat(
- <<
*/
-class VarClonerTest extends \PHPUnit_Framework_TestCase
+class VarClonerTest extends TestCase
{
public function testMaxIntBoundary()
{
@@ -41,6 +42,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
[handle] => 0
[refCount] => 0
[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
[maxItemsPerDepth: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
[refCount] => 0
[position] => 1
+ [attr] => Array
+ (
+ )
+
)
)
@@ -99,6 +110,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
[handle] => %i
[refCount] => 0
[position] => 2
+ [attr] => Array
+ (
+ )
+
)
[\000+\0002] => Symfony\Component\VarDumper\Cloner\Stub Object
@@ -110,6 +125,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
[handle] => %i
[refCount] => 0
[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
[maxItemsPerDepth: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));
}
+ 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()
{
$cloner = new VarCloner(array(
@@ -165,6 +266,10 @@ Symfony\Component\VarDumper\Cloner\Data Object
[handle] => %i
[refCount] => 0
[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
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
diff --git a/htdocs/includes/symfony/var-dumper/composer.json b/htdocs/includes/symfony/var-dumper/composer.json
index 05955f69430..44dbdebcce2 100644
--- a/htdocs/includes/symfony/var-dumper/composer.json
+++ b/htdocs/includes/symfony/var-dumper/composer.json
@@ -20,9 +20,14 @@
"symfony/polyfill-mbstring": "~1.0"
},
"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": {
+ "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": ""
},
"autoload": {
@@ -35,7 +40,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.2-dev"
}
}
}
diff --git a/htdocs/includes/symfony/var-dumper/phpunit.xml.dist b/htdocs/includes/symfony/var-dumper/phpunit.xml.dist
index bb16a3a4ec0..4a25f42db82 100644
--- a/htdocs/includes/symfony/var-dumper/phpunit.xml.dist
+++ b/htdocs/includes/symfony/var-dumper/phpunit.xml.dist
@@ -5,9 +5,13 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
';
- protected $dumpSuffix = '
';
+ protected $dumpSuffix = '';
protected $dumpId = 'sf-dump';
protected $colors = true;
protected $headerIsDumped = false;
protected $lastDepth = -1;
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',
'const' => 'font-weight:bold',
'str' => 'font-weight:bold; color:#56DB3A',
@@ -43,27 +43,24 @@ class HtmlDumper extends CliDumper
'meta' => 'color:#B729D9',
'key' => 'color:#56DB3A',
'index' => 'color:#1299DA',
+ 'ellipsis' => 'color:#FF8400',
);
+ private $displayOptions = array(
+ 'maxDepth' => 1,
+ 'maxStringLength' => 160,
+ 'fileLinkFormat' => null,
+ );
+ private $extraDisplayOptions = array();
+
/**
* {@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();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setOutput($output)
- {
- if ($output !== $prev = parent::setOutput($output)) {
- $this->headerIsDumped = false;
- }
-
- return $prev;
+ $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
}
/**
@@ -75,10 +72,21 @@ class HtmlDumper extends CliDumper
$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.
*
- * @param string $header An HTML string.
+ * @param string $header An HTML string
*/
public function setDumpHeader($header)
{
@@ -88,8 +96,8 @@ class HtmlDumper extends CliDumper
/**
* Sets an HTML prefix and suffix that will encapse every single dump.
*
- * @param string $prefix The prepended HTML string.
- * @param string $suffix The appended HTML string.
+ * @param string $prefix The prepended HTML string
+ * @param string $suffix The appended HTML string
*/
public function setDumpBoundaries($prefix, $suffix)
{
@@ -100,10 +108,13 @@ class HtmlDumper extends CliDumper
/**
* {@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();
+
+ return $result;
}
/**
@@ -111,13 +122,13 @@ class HtmlDumper extends CliDumper
*/
protected function getDumpHeader()
{
- $this->headerIsDumped = true;
+ $this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
if (null !== $this->dumpHeader) {
return $this->dumpHeader;
}
- $line = <<<'EOHTML'
+ $line = str_replace('{$options}', json_encode($this->displayOptions, JSON_FORCE_OBJECT), <<<'EOHTML'
-'.$this->dumpHeader;
@@ -374,7 +448,7 @@ EOHTML;
return '';
}
- $v = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
+ $v = esc($value);
if ('ref' === $style) {
if (empty($attr['count'])) {
@@ -385,41 +459,47 @@ EOHTML;
return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v);
}
- if ('const' === $style && array_key_exists('value', $attr)) {
- $style .= sprintf(' title="%s"', htmlspecialchars(json_encode($attr['value']), ENT_QUOTES, 'UTF-8'));
+ if ('const' === $style && isset($attr['value'])) {
+ $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
} elseif ('public' === $style) {
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
} 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, '\\')) {
return sprintf('%s', $v, $style, substr($v, $c + 1));
} elseif ('protected' === $style) {
$style .= ' title="Protected property"';
+ } elseif ('meta' === $style && isset($attr['title'])) {
+ $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title'])));
} 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('%s%s', substr($v, 0, -strlen($label)), $label);
}
- $map = static::$controlCharsMap;
- $style = "";
- $v = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $style) {
- $s = '';
+ $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
+ $s = '';
$c = $c[$i = 0];
do {
$s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', ord($c[$i]));
} while (isset($c[++$i]));
- return $s.$style;
- }, $v, -1, $cchrCount);
+ return $s.'';
+ }, $v).'';
- if ($cchrCount && '<' === $v[0]) {
- $v = substr($v, 7);
- } else {
- $v = $style.$v;
+ if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) {
+ $attr['href'] = $href;
}
- if ($cchrCount && '>' === substr($v, -1)) {
- $v = substr($v, 0, -strlen($style));
- } else {
- $v .= '';
+ if (isset($attr['href'])) {
+ $v = sprintf('%s', esc($this->utf8Encode($attr['href'])), $v);
+ }
+ if (isset($attr['lang'])) {
+ $v = sprintf('%s', esc($attr['lang']), $v);
}
return $v;
@@ -433,12 +513,17 @@ EOHTML;
if (-1 === $this->lastDepth) {
$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;
}
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;
@@ -449,4 +534,20 @@ EOHTML;
}
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');
}
diff --git a/htdocs/includes/symfony/var-dumper/LICENSE b/htdocs/includes/symfony/var-dumper/LICENSE
index ef1cde91a61..207646a052d 100644
--- a/htdocs/includes/symfony/var-dumper/LICENSE
+++ b/htdocs/includes/symfony/var-dumper/LICENSE
@@ -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
of this software and associated documentation files (the "Software"), to deal
diff --git a/htdocs/includes/symfony/var-dumper/README.md b/htdocs/includes/symfony/var-dumper/README.md
index 71bff335a70..3b5d55f5f5b 100644
--- a/htdocs/includes/symfony/var-dumper/README.md
+++ b/htdocs/includes/symfony/var-dumper/README.md
@@ -1,14 +1,15 @@
-Symfony mechanism for exploring and dumping PHP variables
-=========================================================
+VarDumper Component
+===================
-This component provides a mechanism that allows exploring then dumping
-any PHP variable.
+The VarDumper component provides mechanisms for walking through any arbitrary
+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
-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.
+Resources
+---------
-The component exposes all the parts involved in the different steps of
-cloning then dumping a PHP variable, while applying size limits and having
-specialized output formats and methods.
+ * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [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)
diff --git a/htdocs/includes/symfony/var-dumper/Test/VarDumperTestTrait.php b/htdocs/includes/symfony/var-dumper/Test/VarDumperTestTrait.php
index e5f6bf5b98e..40ec83d1322 100644
--- a/htdocs/includes/symfony/var-dumper/Test/VarDumperTestTrait.php
+++ b/htdocs/includes/symfony/var-dumper/Test/VarDumperTestTrait.php
@@ -29,17 +29,20 @@ trait VarDumperTestTrait
$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->setMaxItems(-1);
- $dumper = new CliDumper($h);
+ $dumper = new CliDumper(null, null, $flags);
$dumper->setColors(false);
- $dumper->dump($cloner->cloneVar($data)->withRefHandles(false));
- $data = stream_get_contents($h, -1, 0);
- fclose($h);
+ $data = $cloner->cloneVar($data)->withRefHandles(false);
+ if (null !== $key && null === $data = $data->seek($key)) {
+ return;
+ }
- return rtrim($data);
+ return rtrim($dumper->dump($data, true));
}
}
diff --git a/htdocs/includes/symfony/var-dumper/Tests/Caster/CasterTest.php b/htdocs/includes/symfony/var-dumper/Tests/Caster/CasterTest.php
index 43d389ce1c0..105d5638ee1 100644
--- a/htdocs/includes/symfony/var-dumper/Tests/Caster/CasterTest.php
+++ b/htdocs/includes/symfony/var-dumper/Tests/Caster/CasterTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
/**
* @author Nicolas Grekas