Przeglądaj źródła

Update of var_dumper package 3.0 -> 3.2

lmarcouiller 3 lat temu
rodzic
commit
b0133224d8
51 zmienionych plików z 2386 dodań i 578 usunięć
  1. 1 1
      composer.json
  2. 2 2
      composer.lock
  3. 75 29
      htdocs/includes/symfony/var-dumper/Caster/AmqpCaster.php
  4. 80 0
      htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php
  5. 35 9
      htdocs/includes/symfony/var-dumper/Caster/Caster.php
  6. 87 0
      htdocs/includes/symfony/var-dumper/Caster/ClassStub.php
  7. 5 0
      htdocs/includes/symfony/var-dumper/Caster/ConstStub.php
  8. 4 1
      htdocs/includes/symfony/var-dumper/Caster/CutStub.php
  9. 3 3
      htdocs/includes/symfony/var-dumper/Caster/DOMCaster.php
  10. 4 1
      htdocs/includes/symfony/var-dumper/Caster/EnumStub.php
  11. 124 64
      htdocs/includes/symfony/var-dumper/Caster/ExceptionCaster.php
  12. 51 0
      htdocs/includes/symfony/var-dumper/Caster/LinkStub.php
  13. 6 0
      htdocs/includes/symfony/var-dumper/Caster/PdoCaster.php
  14. 77 0
      htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php
  15. 57 35
      htdocs/includes/symfony/var-dumper/Caster/ReflectionCaster.php
  16. 7 2
      htdocs/includes/symfony/var-dumper/Caster/ResourceCaster.php
  17. 7 3
      htdocs/includes/symfony/var-dumper/Caster/SplCaster.php
  18. 13 3
      htdocs/includes/symfony/var-dumper/Caster/StubCaster.php
  19. 77 0
      htdocs/includes/symfony/var-dumper/Caster/XmlReaderCaster.php
  20. 31 22
      htdocs/includes/symfony/var-dumper/Cloner/AbstractCloner.php
  21. 2 2
      htdocs/includes/symfony/var-dumper/Cloner/ClonerInterface.php
  22. 1 0
      htdocs/includes/symfony/var-dumper/Cloner/Cursor.php
  23. 75 23
      htdocs/includes/symfony/var-dumper/Cloner/Data.php
  24. 16 16
      htdocs/includes/symfony/var-dumper/Cloner/DumperInterface.php
  25. 1 0
      htdocs/includes/symfony/var-dumper/Cloner/Stub.php
  26. 54 28
      htdocs/includes/symfony/var-dumper/Cloner/VarCloner.php
  27. 52 27
      htdocs/includes/symfony/var-dumper/Dumper/AbstractDumper.php
  28. 47 29
      htdocs/includes/symfony/var-dumper/Dumper/CliDumper.php
  29. 1 1
      htdocs/includes/symfony/var-dumper/Dumper/DataDumperInterface.php
  30. 170 69
      htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php
  31. 1 1
      htdocs/includes/symfony/var-dumper/LICENSE
  32. 12 11
      htdocs/includes/symfony/var-dumper/README.md
  33. 10 7
      htdocs/includes/symfony/var-dumper/Test/VarDumperTestTrait.php
  34. 2 1
      htdocs/includes/symfony/var-dumper/Tests/Caster/CasterTest.php
  35. 225 0
      htdocs/includes/symfony/var-dumper/Tests/Caster/ExceptionCasterTest.php
  36. 25 18
      htdocs/includes/symfony/var-dumper/Tests/Caster/PdoCasterTest.php
  37. 85 0
      htdocs/includes/symfony/var-dumper/Tests/Caster/RedisCasterTest.php
  38. 54 47
      htdocs/includes/symfony/var-dumper/Tests/Caster/ReflectionCasterTest.php
  39. 30 9
      htdocs/includes/symfony/var-dumper/Tests/Caster/SplCasterTest.php
  40. 171 0
      htdocs/includes/symfony/var-dumper/Tests/Caster/StubCasterTest.php
  41. 248 0
      htdocs/includes/symfony/var-dumper/Tests/Caster/XmlReaderCasterTest.php
  42. 157 84
      htdocs/includes/symfony/var-dumper/Tests/CliDumperTest.php
  43. 11 0
      htdocs/includes/symfony/var-dumper/Tests/Fixtures/FooInterface.php
  44. 7 0
      htdocs/includes/symfony/var-dumper/Tests/Fixtures/NotLoadableClass.php
  45. 15 11
      htdocs/includes/symfony/var-dumper/Tests/Fixtures/Twig.php
  46. 10 0
      htdocs/includes/symfony/var-dumper/Tests/Fixtures/xml_reader.xml
  47. 37 15
      htdocs/includes/symfony/var-dumper/Tests/HtmlDumperTest.php
  48. 2 1
      htdocs/includes/symfony/var-dumper/Tests/Test/VarDumperTestTraitTest.php
  49. 108 1
      htdocs/includes/symfony/var-dumper/Tests/VarClonerTest.php
  50. 7 2
      htdocs/includes/symfony/var-dumper/composer.json
  51. 4 0
      htdocs/includes/symfony/var-dumper/phpunit.xml.dist

+ 1 - 1
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",

+ 2 - 2
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": {

+ 75 - 29
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.'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.'userId' => $c->getUserId(),
-            $prefix.'appId' => $c->getAppId(),
-            $prefix.'messageId' => $c->getMessageId(),
-            $prefix.'replyTo' => $c->getReplyTo(),
-            $prefix.'correlationId' => $c->getCorrelationId(),
-            $prefix.'headers' => $c->getHeaders(),
+            $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;

+ 80 - 0
htdocs/includes/symfony/var-dumper/Caster/ArgsStub.php

@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents a list of function arguments.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ArgsStub extends EnumStub
+{
+    private static $parameters = array();
+
+    public function __construct(array $args, $function, $class)
+    {
+        list($variadic, $params) = self::getParameters($function, $class);
+
+        $values = array();
+        foreach ($args as $k => $v) {
+            $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
+        }
+        if (null === $params) {
+            parent::__construct($values, false);
+
+            return;
+        }
+        if (count($values) < count($params)) {
+            $params = array_slice($params, 0, count($values));
+        } elseif (count($values) > count($params)) {
+            $values[] = new EnumStub(array_splice($values, count($params)), false);
+            $params[] = $variadic;
+        }
+        if (array('...') === $params) {
+            $this->dumpKeys = false;
+            $this->value = $values[0]->value;
+        } else {
+            $this->value = array_combine($params, $values);
+        }
+    }
+
+    private static function getParameters($function, $class)
+    {
+        if (isset(self::$parameters[$k = $class.'::'.$function])) {
+            return self::$parameters[$k];
+        }
+
+        try {
+            $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function);
+        } catch (\ReflectionException $e) {
+            return array(null, null);
+        }
+
+        $variadic = '...';
+        $params = array();
+        foreach ($r->getParameters() as $v) {
+            $k = '$'.$v->name;
+            if ($v->isPassedByReference()) {
+                $k = '&'.$k;
+            }
+            if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
+                $variadic .= $k;
+            } else {
+                $params[] = $k;
+            }
+        }
+
+        return self::$parameters[$k] = array($variadic, $params);
+    }
+}

+ 35 - 9
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;
+    }
 }

+ 87 - 0
htdocs/includes/symfony/var-dumper/Caster/ClassStub.php

@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a PHP class identifier.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ClassStub extends ConstStub
+{
+    /**
+     * Constructor.
+     *
+     * @param string   A PHP identifier, e.g. a class, method, interface, etc. name
+     * @param callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
+     */
+    public function __construct($identifier, $callable = null)
+    {
+        $this->value = $identifier;
+
+        if (0 < $i = strrpos($identifier, '\\')) {
+            $this->attr['ellipsis'] = strlen($identifier) - $i;
+        }
+
+        try {
+            if (null !== $callable) {
+                if ($callable instanceof \Closure) {
+                    $r = new \ReflectionFunction($callable);
+                } elseif (is_object($callable)) {
+                    $r = array($callable, '__invoke');
+                } elseif (is_array($callable)) {
+                    $r = $callable;
+                } elseif (false !== $i = strpos($callable, '::')) {
+                    $r = array(substr($callable, 0, $i), substr($callable, 2 + $i));
+                } else {
+                    $r = new \ReflectionFunction($callable);
+                }
+            } elseif (false !== $i = strpos($identifier, '::')) {
+                $r = array(substr($identifier, 0, $i), substr($identifier, 2 + $i));
+            } else {
+                $r = new \ReflectionClass($identifier);
+            }
+
+            if (is_array($r)) {
+                try {
+                    $r = new \ReflectionMethod($r[0], $r[1]);
+                } catch (\ReflectionException $e) {
+                    $r = new \ReflectionClass($r[0]);
+                }
+            }
+        } catch (\ReflectionException $e) {
+            return;
+        }
+
+        if ($f = $r->getFileName()) {
+            $this->attr['file'] = $f;
+            $this->attr['line'] = $r->getStartLine();
+        }
+    }
+
+    public static function wrapCallable($callable)
+    {
+        if (is_object($callable) || !is_callable($callable)) {
+            return $callable;
+        }
+
+        if (!is_array($callable)) {
+            $callable = new static($callable);
+        } elseif (is_string($callable[0])) {
+            $callable[0] = new static($callable[0]);
+        } else {
+            $callable[1] = new static($callable[1], $callable);
+        }
+
+        return $callable;
+    }
+}

