[VarDumper] add Stub objects for cutting cleanly and dumping consts

This commit is contained in:
Nicolas Grekas 2014-09-08 20:39:52 +02:00
parent c8746a43c9
commit 0d8a942cfa
19 changed files with 482 additions and 271 deletions

View File

@ -218,7 +218,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
$h = headers_list();
$i = count($h);
array_unshift($h, 'Content-Type: ' . ini_get('default_mimetype'));
array_unshift($h, 'Content-Type: '.ini_get('default_mimetype'));
while (0 !== stripos($h[$i], 'Content-Type:')) {
--$i;
}

View File

@ -0,0 +1,62 @@
<?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 the main properties of a PHP variable, pre-casted by a caster.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class CasterStub extends Stub
{
public function __construct($value, $class = '')
{
switch (gettype($value)) {
case 'object':
$this->type = self::TYPE_OBJECT;
$this->class = get_class($value);
$this->value = spl_object_hash($value);
$this->cut = -1;
break;
case 'array':
$this->type = self::TYPE_ARRAY;
$this->class = self::ARRAY_ASSOC;
$this->cut = $this->value = count($value);
break;
case 'resource':
case 'unknown type':
$this->type = self::TYPE_RESOURCE;
$this->class = @get_resource_type($value);
$this->value = (int) $value;
$this->cut = -1;
break;
case 'string':
if ('' === $class) {
$this->type = self::TYPE_STRING;
$this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;
$this->cut = self::STRING_BINARY === $this->class ? strlen($value) : (function_exists('iconv_strlen') ? iconv_strlen($value, 'UTF-8') : -1);
break;
}
// No break;
default:
$this->class = $class;
$this->value = $value;
break;
}
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts DOM related classes to array representation.
*
@ -38,16 +40,37 @@ class DOMCaster
DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR',
);
public static function castException(\DOMException $e, array $a, $isNested, &$cut)
private static $nodeTypes = array(
XML_ELEMENT_NODE => 'XML_ELEMENT_NODE',
XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE',
XML_TEXT_NODE => 'XML_TEXT_NODE',
XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE',
XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE',
XML_ENTITY_NODE => 'XML_ENTITY_NODE',
XML_PI_NODE => 'XML_PI_NODE',
XML_COMMENT_NODE => 'XML_COMMENT_NODE',
XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE',
XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE',
XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE',
XML_NOTATION_NODE => 'XML_NOTATION_NODE',
XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE',
XML_DTD_NODE => 'XML_DTD_NODE',
XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE',
XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE',
XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE',
XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE',
);
public static function castException(\DOMException $e, array $a, Stub $stub, $isNested)
{
if (isset($a["\0*\0code"], self::$errorCodes[$a["\0*\0code"]])) {
$a["\0*\0code"] .= ' ('.self::$errorCodes[$a["\0*\0code"]].')';
$a["\0*\0code"] = new CasterStub(self::$errorCodes[$a["\0*\0code"]], 'const');
}
return $a;
}
public static function castLength($dom, array $a, $isNested, &$cut)
public static function castLength($dom, array $a, Stub $stub, $isNested)
{
$a += array(
'length' => $dom->length,
@ -56,7 +79,7 @@ class DOMCaster
return $a;
}
public static function castImplementation($dom, array $a, $isNested, &$cut)
public static function castImplementation($dom, array $a, Stub $stub, $isNested)
{
$a += array(
"\0~\0Core" => '1.0',
@ -66,53 +89,49 @@ class DOMCaster
return $a;
}
public static function castNode(\DOMNode $dom, array $a, $isNested, &$cut)
public static function castNode(\DOMNode $dom, array $a, Stub $stub, $isNested)
{
// Commented lines denote properties that exist but are better not dumped for clarity.
$a += array(
'nodeName' => $dom->nodeName,
//'nodeValue' => $dom->nodeValue,
'nodeType' => $dom->nodeType,
//'parentNode' => $dom->parentNode,
'nodeValue' => new CasterStub($dom->nodeValue),
'nodeType' => new CasterStub(self::$nodeTypes[$dom->nodeType], 'const'),
'parentNode' => new CasterStub($dom->parentNode),
'childNodes' => $dom->childNodes,
//'firstChild' => $dom->firstChild,
//'lastChild' => $dom->lastChild,
//'previousSibling' => $dom->previousSibling,
//'nextSibling' => $dom->nextSibling,
'firstChild' => new CasterStub($dom->firstChild),
'lastChild' => new CasterStub($dom->lastChild),
'previousSibling' => new CasterStub($dom->previousSibling),
'nextSibling' => new CasterStub($dom->nextSibling),
'attributes' => $dom->attributes,
//'ownerDocument' => $dom->ownerDocument,
'ownerDocument' => new CasterStub($dom->ownerDocument),
'namespaceURI' => $dom->namespaceURI,
'prefix' => $dom->prefix,
'localName' => $dom->localName,
'baseURI' => $dom->baseURI,
//'textContent' => $dom->textContent,
'textContent' => new CasterStub($dom->textContent),
);
$cut += 8;
return $a;
}
public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, $isNested, &$cut)
public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, $isNested)
{
// Commented lines denote properties that exist but are better not dumped for clarity.
$a += array(
'nodeName' => $dom->nodeName,
//'nodeValue' => $dom->nodeValue,
'nodeType' => $dom->nodeType,
'nodeValue' => new CasterStub($dom->nodeValue),
'nodeType' => new CasterStub(self::$nodeTypes[$dom->nodeType], 'const'),
'prefix' => $dom->prefix,
'localName' => $dom->localName,
'namespaceURI' => $dom->namespaceURI,
//'ownerDocument' => $dom->ownerDocument,
//'parentNode' => $dom->parentNode,
'ownerDocument' => new CasterStub($dom->ownerDocument),
'parentNode' => new CasterStub($dom->parentNode),
);
$cut += 3;
return $a;
}
public static function castDocument(\DOMDocument $dom, array $a, $isNested, &$cut)
public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, $isNested)
{
$formatOutput = $dom->formatOutput;
$dom->formatOutput = true;
@ -120,7 +139,7 @@ class DOMCaster
$a += array(
'doctype' => $dom->doctype,
'implementation' => $dom->implementation,
'documentElement' => $dom->documentElement,
'documentElement' => new CasterStub($dom->documentElement),
'actualEncoding' => $dom->actualEncoding,
'encoding' => $dom->encoding,
'xmlEncoding' => $dom->xmlEncoding,
@ -145,7 +164,7 @@ class DOMCaster
return $a;
}
public static function castCharacterData(\DOMCharacterData $dom, array $a, $isNested, &$cut)
public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'data' => $dom->data,
@ -155,7 +174,7 @@ class DOMCaster
return $a;
}
public static function castAttr(\DOMAttr $dom, array $a, $isNested, &$cut)
public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'name' => $dom->name,
@ -168,7 +187,7 @@ class DOMCaster
return $a;
}
public static function castElement(\DOMElement $dom, array $a, $isNested, &$cut)
public static function castElement(\DOMElement $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'tagName' => $dom->tagName,
@ -178,7 +197,7 @@ class DOMCaster
return $a;
}
public static function castText(\DOMText $dom, array $a, $isNested, &$cut)
public static function castText(\DOMText $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'wholeText' => $dom->wholeText,
@ -187,7 +206,7 @@ class DOMCaster
return $a;
}
public static function castTypeinfo(\DOMTypeinfo $dom, array $a, $isNested, &$cut)
public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'typeName' => $dom->typeName,
@ -197,7 +216,7 @@ class DOMCaster
return $a;
}
public static function castDomError(\DOMDomError $dom, array $a, $isNested, &$cut)
public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'severity' => $dom->severity,
@ -211,7 +230,7 @@ class DOMCaster
return $a;
}
public static function castLocator(\DOMLocator $dom, array $a, $isNested, &$cut)
public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'lineNumber' => $dom->lineNumber,
@ -224,7 +243,7 @@ class DOMCaster
return $a;
}
public static function castDocumentType(\DOMDocumentType $dom, array $a, $isNested, &$cut)
public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'name' => $dom->name,
@ -238,7 +257,7 @@ class DOMCaster
return $a;
}
public static function castNotation(\DOMNotation $dom, array $a, $isNested, &$cut)
public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'publicId' => $dom->publicId,
@ -248,7 +267,7 @@ class DOMCaster
return $a;
}
public static function castEntity(\DOMEntity $dom, array $a, $isNested, &$cut)
public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'publicId' => $dom->publicId,
@ -262,7 +281,7 @@ class DOMCaster
return $a;
}
public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, $isNested, &$cut)
public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'target' => $dom->target,
@ -272,7 +291,7 @@ class DOMCaster
return $a;
}
public static function castXPath(\DOMXPath $dom, array $a, $isNested, &$cut)
public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, $isNested)
{
$a += array(
'document' => $dom->document,

View File

@ -11,10 +11,10 @@
namespace Symfony\Component\VarDumper\Caster;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Proxy\Proxy as CommonProxy;
use Doctrine\ORM\Proxy\Proxy as OrmProxy;
use Doctrine\ORM\PersistentCollection;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts Doctrine related classes to array representation.
@ -23,50 +23,36 @@ use Doctrine\ORM\PersistentCollection;
*/
class DoctrineCaster
{
public static function castCommonProxy(CommonProxy $proxy, array $a, $isNested, &$cut)
public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, $isNested)
{
unset(
$a['__cloner__'],
$a['__initializer__']
);
$cut += 2;
$stub->cut += 2;
return $a;
}
public static function castOrmProxy(OrmProxy $proxy, array $a, $isNested, &$cut)
public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, $isNested)
{
$prefix = "\0Doctrine\\ORM\\Proxy\\Proxy\0";
unset(
$a[$prefix.'_entityPersister'],
$a[$prefix.'_identifier']
);
$cut += 2;
$stub->cut += 2;
return $a;
}
public static function castObjectManager(ObjectManager $manager, array $a, $isNested, &$cut)
{
if ($isNested) {
$cut += count($a);
return array();
}
return $a;
}
public static function castPersistentCollection(PersistentCollection $coll, array $a, $isNested, &$cut)
public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, $isNested)
{
$prefix = "\0Doctrine\\ORM\\PersistentCollection\0";
unset(
$a[$prefix.'snapshot'],
$a[$prefix.'association'],
$a[$prefix.'em'],
$a[$prefix.'typeClass']
);
$cut += 4;
$a[$prefix.'snapshot'] = new CasterStub($a[$prefix.'snapshot']);
$a[$prefix.'association'] = new CasterStub($a[$prefix.'association']);
$a[$prefix.'typeClass'] = new CasterStub($a[$prefix.'typeClass']);
return $a;
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts common Exception classes to array representation.
@ -39,7 +40,7 @@ class ExceptionCaster
E_STRICT => 'E_STRICT',
);
public static function castException(\Exception $e, array $a)
public static function castException(\Exception $e, array $a, Stub $stub, $isNested)
{
$trace = $a["\0Exception\0trace"];
unset($a["\0Exception\0trace"]); // Ensures the trace is always last
@ -57,16 +58,16 @@ class ExceptionCaster
return $a;
}
public static function castErrorException(\ErrorException $e, array $a)
public static function castErrorException(\ErrorException $e, array $a, Stub $stub, $isNested)
{
if (isset($a[$s = "\0*\0severity"], self::$errorTypes[$a[$s]])) {
$a[$s] = self::$errorTypes[$a[$s]];
$a[$s] = new CasterStub(self::$errorTypes[$a[$s]], 'const');
}
return $a;
}
public static function castThrowingCasterException(ThrowingCasterException $e, array $a)
public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, $isNested)
{
$b = (array) $a["\0Exception\0previous"];
@ -74,7 +75,7 @@ class ExceptionCaster
$t = static::$traceArgs;
static::$traceArgs = false;
$b = static::castException($a["\0Exception\0previous"], $b);
$b = static::castException($a["\0Exception\0previous"], $b, $stub, $isNested);
static::$traceArgs = $t;
if (empty($a["\0*\0message"])) {

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts PDO related classes to array representation.
*
@ -55,7 +57,7 @@ class PdoCaster
),
);
public static function castPdo(\PDO $c, array $a)
public static function castPdo(\PDO $c, array $a, Stub $stub, $isNested)
{
$a = array();
$errmode = $c->getAttribute(\PDO::ATTR_ERRMODE);
@ -70,7 +72,7 @@ class PdoCaster
try {
$a[$attr] = 'ERRMODE' === $attr ? $errmode : $c->getAttribute(constant("PDO::ATTR_{$attr}"));
if (isset($values[$a[$attr]])) {
$a[$attr] = $values[$a[$attr]];
$a[$attr] = new CasterStub($values[$a[$attr]], 'const');
}
} catch (\Exception $m) {
}
@ -98,7 +100,7 @@ class PdoCaster
return $a;
}
public static function castPdoStatement(\PDOStatement $c, array $a)
public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, $isNested)
{
$m = "\0~\0";
$a[$m.'errorInfo'] = $c->errorInfo();

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts Reflector related classes to array representation.
*
@ -18,16 +20,16 @@ namespace Symfony\Component\VarDumper\Caster;
*/
class ReflectionCaster
{
public static function castReflector(\Reflector $c, array $a)
public static function castReflector(\Reflector $c, array $a, Stub $stub, $isNested)
{
$a["\0~\0reflection"] = $c->__toString();
return $a;
}
public static function castClosure(\Closure $c, array $a)
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
{
$a = static::castReflector(new \ReflectionFunction($c), $a);
$a = static::castReflector(new \ReflectionFunction($c), $a, $stub, $isNested);
unset($a["\0+\0000"], $a['name']);
return $a;

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts common resource types to array representation.
*
@ -18,12 +20,12 @@ namespace Symfony\Component\VarDumper\Caster;
*/
class ResourceCaster
{
public static function castCurl($h, array $a)
public static function castCurl($h, array $a, Stub $stub, $isNested)
{
return curl_getinfo($h);
}
public static function castDba($dba, array $a)
public static function castDba($dba, array $a, Stub $stub, $isNested)
{
$list = dba_list();
$a['file'] = $list[substr((string) $dba, 13)];
@ -31,22 +33,22 @@ class ResourceCaster
return $a;
}
public static function castProcess($process, array $a)
public static function castProcess($process, array $a, Stub $stub, $isNested)
{
return proc_get_status($process);
}
public static function castStream($stream, array $a)
public static function castStream($stream, array $a, Stub $stub, $isNested)
{
return stream_get_meta_data($stream) + static::castStreamContext($stream, $a);
return stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
}
public static function castStreamContext($stream, array $a)
public static function castStreamContext($stream, array $a, Stub $stub, $isNested)
{
return stream_context_get_params($stream);
}
public static function castGd($gd, array $a)
public static function castGd($gd, array $a, Stub $stub, $isNested)
{
$a['size'] = imagesx($gd).'x'.imagesy($gd);
$a['trueColor'] = imageistruecolor($gd);
@ -54,7 +56,7 @@ class ResourceCaster
return $a;
}
public static function castMysqlLink($h, array $a)
public static function castMysqlLink($h, array $a, Stub $stub, $isNested)
{
$a['host'] = mysql_get_host_info($h);
$a['protocol'] = mysql_get_proto_info($h);

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Caster;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Casts SPL related classes to array representation.
*
@ -18,9 +20,9 @@ namespace Symfony\Component\VarDumper\Caster;
*/
class SplCaster
{
public static function castArrayObject(\ArrayObject $c, array $a)
public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, $isNested)
{
$class = get_class($c);
$class = $stub->class;
$flags = $c->getFlags();
$b = array(
@ -55,7 +57,7 @@ class SplCaster
return $a;
}
public static function castHeap(\Iterator $c, array $a)
public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested)
{
$a += array(
"\0~\0heap" => iterator_to_array(clone $c),
@ -64,13 +66,13 @@ class SplCaster
return $a;
}
public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a)
public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, $isNested)
{
$mode = $c->getIteratorMode();
$c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
$a += array(
"\0~\0mode" => (($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_KEEP) ? 'IT_MODE_KEEP' : 'IT_MODE_DELETE'),
"\0~\0mode" => new CasterStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_KEEP) ? 'IT_MODE_KEEP' : 'IT_MODE_DELETE'), 'const'),
"\0~\0dllist" => iterator_to_array($c),
);
$c->setIteratorMode($mode);
@ -78,7 +80,7 @@ class SplCaster
return $a;
}
public static function castFixedArray(\SplFixedArray $c, array $a)
public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, $isNested)
{
$a += array(
"\0~\0storage" => $c->toArray(),
@ -87,7 +89,7 @@ class SplCaster
return $a;
}
public static function castObjectStorage(\SplObjectStorage $c, array $a)
public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, $isNested)
{
$storage = array();
unset($a["\0+\0\0gcdata"]); // Don't hit https://bugs.php.net/65967

View File

@ -0,0 +1,45 @@
<?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 a CasterStub.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class StubCaster
{
public static function castStub(CasterStub $c, array $a, Stub $stub, $isNested)
{
if ($isNested) {
$stub->type = $c->type;
$stub->class = $c->class;
$stub->value = $c->value;
$stub->cut = $c->cut;
return array();
}
}
public static function castNestedFat($obj, array $a, Stub $stub, $isNested)
{
if ($isNested) {
$stub->cut += count($a);
return array();
}
return $a;
}
}

View File

@ -21,10 +21,12 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
abstract class AbstractCloner implements ClonerInterface
{
public static $defaultCasters = array(
'o:Symfony\Component\VarDumper\Caster\CasterStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
'o:Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
'o:Reflector' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflector',
'o:Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castObjectManager',
'o:Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
'o:Doctrine\Common\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castCommonProxy',
'o:Doctrine\ORM\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castOrmProxy',
'o:Doctrine\ORM\PersistentCollection' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castPersistentCollection',
@ -54,6 +56,8 @@ abstract class AbstractCloner implements ClonerInterface
'o:ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
'o:Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
'o:Symfony\Component\DependencyInjection\ContainerInterface'
=> 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
'o:Symfony\Component\VarDumper\Exception\ThrowingCasterException'
=> 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castThrowingCasterException',
@ -171,19 +175,22 @@ abstract class AbstractCloner implements ClonerInterface
/**
* Casts an object to an array representation.
*
* @param string $class The class of the object.
* @param object $obj The object itself.
* @param Stub $stub The Stub for the casted object.
* @param bool $isNested True if the object is nested in the dumped structure.
* @param int &$cut After the cast, number of items removed from $obj.
*
* @return array The object casted as array.
*/
protected function castObject($class, $obj, $isNested, &$cut)
protected function castObject($obj, Stub $stub, $isNested)
{
$class = $stub->class;
if (isset($this->classInfo[$class])) {
$classInfo = $this->classInfo[$class];
$stub->class = $classInfo[0];
} else {
$classInfo = array(
$class,
method_exists($class, '__debugInfo'),
new \ReflectionClass($class),
array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
@ -192,24 +199,23 @@ abstract class AbstractCloner implements ClonerInterface
$this->classInfo[$class] = $classInfo;
}
if ($classInfo[0]) {
$a = $this->callCaster(array($obj, '__debugInfo'), $obj, array(), $isNested);
if ($classInfo[1]) {
$a = $this->callCaster(array($obj, '__debugInfo'), $obj, array(), null, $isNested);
} else {
$a = (array) $obj;
}
$cut = 0;
foreach ($a as $k => $p) {
if (!isset($k[0]) || ("\0" !== $k[0] && !$classInfo[1]->hasProperty($k))) {
if (!isset($k[0]) || ("\0" !== $k[0] && !$classInfo[2]->hasProperty($k))) {
unset($a[$k]);
$a["\0+\0".$k] = $p;
}
}
foreach ($classInfo[2] as $p) {
foreach ($classInfo[3] as $p) {
if (!empty($this->casters[$p = 'o:'.strtolower($p)])) {
foreach ($this->casters[$p] as $p) {
$a = $this->callCaster($p, $obj, $a, $isNested, $cut);
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
}
}
}
@ -220,19 +226,20 @@ abstract class AbstractCloner implements ClonerInterface
/**
* Casts a resource to an array representation.
*
* @param string $type The type of the resource.
* @param resource $res The resource.
* @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.
*/
protected function castResource($type, $res, $isNested)
protected function castResource($res, Stub $stub, $isNested)
{
$a = array();
$type = $stub->class;
if (!empty($this->casters['r:'.$type])) {
foreach ($this->casters['r:'.$type] as $c) {
$a = $this->callCaster($c, $res, $a, $isNested);
$a = $this->callCaster($c, $res, $a, $stub, $isNested);
}
}
@ -245,15 +252,15 @@ abstract class AbstractCloner implements ClonerInterface
* @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 int &$cut After the cast, number of items removed from $obj.
*
* @return array The casted object/resource.
*/
private function callCaster($callback, $obj, $a, $isNested, &$cut = 0)
private function callCaster($callback, $obj, $a, $stub, $isNested)
{
try {
$cast = call_user_func_array($callback, array($obj, $a, $isNested, &$cut));
$cast = call_user_func($callback, $obj, $a, $stub, $isNested);
if (is_array($cast)) {
$a = $cast;

View File

@ -49,29 +49,34 @@ class Data
* @param DumperInternalsInterface $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 stdClass or the original value being dumped.
* @param mixed $item A Stub object or the original value being dumped.
*/
private function dumpItem($dumper, $cursor, &$refs, $item)
{
$cursor->refIndex = $cursor->refTo = $cursor->refIsHard = false;
$cursor->refIndex = $cursor->softRefTo = $cursor->hardRefTo = false;
if ($item instanceof \stdClass) {
if (property_exists($item, 'val')) {
if (isset($item->ref)) {
if (isset($refs[$r = $item->ref])) {
$cursor->refTo = $refs[$r];
$cursor->refIsHard = true;
} else {
$cursor->refIndex = $refs[$r] = ++$refs[0];
}
}
$item = $item->val;
}
if (isset($item->ref)) {
if (!$item instanceof Stub) {
$type = gettype($item);
} elseif (Stub::TYPE_REF === $item->type) {
if ($item->ref) {
if (isset($refs[$r = $item->ref])) {
if (false === $cursor->refTo) {
$cursor->refTo = $refs[$r];
$cursor->refIsHard = isset($item->count);
$cursor->hardRefTo = $refs[$r];
} else {
$cursor->refIndex = $refs[$r] = ++$refs[0];
}
}
$type = $item->class ?: gettype($item->value);
$item = $item->value;
}
if ($item instanceof Stub) {
if ($item->ref) {
if (isset($refs[$r = $item->ref])) {
if (Stub::TYPE_ARRAY === $item->type) {
if (false === $cursor->hardRefTo) {
$cursor->hardRefTo = $refs[$r];
}
} elseif (false === $cursor->softRefTo) {
$cursor->softRefTo = $refs[$r];
}
} elseif (false !== $cursor->refIndex) {
$refs[$r] = $cursor->refIndex;
@ -79,10 +84,10 @@ class Data
$cursor->refIndex = $refs[$r] = ++$refs[0];
}
}
$cut = isset($item->cut) ? $item->cut : 0;
$cut = $item->cut;
if (isset($item->pos) && false === $cursor->refTo) {
$children = $this->data[$item->pos];
if ($item->position && false === $cursor->softRefTo && false === $cursor->hardRefTo) {
$children = $this->data[$item->position];
if ($cursor->stop) {
if ($cut >= 0) {
@ -93,41 +98,33 @@ class Data
} else {
$children = array();
}
switch (true) {
case isset($item->bin):
$dumper->dumpString($cursor, $item->bin, true, $cut);
switch ($item->type) {
case Stub::TYPE_STRING:
$dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);
break;
return;
case Stub::TYPE_ARRAY:
$dumper->enterArray($cursor, $item->value, Stub::ARRAY_INDEXED === $item->class, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->class);
$dumper->leaveArray($cursor, $item->value, Stub::ARRAY_INDEXED === $item->class, (bool) $children, $cut);
break;
case isset($item->str):
$dumper->dumpString($cursor, $item->str, false, $cut);
return;
case isset($item->count):
$dumper->enterArray($cursor, $item->count, !empty($item->indexed), (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, empty($item->indexed) ? $cursor::HASH_ASSOC : $cursor::HASH_INDEXED);
$dumper->leaveArray($cursor, $item->count, !empty($item->indexed), (bool) $children, $cut);
return;
case isset($item->class):
case Stub::TYPE_OBJECT:
$dumper->enterObject($cursor, $item->class, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_OBJECT);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, Cursor::HASH_OBJECT);
$dumper->leaveObject($cursor, $item->class, (bool) $children, $cut);
break;
return;
case Stub::TYPE_RESOURCE:
$dumper->enterResource($cursor, $item->class, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, Cursor::HASH_RESOURCE);
$dumper->leaveResource($cursor, $item->class, (bool) $children, $cut);
break;
case isset($item->res):
$dumper->enterResource($cursor, $item->res, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_RESOURCE);
$dumper->leaveResource($cursor, $item->res, (bool) $children, $cut);
return;
default:
throw new \RuntimeException(sprintf('Unexpected Stub type: %s', $item->type));
}
}
if ('array' === $type = gettype($item)) {
} elseif ('array' === $type) {
$dumper->enterArray($cursor, 0, true, 0, 0);
$dumper->leaveArray($cursor, 0, true, 0, 0);
} else {
@ -143,7 +140,7 @@ class Data
* @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 int $hashType A Cursor::HASH_* const.
* @param string $hashType A Cursor::HASH_* const.
*
* @return int The final number of removed items.
*/

View File

@ -32,7 +32,7 @@ class ExtCloner extends AbstractCloner
$maxItems = $this->maxItems;
$maxString = $this->maxString;
$a = null; // Array cast for nested structures
$stub = null; // stdClass capturing the main properties of an original item value,
$stub = null; // Stub capturing the main properties of an original item value,
// or null if the original value is used directly
for ($i = 0; $i < $len; ++$i) {
@ -60,15 +60,20 @@ class ExtCloner extends AbstractCloner
switch ($zval['type']) {
case 'string':
if (isset($v[0]) && !preg_match('//u', $v)) {
$stub = new Stub();
$stub->type = Stub::TYPE_STRING;
$stub->class = Stub::STRING_BINARY;
if (0 <= $maxString && 0 < $cut = strlen($v) - $maxString) {
$stub = substr_replace($v, '', -$cut);
$stub = (object) array('cut' => $cut, 'bin' => Data::utf8Encode($stub));
} else {
$stub = (object) array('bin' => Data::utf8Encode($v));
$stub->cut = $cut;
$v = substr_replace($v, '', -$cut);
}
$stub->value = Data::utf8Encode($v);
} elseif (0 <= $maxString && isset($v[1+($maxString>>2)]) && 0 < $cut = iconv_strlen($v, 'UTF-8') - $maxString) {
$stub = iconv_substr($v, 0, $maxString, 'UTF-8');
$stub = (object) array('cut' => $cut, 'str' => $stub);
$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');
}
break;
@ -77,23 +82,33 @@ class ExtCloner extends AbstractCloner
case 'array':
if ($v) {
$stub = (object) array('count' => $zval['array_count']);
$arrayRefs[$len] = $stub;
$stub = $arrayRefs[$len] = new Stub();
$stub->type = Stub::TYPE_ARRAY;
$stub->class = Stub::ARRAY_ASSOC;
$stub->value = $zval['array_count'];
$a = $v;
}
break;
case 'object':
if (empty($softRefs[$h = $zval['object_hash']])) {
$stub = $softRefs[$h] = (object) array('class' => $zval['object_class']);
if (0 > $maxItems || $pos < $maxItems) {
$a = $this->castObject($stub->class, $v, 0 < $i, $cut);
if ($cut) {
$stub->cut = $cut;
}
} else {
$stub->cut = -1;
$stub = new Stub();
$stub->type = Stub::TYPE_OBJECT;
$stub->class = $zval['object_class'];
$stub->value = $h;
$a = $this->castObject($v, $stub, 0 < $i);
if (Stub::TYPE_OBJECT !== $stub->type) {
break;
}
$h = $stub->value;
$stub->value = '';
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = array();
}
}
if (empty($softRefs[$h])) {
$softRefs[$h] = $stub;
} else {
$stub = $softRefs[$h];
$stub->ref = ++$refs;
@ -101,13 +116,24 @@ class ExtCloner extends AbstractCloner
break;
case 'resource':
if (empty($softRefs[$h = $zval['resource_id']])) {
$stub = $softRefs[$h] = (object) array('res' => $zval['resource_type']);
if (0 > $maxItems || $pos < $maxItems) {
$a = $this->castResource($stub->res, $v, 0 < $i);
} else {
$stub->cut = -1;
if (empty($softRefs[$h = (int) $v])) {
$stub = new Stub();
$stub->type = Stub::TYPE_RESOURCE;
$stub->class = $zval['resource_type'];
$stub->value = $h;
$a = $this->castResource($v, $stub, 0 < $i);
if (Stub::TYPE_RESOURCE !== $stub->type) {
break;
}
$h = $stub->value;
$stub->value = '';
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = array();
}
}
if (empty($softRefs[$h])) {
$softRefs[$h] = $stub;
} else {
$stub = $softRefs[$h];
$stub->ref = ++$refs;
@ -117,10 +143,11 @@ class ExtCloner extends AbstractCloner
if (isset($stub)) {
if ($zval['zval_isref']) {
if (isset($stub->count)) {
if (Stub::TYPE_ARRAY === $stub->type) {
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = $stub;
} else {
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = (object) array('val' => $stub);
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
$v->value = $stub;
}
} else {
$queue[$i][$k] = $stub;
@ -132,16 +159,12 @@ class ExtCloner extends AbstractCloner
if ($pos < $maxItems) {
if ($maxItems < $pos += $k) {
$a = array_slice($a, 0, $maxItems - $pos);
if (empty($stub->cut)) {
$stub->cut = $pos - $maxItems;
} elseif ($stub->cut > 0) {
if ($stub->cut >= 0) {
$stub->cut += $pos - $maxItems;
}
}
} else {
if (empty($stub->cut)) {
$stub->cut = $k;
} elseif ($stub->cut > 0) {
if ($stub->cut >= 0) {
$stub->cut += $k;
}
$stub = $a = null;
@ -150,17 +173,18 @@ class ExtCloner extends AbstractCloner
}
}
$queue[$len] = $a;
$stub->pos = $len++;
$stub->position = $len++;
}
$stub = $a = null;
} elseif ($zval['zval_isref']) {
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = (object) array('val' => $v);
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = new Stub();
$queue[$i][$k]->value = $v;
}
}
if (isset($arrayRefs[$i])) {
if ($indexed) {
$arrayRefs[$i]->indexed = 1;
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
}
unset($arrayRefs[$i]);
}

View File

@ -35,7 +35,7 @@ class PhpCloner extends AbstractCloner
$cookie = (object) array(); // Unique object used to detect hard references
$isRef = false;
$a = null; // Array cast for nested structures
$stub = null; // stdClass capturing the main properties of an original item value,
$stub = null; // Stub capturing the main properties of an original item value,
// or null if the original value is used directly
for ($i = 0; $i < $len; ++$i) {
@ -52,7 +52,7 @@ class PhpCloner extends AbstractCloner
if ($queue[$i][$k] === $cookie) {
$queue[$i][$k] =& $stub; // Break hard references to make $queue completely
unset($stub); // independent from the original structure
if ($v instanceof \stdClass && isset($hardRefs[spl_object_hash($v)])) {
if ($v instanceof Stub && isset($hardRefs[spl_object_hash($v)])) {
$v->ref = ++$refs;
$step[$k] = $queue[$i][$k] = $v;
continue;
@ -64,15 +64,22 @@ class PhpCloner extends AbstractCloner
switch (gettype($v)) {
case 'string':
if (isset($v[0]) && !preg_match('//u', $v)) {
$stub = new Stub();
$stub->type = Stub::TYPE_STRING;
$stub->class = Stub::STRING_BINARY;
if (0 <= $maxString && 0 < $cut = strlen($v) - $maxString) {
$stub = substr_replace($v, '', -$cut);
$stub = (object) array('cut' => $cut, 'bin' => Data::utf8Encode($stub));
$stub->cut = $cut;
$cut = substr_replace($v, '', -$cut);
} else {
$stub = (object) array('bin' => Data::utf8Encode($v));
$cut = $v;
}
$stub->value = Data::utf8Encode($cut);
} elseif (0 <= $maxString && isset($v[1+($maxString>>2)]) && 0 < $cut = iconv_strlen($v, 'UTF-8') - $maxString) {
$stub = iconv_substr($v, 0, $maxString, 'UTF-8');
$stub = (object) array('cut' => $cut, 'str' => $stub);
$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');
}
break;
@ -81,23 +88,33 @@ class PhpCloner extends AbstractCloner
case 'array':
if ($v) {
$stub = (object) array('count' => count($v));
$arrayRefs[$len] = $stub;
$stub = $arrayRefs[$len] = new Stub();
$stub->type = Stub::TYPE_ARRAY;
$stub->class = Stub::ARRAY_ASSOC;
$stub->value = count($v);
$a = $v;
}
break;
case 'object':
if (empty($softRefs[$h = spl_object_hash($v)])) {
$stub = $softRefs[$h] = (object) array('class' => get_class($v));
if (0 > $maxItems || $pos < $maxItems) {
$a = $this->castObject($stub->class, $v, 0 < $i, $cut);
if ($cut) {
$stub->cut = $cut;
}
} else {
$stub->cut = -1;
$stub = new Stub();
$stub->type = Stub::TYPE_OBJECT;
$stub->class = get_class($v);
$stub->value = $h;
$a = $this->castObject($v, $stub, 0 < $i);
if (Stub::TYPE_OBJECT !== $stub->type) {
break;
}
$h = $stub->value;
$stub->value = '';
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = array();
}
}
if (empty($softRefs[$h])) {
$softRefs[$h] = $stub;
} else {
$stub = $softRefs[$h];
$stub->ref = ++$refs;
@ -106,13 +123,24 @@ class PhpCloner extends AbstractCloner
case 'resource':
case 'unknown type':
if (empty($softRefs[$h = (int) substr_replace($v, '', 0, 13)])) {
$stub = $softRefs[$h] = (object) array('res' => @get_resource_type($v));
if (0 > $maxItems || $pos < $maxItems) {
$a = $this->castResource($stub->res, $v, 0 < $i);
} else {
$stub->cut = -1;
if (empty($softRefs[$h = (int) $v])) {
$stub = new Stub();
$stub->type = Stub::TYPE_RESOURCE;
$stub->class = get_resource_type($v);
$stub->value = $h;
$a = $this->castResource($v, $stub, 0 < $i);
if (Stub::TYPE_RESOURCE !== $stub->type) {
break;
}
$h = $stub->value;
$stub->value = '';
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = array();
}
}
if (empty($softRefs[$h])) {
$softRefs[$h] = $stub;
} else {
$stub = $softRefs[$h];
$stub->ref = ++$refs;
@ -122,10 +150,11 @@ class PhpCloner extends AbstractCloner
if (isset($stub)) {
if ($isRef) {
if (isset($stub->count)) {
if (Stub::TYPE_ARRAY === $stub->type) {
$step[$k] = $stub;
} else {
$step[$k] = (object) array('val' => $stub);
$step[$k] = new Stub();
$step[$k]->value = $stub;
}
$h = spl_object_hash($step[$k]);
$queue[$i][$k] = $hardRefs[$h] =& $step[$k];
@ -141,16 +170,12 @@ class PhpCloner extends AbstractCloner
if ($pos < $maxItems) {
if ($maxItems < $pos += $k) {
$a = array_slice($a, 0, $maxItems - $pos);
if (empty($stub->cut)) {
$stub->cut = $pos - $maxItems;
} elseif ($stub->cut > 0) {
if ($stub->cut >= 0) {
$stub->cut += $pos - $maxItems;
}
}
} else {
if (empty($stub->cut)) {
$stub->cut = $k;
} elseif ($stub->cut > 0) {
if ($stub->cut >= 0) {
$stub->cut += $k;
}
$stub = $a = null;
@ -159,21 +184,22 @@ class PhpCloner extends AbstractCloner
}
}
$queue[$len] = $a;
$stub->pos = $len++;
$stub->position = $len++;
}
$stub = $a = null;
} elseif ($isRef) {
$step[$k] = $queue[$i][$k] = $v = (object) array('val' => $v);
$h = spl_object_hash($v);
$step[$k] = $queue[$i][$k] = new Stub();
$step[$k]->value = $v;
$h = spl_object_hash($step[$k]);
$hardRefs[$h] =& $step[$k];
$values[$h] = $v->val;
$values[$h] = $v;
$isRef = false;
}
}
if (isset($arrayRefs[$i])) {
if ($indexed) {
$arrayRefs[$i]->indexed = 1;
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
}
unset($arrayRefs[$i]);
}

View File

@ -0,0 +1,39 @@
<?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\Cloner;
/**
* Represents the main properties of a PHP variable.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class Stub
{
const TYPE_REF = 'ref';
const TYPE_STRING = 'string';
const TYPE_ARRAY = 'array';
const TYPE_OBJECT = 'object';
const TYPE_RESOURCE = 'resource';
const STRING_BINARY = 'bin';
const STRING_UTF8 = 'utf8';
const ARRAY_ASSOC = 'assoc';
const ARRAY_INDEXED = 'indexed';
public $type = self::TYPE_REF;
public $class = '';
public $value;
public $cut = 0;
public $ref = 0;
public $position = 0;
}

View File

@ -93,7 +93,7 @@ class CliDumper extends AbstractDumper
$style = 'const';
switch ($type) {
case 'int':
case 'integer':
$style = 'num';
break;
@ -124,10 +124,6 @@ class CliDumper extends AbstractDumper
$this->line .= $this->style($style, $val);
if (false !== $cursor->refTo) {
$this->line .= ' '.$this->style('ref', '&'.$cursor->refTo);
}
$this->endLine($cursor);
}
@ -140,14 +136,11 @@ class CliDumper extends AbstractDumper
if ('' === $str) {
$this->line .= '""';
if (false !== $cursor->refTo) {
$this->line .= ' '.$this->style('ref', '&'.$cursor->refTo);
}
$this->endLine($cursor);
} else {
$str = explode("\n", $str);
$m = count($str) - 1;
$i = 0;
$i = $lineCut = 0;
if ($bin) {
$this->line .= 'b';
@ -155,9 +148,6 @@ class CliDumper extends AbstractDumper
if ($m) {
$this->line .= '"""';
if (false !== $cursor->refTo) {
$this->line .= $this->style('ref', '&'.$cursor->refTo);
}
$this->endLine($cursor);
} else {
$this->line .= '"';
@ -165,32 +155,31 @@ class CliDumper extends AbstractDumper
foreach ($str as $str) {
if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = iconv_strlen($str, 'UTF-8')) {
$str = iconv_substr($str, 0, $this->maxStringWidth - 1, 'UTF-8');
$str = $this->style('str', $str).'…';
} else {
$str = $this->style('str', $str);
$str = iconv_substr($str, 0, $this->maxStringWidth, 'UTF-8');
$lineCut = $len - $this->maxStringWidth;
}
if ($m) {
$this->line .= $this->indentPad;
}
$this->line .= $str;
$this->line .= $this->style('str', $str);
if ($i++ == $m) {
if ($cut) {
if (0 >= $this->maxStringWidth || $this->maxStringWidth >= $len) {
$this->line .= '…';
}
$this->line .= $cut;
} elseif ($m) {
$this->line .= '"""';
} else {
$this->line .= '"';
$this->line .= '"';
if ($m) {
$this->line .= '""';
}
if (!$m && false !== $cursor->refTo) {
$this->line .= $this->style('ref', '&'.$cursor->refTo);
if ($cut < 0) {
$this->line .= '…';
$lineCut = 0;
} elseif ($cut) {
$lineCut += $cut;
}
}
if ($lineCut) {
$this->line .= '…'.$lineCut;
$lineCut = 0;
}
$this->endLine($cursor, !$m);
}
@ -257,8 +246,10 @@ class CliDumper extends AbstractDumper
$this->dumpKey($cursor);
$this->line .= $prefix;
if (false !== $cursor->refTo) {
$this->line .= $this->style('ref', ($cursor->refIsHard ? '&' : '@').$cursor->refTo);
if (false !== $cursor->softRefTo) {
$this->line .= $this->style('ref', '@'.$cursor->softRefTo);
} elseif (false !== $cursor->hardRefTo) {
$this->line .= $this->style('ref', '@'.$cursor->hardRefTo);
} elseif ($hasChild) {
$this->endLine($cursor);
}
@ -274,7 +265,7 @@ class CliDumper extends AbstractDumper
*/
protected function leaveHash(Cursor $cursor, $suffix, $hasChild, $cut)
{
if ($cut && false === $cursor->refTo) {
if ($cut && false === $cursor->softRefTo && false === $cursor->hardRefTo) {
$this->line .= '…';
if (0 < $cut) {
$this->line .= $cut;
@ -336,6 +327,10 @@ class CliDumper extends AbstractDumper
}
break;
}
if (false !== $cursor->hardRefTo) {
$this->line .= $this->style('ref', '&'.$cursor->hardRefTo).' ';
}
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\VarDumper\Dumper;
use Symfony\Component\VarDumper\Cloner\Stub;
/**
* Represents the current state of a dumper while dumping.
*
@ -18,15 +20,15 @@ namespace Symfony\Component\VarDumper\Dumper;
*/
class Cursor
{
const HASH_INDEXED = 'indexed-array';
const HASH_ASSOC = 'associative-array';
const HASH_OBJECT = 'object';
const HASH_RESOURCE = 'resource';
const HASH_INDEXED = Stub::ARRAY_INDEXED;
const HASH_ASSOC = Stub::ARRAY_ASSOC;
const HASH_OBJECT = Stub::TYPE_OBJECT;
const HASH_RESOURCE = Stub::TYPE_RESOURCE;
public $depth = 0;
public $refIndex = false;
public $refTo = false;
public $refIsHard = false;
public $softRefTo = false;
public $hardRefTo = false;
public $hashType;
public $hashKey;
public $hashIndex = 0;

View File

@ -82,11 +82,11 @@ array:25 [
0 => {} #3
]
"recurs" => array:1 [ #4
0 => array:1 [&4]
0 => &4 array:1 [@4]
]
9 => null &1
9 => &1 null
"sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {@2}
"snobj" => {&3}
"snobj" => &3 {@3}
"snobj2" => {@3}
"file" => "{$var['file']}"
b"bin-key-é" => ""

View File

@ -52,7 +52,7 @@ span.sf-dump-meta {color:#005FFF}
</style>
<pre class=sf-dump style=white-space:pre><span class=sf-dump-0><span class=sf-dump-note>array:25</span> [
<span class=sf-dump-1>"<span class=sf-dump-meta>number</span>" => <span class=sf-dump-const>1</span>
<span class=sf-dump-1>"<span class=sf-dump-meta>number</span>" => <span class=sf-dump-num>1</span>
<span class=sf-dump-meta>0</span> => <span class=sf-dump-const>null</span> <a class=sf-dump-ref name="sf-dump-ref1">#1</a>
"<span class=sf-dump-meta>const</span>" => <span class=sf-dump-num>1.1</span>
<span class=sf-dump-meta>1</span> => <span class=sf-dump-const>true</span>
@ -60,7 +60,7 @@ span.sf-dump-meta {color:#005FFF}
<span class=sf-dump-meta>3</span> => <span class=sf-dump-num>NAN</span>
<span class=sf-dump-meta>4</span> => <span class=sf-dump-num>INF</span>
<span class=sf-dump-meta>5</span> => <span class=sf-dump-num>-INF</span>
<span class=sf-dump-meta>6</span> => <span class=sf-dump-const>9223372036854775807</span>
<span class=sf-dump-meta>6</span> => <span class=sf-dump-num>9223372036854775807</span>
"<span class=sf-dump-meta>str</span>" => "<span class=sf-dump-str>déjà</span>"
<span class=sf-dump-meta>7</span> => b"<span class=sf-dump-str>é</span>"
"<span class=sf-dump-meta>[]</span>" => []
@ -68,7 +68,7 @@ span.sf-dump-meta {color:#005FFF}
<span class=sf-dump-2><span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str>plainfile</span>"
<span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str>dir</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-const>0</span>
<span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
<span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
<span class=sf-dump-meta>timed_out</span>: <span class=sf-dump-const>false</span>
<span class=sf-dump-meta>blocked</span>: <span class=sf-dump-const>true</span>
@ -92,16 +92,16 @@ span.sf-dump-meta {color:#005FFF}
<span class=sf-dump-str>}</span>
"""
</span>}
"<span class=sf-dump-meta>line</span>" => <span class=sf-dump-const>{$var['line']}</span>
"<span class=sf-dump-meta>line</span>" => <span class=sf-dump-num>{$var['line']}</span>
"<span class=sf-dump-meta>nobj</span>" => <span class=sf-dump-note>array:1</span> [
<span class=sf-dump-2><span class=sf-dump-meta>0</span> => {} <a class=sf-dump-ref name="sf-dump-ref3">#3</a>
</span>]
"<span class=sf-dump-meta>recurs</span>" => <span class=sf-dump-note>array:1</span> [ <a class=sf-dump-ref name="sf-dump-ref4">#4</a>
<span class=sf-dump-2><span class=sf-dump-meta>0</span> => <span class=sf-dump-note>array:1</span> [<a class=sf-dump-ref href="#sf-dump-ref4">&4</a>]
<span class=sf-dump-2><span class=sf-dump-meta>0</span> => <a class=sf-dump-ref href="#sf-dump-ref4">&4</a> <span class=sf-dump-note>array:1</span> [<a class=sf-dump-ref href="#sf-dump-ref4">@4</a>]
</span>]
<span class=sf-dump-meta>9</span> => <span class=sf-dump-const>null</span> <a class=sf-dump-ref href="#sf-dump-ref1">&1</a>
<span class=sf-dump-meta>9</span> => <a class=sf-dump-ref href="#sf-dump-ref1">&1</a> <span class=sf-dump-const>null</span>
"<span class=sf-dump-meta>sobj</span>" => <span class=sf-dump-note>Symfony\Component\VarDumper\Tests\Fixture\DumbFoo</span> {<a class=sf-dump-ref href="#sf-dump-ref2">@2</a>}
"<span class=sf-dump-meta>snobj</span>" => {<a class=sf-dump-ref href="#sf-dump-ref3">&3</a>}
"<span class=sf-dump-meta>snobj</span>" => <a class=sf-dump-ref href="#sf-dump-ref3">&3</a> {<a class=sf-dump-ref href="#sf-dump-ref3">@3</a>}
"<span class=sf-dump-meta>snobj2</span>" => {<a class=sf-dump-ref href="#sf-dump-ref3">@3</a>}
"<span class=sf-dump-meta>file</span>" => "<span class=sf-dump-str>{$var['file']}</span>"
b"<span class=sf-dump-meta>bin-key-é</span>" => ""