[TwigBridge] add Twig dump() function + tests and fixes
This commit is contained in:
parent
0f8d30fd89
commit
2e167ba351
|
@ -85,10 +85,7 @@
|
||||||
"src/Symfony/Component/HttpFoundation/Resources/stubs",
|
"src/Symfony/Component/HttpFoundation/Resources/stubs",
|
||||||
"src/Symfony/Component/Intl/Resources/stubs"
|
"src/Symfony/Component/Intl/Resources/stubs"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [ "src/Symfony/Component/Intl/Resources/stubs/functions.php" ]
|
||||||
"src/Symfony/Component/Intl/Resources/stubs/functions.php",
|
|
||||||
"src/Symfony/Component/VarDumper/Resources/functions/dump.php"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
namespace Symfony\Bridge\Twig\Extension;
|
namespace Symfony\Bridge\Twig\Extension;
|
||||||
|
|
||||||
use Symfony\Bridge\Twig\TokenParser\DumpTokenParser;
|
use Symfony\Bridge\Twig\TokenParser\DumpTokenParser;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||||
|
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides integration of the dump() function with Twig.
|
* Provides integration of the dump() function with Twig.
|
||||||
|
@ -20,6 +22,18 @@ use Symfony\Bridge\Twig\TokenParser\DumpTokenParser;
|
||||||
*/
|
*/
|
||||||
class DumpExtension extends \Twig_Extension
|
class DumpExtension extends \Twig_Extension
|
||||||
{
|
{
|
||||||
|
public function __construct(ClonerInterface $cloner = null)
|
||||||
|
{
|
||||||
|
$this->cloner = $cloner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
new \Twig_SimpleFunction('dump', array($this, 'dump'), array('is_safe' => array('html'), 'needs_context' => true, 'needs_environment' => true)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function getTokenParsers()
|
public function getTokenParsers()
|
||||||
{
|
{
|
||||||
return array(new DumpTokenParser());
|
return array(new DumpTokenParser());
|
||||||
|
@ -29,4 +43,38 @@ class DumpExtension extends \Twig_Extension
|
||||||
{
|
{
|
||||||
return 'dump';
|
return 'dump';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dump(\Twig_Environment $env, $context)
|
||||||
|
{
|
||||||
|
if (!$env->isDebug() || !$this->cloner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 === func_num_args()) {
|
||||||
|
$vars = array();
|
||||||
|
foreach ($context as $key => $value) {
|
||||||
|
if (!$value instanceof \Twig_Template) {
|
||||||
|
$vars[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$vars = array($vars);
|
||||||
|
} else {
|
||||||
|
$vars = func_get_args();
|
||||||
|
unset($vars[0], $vars[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = '';
|
||||||
|
$dumper = new HtmlDumper(function ($line, $depth) use (&$html) {
|
||||||
|
if (-1 !== $depth) {
|
||||||
|
$html .= str_repeat(' ', $depth).$line."\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($vars as $value) {
|
||||||
|
$dumper->dump($this->cloner->cloneVar($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,20 +13,22 @@ namespace Symfony\Bridge\Twig\Tests\Extension;
|
||||||
|
|
||||||
use Symfony\Bridge\Twig\Extension\DumpExtension;
|
use Symfony\Bridge\Twig\Extension\DumpExtension;
|
||||||
use Symfony\Component\VarDumper\VarDumper;
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\PhpCloner;
|
||||||
|
|
||||||
class DumpExtensionTest extends \PHPUnit_Framework_TestCase
|
class DumpExtensionTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider getDumpParams
|
* @dataProvider getDumpTags
|
||||||
*/
|
*/
|
||||||
public function testDebugDump($template, $debug, $expectedOutput, $expectedDumped)
|
public function testDumpTag($template, $debug, $expectedOutput, $expectedDumped)
|
||||||
{
|
{
|
||||||
|
$extension = new DumpExtension(new PhpCloner());
|
||||||
$twig = new \Twig_Environment(new \Twig_Loader_String(), array(
|
$twig = new \Twig_Environment(new \Twig_Loader_String(), array(
|
||||||
'debug' => $debug,
|
'debug' => $debug,
|
||||||
'cache' => false,
|
'cache' => false,
|
||||||
'optimizations' => 0,
|
'optimizations' => 0,
|
||||||
));
|
));
|
||||||
$twig->addExtension(new DumpExtension());
|
$twig->addExtension($extension);
|
||||||
|
|
||||||
$dumped = null;
|
$dumped = null;
|
||||||
$exception = null;
|
$exception = null;
|
||||||
|
@ -46,7 +48,7 @@ class DumpExtensionTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertSame($expectedDumped, $dumped);
|
$this->assertSame($expectedDumped, $dumped);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDumpParams()
|
public function getDumpTags()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('A{% dump %}B', true, 'AB', array()),
|
array('A{% dump %}B', true, 'AB', array()),
|
||||||
|
@ -54,4 +56,50 @@ class DumpExtensionTest extends \PHPUnit_Framework_TestCase
|
||||||
array('A{% dump %}B', false, 'AB', null),
|
array('A{% dump %}B', false, 'AB', null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getDumpArgs
|
||||||
|
*/
|
||||||
|
public function testDump($context, $args, $expectedOutput, $debug = true)
|
||||||
|
{
|
||||||
|
$extension = new DumpExtension(new PhpCloner());
|
||||||
|
$twig = new \Twig_Environment(new \Twig_Loader_String(), array(
|
||||||
|
'debug' => $debug,
|
||||||
|
'cache' => false,
|
||||||
|
'optimizations' => 0,
|
||||||
|
));
|
||||||
|
|
||||||
|
array_unshift($args, $context);
|
||||||
|
array_unshift($args, $twig);
|
||||||
|
|
||||||
|
$dump = call_user_func_array(array($extension, 'dump'), $args);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
$this->assertStringStartsWith('<script>', $dump);
|
||||||
|
$dump = preg_replace('/^.*?<pre/', '<pre', $dump);
|
||||||
|
}
|
||||||
|
$this->assertEquals($expectedOutput, $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDumpArgs()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(array(), array(), '', false),
|
||||||
|
array(array(), array(), "<pre id=sf-dump><span class=sf-dump-0>[]\n</span></pre><script>Sfjs.dump.instrument()</script>\n"),
|
||||||
|
array(
|
||||||
|
array(),
|
||||||
|
array(123, 456),
|
||||||
|
"<pre id=sf-dump><span class=sf-dump-0><span class=sf-dump-num>123</span>\n</span></pre><script>Sfjs.dump.instrument()</script>\n"
|
||||||
|
."<pre id=sf-dump><span class=sf-dump-0><span class=sf-dump-num>456</span>\n</span></pre><script>Sfjs.dump.instrument()</script>\n",
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array('foo' => 'bar'),
|
||||||
|
array(),
|
||||||
|
"<pre id=sf-dump><span class=sf-dump-0><span class=sf-dump-note>array:1</span> [<span name=sf-dump-child>\n"
|
||||||
|
." <span class=sf-dump-1>\"<span class=sf-dump-meta>foo</span>\" => \"<span class=sf-dump-str>bar</span>\"\n"
|
||||||
|
."</span></span>]\n"
|
||||||
|
."</span></pre><script>Sfjs.dump.instrument()</script>\n",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,9 @@
|
||||||
<argument type="service" id="debug.stopwatch" />
|
<argument type="service" id="debug.stopwatch" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="twig.extension.debug" class="Twig_Extension_Debug" public="false">
|
|
||||||
<tag name="twig.extension" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<service id="twig.extension.dump" class="%twig.extension.dump.class%" public="false">
|
<service id="twig.extension.dump" class="%twig.extension.dump.class%" public="false">
|
||||||
<tag name="twig.extension" />
|
<tag name="twig.extension" />
|
||||||
|
<argument type="service" id="var_dumper.cloner" on-invalid="null" />
|
||||||
</service>
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
@ -169,7 +169,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||||
$dumper->dump(
|
$dumper->dump(
|
||||||
$dump['data']->getLimitedClone($maxDepthLimit, $maxItemsPerDepth),
|
$dump['data']->getLimitedClone($maxDepthLimit, $maxItemsPerDepth),
|
||||||
function ($line, $depth) use (&$data) {
|
function ($line, $depth) use (&$data) {
|
||||||
if (false !==$depth) {
|
if (-1 !== $depth) {
|
||||||
$data .= str_repeat(' ', $depth).$line."\n";
|
$data .= str_repeat(' ', $depth).$line."\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,17 @@ class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$xDump = array(
|
$xDump = array(
|
||||||
array(
|
array(
|
||||||
'data' => "<!DOCTYPE html><style> pre.sf-dump { background-color: #300a24; white-space: pre; line-height: 1.2em; color: #eee8d5; font-family: monospace, sans-serif; padding: 5px; } .sf-dump span { display: inline; }a.sf-dump-ref {color:#444444}span.sf-dump-num {font-weight:bold;color:#0087FF}span.sf-dump-const {font-weight:bold;color:#0087FF}span.sf-dump-str {font-weight:bold;color:#00D7FF}span.sf-dump-cchr {font-style: italic}span.sf-dump-note {color:#D7AF00}span.sf-dump-ref {color:#444444}span.sf-dump-public {color:#008700}span.sf-dump-protected {color:#D75F00}span.sf-dump-private {color:#D70000}span.sf-dump-meta {color:#005FFF}</style><pre class=sf-dump><span class=sf-dump-0><span class=sf-dump-num>123</span>\n</pre>\n",
|
'data' => "<pre id=sf-dump><span class=sf-dump-0><span class=sf-dump-num>123</span>\n</span></pre><script>Sfjs.dump.instrument()</script>\n",
|
||||||
'name' => 'DumpDataCollectorTest.php',
|
'name' => 'DumpDataCollectorTest.php',
|
||||||
'file' => __FILE__,
|
'file' => __FILE__,
|
||||||
'line' => $line,
|
'line' => $line,
|
||||||
'fileExcerpt' => false,
|
'fileExcerpt' => false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$this->assertSame($xDump, $collector->getDumps('html'));
|
$dump = $collector->getDumps('html');
|
||||||
|
$this->assertTrue(isset($dump[0]['data']));
|
||||||
|
$dump[0]['data'] = preg_replace('/^.*?<pre/', '<pre', $dump[0]['data']);
|
||||||
|
$this->assertSame($xDump, $dump);
|
||||||
|
|
||||||
$this->assertStringStartsWith(
|
$this->assertStringStartsWith(
|
||||||
'a:1:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":3:{s:45:"Symfony\Component\VarDumper\Cloner\Datadata";a:1:{i:0;a:1:{i:0;i:123;}}s:49:"Symfony\Component\VarDumper\Cloner\DatamaxDepth";i:-1;s:57:"Symfony\Component\VarDumper\Cloner\DatamaxItemsPerDepth";i:-1;}s:4:"name";s:25:"DumpDataCollectorTest.php";s:4:"file";s:',
|
'a:1:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":3:{s:45:"Symfony\Component\VarDumper\Cloner\Datadata";a:1:{i:0;a:1:{i:0;i:123;}}s:49:"Symfony\Component\VarDumper\Cloner\DatamaxDepth";i:-1;s:57:"Symfony\Component\VarDumper\Cloner\DatamaxItemsPerDepth";i:-1;}s:4:"name";s:25:"DumpDataCollectorTest.php";s:4:"file";s:',
|
||||||
|
|
|
@ -29,8 +29,9 @@ class ReflectionCaster
|
||||||
|
|
||||||
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
|
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
|
$stub->class = 'Closure'; // HHVM generates unique class names for closures
|
||||||
$a = static::castReflector(new \ReflectionFunction($c), $a, $stub, $isNested);
|
$a = static::castReflector(new \ReflectionFunction($c), $a, $stub, $isNested);
|
||||||
unset($a["\0+\0000"], $a['name']);
|
unset($a["\0+\0000"], $a['name'], $a["\0+\0this"], $a["\0+\0parameter"]);
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class ResourceCaster
|
||||||
public static function castDba($dba, array $a, Stub $stub, $isNested)
|
public static function castDba($dba, array $a, Stub $stub, $isNested)
|
||||||
{
|
{
|
||||||
$list = dba_list();
|
$list = dba_list();
|
||||||
$a['file'] = $list[substr((string) $dba, 13)];
|
$a['file'] = $list[(int) $dba];
|
||||||
|
|
||||||
return $a;
|
return $a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,64 +21,64 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
|
||||||
abstract class AbstractCloner implements ClonerInterface
|
abstract class AbstractCloner implements ClonerInterface
|
||||||
{
|
{
|
||||||
public static $defaultCasters = array(
|
public static $defaultCasters = array(
|
||||||
'o:Symfony\Component\VarDumper\Caster\CasterStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
'Symfony\Component\VarDumper\Caster\CasterStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
||||||
|
|
||||||
'o:Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
|
'Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
|
||||||
'o:Reflector' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflector',
|
'Reflector' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflector',
|
||||||
|
|
||||||
'o:Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
|
'Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
|
||||||
'o:Doctrine\Common\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castCommonProxy',
|
'Doctrine\Common\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castCommonProxy',
|
||||||
'o:Doctrine\ORM\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castOrmProxy',
|
'Doctrine\ORM\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castOrmProxy',
|
||||||
'o:Doctrine\ORM\PersistentCollection' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castPersistentCollection',
|
'Doctrine\ORM\PersistentCollection' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castPersistentCollection',
|
||||||
|
|
||||||
'o:DOMException' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castException',
|
'DOMException' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castException',
|
||||||
'o:DOMStringList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
'DOMStringList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||||
'o:DOMNameList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
'DOMNameList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||||
'o:DOMImplementation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castImplementation',
|
'DOMImplementation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castImplementation',
|
||||||
'o:DOMImplementationList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
'DOMImplementationList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||||
'o:DOMNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNode',
|
'DOMNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNode',
|
||||||
'o:DOMNameSpaceNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNameSpaceNode',
|
'DOMNameSpaceNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNameSpaceNode',
|
||||||
'o:DOMDocument' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocument',
|
'DOMDocument' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocument',
|
||||||
'o:DOMNodeList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
'DOMNodeList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||||
'o:DOMNamedNodeMap' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
'DOMNamedNodeMap' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||||
'o:DOMCharacterData' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castCharacterData',
|
'DOMCharacterData' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castCharacterData',
|
||||||
'o:DOMAttr' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castAttr',
|
'DOMAttr' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castAttr',
|
||||||
'o:DOMElement' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castElement',
|
'DOMElement' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castElement',
|
||||||
'o:DOMText' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castText',
|
'DOMText' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castText',
|
||||||
'o:DOMTypeinfo' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castTypeinfo',
|
'DOMTypeinfo' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castTypeinfo',
|
||||||
'o:DOMDomError' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDomError',
|
'DOMDomError' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDomError',
|
||||||
'o:DOMLocator' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLocator',
|
'DOMLocator' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLocator',
|
||||||
'o:DOMDocumentType' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocumentType',
|
'DOMDocumentType' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocumentType',
|
||||||
'o:DOMNotation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNotation',
|
'DOMNotation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNotation',
|
||||||
'o:DOMEntity' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castEntity',
|
'DOMEntity' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castEntity',
|
||||||
'o:DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
|
'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
|
||||||
'o:DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
|
'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
|
||||||
|
|
||||||
'o:ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
|
'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
|
||||||
'o:Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
|
'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
|
||||||
'o:Symfony\Component\DependencyInjection\ContainerInterface'
|
'Symfony\Component\DependencyInjection\ContainerInterface'
|
||||||
=> 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
|
=> 'Symfony\Component\VarDumper\Caster\StubCaster::castNestedFat',
|
||||||
'o:Symfony\Component\VarDumper\Exception\ThrowingCasterException'
|
'Symfony\Component\VarDumper\Exception\ThrowingCasterException'
|
||||||
=> 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castThrowingCasterException',
|
=> 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castThrowingCasterException',
|
||||||
|
|
||||||
'o:PDO' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdo',
|
'PDO' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdo',
|
||||||
'o:PDOStatement' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdoStatement',
|
'PDOStatement' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdoStatement',
|
||||||
|
|
||||||
'o:ArrayObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castArrayObject',
|
'ArrayObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castArrayObject',
|
||||||
'o:SplDoublyLinkedList' => 'Symfony\Component\VarDumper\Caster\SplCaster::castDoublyLinkedList',
|
'SplDoublyLinkedList' => 'Symfony\Component\VarDumper\Caster\SplCaster::castDoublyLinkedList',
|
||||||
'o:SplFixedArray' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFixedArray',
|
'SplFixedArray' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFixedArray',
|
||||||
'o:SplHeap' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
'SplHeap' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
||||||
'o:SplObjectStorage' => 'Symfony\Component\VarDumper\Caster\SplCaster::castObjectStorage',
|
'SplObjectStorage' => 'Symfony\Component\VarDumper\Caster\SplCaster::castObjectStorage',
|
||||||
'o:SplPriorityQueue' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
'SplPriorityQueue' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
||||||
|
|
||||||
'r:curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
|
':curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
|
||||||
'r:dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
':dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||||
'r:dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
':dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||||
'r:gd' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castGd',
|
':gd' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castGd',
|
||||||
'r:mysql link' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castMysqlLink',
|
':mysql link' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castMysqlLink',
|
||||||
'r:process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
|
':process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
|
||||||
'r:stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
':stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
||||||
'r:stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
|
':stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $maxItems = 250;
|
protected $maxItems = 250;
|
||||||
|
@ -107,8 +107,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||||
*
|
*
|
||||||
* Maps resources or objects types to a callback.
|
* Maps resources or objects types to a callback.
|
||||||
* Types are in the key, with a callable caster for value.
|
* Types are in the key, with a callable caster for value.
|
||||||
* Objects class are to be prefixed with a `o:`,
|
* Resource types are to be prefixed with a `:`,
|
||||||
* resources type are to be prefixed with a `r:`,
|
|
||||||
* see e.g. static::$defaultCasters.
|
* see e.g. static::$defaultCasters.
|
||||||
*
|
*
|
||||||
* @param callable[] $casters A map of casters.
|
* @param callable[] $casters A map of casters.
|
||||||
|
@ -193,7 +192,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||||
$class,
|
$class,
|
||||||
method_exists($class, '__debugInfo'),
|
method_exists($class, '__debugInfo'),
|
||||||
new \ReflectionClass($class),
|
new \ReflectionClass($class),
|
||||||
array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
|
array_reverse(array($class => $class) + class_parents($class) + class_implements($class)),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->classInfo[$class] = $classInfo;
|
$this->classInfo[$class] = $classInfo;
|
||||||
|
@ -213,7 +212,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($classInfo[3] as $p) {
|
foreach ($classInfo[3] as $p) {
|
||||||
if (!empty($this->casters[$p = 'o:'.strtolower($p)])) {
|
if (!empty($this->casters[$p = strtolower($p)])) {
|
||||||
foreach ($this->casters[$p] as $p) {
|
foreach ($this->casters[$p] as $p) {
|
||||||
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
|
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
|
||||||
}
|
}
|
||||||
|
@ -237,8 +236,8 @@ abstract class AbstractCloner implements ClonerInterface
|
||||||
$a = array();
|
$a = array();
|
||||||
$type = $stub->class;
|
$type = $stub->class;
|
||||||
|
|
||||||
if (!empty($this->casters['r:'.$type])) {
|
if (!empty($this->casters[':'.$type])) {
|
||||||
foreach ($this->casters['r:'.$type] as $c) {
|
foreach ($this->casters[':'.$type] as $c) {
|
||||||
$a = $this->callCaster($c, $res, $a, $stub, $isNested);
|
$a = $this->callCaster($c, $res, $a, $stub, $isNested);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,7 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Dumper;
|
namespace Symfony\Component\VarDumper\Cloner;
|
||||||
|
|
||||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the current state of a dumper while dumping.
|
* Represents the current state of a dumper while dumping.
|
|
@ -11,9 +11,6 @@
|
||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Cloner;
|
namespace Symfony\Component\VarDumper\Cloner;
|
||||||
|
|
||||||
use Symfony\Component\VarDumper\Dumper\DumperInternalsInterface;
|
|
||||||
use Symfony\Component\VarDumper\Dumper\Cursor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
|
@ -57,18 +54,18 @@ class Data
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps data with a DumperInternalsInterface dumper.
|
* Dumps data with a DumperInterface dumper.
|
||||||
*/
|
*/
|
||||||
public function dump(DumperInternalsInterface $dumper)
|
public function dump(DumperInterface $dumper)
|
||||||
{
|
{
|
||||||
$refs = array(0);
|
$refs = array(0);
|
||||||
$this->dumpItem($dumper, new Cursor, $refs, $this->data[0][0]);
|
$this->dumpItem($dumper, new Cursor, $refs, $this->data[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breadth-first dumping of items.
|
* Depth-first dumping of items.
|
||||||
*
|
*
|
||||||
* @param DumperInternalsInterface $dumper The dumper being used for dumping.
|
* @param DumperInterface $dumper The dumper being used for dumping.
|
||||||
* @param Cursor $cursor A cursor used for tracking dumper state position.
|
* @param Cursor $cursor A cursor used for tracking dumper state position.
|
||||||
* @param array &$refs A map of all references discovered while dumping.
|
* @param array &$refs A map of all references discovered while dumping.
|
||||||
* @param mixed $item A Stub object or the original value being dumped.
|
* @param mixed $item A Stub object or the original value being dumped.
|
||||||
|
@ -157,7 +154,7 @@ class Data
|
||||||
/**
|
/**
|
||||||
* Dumps children of hash structures.
|
* Dumps children of hash structures.
|
||||||
*
|
*
|
||||||
* @param DumperInternalsInterface $dumper
|
* @param DumperInterface $dumper
|
||||||
* @param Cursor $parentCursor The cursor of the parent hash.
|
* @param Cursor $parentCursor The cursor of the parent hash.
|
||||||
* @param array &$refs A map of all references discovered while dumping.
|
* @param array &$refs A map of all references discovered while dumping.
|
||||||
* @param array $children The children to dump.
|
* @param array $children The children to dump.
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Dumper;
|
namespace Symfony\Component\VarDumper\Cloner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DumperInterface used by Data objects.
|
* DumperInterface used by Data objects.
|
||||||
*
|
*
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
interface DumperInternalsInterface
|
interface DumperInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Dumps a scalar value.
|
* Dumps a scalar value.
|
|
@ -12,13 +12,14 @@
|
||||||
namespace Symfony\Component\VarDumper\Dumper;
|
namespace Symfony\Component\VarDumper\Dumper;
|
||||||
|
|
||||||
use Symfony\Component\VarDumper\Cloner\Data;
|
use Symfony\Component\VarDumper\Cloner\Data;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\DumperInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract mechanism for dumping a Data object.
|
* Abstract mechanism for dumping a Data object.
|
||||||
*
|
*
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
abstract class AbstractDumper implements DataDumperInterface, DumperInternalsInterface
|
abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||||
{
|
{
|
||||||
public static $defaultOutputStream = 'php://output';
|
public static $defaultOutputStream = 'php://output';
|
||||||
|
|
||||||
|
@ -87,14 +88,22 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInternalsInt
|
||||||
*/
|
*/
|
||||||
public function dump(Data $data, $lineDumper = null)
|
public function dump(Data $data, $lineDumper = null)
|
||||||
{
|
{
|
||||||
$this->decimalPoint = (string) 0.5;
|
$exception = null;
|
||||||
$this->decimalPoint = $this->decimalPoint[1];
|
|
||||||
$dumper = clone $this;
|
|
||||||
if ($lineDumper) {
|
if ($lineDumper) {
|
||||||
$dumper->setLineDumper($lineDumper);
|
$prevLineDumper = $this->setLineDumper($lineDumper);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$data->dump($this);
|
||||||
|
$this->dumpLine(-1);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
// Re-thrown below
|
||||||
|
}
|
||||||
|
if ($lineDumper) {
|
||||||
|
$this->setLineDumper($prevLineDumper);
|
||||||
|
}
|
||||||
|
if (null !== $exception) {
|
||||||
|
throw $exception;
|
||||||
}
|
}
|
||||||
$data->dump($dumper);
|
|
||||||
$dumper->dumpLine(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,7 +125,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInternalsInt
|
||||||
*/
|
*/
|
||||||
protected function echoLine($line, $depth)
|
protected function echoLine($line, $depth)
|
||||||
{
|
{
|
||||||
if (false !== $depth) {
|
if (-1 !== $depth) {
|
||||||
fwrite($this->outputStream, str_repeat($this->indentPad, $depth).$line."\n");
|
fwrite($this->outputStream, str_repeat($this->indentPad, $depth).$line."\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
namespace Symfony\Component\VarDumper\Dumper;
|
namespace Symfony\Component\VarDumper\Dumper;
|
||||||
|
|
||||||
use Symfony\Component\VarDumper\Cloner\Data;
|
use Symfony\Component\VarDumper\Cloner\Data;
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Cursor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CliDumper dumps variables for command line output.
|
* CliDumper dumps variables for command line output.
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Component\VarDumper\Dumper;
|
namespace Symfony\Component\VarDumper\Dumper;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\Cursor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HtmlDumper dumps variables as HTML.
|
* HtmlDumper dumps variables as HTML.
|
||||||
*
|
*
|
||||||
|
@ -21,8 +23,8 @@ class HtmlDumper extends CliDumper
|
||||||
public static $defaultOutputStream = 'php://output';
|
public static $defaultOutputStream = 'php://output';
|
||||||
|
|
||||||
protected $dumpHeader;
|
protected $dumpHeader;
|
||||||
protected $dumpPrefix = '<pre class=sf-dump>';
|
protected $dumpPrefix = '<pre id=sf-dump>';
|
||||||
protected $dumpSuffix = '</pre>';
|
protected $dumpSuffix = '</pre><script>Sfjs.dump.instrument()</script>';
|
||||||
protected $colors = true;
|
protected $colors = true;
|
||||||
protected $headerIsDumped = false;
|
protected $headerIsDumped = false;
|
||||||
protected $lastDepth = -1;
|
protected $lastDepth = -1;
|
||||||
|
@ -74,7 +76,7 @@ class HtmlDumper extends CliDumper
|
||||||
* @param string $prefix The prepended HTML string.
|
* @param string $prefix The prepended HTML string.
|
||||||
* @param string $suffix The appended HTML string.
|
* @param string $suffix The appended HTML string.
|
||||||
*/
|
*/
|
||||||
public function setDumpBoudaries($prefix, $suffix)
|
public function setDumpBoundaries($prefix, $suffix)
|
||||||
{
|
{
|
||||||
$this->dumpPrefix = $prefix;
|
$this->dumpPrefix = $prefix;
|
||||||
$this->dumpSuffix = $suffix;
|
$this->dumpSuffix = $suffix;
|
||||||
|
@ -87,28 +89,104 @@ class HtmlDumper extends CliDumper
|
||||||
{
|
{
|
||||||
$this->headerIsDumped = true;
|
$this->headerIsDumped = true;
|
||||||
|
|
||||||
$p = 'sf-dump';
|
if (null !== $this->dumpHeader) {
|
||||||
$line = <<<EOHTML
|
return $this->dumpHeader;
|
||||||
<!DOCTYPE html><style>
|
}
|
||||||
pre.sf-dump {
|
|
||||||
|
$line = <<<'EOHTML'
|
||||||
|
<script>
|
||||||
|
Sfjs = window.Sfjs || {};
|
||||||
|
Sfjs.dump = Sfjs.dump || {};
|
||||||
|
Sfjs.dump.childElts = document.getElementsByName('sf-dump-child');
|
||||||
|
Sfjs.dump.childLen = 0;
|
||||||
|
Sfjs.dump.instrument = function () {
|
||||||
|
var elt,
|
||||||
|
i = this.childLen,
|
||||||
|
aCompact = '▶</a><span class="sf-dump-compact">',
|
||||||
|
aExpanded = '▼</a><span class="sf-dump-expanded">';
|
||||||
|
|
||||||
|
this.childLen= this.childElts.length;
|
||||||
|
|
||||||
|
while (i < this.childLen) {
|
||||||
|
elt = this.childElts[i];
|
||||||
|
if ("" == elt.className) {
|
||||||
|
elt.className = "sf-dump-child";
|
||||||
|
elt.innerHTML = '<a class=sf-dump-ref onclick="Sfjs.dump.toggle(this)">'+('sf-dump-0' == elt.parentNode.className ? aExpanded : aCompact)+elt.innerHTML+'</span>';
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Sfjs.dump.toggle = function(a) {
|
||||||
|
var s = a.nextElementSibling;
|
||||||
|
|
||||||
|
if ('sf-dump-compact' == s.className) {
|
||||||
|
a.innerHTML = '▼';
|
||||||
|
s.className = 'sf-dump-expanded';
|
||||||
|
} else {
|
||||||
|
a.innerHTML = '▶';
|
||||||
|
s.className = 'sf-dump-compact';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#sf-dump {
|
||||||
|
display: block;
|
||||||
background-color: #300a24;
|
background-color: #300a24;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
color: #eee8d5;
|
color: #eee8d5;
|
||||||
font-family: monospace, sans-serif;
|
font: 12px monospace, sans-serif;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.sf-dump span {
|
#sf-dump span {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
#sf-dump .sf-dump-compact {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#sf-dump abbr {
|
||||||
|
text-decoration: none;
|
||||||
|
border: none;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
#sf-dump a {
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#sf-dump a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
EOHTML;
|
EOHTML;
|
||||||
$line .= "a.$p-ref {{$this->styles['ref']}}";
|
|
||||||
|
|
||||||
foreach ($this->styles as $class => $style) {
|
foreach ($this->styles as $class => $style) {
|
||||||
$line .= "span.$p-$class {{$style}}";
|
$line .= "#sf-dump .sf-dump-$class {{$style}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function enterHash(Cursor $cursor, $prefix, $hasChild)
|
||||||
|
{
|
||||||
|
if ($hasChild) {
|
||||||
|
$prefix .= '<span name=sf-dump-child>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::enterHash($cursor, $prefix, $hasChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function leaveHash(Cursor $cursor, $suffix, $hasChild, $cut)
|
||||||
|
{
|
||||||
|
if ($hasChild) {
|
||||||
|
$suffix = '</span>'.$suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::leaveHash($cursor, $suffix, $hasChild, $cut);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,6 +216,10 @@ EOHTML;
|
||||||
$val = str_replace($c, "<span class=sf-dump-cchr>$r</span>", $val);
|
$val = str_replace($c, "<span class=sf-dump-cchr>$r</span>", $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif ('note' === $style) {
|
||||||
|
if (false !== $c = strrpos($val, '\\')) {
|
||||||
|
$val = sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $val, $style, substr($val, $c+1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<span class=sf-dump-$style>$val</span>";
|
return "<span class=sf-dump-$style>$val</span>";
|
||||||
|
@ -148,7 +230,6 @@ EOHTML;
|
||||||
*/
|
*/
|
||||||
protected function dumpLine($depth)
|
protected function dumpLine($depth)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch ($this->lastDepth - $depth) {
|
switch ($this->lastDepth - $depth) {
|
||||||
case +1: $this->line = '</span>'.$this->line; break;
|
case +1: $this->line = '</span>'.$this->line; break;
|
||||||
case -1: $this->line = "<span class=sf-dump-$depth>$this->line"; break;
|
case -1: $this->line = "<span class=sf-dump-$depth>$this->line"; break;
|
||||||
|
@ -161,13 +242,11 @@ EOHTML;
|
||||||
$this->line = $this->getDumpHeader().$this->line;
|
$this->line = $this->getDumpHeader().$this->line;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false === $depth) {
|
if (-1 === $depth) {
|
||||||
$this->lastDepth = -1;
|
|
||||||
$this->line .= $this->dumpSuffix;
|
$this->line .= $this->dumpSuffix;
|
||||||
parent::dumpLine(0);
|
parent::dumpLine(0);
|
||||||
} else {
|
|
||||||
$this->lastDepth = $depth;
|
|
||||||
}
|
}
|
||||||
|
$this->lastDepth = $depth;
|
||||||
|
|
||||||
parent::dumpLine($depth);
|
parent::dumpLine($depth);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
Symfony mechanim for exploring and dumping PHP variables
|
Symfony mechanism for exploring and dumping PHP variables
|
||||||
========================================================
|
=========================================================
|
||||||
|
|
||||||
This component provides a mechanism that allows exploring then dumping
|
This component provides a mechanism that allows exploring then dumping
|
||||||
any PHP variable.
|
any PHP variable.
|
||||||
|
|
||||||
It handles scalar, objects and resources properly, taking hard and soft
|
It handles scalars, objects and resources properly, taking hard and soft
|
||||||
references into account. More than being immune to inifinite recursion
|
references into account. More than being immune to inifinite recursion
|
||||||
problems, it allows dumping where references link to each other.
|
problems, it allows dumping where references link to each other.
|
||||||
It explores recursive structures using a breadth-first algorithm.
|
It explores recursive structures using a breadth-first algorithm.
|
||||||
|
|
|
@ -26,6 +26,13 @@ class CliDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
$dumper = new CliDumper('php://output');
|
$dumper = new CliDumper('php://output');
|
||||||
$dumper->setColors(false);
|
$dumper->setColors(false);
|
||||||
$cloner = new PhpCloner();
|
$cloner = new PhpCloner();
|
||||||
|
$cloner->addCasters(array(
|
||||||
|
':stream' => function ($res, $a) {
|
||||||
|
unset($a['uri']);
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
));
|
||||||
$data = $cloner->cloneVar($var);
|
$data = $cloner->cloneVar($var);
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
|
@ -51,7 +58,7 @@ array:25 [
|
||||||
"[]" => []
|
"[]" => []
|
||||||
"res" => resource:stream {
|
"res" => resource:stream {
|
||||||
wrapper_type: "plainfile"
|
wrapper_type: "plainfile"
|
||||||
stream_type: "dir"
|
stream_type: "STDIO"
|
||||||
mode: "r"
|
mode: "r"
|
||||||
unread_bytes: 0
|
unread_bytes: 0
|
||||||
seekable: true
|
seekable: true
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Fixture;
|
||||||
|
|
||||||
|
if (!class_exists('Symfony\Component\VarDumper\Tests\Fixture\DumbFoo')) {
|
||||||
|
class DumbFoo
|
||||||
|
{
|
||||||
|
public $foo = 'foo';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$foo = new DumbFoo();
|
||||||
|
$foo->bar = 'bar';
|
||||||
|
|
||||||
|
$g = fopen(__FILE__, 'r');
|
||||||
|
$h = fopen(__FILE__, 'r');
|
||||||
|
fclose($h);
|
||||||
|
|
||||||
|
$var = array(
|
||||||
|
'number' => 1, null,
|
||||||
|
'const' => 1.1, true, false, NAN, INF, -INF, PHP_INT_MAX,
|
||||||
|
'str' => "déjà", "\xE9",
|
||||||
|
'[]' => array(),
|
||||||
|
'res' => $g,
|
||||||
|
$h,
|
||||||
|
'obj' => $foo,
|
||||||
|
'closure' => function ($a, \PDO &$b = null) {},
|
||||||
|
'line' => __LINE__ - 1,
|
||||||
|
'nobj' => array((object) array()),
|
||||||
|
);
|
||||||
|
|
||||||
|
$r = array();
|
||||||
|
$r[] =& $r;
|
||||||
|
|
||||||
|
$var['recurs'] =& $r;
|
||||||
|
$var[] =& $var[0];
|
||||||
|
$var['sobj'] = $var['obj'];
|
||||||
|
$var['snobj'] =& $var['nobj'][0];
|
||||||
|
$var['snobj2'] = $var['nobj'][0];
|
||||||
|
$var['file'] = __FILE__;
|
||||||
|
$var["bin-key-\xE9"] = "";
|
||||||
|
|
||||||
|
unset($g, $h, $r);
|
|
@ -25,7 +25,16 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$dumper = new HtmlDumper('php://output');
|
$dumper = new HtmlDumper('php://output');
|
||||||
$dumper->setColors(false);
|
$dumper->setColors(false);
|
||||||
|
$dumper->setDumpHeader('<foo></foo>');
|
||||||
|
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||||
$cloner = new PhpCloner();
|
$cloner = new PhpCloner();
|
||||||
|
$cloner->addCasters(array(
|
||||||
|
':stream' => function ($res, $a) {
|
||||||
|
unset($a['uri']);
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
));
|
||||||
$data = $cloner->cloneVar($var);
|
$data = $cloner->cloneVar($var);
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
|
@ -37,7 +46,7 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
<<<EOTXT
|
<<<EOTXT
|
||||||
<!DOCTYPE html><style> pre.sf-dump { background-color: #300a24; white-space: pre; line-height: 1.2em; color: #eee8d5; font-family: monospace, sans-serif; padding: 5px; } .sf-dump span { display: inline; }a.sf-dump-ref {color:#444444}span.sf-dump-num {font-weight:bold;color:#0087FF}span.sf-dump-const {font-weight:bold;color:#0087FF}span.sf-dump-str {font-weight:bold;color:#00D7FF}span.sf-dump-cchr {font-style: italic}span.sf-dump-note {color:#D7AF00}span.sf-dump-ref {color:#444444}span.sf-dump-public {color:#008700}span.sf-dump-protected {color:#D75F00}span.sf-dump-private {color:#D70000}span.sf-dump-meta {color:#005FFF}</style><pre class=sf-dump><span class=sf-dump-0><span class=sf-dump-note>array:25</span> [
|
<foo></foo><bar><span class=sf-dump-0><span class=sf-dump-note>array:25</span> [<span name=sf-dump-child>
|
||||||
<span class=sf-dump-1>"<span class=sf-dump-meta>number</span>" => <span class=sf-dump-num>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>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>const</span>" => <span class=sf-dump-num>1.1</span>
|
||||||
|
@ -50,9 +59,9 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
"<span class=sf-dump-meta>str</span>" => "<span class=sf-dump-str>déjà</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>7</span> => b"<span class=sf-dump-str>é</span>"
|
||||||
"<span class=sf-dump-meta>[]</span>" => []
|
"<span class=sf-dump-meta>[]</span>" => []
|
||||||
"<span class=sf-dump-meta>res</span>" => resource:<span class=sf-dump-note>stream</span> {
|
"<span class=sf-dump-meta>res</span>" => resource:<span class=sf-dump-note>stream</span> {<span name=sf-dump-child>
|
||||||
<span class=sf-dump-2><span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str>plainfile</span>"
|
<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>stream_type</span>: "<span class=sf-dump-str>STDIO</span>"
|
||||||
<span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
|
<span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
|
||||||
<span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
|
<span class=sf-dump-meta>unread_bytes</span>: <span class=sf-dump-num>0</span>
|
||||||
<span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
|
<span class=sf-dump-meta>seekable</span>: <span class=sf-dump-const>true</span>
|
||||||
|
@ -60,13 +69,13 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
<span class=sf-dump-meta>blocked</span>: <span class=sf-dump-const>true</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>eof</span>: <span class=sf-dump-const>false</span>
|
||||||
<span class=sf-dump-meta>options</span>: []
|
<span class=sf-dump-meta>options</span>: []
|
||||||
</span>}
|
</span></span>}
|
||||||
<span class=sf-dump-meta>8</span> => resource:<span class=sf-dump-note>Unknown</span> {}
|
<span class=sf-dump-meta>8</span> => resource:<span class=sf-dump-note>Unknown</span> {}
|
||||||
"<span class=sf-dump-meta>obj</span>" => <span class=sf-dump-note>Symfony\Component\VarDumper\Tests\Fixture\DumbFoo</span> { <a class=sf-dump-ref name="sf-dump-ref2">#2</a>
|
"<span class=sf-dump-meta>obj</span>" => <span class=sf-dump-note><abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr></span> {<span name=sf-dump-child> <a class=sf-dump-ref name="sf-dump-ref2">#2</a>
|
||||||
<span class=sf-dump-2><span class=sf-dump-public>foo</span>: "<span class=sf-dump-str>foo</span>"
|
<span class=sf-dump-2><span class=sf-dump-public>foo</span>: "<span class=sf-dump-str>foo</span>"
|
||||||
"<span class=sf-dump-public>bar</span>": "<span class=sf-dump-str>bar</span>"
|
"<span class=sf-dump-public>bar</span>": "<span class=sf-dump-str>bar</span>"
|
||||||
</span>}
|
</span></span>}
|
||||||
"<span class=sf-dump-meta>closure</span>" => <span class=sf-dump-note>Closure</span> {
|
"<span class=sf-dump-meta>closure</span>" => <span class=sf-dump-note>Closure</span> {<span name=sf-dump-child>
|
||||||
<span class=sf-dump-2><span class=sf-dump-meta>reflection</span>: """
|
<span class=sf-dump-2><span class=sf-dump-meta>reflection</span>: """
|
||||||
<span class=sf-dump-str>Closure [ <user> {$closureLabel} Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {</span>
|
<span class=sf-dump-str>Closure [ <user> {$closureLabel} Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {</span>
|
||||||
<span class=sf-dump-str> @@ {$var['file']} {$var['line']} - {$var['line']}</span>
|
<span class=sf-dump-str> @@ {$var['file']} {$var['line']} - {$var['line']}</span>
|
||||||
|
@ -77,22 +86,22 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
<span class=sf-dump-str> }</span>
|
<span class=sf-dump-str> }</span>
|
||||||
<span class=sf-dump-str>}</span>
|
<span class=sf-dump-str>}</span>
|
||||||
"""
|
"""
|
||||||
</span>}
|
</span></span>}
|
||||||
"<span class=sf-dump-meta>line</span>" => <span class=sf-dump-num>{$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-meta>nobj</span>" => <span class=sf-dump-note>array:1</span> [<span name=sf-dump-child>
|
||||||
<span class=sf-dump-2><span class=sf-dump-meta>0</span> => {} <a class=sf-dump-ref name="sf-dump-ref3">#3</a>
|
<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></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-meta>recurs</span>" => <span class=sf-dump-note>array:1</span> [<span name=sf-dump-child> <a class=sf-dump-ref name="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 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></span>]
|
||||||
<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>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>sobj</span>" => <span class=sf-dump-note><abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr></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> {<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>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>"
|
"<span class=sf-dump-meta>file</span>" => "<span class=sf-dump-str>{$var['file']}</span>"
|
||||||
b"<span class=sf-dump-meta>bin-key-é</span>" => ""
|
b"<span class=sf-dump-meta>bin-key-é</span>" => ""
|
||||||
</span>]
|
</span></span>]
|
||||||
</pre>
|
</span></bar>
|
||||||
|
|
||||||
EOTXT
|
EOTXT
|
||||||
,
|
,
|
||||||
|
|
Reference in New Issue