+ 5 - 0
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;
+    }
 }

+ 4 - 1
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;
 

+ 3 - 3
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;

+ 4 - 1
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;
     }
 }

+ 124 - 64
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;
-        }
-        $a[Caster::PREFIX_VIRTUAL.$j.'. {main}'.$lastCall] = new FrameStub(
-            array(
-                'object' => null,
-                'class' => null,
-                'type' => null,
-                'function' => '{main}',
-            ) + $frames[$i - 1],
-            $trace->keepArgs,
-            true
-        );
+            $lastCall = $call;
+        }
         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;
+
+                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']));
 
-                    try {
-                        $templateName = $template->getTemplateName();
-                        $templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
+                        $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);
     }
 }

+ 51 - 0
htdocs/includes/symfony/var-dumper/Caster/LinkStub.php

@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a file or a URL.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class LinkStub extends ConstStub
+{
+    public function __construct($label, $line = 0, $href = null)
+    {
+        $this->value = $label;
+
+        if (null === $href) {
+            $href = $label;
+        }
+        if (is_string($href)) {
+            if (0 === strpos($href, 'file://')) {
+                if ($href === $label) {
+                    $label = substr($label, 7);
+                }
+                $href = substr($href, 7);
+            } elseif (false !== strpos($href, '://')) {
+                $this->attr['href'] = $href;
+
+                return;
+            }
+            if (file_exists($href)) {
+                if ($line) {
+                    $this->attr['line'] = $line;
+                }
+                $this->attr['file'] = realpath($href) ?: $href;
+
+                if ($this->attr['file'] === $label && 3 < count($ellipsis = explode(DIRECTORY_SEPARATOR, $href))) {
+                    $this->attr['ellipsis'] = 2 + strlen(implode(array_slice($ellipsis, -2)));
+                }
+            }
+        }
+    }
+}

+ 6 - 0
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(

+ 77 - 0
htdocs/includes/symfony/var-dumper/Caster/RedisCaster.php

@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Redis class from ext-redis to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class RedisCaster
+{
+    private static $serializer = array(
+        \Redis::SERIALIZER_NONE => 'NONE',
+        \Redis::SERIALIZER_PHP => 'PHP',
+        2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY
+    );
+
+    public static function castRedis(\Redis $c, array $a, Stub $stub, $isNested)
+    {
+        $prefix = Caster::PREFIX_VIRTUAL;
+
+        if (defined('HHVM_VERSION_ID')) {
+            if (isset($a[Caster::PREFIX_PROTECTED.'serializer'])) {
+                $ser = $a[Caster::PREFIX_PROTECTED.'serializer'];
+                $a[Caster::PREFIX_PROTECTED.'serializer'] = isset(self::$serializer[$ser]) ? new ConstStub(self::$serializer[$ser], $ser) : $ser;
+            }
+
+            return $a;
+        }
+
+        if (!$connected = $c->isConnected()) {
+            return $a + array(
+                $prefix.'isConnected' => $connected,
+            );
+        }
+
+        $ser = $c->getOption(\Redis::OPT_SERIALIZER);
+        $retry = defined('Redis::OPT_SCAN') ? $c->getOption(\Redis::OPT_SCAN) : 0;
+
+        return $a + array(
+            $prefix.'isConnected' => $connected,
+            $prefix.'host' => $c->getHost(),
+            $prefix.'port' => $c->getPort(),
+            $prefix.'auth' => $c->getAuth(),
+            $prefix.'dbNum' => $c->getDbNum(),
+            $prefix.'timeout' => $c->getTimeout(),
+            $prefix.'persistentId' => $c->getPersistentID(),
+            $prefix.'options' => new EnumStub(array(
+                'READ_TIMEOUT' => $c->getOption(\Redis::OPT_READ_TIMEOUT),
+                'SERIALIZER' => isset(self::$serializer[$ser]) ? new ConstStub(self::$serializer[$ser], $ser) : $ser,
+                'PREFIX' => $c->getOption(\Redis::OPT_PREFIX),
+                'SCAN' => new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry),
+            )),
+        );
+    }
+
+    public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, $isNested)
+    {
+        $prefix = Caster::PREFIX_VIRTUAL;
+
+        return $a + array(
+            $prefix.'hosts' => $c->_hosts(),
+            $prefix.'function' => ClassStub::wrapCallable($c->_function()),
+        );
+    }
+}

+ 57 - 35
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();
         }
 

+ 7 - 2
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)

+ 7 - 3
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(),

+ 13 - 3
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);

+ 77 - 0
htdocs/includes/symfony/var-dumper/Caster/XmlReaderCaster.php

@@ -0,0 +1,77 @@
+<?php
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts XmlReader class to array representation.
+ *
+ * @author Baptiste Clavié <clavie.b@gmail.com>
+ */
+class XmlReaderCaster
+{
+    private static $nodeTypes = array(
+        \XmlReader::NONE => 'NONE',
+        \XmlReader::ELEMENT => 'ELEMENT',
+        \XmlReader::ATTRIBUTE => 'ATTRIBUTE',
+        \XmlReader::TEXT => 'TEXT',
+        \XmlReader::CDATA => 'CDATA',
+        \XmlReader::ENTITY_REF => 'ENTITY_REF',
+        \XmlReader::ENTITY => 'ENTITY',
+        \XmlReader::PI => 'PI (Processing Instruction)',
+        \XmlReader::COMMENT => 'COMMENT',
+        \XmlReader::DOC => 'DOC',
+        \XmlReader::DOC_TYPE => 'DOC_TYPE',
+        \XmlReader::DOC_FRAGMENT => 'DOC_FRAGMENT',
+        \XmlReader::NOTATION => 'NOTATION',
+        \XmlReader::WHITESPACE => 'WHITESPACE',
+        \XmlReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',
+        \XmlReader::END_ELEMENT => 'END_ELEMENT',
+        \XmlReader::END_ENTITY => 'END_ENTITY',
+        \XmlReader::XML_DECLARATION => 'XML_DECLARATION',
+    );
+
+    public static function castXmlReader(\XmlReader $reader, array $a, Stub $stub, $isNested)
+    {
+        $props = Caster::PREFIX_VIRTUAL.'parserProperties';
+        $info = array(
+            'localName' => $reader->localName,
+            'prefix' => $reader->prefix,
+            'nodeType' => new ConstStub(self::$nodeTypes[$reader->nodeType], $reader->nodeType),
+            'depth' => $reader->depth,
+            'isDefault' => $reader->isDefault,
+            'isEmptyElement' => \XmlReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement,
+            'xmlLang' => $reader->xmlLang,
+            'attributeCount' => $reader->attributeCount,
+            'value' => $reader->value,
+            'namespaceURI' => $reader->namespaceURI,
+            'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,
+            $props => array(
+                'LOADDTD' => $reader->getParserProperty(\XmlReader::LOADDTD),
+                'DEFAULTATTRS' => $reader->getParserProperty(\XmlReader::DEFAULTATTRS),
+                'VALIDATE' => $reader->getParserProperty(\XmlReader::VALIDATE),
+                'SUBST_ENTITIES' => $reader->getParserProperty(\XmlReader::SUBST_ENTITIES),
+            ),
+        );
+
+        if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, array(), $count)) {
+            $info[$props] = new EnumStub($info[$props]);
+            $info[$props]->cut = $count;
+        }
+
+        $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, array(), $count);
+        // +2 because hasValue and hasAttributes are always filtered
+        $stub->cut += $count + 2;
+
+        return $a + $info;
+    }
+}

+ 31 - 22
htdocs/includes/symfony/var-dumper/Cloner/AbstractCloner.php

@@ -22,6 +22,8 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
 abstract class AbstractCloner implements ClonerInterface
 {
     public static $defaultCasters = array(
+        '__PHP_Incomplete_Class' => 'Symfony\Component\VarDumper\Caster\Caster::castPhpIncompleteClass',
+
         'Symfony\Component\VarDumper\Caster\CutStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
         'Symfony\Component\VarDumper\Caster\CutArrayStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castCutArray',
         'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
@@ -67,6 +69,8 @@ abstract class AbstractCloner implements ClonerInterface
         'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
         'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
 
+        'XmlReader' => 'Symfony\Component\VarDumper\Caster\XmlReaderCaster::castXmlReader',
+
         'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
         'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
         'Error' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castError',
@@ -100,6 +104,9 @@ abstract class AbstractCloner implements ClonerInterface
 
         'MongoCursorInterface' => 'Symfony\Component\VarDumper\Caster\MongoCaster::castCursor',
 
+        'Redis' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedis',
+        'RedisArray' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedisArray',
+
         ':curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
         ':dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
         ':dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
@@ -111,6 +118,7 @@ abstract class AbstractCloner implements ClonerInterface
         ':pgsql result' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castResult',
         ':process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
         ':stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
+        ':persistent stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
         ':stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
         ':xml' => 'Symfony\Component\VarDumper\Caster\XmlResourceCaster::castXml',
     );
@@ -125,7 +133,7 @@ abstract class AbstractCloner implements ClonerInterface
     private $filter = 0;
 
     /**
-     * @param callable[]|null $casters A map of casters.
+     * @param callable[]|null $casters A map of casters
      *
      * @see addCasters
      */
@@ -146,7 +154,7 @@ abstract class AbstractCloner implements ClonerInterface
      * Resource types are to be prefixed with a `:`,
      * see e.g. static::$defaultCasters.
      *
-     * @param callable[] $casters A map of casters.
+     * @param callable[] $casters A map of casters
      */
     public function addCasters(array $casters)
     {
@@ -178,10 +186,10 @@ abstract class AbstractCloner implements ClonerInterface
     /**
      * Clones a PHP variable.
      *
-     * @param mixed $var    Any PHP variable.
-     * @param int   $filter A bit field of Caster::EXCLUDE_* constants.
+     * @param mixed $var    Any PHP variable
+     * @param int   $filter A bit field of Caster::EXCLUDE_* constants
      *
-     * @return Data The cloned variable represented by a Data object.
+     * @return Data The cloned variable represented by a Data object
      */
     public function cloneVar($var, $filter = 0)
     {
@@ -216,19 +224,19 @@ abstract class AbstractCloner implements ClonerInterface
     /**
      * Effectively clones the PHP variable.
      *
-     * @param mixed $var Any PHP variable.
+     * @param mixed $var Any PHP variable
      *
-     * @return array The cloned variable represented in an array.
+     * @return array The cloned variable represented in an array
      */
     abstract protected function doClone($var);
 
     /**
      * Casts an object to an array representation.
      *
-     * @param Stub $stub     The Stub for the casted object.
-     * @param bool $isNested True if the object is nested in the dumped structure.
+     * @param Stub $stub     The Stub for the casted object
+     * @param bool $isNested True if the object is nested in the dumped structure
      *
-     * @return array The object casted as array.
+     * @return array The object casted as array
      */
     protected function castObject(Stub $stub, $isNested)
     {
@@ -245,14 +253,15 @@ abstract class AbstractCloner implements ClonerInterface
                 new \ReflectionClass($class),
                 array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
             );
+            $classInfo[1] = array_map('strtolower', $classInfo[1]);
 
             $this->classInfo[$class] = $classInfo;
         }
 
-        $a = $this->callCaster('Symfony\Component\VarDumper\Caster\Caster::castObject', $obj, $classInfo[0], null, $isNested);
+        $a = Caster::castObject($obj, $classInfo[0]);
 
         foreach ($classInfo[1] as $p) {
-            if (!empty($this->casters[$p = strtolower($p)])) {
+            if (!empty($this->casters[$p])) {
                 foreach ($this->casters[$p] as $p) {
                     $a = $this->callCaster($p, $obj, $a, $stub, $isNested);
                 }
@@ -265,10 +274,10 @@ abstract class AbstractCloner implements ClonerInterface
     /**
      * Casts a resource to an array representation.
      *
-     * @param Stub $stub     The Stub for the casted resource.
-     * @param bool $isNested True if the object is nested in the dumped structure.
+     * @param Stub $stub     The Stub for the casted resource
+     * @param bool $isNested True if the object is nested in the dumped structure
      *
-     * @return array The resource casted as array.
+     * @return array The resource casted as array
      */
     protected function castResource(Stub $stub, $isNested)
     {
@@ -288,13 +297,13 @@ abstract class AbstractCloner implements ClonerInterface
     /**
      * Calls a custom caster.
      *
-     * @param callable        $callback The caster.
-     * @param object|resource $obj      The object/resource being casted.
-     * @param array           $a        The result of the previous cast for chained casters.
-     * @param Stub            $stub     The Stub for the casted object/resource.
-     * @param bool            $isNested True if $obj is nested in the dumped structure.
+     * @param callable        $callback The caster
+     * @param object|resource $obj      The object/resource being casted
+     * @param array           $a        The result of the previous cast for chained casters
+     * @param Stub            $stub     The Stub for the casted object/resource
+     * @param bool            $isNested True if $obj is nested in the dumped structure
      *
-     * @return array The casted object/resource.
+     * @return array The casted object/resource
      */
     private function callCaster($callback, $obj, $a, $stub, $isNested)
     {
@@ -305,7 +314,7 @@ abstract class AbstractCloner implements ClonerInterface
                 $a = $cast;
             }
         } catch (\Exception $e) {
-            $a[(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠'] = new ThrowingCasterException($e);
+            $a = array((Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)) + $a;
         }
 
         return $a;

+ 2 - 2
htdocs/includes/symfony/var-dumper/Cloner/ClonerInterface.php

@@ -19,9 +19,9 @@ interface ClonerInterface
     /**
      * Clones a PHP variable.
      *
-     * @param mixed $var Any PHP variable.
+     * @param mixed $var Any PHP variable
      *
-     * @return Data The cloned variable represented by a Data object.
+     * @return Data The cloned variable represented by a Data object
      */
     public function cloneVar($var);
 }

+ 1 - 0
htdocs/includes/symfony/var-dumper/Cloner/Cursor.php

@@ -38,4 +38,5 @@ class Cursor
     public $hashLength = 0;
     public $hashCut = 0;
     public $stop = false;
+    public $attr = array();
 }

+ 75 - 23
htdocs/includes/symfony/var-dumper/Cloner/Data.php

@@ -11,18 +11,22 @@
 
 namespace Symfony\Component\VarDumper\Cloner;
 
+use Symfony\Component\VarDumper\Caster\Caster;
+
 /**
  * @author Nicolas Grekas <p@tchwork.com>
  */
 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;

+ 16 - 16
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);
 }

+ 1 - 0
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();
 }

+ 54 - 28
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 = strlen(substr(ob_get_clean(), 17));
+                self::$hashMask = (int) substr(ob_get_clean(), 17);
             }
         }
 

+ 52 - 27
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;
         }

+ 47 - 29
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;

+ 1 - 1
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);
 }

+ 170 - 69
htdocs/includes/symfony/var-dumper/Dumper/HtmlDumper.php

@@ -25,13 +25,13 @@ class HtmlDumper extends CliDumper
 
     protected $dumpHeader;
     protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
-    protected $dumpSuffix = '</pre><script>Sfdump("%s")</script>';
+    protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';
     protected $dumpId = 'sf-dump';
     protected $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,42 +43,50 @@ 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();
+        $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
     }
 
     /**
      * {@inheritdoc}
      */
-    public function setOutput($output)
+    public function setStyles(array $styles)
     {
-        if ($output !== $prev = parent::setOutput($output)) {
-            $this->headerIsDumped = false;
-        }
-
-        return $prev;
+        $this->headerIsDumped = false;
+        $this->styles = $styles + $this->styles;
     }
 
     /**
-     * {@inheritdoc}
+     * Configures display options.
+     *
+     * @param array $displayOptions A map of display options to customize the behavior
      */
-    public function setStyles(array $styles)
+    public function setDisplayOptions(array $displayOptions)
     {
         $this->headerIsDumped = false;
-        $this->styles = $styles + $this->styles;
+        $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'
 <script>
 Sfdump = window.Sfdump || (function (doc) {
 
@@ -173,15 +184,30 @@ function toggle(a, recursive) {
     return true;
 };
 
-return function (root) {
+return function (root, x) {
     root = doc.getElementById(root);
 
+    var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '  ').replace(rxEsc, '\\$1')+')+', 'm'),
+        options = {$options},
+        elt = root.getElementsByTagName('A'),
+        len = elt.length,
+        i = 0, s, h,
+        t = [];
+
+    while (i < len) t.push(elt[i++]);
+
+    for (i in x) {
+        options[i] = x[i];
+    }
+
     function a(e, f) {
         addEventListener(root, e, function (e) {
             if ('A' == e.target.tagName) {
                 f(e.target, e);
             } else if ('A' == e.target.parentNode.tagName) {
                 f(e.target.parentNode, e);
+            } else if (e.target.nextElementSibling && 'A' == e.target.nextElementSibling.tagName) {
+                f(e.target.nextElementSibling, e, true);
             }
         });
     };
@@ -193,15 +219,17 @@ return function (root) {
             refStyle.innerHTML = '';
         }
     });
-    a('mouseover', function (a) {
-        if (a = idRx.exec(a.className)) {
+    a('mouseover', function (a, e, c) {
+        if (c) {
+            e.target.style.cursor = "pointer";
+        } else if (a = idRx.exec(a.className)) {
             try {
                 refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';
             } catch (e) {
             }
         }
     });
-    a('click', function (a, e) {
+    a('click', function (a, e, c) {
         if (/\bsf-dump-toggle\b/.test(a.className)) {
             e.preventDefault();
             if (!toggle(a, isCtrlKey(e))) {
@@ -222,7 +250,8 @@ return function (root) {
                 }
             }
 
-            if (doc.getSelection) {
+            if (c) {
+            } else if (doc.getSelection) {
                 try {
                     doc.getSelection().removeAllRanges();
                 } catch (e) {
@@ -231,31 +260,24 @@ return function (root) {
             } else {
                 doc.selection.empty();
             }
+        } else if (/\bsf-dump-str-toggle\b/.test(a.className)) {
+            e.preventDefault();
+            e = a.parentNode.parentNode;
+            e.className = e.className.replace(/sf-dump-str-(expand|collapse)/, a.parentNode.className);
         }
     });
 
-    var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '  ').replace(rxEsc, '\\$1')+')+', 'm'),
-        elt = root.getElementsByTagName('A'),
-        len = elt.length,
-        i = 0,
-        t = [];
-
-    while (i < len) t.push(elt[i++]);
-
     elt = root.getElementsByTagName('SAMP');
     len = elt.length;
     i = 0;
 
     while (i < len) t.push(elt[i++]);
-
-    root = t;
     len = t.length;
-    i = t = 0;
 
-    while (i < len) {
-        elt = root[i];
-        if ("SAMP" == elt.tagName) {
-            elt.className = "sf-dump-expanded";
+    for (i = 0; i < len; ++i) {
+        elt = t[i];
+        if ('SAMP' == elt.tagName) {
+            elt.className = 'sf-dump-expanded';
             a = elt.previousSibling || {};
             if ('A' != a.tagName) {
                 a = doc.createElement('A');
@@ -267,19 +289,24 @@ return function (root) {
             a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
             a.innerHTML += '<span>▼</span>';
             a.className += ' sf-dump-toggle';
+            x = 1;
             if ('sf-dump' != elt.parentNode.className) {
+                x += elt.parentNode.getAttribute('data-depth')/1;
+            }
+            elt.setAttribute('data-depth', x);
+            if (x > options.maxDepth) {
                 toggle(a);
             }
-        } else if ("sf-dump-ref" == elt.className && (a = elt.getAttribute('href'))) {
+        } else if ('sf-dump-ref' == elt.className && (a = elt.getAttribute('href'))) {
             a = a.substr(1);
             elt.className += ' '+a;
 
             if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
                 a = a != elt.nextSibling.id && doc.getElementById(a);
                 try {
-                    t = a.nextSibling;
+                    s = a.nextSibling;
                     elt.appendChild(a);
-                    t.parentNode.insertBefore(a, t);
+                    s.parentNode.insertBefore(a, s);
                     if (/^[@#]/.test(elt.innerHTML)) {
                         elt.innerHTML += ' <span>▶</span>';
                     } else {
@@ -295,13 +322,38 @@ return function (root) {
                 }
             }
         }
-        ++i;
+    }
+
+    if (0 >= options.maxStringLength) {
+        return;
+    }
+    try {
+        elt = root.querySelectorAll('.sf-dump-str');
+        len = elt.length;
+        i = 0;
+        t = [];
+
+        while (i < len) t.push(elt[i++]);
+        len = t.length;
+
+        for (i = 0; i < len; ++i) {
+            elt = t[i];
+            s = elt.innerText || elt.textContent;
+            x = s.length - options.maxStringLength;
+            if (0 < x) {
+                h = elt.innerHTML;
+                elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);
+                elt.className += ' sf-dump-str-collapse';
+                elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+
+                    '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>';
+            }
+        }
+    } catch (e) {
     }
 };
 
 })(document);
-</script>
-<style>
+</script><style>
 pre.sf-dump {
     display: block;
     white-space: pre;
@@ -323,11 +375,33 @@ pre.sf-dump a {
     cursor: pointer;
     border: 0;
     outline: none;
+    color: inherit;
 }
-EOHTML;
+pre.sf-dump .sf-dump-ellipsis {
+    display: inline-block;
+    overflow: visible;
+    text-overflow: ellipsis;
+    max-width: 5em;
+    white-space: nowrap;
+    overflow: hidden;
+    vertical-align: top;
+}
+pre.sf-dump code {
+    display:inline;
+    padding:0;
+    background:none;
+}
+.sf-dump-str-collapse .sf-dump-str-collapse {
+    display: none;
+}
+.sf-dump-str-expand .sf-dump-str-expand {
+    display: none;
+}
+EOHTML
+        );
 
         foreach ($this->styles as $class => $style) {
-            $line .= 'pre.sf-dump'.('default' !== $class ? ' .sf-dump-'.$class : '').'{'.$style.'}';
+            $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';
         }
 
         return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
@@ -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('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
         }
 
-        if ('const' === $style && array_key_exists('value', $attr)) {
-            $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('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $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:&#10;`%s`"', $attr['class']);
+            $style .= sprintf(' title="Private property defined in class:&#10;`%s`"', esc($this->utf8Encode($attr['class'])));
         }
-
         $map = static::$controlCharsMap;
-        $style = "<span class=sf-dump-{$style}>";
-        $v = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $style) {
-            $s = '</span>';
+
+        if (isset($attr['ellipsis'])) {
+            $label = esc(substr($value, -$attr['ellipsis']));
+            $style = str_replace(' title="', " title=\"$v\n", $style);
+            $v = sprintf('<span class=sf-dump-ellipsis>%s</span>%s', substr($v, 0, -strlen($label)), $label);
+        }
+
+        $v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
+            $s = '<span class=sf-dump-default>';
             $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.'</span>';
+        }, $v).'</span>';
 
-        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 (isset($attr['href'])) {
+            $v = sprintf('<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $v);
         }
-        if ($cchrCount && '>' === substr($v, -1)) {
-            $v = substr($v, 0, -strlen($style));
-        } else {
-            $v .= '</span>';
+        if (isset($attr['lang'])) {
+            $v = sprintf('<code class="%s">%s</code>', 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');
 }

+ 1 - 1
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

+ 12 - 11
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)

+ 10 - 7
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));
     }
 }

+ 2 - 1
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 <p@tchwork.com>
  */
-class CasterTest extends \PHPUnit_Framework_TestCase
+class CasterTest extends TestCase
 {
     use VarDumperTestTrait;
 

+ 225 - 0
htdocs/includes/symfony/var-dumper/Tests/Caster/ExceptionCasterTest.php

@@ -0,0 +1,225 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\VarDumper\Caster\ExceptionCaster;
+use Symfony\Component\VarDumper\Caster\FrameStub;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+
+class ExceptionCasterTest extends TestCase
+{
+    use VarDumperTestTrait;
+
+    private function getTestException($msg, &$ref = null)
+    {
+        return new \Exception(''.$msg);
+    }
+
+    protected function tearDown()
+    {
+        ExceptionCaster::$srcContext = 1;
+        ExceptionCaster::$traceArgs = true;
+    }
+
+    public function testDefaultSettings()
+    {
+        $ref = array('foo');
+        $e = $this->getTestException('foo', $ref);
+
+        $expectedDump = <<<'EODUMP'
+Exception {
+  #message: "foo"
+  #code: 0
+  #file: "%sExceptionCasterTest.php"
+  #line: 27
+  -trace: {
+    %sExceptionCasterTest.php:27: {
+      : {
+      :     return new \Exception(''.$msg);
+      : }
+    }
+    %sExceptionCasterTest.php:%d: {
+      : $ref = array('foo');
+      : $e = $this->getTestException('foo', $ref);
+      : 
+      arguments: {
+        $msg: "foo"
+        &$ref: array:1 [ …1]
+      }
+    }
+%A
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $e);
+        $this->assertSame(array('foo'), $ref);
+    }
+
+    public function testSeek()
+    {
+        $e = $this->getTestException(2);
+
+        $expectedDump = <<<'EODUMP'
+{
+  %sExceptionCasterTest.php:27: {
+    : {
+    :     return new \Exception(''.$msg);
+    : }
+  }
+  %sExceptionCasterTest.php:%d: {
+    : {
+    :     $e = $this->getTestException(2);
+    : 
+    arguments: {
+      $msg: 2
+    }
+  }
+%A
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $this->getDump($e, 'trace'));
+    }
+
+    public function testNoArgs()
+    {
+        $e = $this->getTestException(1);
+        ExceptionCaster::$traceArgs = false;
+
+        $expectedDump = <<<'EODUMP'
+Exception {
+  #message: "1"
+  #code: 0
+  #file: "%sExceptionCasterTest.php"
+  #line: 27
+  -trace: {
+    %sExceptionCasterTest.php:27: {
+      : {
+      :     return new \Exception(''.$msg);
+      : }
+    }
+    %sExceptionCasterTest.php:%d: {
+      : {
+      :     $e = $this->getTestException(1);
+      :     ExceptionCaster::$traceArgs = false;
+    }
+%A
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $e);
+    }
+
+    public function testNoSrcContext()
+    {
+        $e = $this->getTestException(1);
+        ExceptionCaster::$srcContext = -1;
+
+        $expectedDump = <<<'EODUMP'
+Exception {
+  #message: "1"
+  #code: 0
+  #file: "%sExceptionCasterTest.php"
+  #line: 27
+  -trace: {
+    %sExceptionCasterTest.php: 27
+    %sExceptionCasterTest.php: %d
+%A
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $e);
+    }
+
+    public function testHtmlDump()
+    {
+        $e = $this->getTestException(1);
+        ExceptionCaster::$srcContext = -1;
+
+        $cloner = new VarCloner();
+        $cloner->setMaxItems(1);
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $dump = $dumper->dump($cloner->cloneVar($e)->withRefHandles(false), true);
+
+        $expectedDump = <<<'EODUMP'
+<foo></foo><bar><span class=sf-dump-note>Exception</span> {<samp>
+  #<span class=sf-dump-protected title="Protected property">message</span>: "<span class=sf-dump-str>1</span>"
+  #<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span>
+  #<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%sExceptionCasterTest.php
+%d characters"><span class=sf-dump-ellipsis>%sTests</span>%eCaster%eExceptionCasterTest.php</span>"
+  #<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>27</span>
+  -<span class=sf-dump-private title="Private property defined in class:&#10;`Exception`">trace</span>: {<samp>
+    <span class=sf-dump-meta title="%sExceptionCasterTest.php
+Stack level %d."><span class=sf-dump-ellipsis>%sVarDumper%eTests</span>%eCaster%eExceptionCasterTest.php</span>: <span class=sf-dump-num>27</span>
+     &hellip;%d
+  </samp>}
+</samp>}
+</bar>
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $dump);
+    }
+
+    /**
+     * @requires function Twig\Template::getSourceContext
+     */
+    public function testFrameWithTwig()
+    {
+        require_once dirname(__DIR__).'/Fixtures/Twig.php';
+
+        $f = array(
+            new FrameStub(array(
+                'file' => dirname(__DIR__).'/Fixtures/Twig.php',
+                'line' => 20,
+                'class' => '__TwigTemplate_VarDumperFixture_u75a09',
+            )),
+            new FrameStub(array(
+                'file' => dirname(__DIR__).'/Fixtures/Twig.php',
+                'line' => 21,
+                'class' => '__TwigTemplate_VarDumperFixture_u75a09',
+                'object' => new \__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__),
+            )),
+        );
+
+        $expectedDump = <<<'EODUMP'
+array:2 [
+  0 => {
+    class: "__TwigTemplate_VarDumperFixture_u75a09"
+    src: {
+      %sTwig.php:1: {
+        : 
+        : foo bar
+        :   twig source
+      }
+    }
+  }
+  1 => {
+    class: "__TwigTemplate_VarDumperFixture_u75a09"
+    object: __TwigTemplate_VarDumperFixture_u75a09 {
+    %A
+    }
+    src: {
+      %sExceptionCasterTest.php:2: {
+        : foo bar
+        :   twig source
+        : 
+      }
+    }
+  }
+]
+
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $f);
+    }
+}

+ 25 - 18
htdocs/includes/symfony/var-dumper/Tests/Caster/PdoCasterTest.php

@@ -11,14 +11,18 @@
 
 namespace Symfony\Component\VarDumper\Tests\Caster;
 
+use PHPUnit\Framework\TestCase;
 use Symfony\Component\VarDumper\Caster\PdoCaster;
 use Symfony\Component\VarDumper\Cloner\Stub;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
 
 /**
  * @author Nicolas Grekas <p@tchwork.com>
  */
-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]);
-
-        $this->assertSame($xCast, $cast);
+        $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->assertDumpMatchesFormat($xDump, $cast);
     }
 }

+ 85 - 0
htdocs/includes/symfony/var-dumper/Tests/Caster/RedisCasterTest.php

@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @requires extension redis
+ */
+class RedisCasterTest extends TestCase
+{
+    use VarDumperTestTrait;
+
+    public function testNotConnected()
+    {
+        $redis = new \Redis();
+
+        if (defined('HHVM_VERSION_ID')) {
+            $xCast = <<<'EODUMP'
+Redis {
+  #host: ""
+%A
+}
+EODUMP;
+        } else {
+            $xCast = <<<'EODUMP'
+Redis {
+  isConnected: false
+}
+EODUMP;
+        }
+
+        $this->assertDumpMatchesFormat($xCast, $redis);
+    }
+
+    public function testConnected()
+    {
+        $redis = new \Redis();
+        if (!@$redis->connect('127.0.0.1')) {
+            $e = error_get_last();
+            self::markTestSkipped($e['message']);
+        }
+
+        if (defined('HHVM_VERSION_ID')) {
+            $xCast = <<<'EODUMP'
+Redis {
+  #host: "127.0.0.1"
+%A
+}
+EODUMP;
+        } else {
+            $xCast = <<<'EODUMP'
+Redis {
+  +"socket": Redis Socket Buffer resource
+  isConnected: true
+  host: "127.0.0.1"
+  port: 6379
+  auth: null
+  dbNum: 0
+  timeout: 0.0
+  persistentId: null
+  options: {
+    READ_TIMEOUT: 0.0
+    SERIALIZER: NONE
+    PREFIX: null
+    SCAN: NORETRY
+  }
+}
+EODUMP;
+        }
+
+        $this->assertDumpMatchesFormat($xCast, $redis);
+    }
+}

+ 54 - 47
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 <p@tchwork.com>
  */
-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');
+        }
+
+        $generator = new GeneratorDemo();
+        $generator = $generator->baz();
 
-        $xDump = <<<'EODUMP'
+        $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)
 {
 }

+ 30 - 9
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 <lyrixx@lyrixx.info>
  */
-class SplCasterTest extends \PHPUnit_Framework_TestCase
+class SplCasterTest extends TestCase
 {
     use VarDumperTestTrait;
 
@@ -57,12 +58,6 @@ SplFileInfo {
   pathname: "https://google.com/about"
   extension: ""
   realPath: false
-  writable: false
-  readable: false
-  executable: false
-  file: false
-  dir: false
-  link: false
 %A}
 EOTXT
             ),
@@ -102,10 +97,10 @@ SplFileObject {
   file: true
   dir: false
   link: false
-%AcsvControl: array:2 [
+%AcsvControl: array:%d [
     0 => ","
     1 => """
-  ]
+%A]
   flags: DROP_NEW_LINE|SKIP_EMPTY
   maxLineLen: 0
   fstat: array:26 [
@@ -123,4 +118,30 @@ SplFileObject {
 EOTXT;
         $this->assertDumpMatchesFormat($dump, $var);
     }
+
+    /**
+     * @dataProvider provideCastSplDoublyLinkedList
+     */
+    public function testCastSplDoublyLinkedList($modeValue, $modeDump)
+    {
+        $var = new \SplDoublyLinkedList();
+        $var->setIteratorMode($modeValue);
+        $dump = <<<EOTXT
+SplDoublyLinkedList {
+%Amode: $modeDump
+  dllist: []
+}
+EOTXT;
+        $this->assertDumpMatchesFormat($dump, $var);
+    }
+
+    public function provideCastSplDoublyLinkedList()
+    {
+        return array(
+            array(\SplDoublyLinkedList::IT_MODE_FIFO, 'IT_MODE_FIFO | IT_MODE_KEEP'),
+            array(\SplDoublyLinkedList::IT_MODE_LIFO, 'IT_MODE_LIFO | IT_MODE_KEEP'),
+            array(\SplDoublyLinkedList::IT_MODE_FIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_FIFO | IT_MODE_DELETE'),
+            array(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'),
+        );
+    }
 }

+ 171 - 0
htdocs/includes/symfony/var-dumper/Tests/Caster/StubCasterTest.php

@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\VarDumper\Caster\ArgsStub;
+use Symfony\Component\VarDumper\Caster\ClassStub;
+use Symfony\Component\VarDumper\Caster\LinkStub;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+use Symfony\Component\VarDumper\Tests\Fixtures\FooInterface;
+
+class StubCasterTest extends TestCase
+{
+    use VarDumperTestTrait;
+
+    public function testArgsStubWithDefaults($foo = 234, $bar = 456)
+    {
+        $args = array(new ArgsStub(array(123), __FUNCTION__, __CLASS__));
+
+        $expectedDump = <<<'EODUMP'
+array:1 [
+  0 => {
+    $foo: 123
+  }
+]
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $args);
+    }
+
+    public function testArgsStubWithExtraArgs($foo = 234)
+    {
+        $args = array(new ArgsStub(array(123, 456), __FUNCTION__, __CLASS__));
+
+        $expectedDump = <<<'EODUMP'
+array:1 [
+  0 => {
+    $foo: 123
+    ...: {
+      456
+    }
+  }
+]
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $args);
+    }
+
+    public function testArgsStubNoParamWithExtraArgs()
+    {
+        $args = array(new ArgsStub(array(123), __FUNCTION__, __CLASS__));
+
+        $expectedDump = <<<'EODUMP'
+array:1 [
+  0 => {
+    123
+  }
+]
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $args);
+    }
+
+    public function testArgsStubWithClosure()
+    {
+        $args = array(new ArgsStub(array(123), '{closure}', null));
+
+        $expectedDump = <<<'EODUMP'
+array:1 [
+  0 => {
+    123
+  }
+]
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $args);
+    }
+
+    public function testLinkStub()
+    {
+        $var = array(new LinkStub(__CLASS__, 0, __FILE__));
+
+        $cloner = new VarCloner();
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $dumper->setDisplayOptions(array('fileLinkFormat' => '%f:%l'));
+        $dump = $dumper->dump($cloner->cloneVar($var), true);
+
+        $expectedDump = <<<'EODUMP'
+<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
+  <span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:0" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="55 characters">Symfony\Component\VarDumper\Tests\Caster\StubCasterTest</span></a>"
+</samp>]
+</bar>
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $dump);
+    }
+
+    public function testClassStub()
+    {
+        $var = array(new ClassStub('hello', array(FooInterface::class, 'foo')));
+
+        $cloner = new VarCloner();
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $dump = $dumper->dump($cloner->cloneVar($var), true, array('fileLinkFormat' => '%f:%l'));
+
+        $expectedDump = <<<'EODUMP'
+<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
+  <span class=sf-dump-index>0</span> => "<a href="%sFooInterface.php:10" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="5 characters">hello</span></a>"
+</samp>]
+</bar>
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $dump);
+    }
+
+    public function testClassStubWithNotExistingClass()
+    {
+        $var = array(new ClassStub(NotExisting::class));
+
+        $cloner = new VarCloner();
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $dump = $dumper->dump($cloner->cloneVar($var), true);
+
+        $expectedDump = <<<'EODUMP'
+<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
+  <span class=sf-dump-index>0</span> => "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\Caster\NotExisting
+52 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests\Caster</span>\NotExisting</span>"
+</samp>]
+</bar>
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $dump);
+    }
+
+    public function testClassStubWithNotExistingMethod()
+    {
+        $var = array(new ClassStub('hello', array(FooInterface::class, 'missing')));
+
+        $cloner = new VarCloner();
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $dump = $dumper->dump($cloner->cloneVar($var), true, array('fileLinkFormat' => '%f:%l'));
+
+        $expectedDump = <<<'EODUMP'
+<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp>
+  <span class=sf-dump-index>0</span> => "<a href="%sFooInterface.php:5" target="_blank" rel="noopener noreferrer"><span class=sf-dump-str title="5 characters">hello</span></a>"
+</samp>]
+</bar>
+EODUMP;
+
+        $this->assertStringMatchesFormat($expectedDump, $dump);
+    }
+}

+ 248 - 0
htdocs/includes/symfony/var-dumper/Tests/Caster/XmlReaderCasterTest.php

@@ -0,0 +1,248 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+
+/**
+ * @author Baptiste Clavié <clavie.b@gmail.com>
+ */
+class XmlReaderCasterTest extends TestCase
+{
+    use VarDumperTestTrait;
+
+    /** @var \XmlReader */
+    private $reader;
+
+    protected function setUp()
+    {
+        $this->reader = new \XmlReader();
+        $this->reader->open(__DIR__.'/../Fixtures/xml_reader.xml');
+    }
+
+    protected function tearDown()
+    {
+        $this->reader->close();
+    }
+
+    public function testParserProperty()
+    {
+        $this->reader->setParserProperty(\XMLReader::SUBST_ENTITIES, true);
+
+        $expectedDump = <<<'EODUMP'
+XMLReader {
+  +nodeType: NONE
+  parserProperties: {
+    SUBST_ENTITIES: true
+     …3
+  }
+   …12
+}
+EODUMP;
+
+        $this->assertDumpMatchesFormat($expectedDump, $this->reader);
+    }
+
+    /**
+     * @dataProvider provideNodes
+     */
+    public function testNodes($seek, $expectedDump)
+    {
+        while ($seek--) {
+            $this->reader->read();
+        }
+        $this->assertDumpMatchesFormat($expectedDump, $this->reader);
+    }
+
+    public function provideNodes()
+    {
+        return array(
+            array(0, <<<'EODUMP'
+XMLReader {
+  +nodeType: NONE
+   …13
+}
+EODUMP
+            ),
+            array(1, <<<'EODUMP'
+XMLReader {
+  +localName: "foo"
+  +nodeType: ELEMENT
+  +baseURI: "%sxml_reader.xml"
+   …11
+}
+EODUMP
+            ),
+            array(2, <<<'EODUMP'
+XMLReader {
+  +localName: "#text"
+  +nodeType: SIGNIFICANT_WHITESPACE
+  +depth: 1
+  +value: """
+    \n
+        
+    """
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(3, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: ELEMENT
+  +depth: 1
+  +baseURI: "%sxml_reader.xml"
+   …10
+}
+EODUMP
+            ),
+            array(4, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: END_ELEMENT
+  +depth: 1
+  +baseURI: "%sxml_reader.xml"
+   …10
+}
+EODUMP
+            ),
+            array(6, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: ELEMENT
+  +depth: 1
+  +isEmptyElement: true
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(9, <<<'EODUMP'
+XMLReader {
+  +localName: "#text"
+  +nodeType: TEXT
+  +depth: 2
+  +value: "With text"
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(12, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: ELEMENT
+  +depth: 1
+  +attributeCount: 2
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(13, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: END_ELEMENT
+  +depth: 1
+  +baseURI: "%sxml_reader.xml"
+   …10
+}
+EODUMP
+            ),
+            array(15, <<<'EODUMP'
+XMLReader {
+  +localName: "bar"
+  +nodeType: ELEMENT
+  +depth: 1
+  +attributeCount: 1
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(16, <<<'EODUMP'
+XMLReader {
+  +localName: "#text"
+  +nodeType: SIGNIFICANT_WHITESPACE
+  +depth: 2
+  +value: """
+    \n
+            
+    """
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(17, <<<'EODUMP'
+XMLReader {
+  +localName: "baz"
+  +prefix: "baz"
+  +nodeType: ELEMENT
+  +depth: 2
+  +namespaceURI: "http://symfony.com"
+  +baseURI: "%sxml_reader.xml"
+   …8
+}
+EODUMP
+            ),
+            array(18, <<<'EODUMP'
+XMLReader {
+  +localName: "baz"
+  +prefix: "baz"
+  +nodeType: END_ELEMENT
+  +depth: 2
+  +namespaceURI: "http://symfony.com"
+  +baseURI: "%sxml_reader.xml"
+   …8
+}
+EODUMP
+            ),
+            array(19, <<<'EODUMP'
+XMLReader {
+  +localName: "#text"
+  +nodeType: SIGNIFICANT_WHITESPACE
+  +depth: 2
+  +value: """
+    \n
+        
+    """
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(21, <<<'EODUMP'
+XMLReader {
+  +localName: "#text"
+  +nodeType: SIGNIFICANT_WHITESPACE
+  +depth: 1
+  +value: "\n"
+  +baseURI: "%sxml_reader.xml"
+   …9
+}
+EODUMP
+            ),
+            array(22, <<<'EODUMP'
+XMLReader {
+  +localName: "foo"
+  +nodeType: END_ELEMENT
+  +baseURI: "%sxml_reader.xml"
+   …11
+}
+EODUMP
+            ),
+        );
+    }
+}

+ 157 - 84
htdocs/includes/symfony/var-dumper/Tests/CliDumperTest.php

@@ -11,14 +11,17 @@
 
 namespace Symfony\Component\VarDumper\Tests;
 
+use PHPUnit\Framework\TestCase;
 use Symfony\Component\VarDumper\Cloner\VarCloner;
 use Symfony\Component\VarDumper\Dumper\CliDumper;
 use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+use Twig\Environment;
+use Twig\Loader\FilesystemLoader;
 
 /**
  * @author Nicolas Grekas <p@tchwork.com>
  */
-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(
-            <<<EOTXT
+            <<<'EOTXT'
 xml resource {
   current_byte_index: %i
   current_column_number: %i
@@ -131,6 +131,72 @@ EOTXT
         );
     }
 
+    public function testJsonCast()
+    {
+        $var = (array) json_decode('{"0":{},"1":null}');
+        foreach ($var as &$v) {
+        }
+        $var[] = &$v;
+        $var[''] = 2;
+
+        if (\PHP_VERSION_ID >= 70200) {
+            $this->assertDumpMatchesFormat(
+                <<<'EOTXT'
+array:4 [
+  0 => {}
+  1 => &1 null
+  2 => &1 null
+  "" => 2
+]
+EOTXT
+                ,
+                $var
+            );
+        } else {
+            $this->assertDumpMatchesFormat(
+                <<<'EOTXT'
+array:4 [
+  "0" => {}
+  "1" => &1 null
+  0 => &1 null
+  "" => 2
+]
+EOTXT
+                ,
+                $var
+            );
+        }
+    }
+
+    public function testObjectCast()
+    {
+        $var = (object) array(1 => 1);
+        $var->{1} = 2;
+
+        if (\PHP_VERSION_ID >= 70200) {
+            $this->assertDumpMatchesFormat(
+                <<<'EOTXT'
+{
+  +"1": 2
+}
+EOTXT
+                ,
+                $var
+            );
+        } else {
+            $this->assertDumpMatchesFormat(
+                <<<'EOTXT'
+{
+  +1: 1
+  +"1": 2
+}
+EOTXT
+                ,
+                $var
+            );
+        }
+    }
+
     public function testClosedResource()
     {
         if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {
@@ -152,7 +218,7 @@ EOTXT
 
         $this->assertStringMatchesFormat(
             <<<EOTXT
-Unknown resource @{$res}
+Closed resource @{$res}
 
 EOTXT
             ,
@@ -160,12 +226,47 @@ EOTXT
         );
     }
 
+    public function testFlags()
+    {
+        putenv('DUMP_LIGHT_ARRAY=1');
+        putenv('DUMP_STRING_LENGTH=1');
+
+        $var = array(
+            range(1, 3),
+            array('foo', 2 => 'bar'),
+        );
+
+        $this->assertDumpEquals(
+            <<<EOTXT
+[
+  [
+    1
+    2
+    3
+  ]
+  [
+    0 => (3) "foo"
+    2 => (3) "bar"
+  ]
+]
+EOTXT
+            ,
+            $var
+        );
+
+        putenv('DUMP_LIGHT_ARRAY=');
+        putenv('DUMP_STRING_LENGTH=');
+    }
+
+    /**
+     * @requires function Twig\Template::getSourceContext
+     */
     public function testThrowingCaster()
     {
         $out = fopen('php://memory', 'r+b');
 
         require_once __DIR__.'/Fixtures/Twig.php';
-        $twig = new \__TwigTemplate_VarDumperFixture_u75a09(new \Twig_Environment(new \Twig_Loader_Filesystem()));
+        $twig = new \__TwigTemplate_VarDumperFixture_u75a09(new Environment(new FilesystemLoader()));
 
         $dumper = new CliDumper();
         $dumper->setColors(false);
@@ -181,96 +282,56 @@ EOTXT
             ':stream' => eval('return function () use ($twig) {
                 try {
                     $twig->render(array());
-                } catch (\Twig_Error_Runtime $e) {
+                } catch (\Twig\Error\RuntimeError $e) {
                     throw $e->getPrevious();
                 }
             };'),
         ));
-        $line = __LINE__ - 2;
         $ref = (int) $out;
 
         $data = $cloner->cloneVar($out);
         $dumper->dump($data, $out);
-        rewind($out);
-        $out = stream_get_contents($out);
-
-        if (method_exists($twig, 'getSource')) {
-            $twig = <<<EOTXT
-          foo.twig:2: """
-            foo bar\\n
-                twig source\\n
-            \\n
-            """
-
-EOTXT;
-        } else {
-            $twig = '';
-        }
+        $out = stream_get_contents($out, -1, 0);
 
         $r = defined('HHVM_VERSION') ? '' : '#%d';
         $this->assertStringMatchesFormat(
             <<<EOTXT
 stream resource {@{$ref}
-  wrapper_type: "PHP"
-  stream_type: "MEMORY"
-  mode: "%s+b"
-  unread_bytes: 0
-  seekable: true
-  uri: "php://memory"
-  timed_out: false
-  blocked: true
-  eof: false
-  options: []
   ⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
     #message: "Unexpected Exception thrown from a caster: Foobar"
     -trace: {
-      %d. __TwigTemplate_VarDumperFixture_u75a09->doDisplay() ==> new Exception(): {
-        src: {
-          %sTwig.php:19: """
-                // line 2\\n
-                throw new \Exception('Foobar');\\n
-            }\\n
-            """
-{$twig}        }
+      %sTwig.php:2: {
+        : foo bar
+        :   twig source
+        : 
       }
-      %d. Twig_Template->displayWithErrorHandling() ==> __TwigTemplate_VarDumperFixture_u75a09->doDisplay(): {
-        src: {
-          %sTemplate.php:%d: """
-            try {\\n
-                \$this->doDisplay(\$context, \$blocks);\\n
-            } catch (Twig_Error \$e) {\\n
-            """
-        }
+      %sTemplate.php:%d: {
+        : try {
+        :     \$this->doDisplay(\$context, \$blocks);
+        : } catch (Twig%sError \$e) {
       }
-      %d. Twig_Template->display() ==> Twig_Template->displayWithErrorHandling(): {
-        src: {
-          %sTemplate.php:%d: """
-            {\\n
-                \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));\\n
-            }\\n
-            """
-        }
+      %sTemplate.php:%d: {
+        : {
+        :     \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));
+        : }
       }
-      %d. Twig_Template->render() ==> Twig_Template->display(): {
-        src: {
-          %sTemplate.php:%d: """
-            try {\\n
-                \$this->display(\$context);\\n
-            } catch (Exception \$e) {\\n
-            """
-        }
+      %sTemplate.php:%d: {
+        : try {
+        :     \$this->display(\$context);
+        : } catch (%s \$e) {
       }
-      %d. %slosure%s() ==> Twig_Template->render(): {
-        src: {
-          %sCliDumperTest.php:{$line}: """
-                    }\\n
-                };'),\\n
-            ));\\n
-            """
-        }
+      %sCliDumperTest.php:%d: {
+%A
       }
     }
   }
+%Awrapper_type: "PHP"
+  stream_type: "MEMORY"
+  mode: "%s+b"
+  unread_bytes: 0
+  seekable: true
+  uri: "php://memory"
+%Aoptions: []
 }
 
 EOTXT
@@ -288,11 +349,8 @@ EOTXT
         $dumper->setColors(false);
         $cloner = new VarCloner();
 
-        $out = fopen('php://memory', 'r+b');
         $data = $cloner->cloneVar($var);
-        $dumper->dump($data, $out);
-        rewind($out);
-        $out = stream_get_contents($out);
+        $out = $dumper->dump($data, true);
 
         $r = defined('HHVM_VERSION') ? '' : '#%d';
         $this->assertStringMatchesFormat(
@@ -318,7 +376,7 @@ EOTXT
         $var = $this->getSpecialVars();
 
         $this->assertDumpEquals(
-            <<<EOTXT
+            <<<'EOTXT'
 array:3 [
   0 => array:1 [
     0 => &1 array:1 [
@@ -364,7 +422,7 @@ EOTXT
         $dumper->dump($data);
 
         $this->assertSame(
-            <<<EOTXT
+            <<<'EOTXT'
 array:2 [
   1 => array:1 [
     "GLOBALS" => &1 array:1 [
@@ -386,7 +444,7 @@ EOTXT
      */
     public function testBuggyRefs()
     {
-        if (PHP_VERSION_ID >= 50600) {
+        if (\PHP_VERSION_ID >= 50600) {
             $this->markTestSkipped('PHP 5.6 fixed refs counting');
         }
 
@@ -406,7 +464,7 @@ EOTXT
         });
 
         $this->assertSame(
-            <<<EOTXT
+            <<<'EOTXT'
 array:1 [
   0 => array:1 [
     0 => array:1 [
@@ -421,6 +479,21 @@ EOTXT
         );
     }
 
+    public function testIncompleteClass()
+    {
+        $unserializeCallbackHandler = ini_set('unserialize_callback_func', null);
+        $var = unserialize('O:8:"Foo\Buzz":0:{}');
+        ini_set('unserialize_callback_func', $unserializeCallbackHandler);
+
+        $this->assertDumpMatchesFormat(
+            <<<EOTXT
+__PHP_Incomplete_Class(Foo\Buzz) {}
+EOTXT
+            ,
+            $var
+        );
+    }
+
     private function getSpecialVars()
     {
         foreach (array_keys($GLOBALS) as $var) {

+ 11 - 0
htdocs/includes/symfony/var-dumper/Tests/Fixtures/FooInterface.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace Symfony\Component\VarDumper\Tests\Fixtures;
+
+interface FooInterface
+{
+    /**
+     * Hello.
+     */
+    public function foo();
+}

+ 7 - 0
htdocs/includes/symfony/var-dumper/Tests/Fixtures/NotLoadableClass.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\VarDumper\Tests\Fixtures;
+
+class NotLoadableClass extends NotLoadableClass
+{
+}

+ 15 - 11
htdocs/includes/symfony/var-dumper/Tests/Fixtures/Twig.php

@@ -1,16 +1,18 @@
 <?php
 
 /* foo.twig */
-class __TwigTemplate_VarDumperFixture_u75a09 extends Twig_Template
+class __TwigTemplate_VarDumperFixture_u75a09 extends Twig\Template
 {
-    public function __construct(Twig_Environment $env)
-    {
-        parent::__construct($env);
+    private $path;
 
+    public function __construct(Twig\Environment $env = null, $path = null)
+    {
+        if (null !== $env) {
+            parent::__construct($env);
+        }
         $this->parent = false;
-
-        $this->blocks = array(
-        );
+        $this->blocks = array();
+        $this->path = $path;
     }
 
     protected function doDisplay(array $context, array $blocks = array())
@@ -26,9 +28,11 @@ class __TwigTemplate_VarDumperFixture_u75a09 extends Twig_Template
 
     public function getDebugInfo()
     {
-        return array (19 => 2);
+        return array(20 => 1, 21 => 2);
+    }
+
+    public function getSourceContext()
+    {
+        return new Twig\Source("   foo bar\n     twig source\n\n", 'foo.twig', $this->path ?: __FILE__);
     }
 }
-/* foo bar*/
-/*     twig source*/
-/* */

+ 10 - 0
htdocs/includes/symfony/var-dumper/Tests/Fixtures/xml_reader.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+    <bar></bar>
+    <bar />
+    <bar>With text</bar>
+    <bar foo="bar" baz="fubar"></bar>
+    <bar xmlns:baz="http://symfony.com">
+        <baz:baz></baz:baz>
+    </bar>
+</foo>

+ 37 - 15
htdocs/includes/symfony/var-dumper/Tests/HtmlDumperTest.php

@@ -11,13 +11,14 @@
 
 namespace Symfony\Component\VarDumper\Tests;
 
+use PHPUnit\Framework\TestCase;
 use Symfony\Component\VarDumper\Cloner\VarCloner;
 use Symfony\Component\VarDumper\Dumper\HtmlDumper;
 
 /**
  * @author Nicolas Grekas <p@tchwork.com>
  */
-class HtmlDumperTest extends \PHPUnit_Framework_TestCase
+class HtmlDumperTest extends TestCase
 {
     public function testGet()
     {
@@ -59,26 +60,24 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
   <span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>
   <span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>
   <span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>
-  "<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&%s;j&%s;</span>\\n"
-  <span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&%s;</span>\\x00"
+  "<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&%s;j&%s;<span class=sf-dump-default>\\n</span></span>"
+  <span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&%s;<span class=sf-dump-default>\\x00</span></span>"
   "<span class=sf-dump-key>[]</span>" => []
   "<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
-    <span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
+%A  <span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
     <span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str title="5 characters">STDIO</span>"
     <span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
     <span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
     <span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
-    <span class=sf-dump-meta>timed_out</span>: <span class=sf-dump-const>false</span>
-    <span class=sf-dump-meta>blocked</span>: <span class=sf-dump-const>true</span>
-    <span class=sf-dump-meta>eof</span>: <span class=sf-dump-const>false</span>
-    <span class=sf-dump-meta>options</span>: []
+%A  <span class=sf-dump-meta>options</span>: []
   </samp>}
   "<span class=sf-dump-key>obj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a><samp id={$dumpId}-ref2%d>
     +<span class=sf-dump-public title="Public property">foo</span>: "<span class=sf-dump-str title="3 characters">foo</span>"
     +"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
   </samp>}
   "<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {{$r}<samp>
-    <span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="48 characters">Symfony\Component\VarDumper\Tests\HtmlDumperTest</span>"
+    <span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\HtmlDumperTest
+48 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests</span>\HtmlDumperTest</span>"
     <span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
     <span class=sf-dump-meta>parameters</span>: {<samp>
       <span class=sf-dump-meta>\$a</span>: {}
@@ -87,7 +86,8 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
         <span class=sf-dump-meta>default</span>: <span class=sf-dump-const>null</span>
       </samp>}
     </samp>}
-    <span class=sf-dump-meta>file</span>: "<span class=sf-dump-str title="%d characters">{$var['file']}</span>"
+    <span class=sf-dump-meta>file</span>: "<span class=sf-dump-str title="{$var['file']}
+%d characters"><span class=sf-dump-ellipsis>%sTests</span>%eFixtures%edumb-var.php</span>"
     <span class=sf-dump-meta>line</span>: "<span class=sf-dump-str title="%d characters">{$var['line']} to {$var['line']}</span>"
   </samp>}
   "<span class=sf-dump-key>line</span>" => <span class=sf-dump-num>{$var['line']}</span>
@@ -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(
-            <<<EOTXT
+            <<<'EOTXT'
 <foo></foo><bar>b"<span class=sf-dump-str title="7 binary or non-UTF-8 characters">&#1057;&#1083;&#1086;&#1074;&#1072;&#1088;&#1100;</span>"
 </bar>
 
 EOTXT
             ,
+            $out
+        );
+    }
 
+    public function testAppend()
+    {
+        $out = fopen('php://memory', 'r+b');
+
+        $dumper = new HtmlDumper();
+        $dumper->setDumpHeader('<foo></foo>');
+        $dumper->setDumpBoundaries('<bar>', '</bar>');
+        $cloner = new VarCloner();
+
+        $dumper->dump($cloner->cloneVar(123), $out);
+        $dumper->dump($cloner->cloneVar(456), $out);
+
+        $out = stream_get_contents($out, -1, 0);
+
+        $this->assertSame(<<<'EOTXT'
+<foo></foo><bar><span class=sf-dump-num>123</span>
+</bar>
+<bar><span class=sf-dump-num>456</span>
+</bar>
+
+EOTXT
+            ,
             $out
         );
     }

+ 2 - 1
htdocs/includes/symfony/var-dumper/Tests/Test/VarDumperTestTraitTest.php

@@ -11,9 +11,10 @@
 
 namespace Symfony\Component\VarDumper\Tests\Test;
 
+use PHPUnit\Framework\TestCase;
 use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
 
-class VarDumperTestTraitTest extends \PHPUnit_Framework_TestCase
+class VarDumperTestTraitTest extends TestCase
 {
     use VarDumperTestTrait;
 

+ 108 - 1
htdocs/includes/symfony/var-dumper/Tests/VarClonerTest.php

@@ -11,12 +11,13 @@
 
 namespace Symfony\Component\VarDumper\Tests;
 
+use PHPUnit\Framework\TestCase;
 use Symfony\Component\VarDumper\Cloner\VarCloner;
 
 /**
  * @author Nicolas Grekas <p@tchwork.com>
  */
-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

+ 7 - 2
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"
         }
     }
 }

+ 4 - 0
htdocs/includes/symfony/var-dumper/phpunit.xml.dist

@@ -5,9 +5,13 @@
          backupGlobals="false"
          colors="true"
          bootstrap="vendor/autoload.php"
+         failOnRisky="true"
+         failOnWarning="true"
 >
     <php>
         <ini name="error_reporting" value="-1" />
+        <env name="DUMP_LIGHT_ARRAY" value="" />
+        <env name="DUMP_STRING_LENGTH" value="" />
     </php>
 
     <testsuites>