[VarDumper] Allow seamless use of Data clones
This commit is contained in:
parent
e7a9f03bae
commit
ab716c64de
@ -20,6 +20,7 @@ use Symfony\Component\Security\Core\Role\RoleInterface;
|
||||
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\Security\Http\FirewallMapInterface;
|
||||
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
|
||||
@ -36,6 +37,7 @@ class SecurityDataCollector extends DataCollector
|
||||
private $logoutUrlGenerator;
|
||||
private $accessDecisionManager;
|
||||
private $firewallMap;
|
||||
private $hasVarDumper;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -53,6 +55,7 @@ class SecurityDataCollector extends DataCollector
|
||||
$this->logoutUrlGenerator = $logoutUrlGenerator;
|
||||
$this->accessDecisionManager = $accessDecisionManager;
|
||||
$this->firewallMap = $firewallMap;
|
||||
$this->hasVarDumper = class_exists(ClassStub::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,28 +112,23 @@ class SecurityDataCollector extends DataCollector
|
||||
$this->data = array(
|
||||
'enabled' => true,
|
||||
'authenticated' => $token->isAuthenticated(),
|
||||
'token' => $this->cloneVar($token),
|
||||
'token_class' => get_class($token),
|
||||
'token' => $token,
|
||||
'token_class' => $this->hasVarDumper ? new ClassStub(get_class($token)) : get_class($token),
|
||||
'logout_url' => $logoutUrl,
|
||||
'user' => $token->getUsername(),
|
||||
'roles' => $this->cloneVar(array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles)),
|
||||
'inherited_roles' => $this->cloneVar(array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles)),
|
||||
'roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles),
|
||||
'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles),
|
||||
'supports_role_hierarchy' => null !== $this->roleHierarchy,
|
||||
);
|
||||
}
|
||||
|
||||
// collect voters and access decision manager information
|
||||
if ($this->accessDecisionManager instanceof TraceableAccessDecisionManager) {
|
||||
$this->data['access_decision_log'] = array_map(function ($decision) {
|
||||
$decision['object'] = $this->cloneVar($decision['object']);
|
||||
|
||||
return $decision;
|
||||
}, $this->accessDecisionManager->getDecisionLog());
|
||||
|
||||
$this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog();
|
||||
$this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy();
|
||||
|
||||
foreach ($this->accessDecisionManager->getVoters() as $voter) {
|
||||
$this->data['voters'][] = get_class($voter);
|
||||
$this->data['voters'][] = $this->hasVarDumper ? new ClassStub(get_class($voter)) : get_class($voter);
|
||||
}
|
||||
} else {
|
||||
$this->data['access_decision_log'] = array();
|
||||
@ -155,10 +153,12 @@ class SecurityDataCollector extends DataCollector
|
||||
'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(),
|
||||
'access_denied_url' => $firewallConfig->getAccessDeniedUrl(),
|
||||
'user_checker' => $firewallConfig->getUserChecker(),
|
||||
'listeners' => $this->cloneVar($firewallConfig->getListeners()),
|
||||
'listeners' => $firewallConfig->getListeners(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,14 +66,10 @@ class SecurityDataCollectorTest extends TestCase
|
||||
|
||||
$this->assertTrue($collector->isEnabled());
|
||||
$this->assertTrue($collector->isAuthenticated());
|
||||
$this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass());
|
||||
$this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass()->getValue());
|
||||
$this->assertTrue($collector->supportsRoleHierarchy());
|
||||
$this->assertSame($normalizedRoles, $collector->getRoles()->getRawData()[1]);
|
||||
if ($inheritedRoles) {
|
||||
$this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getRawData()[1]);
|
||||
} else {
|
||||
$this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getRawData()[0][0]);
|
||||
}
|
||||
$this->assertSame($normalizedRoles, $collector->getRoles()->getValue(true));
|
||||
$this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getValue(true));
|
||||
$this->assertSame('hhamon', $collector->getUser());
|
||||
}
|
||||
|
||||
@ -107,7 +103,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
$this->assertSame($firewallConfig->getAccessDeniedHandler(), $collected['access_denied_handler']);
|
||||
$this->assertSame($firewallConfig->getAccessDeniedUrl(), $collected['access_denied_url']);
|
||||
$this->assertSame($firewallConfig->getUserChecker(), $collected['user_checker']);
|
||||
$this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getRawData()[0][0]);
|
||||
$this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getValue());
|
||||
}
|
||||
|
||||
public function testGetFirewallReturnsNull()
|
||||
|
@ -19,7 +19,7 @@
|
||||
"php": ">=5.5.9",
|
||||
"symfony/security": "~3.3",
|
||||
"symfony/dependency-injection": "~3.3",
|
||||
"symfony/http-kernel": "~3.2",
|
||||
"symfony/http-kernel": "~3.3",
|
||||
"symfony/polyfill-php70": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -37,12 +37,15 @@
|
||||
"symfony/twig-bridge": "~2.8|~3.0",
|
||||
"symfony/process": "~2.8|~3.0",
|
||||
"symfony/validator": "^3.2.5",
|
||||
"symfony/var-dumper": "~3.2",
|
||||
"symfony/var-dumper": "~3.3",
|
||||
"symfony/yaml": "~2.8|~3.0",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"doctrine/doctrine-bundle": "~1.4",
|
||||
"twig/twig": "~1.28|~2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/var-dumper": "<3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/security-acl": "For using the ACL functionality of this bundle"
|
||||
},
|
||||
|
@ -90,7 +90,7 @@
|
||||
<div class="metric">
|
||||
<span class="value">
|
||||
{% if key == 'time' %}
|
||||
{{ '%0.2f'|format(1000*value) }} ms
|
||||
{{ '%0.2f'|format(1000*value.value) }} ms
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
|
@ -267,7 +267,7 @@
|
||||
{% for name in collector.bundles|keys|sort %}
|
||||
<tr>
|
||||
<th scope="row" class="font-normal">{{ name }}</th>
|
||||
<td class="font-normal">{{ collector.bundles[name] }}</td>
|
||||
<td class="font-normal">{{ profiler_dump(collector.bundles[name]) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -75,7 +75,7 @@
|
||||
|
||||
<tr>
|
||||
<td class="text-right">{{ listener.priority|default('-') }}</td>
|
||||
<td class="font-normal">{{ profiler_dump(listener.data) }}</td>
|
||||
<td class="font-normal">{{ profiler_dump(listener.stub) }}</td>
|
||||
</tr>
|
||||
|
||||
{% if loop.last %}
|
||||
|
@ -182,7 +182,7 @@
|
||||
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide trace">Show trace</a>
|
||||
|
||||
<div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden">
|
||||
{{ profiler_dump(log.context.seek('exception').seek('\0Exception\0trace'), maxDepth=2) }}
|
||||
{{ profiler_dump(log.context.exception['\0Exception\0trace'], maxDepth=2) }}
|
||||
</div>
|
||||
</span>
|
||||
{% elseif log.context is defined and log.context is not empty %}
|
||||
|
@ -98,9 +98,9 @@ class WebProfilerExtension extends \Twig_Extension_Profiler
|
||||
}
|
||||
|
||||
$replacements = array();
|
||||
foreach ($context->getRawData()[1] as $k => $v) {
|
||||
$v = '{'.twig_escape_filter($env, $k).'}';
|
||||
$replacements['"'.$v.'"'] = $replacements[$v] = $this->dumpData($env, $context->seek($k));
|
||||
foreach ($context as $k => $v) {
|
||||
$k = '{'.twig_escape_filter($env, $k).'}';
|
||||
$replacements['"'.$k.'"'] = $replacements[$k] = $this->dumpData($env, $v);
|
||||
}
|
||||
|
||||
return '<span class="dump-inline">'.strtr($message, $replacements).'</span>';
|
||||
|
@ -22,7 +22,7 @@
|
||||
"symfony/routing": "~2.8|~3.0",
|
||||
"symfony/twig-bridge": "~2.8|~3.0",
|
||||
"twig/twig": "~1.28|~2.0",
|
||||
"symfony/var-dumper": "~3.2"
|
||||
"symfony/var-dumper": "~3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/config": "~2.8|~3.0",
|
||||
@ -31,7 +31,8 @@
|
||||
"symfony/stopwatch": "~2.8|~3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/event-dispatcher": "<3.2"
|
||||
"symfony/event-dispatcher": "<3.2",
|
||||
"symfony/var-dumper": "<3.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Bundle\\WebProfilerBundle\\": "" },
|
||||
|
@ -45,20 +45,13 @@ class CacheDataCollector extends DataCollector
|
||||
$empty = array('calls' => array(), 'config' => array(), 'options' => array(), 'statistics' => array());
|
||||
$this->data = array('instances' => $empty, 'total' => $empty);
|
||||
foreach ($this->instances as $name => $instance) {
|
||||
$calls = $instance->getCalls();
|
||||
foreach ($calls as $call) {
|
||||
if (isset($call->result)) {
|
||||
$call->result = $this->cloneVar($call->result);
|
||||
}
|
||||
if (isset($call->argument)) {
|
||||
$call->argument = $this->cloneVar($call->argument);
|
||||
}
|
||||
}
|
||||
$this->data['instances']['calls'][$name] = $calls;
|
||||
$this->data['instances']['calls'][$name] = $instance->getCalls();
|
||||
}
|
||||
|
||||
$this->data['instances']['statistics'] = $this->calculateStatistics();
|
||||
$this->data['total']['statistics'] = $this->calculateTotalStatistics();
|
||||
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +126,7 @@ class CacheDataCollector extends DataCollector
|
||||
$statistics[$name]['misses'] += $count - $call->misses;
|
||||
} elseif ('hasItem' === $call->name) {
|
||||
$statistics[$name]['reads'] += 1;
|
||||
if (false === $call->result->getRawData()[0][0]) {
|
||||
if (false === $call->result) {
|
||||
$statistics[$name]['misses'] += 1;
|
||||
} else {
|
||||
$statistics[$name]['hits'] += 1;
|
||||
|
@ -31,6 +31,9 @@
|
||||
"doctrine/dbal": "~2.4",
|
||||
"predis/predis": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/var-dumper": "<3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/polyfill-apcu": "For using ApcuAdapter on HHVM"
|
||||
},
|
||||
|
@ -29,7 +29,7 @@ class WrappedListener
|
||||
private $stopwatch;
|
||||
private $dispatcher;
|
||||
private $pretty;
|
||||
private $data;
|
||||
private $stub;
|
||||
|
||||
private static $cloner;
|
||||
|
||||
@ -91,15 +91,15 @@ class WrappedListener
|
||||
|
||||
public function getInfo($eventName)
|
||||
{
|
||||
if (null === $this->data) {
|
||||
$this->data = false !== self::$cloner ? self::$cloner->cloneVar(array(new ClassStub($this->pretty.'()', $this->listener)))->seek(0) : $this->pretty;
|
||||
if (null === $this->stub) {
|
||||
$this->stub = false === self::$cloner ? $this->pretty.'()' : new ClassStub($this->pretty.'()', $this->listener);
|
||||
}
|
||||
|
||||
return array(
|
||||
'event' => $eventName,
|
||||
'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null,
|
||||
'pretty' => $this->pretty,
|
||||
'data' => $this->data,
|
||||
'stub' => $this->stub,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -97,16 +97,16 @@ class TraceableEventDispatcherTest extends TestCase
|
||||
$tdispatcher->addListener('foo', $listener = function () {});
|
||||
|
||||
$listeners = $tdispatcher->getNotCalledListeners();
|
||||
$this->assertArrayHasKey('data', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['data']);
|
||||
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['stub']);
|
||||
$this->assertEquals(array(), $tdispatcher->getCalledListeners());
|
||||
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 0)), $listeners);
|
||||
|
||||
$tdispatcher->dispatch('foo');
|
||||
|
||||
$listeners = $tdispatcher->getCalledListeners();
|
||||
$this->assertArrayHasKey('data', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['data']);
|
||||
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['stub']);
|
||||
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => null)), $listeners);
|
||||
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
|
||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||
use Symfony\Component\VarDumper\Caster\Caster;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Caster\CutStub;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
@ -80,7 +81,8 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
|
||||
* @var ClonerInterface
|
||||
*/
|
||||
private $cloner;
|
||||
private $clonerCache = array();
|
||||
|
||||
private $hasVarDumper;
|
||||
|
||||
public function __construct(FormDataExtractorInterface $dataExtractor)
|
||||
{
|
||||
@ -90,6 +92,7 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
|
||||
'forms_by_hash' => array(),
|
||||
'nb_errors' => 0,
|
||||
);
|
||||
$this->hasVarDumper = class_exists(ClassStub::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,38 +241,15 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
$cloneVar = array($this, 'cloneVar');
|
||||
|
||||
foreach ($this->data['forms_by_hash'] as &$form) {
|
||||
foreach ($form as $k => $v) {
|
||||
switch ($k) {
|
||||
case 'type_class':
|
||||
$form[$k] = $cloneVar($v, true);
|
||||
break;
|
||||
case 'synchronized':
|
||||
$form[$k] = $cloneVar($v);
|
||||
break;
|
||||
case 'view_vars':
|
||||
case 'passed_options':
|
||||
case 'resolved_options':
|
||||
case 'default_data':
|
||||
case 'submitted_data':
|
||||
if ($v && is_array($v)) {
|
||||
$form[$k] = array_map($cloneVar, $v);
|
||||
}
|
||||
break;
|
||||
case 'errors':
|
||||
foreach ($v as $i => $e) {
|
||||
if (!empty($e['trace'])) {
|
||||
$form['errors'][$i]['trace'] = array_map($cloneVar, $e['trace']);
|
||||
}
|
||||
}
|
||||
break;
|
||||
if ($this->hasVarDumper) {
|
||||
foreach ($this->data['forms_by_hash'] as &$form) {
|
||||
if (isset($form['type_class']) && !$form['type_class'] instanceof ClassStub) {
|
||||
$form['type_class'] = new ClassStub($form['type_class']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serialize($this->data);
|
||||
return serialize($this->cloneVar($this->data));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,14 +261,15 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
|
||||
return $var;
|
||||
}
|
||||
if (null === $this->cloner) {
|
||||
if (class_exists(ClassStub::class)) {
|
||||
if ($this->hasVarDumper) {
|
||||
$this->cloner = new VarCloner();
|
||||
$this->cloner->setMaxItems(25);
|
||||
$this->cloner->setMaxItems(-1);
|
||||
$this->cloner->addCasters(array(
|
||||
'*' => function ($v, array $a, Stub $s, $isNested) {
|
||||
if ($isNested && !$v instanceof \DateTimeInterface) {
|
||||
$s->cut = -1;
|
||||
$a = array();
|
||||
foreach ($a as &$v) {
|
||||
if (is_object($v) && !$v instanceof \DateTimeInterface) {
|
||||
$v = new CutStub($v);
|
||||
}
|
||||
}
|
||||
|
||||
return $a;
|
||||
@ -320,34 +301,15 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
|
||||
$this->cloner = false;
|
||||
}
|
||||
}
|
||||
if (false === $this->cloner) {
|
||||
if (null === $this->valueExporter) {
|
||||
$this->valueExporter = new ValueExporter();
|
||||
}
|
||||
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
if (null === $var) {
|
||||
$type = $hash = 'null';
|
||||
} elseif (array() === $var) {
|
||||
$type = $hash = 'array';
|
||||
} elseif ('object' === $type = gettype($var)) {
|
||||
$hash = spl_object_hash($var);
|
||||
} elseif ('double' === $type) {
|
||||
$hash = (string) $var;
|
||||
} elseif ('integer' === $type || 'string' === $type) {
|
||||
$hash = $var;
|
||||
} else {
|
||||
$type = null;
|
||||
}
|
||||
if (null !== $type && null !== $cache = &$this->clonerCache[$type][$hash]) {
|
||||
return $cache;
|
||||
}
|
||||
if ($isClass) {
|
||||
return $cache = $this->cloner->cloneVar(array(new ClassStub($var)))->seek(0);
|
||||
if (false !== $this->cloner) {
|
||||
return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE);
|
||||
}
|
||||
|
||||
return $cache = $this->cloner->cloneVar($var);
|
||||
if (null === $this->valueExporter) {
|
||||
$this->valueExporter = new ValueExporter();
|
||||
}
|
||||
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
|
||||
private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash)
|
||||
|
@ -32,13 +32,14 @@
|
||||
"symfony/http-kernel": "~2.8|~3.0",
|
||||
"symfony/security-csrf": "~2.8|~3.0",
|
||||
"symfony/translation": "~2.8|~3.0",
|
||||
"symfony/var-dumper": "~3.2"
|
||||
"symfony/var-dumper": "~3.3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
|
||||
"symfony/doctrine-bridge": "<2.7",
|
||||
"symfony/framework-bundle": "<2.7",
|
||||
"symfony/twig-bridge": "<2.7"
|
||||
"symfony/twig-bridge": "<2.7",
|
||||
"symfony/var-dumper": "~3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/validator": "For form validation.",
|
||||
|
@ -15,6 +15,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\VarDumper\Caster\LinkStub;
|
||||
|
||||
/**
|
||||
* ConfigDataCollector.
|
||||
@ -29,6 +30,7 @@ class ConfigDataCollector extends DataCollector
|
||||
private $kernel;
|
||||
private $name;
|
||||
private $version;
|
||||
private $hasVarDumper;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -40,6 +42,7 @@ class ConfigDataCollector extends DataCollector
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->hasVarDumper = class_exists(LinkStub::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,7 +82,7 @@ class ConfigDataCollector extends DataCollector
|
||||
|
||||
if (isset($this->kernel)) {
|
||||
foreach ($this->kernel->getBundles() as $name => $bundle) {
|
||||
$this->data['bundles'][$name] = $bundle->getPath();
|
||||
$this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath();
|
||||
}
|
||||
|
||||
$this->data['symfony_state'] = $this->determineSymfonyState();
|
||||
@ -94,6 +97,7 @@ class ConfigDataCollector extends DataCollector
|
||||
$this->data['php_version'] = $matches[1];
|
||||
$this->data['php_version_extra'] = $matches[2];
|
||||
}
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
public function getApplicationName()
|
||||
|
@ -13,11 +13,8 @@ namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Caster\LinkStub;
|
||||
use Symfony\Component\VarDumper\Caster\StubCaster;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
/**
|
||||
@ -40,7 +37,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
/**
|
||||
* @var ClonerInterface
|
||||
*/
|
||||
private $cloner;
|
||||
private static $cloner;
|
||||
|
||||
private static $stubsCache = array();
|
||||
|
||||
@ -66,21 +63,16 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
*/
|
||||
protected function cloneVar($var)
|
||||
{
|
||||
if (null === $this->cloner) {
|
||||
if (null === self::$cloner) {
|
||||
if (class_exists(ClassStub::class)) {
|
||||
$this->cloner = new VarCloner();
|
||||
$this->cloner->setMaxItems(250);
|
||||
$this->cloner->addCasters(array(
|
||||
Stub::class => function (Stub $v, array $a, Stub $s, $isNested) {
|
||||
return $isNested ? $a : StubCaster::castStub($v, $a, $s, true);
|
||||
},
|
||||
));
|
||||
self::$cloner = new VarCloner();
|
||||
self::$cloner->setMaxItems(-1);
|
||||
} else {
|
||||
@trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED);
|
||||
$this->cloner = false;
|
||||
self::$cloner = false;
|
||||
}
|
||||
}
|
||||
if (false === $this->cloner) {
|
||||
if (false === self::$cloner) {
|
||||
if (null === $this->valueExporter) {
|
||||
$this->valueExporter = new ValueExporter();
|
||||
}
|
||||
@ -88,7 +80,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
|
||||
return $this->cloner->cloneVar($this->decorateVar($var));
|
||||
return self::$cloner->cloneVar($var);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,36 +102,4 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
|
||||
private function decorateVar($var)
|
||||
{
|
||||
if (is_array($var)) {
|
||||
if (isset($var[0], $var[1]) && is_callable($var)) {
|
||||
return ClassStub::wrapCallable($var);
|
||||
}
|
||||
foreach ($var as $k => $v) {
|
||||
if ($v !== $d = $this->decorateVar($v)) {
|
||||
$var[$k] = $d;
|
||||
}
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
if (is_string($var)) {
|
||||
if (isset(self::$stubsCache[$var])) {
|
||||
return self::$stubsCache[$var];
|
||||
}
|
||||
if (false !== strpos($var, '\\')) {
|
||||
$c = (false !== $i = strpos($var, '::')) ? substr($var, 0, $i) : $var;
|
||||
if (class_exists($c, false) || interface_exists($c, false) || trait_exists($c, false)) {
|
||||
return self::$stubsCache[$var] = new ClassStub($var);
|
||||
}
|
||||
}
|
||||
if (false !== strpos($var, DIRECTORY_SEPARATOR) && false === strpos($var, '://') && false === strpos($var, "\0") && @is_file($var)) {
|
||||
return self::$stubsCache[$var] = new LinkStub($var);
|
||||
}
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
$this->setCalledListeners($this->dispatcher->getCalledListeners());
|
||||
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
|
||||
}
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
if (null !== $this->logger) {
|
||||
$this->data = $this->computeErrorsCount();
|
||||
$this->data['logs'] = $this->sanitizeLogs($this->logger->getLogs());
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +101,6 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
|
||||
foreach ($logs as $log) {
|
||||
if (!$this->isSilencedOrDeprecationErrorLog($log)) {
|
||||
$log['context'] = $log['context'] ? $this->cloneVar($log['context']) : $log['context'];
|
||||
$sanitizedLogs[] = $log;
|
||||
|
||||
continue;
|
||||
@ -112,8 +112,6 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
if (isset($sanitizedLogs[$errorId])) {
|
||||
++$sanitizedLogs[$errorId]['errorCount'];
|
||||
} else {
|
||||
$log['context'] = $log['context'] ? $this->cloneVar($log['context']) : $log['context'];
|
||||
|
||||
$log += array(
|
||||
'errorCount' => 1,
|
||||
'scream' => $exception instanceof SilencedErrorContext,
|
||||
|
@ -116,10 +116,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
continue;
|
||||
}
|
||||
if ('request_headers' === $key || 'response_headers' === $key) {
|
||||
$value = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
|
||||
}
|
||||
if ('request_server' !== $key && 'request_cookies' !== $key) {
|
||||
$this->data[$key] = array_map(array($this, 'cloneVar'), $value);
|
||||
$this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +141,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
@ -158,52 +157,52 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
|
||||
public function getRequestRequest()
|
||||
{
|
||||
return new ParameterBag($this->data['request_request']);
|
||||
return new ParameterBag($this->data['request_request']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestQuery()
|
||||
{
|
||||
return new ParameterBag($this->data['request_query']);
|
||||
return new ParameterBag($this->data['request_query']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestHeaders()
|
||||
{
|
||||
return new ParameterBag($this->data['request_headers']);
|
||||
return new ParameterBag($this->data['request_headers']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestServer($raw = false)
|
||||
{
|
||||
return new ParameterBag($raw ? $this->data['request_server'] : array_map(array($this, 'cloneVar'), $this->data['request_server']));
|
||||
return new ParameterBag($this->data['request_server']->getValue($raw));
|
||||
}
|
||||
|
||||
public function getRequestCookies($raw = false)
|
||||
{
|
||||
return new ParameterBag($raw ? $this->data['request_cookies'] : array_map(array($this, 'cloneVar'), $this->data['request_cookies']));
|
||||
return new ParameterBag($this->data['request_cookies']->getValue($raw));
|
||||
}
|
||||
|
||||
public function getRequestAttributes()
|
||||
{
|
||||
return new ParameterBag($this->data['request_attributes']);
|
||||
return new ParameterBag($this->data['request_attributes']->getValue());
|
||||
}
|
||||
|
||||
public function getResponseHeaders()
|
||||
{
|
||||
return new ParameterBag($this->data['response_headers']);
|
||||
return new ParameterBag($this->data['response_headers']->getValue());
|
||||
}
|
||||
|
||||
public function getSessionMetadata()
|
||||
{
|
||||
return $this->data['session_metadata'];
|
||||
return $this->data['session_metadata']->getValue();
|
||||
}
|
||||
|
||||
public function getSessionAttributes()
|
||||
{
|
||||
return $this->data['session_attributes'];
|
||||
return $this->data['session_attributes']->getValue();
|
||||
}
|
||||
|
||||
public function getFlashes()
|
||||
{
|
||||
return $this->data['flashes'];
|
||||
return $this->data['flashes']->getValue();
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
@ -262,22 +261,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
*/
|
||||
public function getRouteParams()
|
||||
{
|
||||
if (!isset($this->data['request_attributes']['_route_params'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$data = $this->data['request_attributes']['_route_params'];
|
||||
$rawData = $data->getRawData();
|
||||
if (!isset($rawData[1])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$params = array();
|
||||
foreach ($rawData[1] as $k => $v) {
|
||||
$params[$k] = $data->seek($k);
|
||||
}
|
||||
|
||||
return $params;
|
||||
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : array();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,9 +15,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Tests\Fixtures\DataCollector\CloneVarDataCollector;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
|
||||
class DataCollectorTest extends TestCase
|
||||
{
|
||||
@ -32,19 +30,9 @@ class DataCollectorTest extends TestCase
|
||||
|
||||
public function testCloneVarExistingFilePath()
|
||||
{
|
||||
$c = new CloneVarDataCollector($filePath = tempnam(sys_get_temp_dir(), 'clone_var_data_collector_'));
|
||||
$c = new CloneVarDataCollector(array($filePath = tempnam(sys_get_temp_dir(), 'clone_var_data_collector_')));
|
||||
$c->collect(new Request(), new Response());
|
||||
|
||||
$data = $c->getData();
|
||||
$this->assertInstanceOf(Stub::class, $data->getRawData()[0][0]);
|
||||
$this->assertDumpEquals("\"$filePath\"", $data);
|
||||
}
|
||||
|
||||
private function assertDumpEquals($dump, $data, $message = '')
|
||||
{
|
||||
$dumper = new CliDumper();
|
||||
$dumper->setColors(false);
|
||||
|
||||
$this->assertSame(rtrim($dump), rtrim($dumper->dump($data, true)), $message);
|
||||
$this->assertSame($filePath, $c->getData()[0]);
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,9 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Debug\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
class LoggerDataCollectorTest extends TestCase
|
||||
{
|
||||
private static $data;
|
||||
|
||||
/**
|
||||
* @dataProvider getCollectTestData
|
||||
*/
|
||||
@ -29,31 +26,31 @@ class LoggerDataCollectorTest extends TestCase
|
||||
$logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb));
|
||||
$logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs));
|
||||
|
||||
// disable cloning the context, to ease fixtures creation.
|
||||
$c = $this->getMockBuilder(LoggerDataCollector::class)
|
||||
->setMethods(array('cloneVar'))
|
||||
->setConstructorArgs(array($logger))
|
||||
->getMock();
|
||||
$c->expects($this->any())->method('cloneVar')->willReturn(self::$data);
|
||||
$c = new LoggerDataCollector($logger);
|
||||
$c->lateCollect();
|
||||
|
||||
$this->assertEquals('logger', $c->getName());
|
||||
$this->assertEquals($nb, $c->countErrors());
|
||||
$this->assertEquals($expectedLogs, $c->getLogs());
|
||||
|
||||
$logs = array_map(function ($v) {
|
||||
if (isset($v['context']['exception'])) {
|
||||
$e = &$v['context']['exception'];
|
||||
$e = isset($e["\0*\0message"]) ? array($e["\0*\0message"], $e["\0*\0severity"]) : array($e["\0Symfony\Component\Debug\Exception\SilencedErrorContext\0severity"]);
|
||||
}
|
||||
|
||||
return $v;
|
||||
}, $c->getLogs()->getValue(true));
|
||||
$this->assertEquals($expectedLogs, $logs);
|
||||
$this->assertEquals($expectedDeprecationCount, $c->countDeprecations());
|
||||
$this->assertEquals($expectedScreamCount, $c->countScreams());
|
||||
|
||||
if (isset($expectedPriorities)) {
|
||||
$this->assertSame($expectedPriorities, $c->getPriorities());
|
||||
$this->assertSame($expectedPriorities, $c->getPriorities()->getValue(true));
|
||||
}
|
||||
}
|
||||
|
||||
public function getCollectTestData()
|
||||
{
|
||||
if (null === self::$data) {
|
||||
self::$data = new Data(array());
|
||||
}
|
||||
|
||||
yield 'simple log' => array(
|
||||
1,
|
||||
array(array('message' => 'foo', 'context' => array(), 'priority' => 100, 'priorityName' => 'DEBUG')),
|
||||
@ -65,7 +62,7 @@ class LoggerDataCollectorTest extends TestCase
|
||||
yield 'log with a context' => array(
|
||||
1,
|
||||
array(array('message' => 'foo', 'context' => array('foo' => 'bar'), 'priority' => 100, 'priorityName' => 'DEBUG')),
|
||||
array(array('message' => 'foo', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG')),
|
||||
array(array('message' => 'foo', 'context' => array('foo' => 'bar'), 'priority' => 100, 'priorityName' => 'DEBUG')),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
@ -82,9 +79,9 @@ class LoggerDataCollectorTest extends TestCase
|
||||
array('message' => 'foo2', 'context' => array('exception' => new \ErrorException('deprecated', 0, E_USER_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
),
|
||||
array(
|
||||
array('message' => 'foo3', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
array('message' => 'foo', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false),
|
||||
array('message' => 'foo2', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false),
|
||||
array('message' => 'foo3', 'context' => array('exception' => array('warning', E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
array('message' => 'foo', 'context' => array('exception' => array('deprecated', E_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false),
|
||||
array('message' => 'foo2', 'context' => array('exception' => array('deprecated', E_USER_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false),
|
||||
),
|
||||
2,
|
||||
0,
|
||||
@ -98,8 +95,8 @@ class LoggerDataCollectorTest extends TestCase
|
||||
array('message' => 'foo3', 'context' => array('exception' => new SilencedErrorContext(E_USER_WARNING, __FILE__, __LINE__)), 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
),
|
||||
array(
|
||||
array('message' => 'foo3', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
array('message' => 'foo3', 'context' => self::$data, 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true),
|
||||
array('message' => 'foo3', 'context' => array('exception' => array('warning', E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'),
|
||||
array('message' => 'foo3', 'context' => array('exception' => array(E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true),
|
||||
),
|
||||
0,
|
||||
1,
|
||||
|
@ -48,11 +48,11 @@ class RequestDataCollectorTest extends TestCase
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery());
|
||||
$this->assertSame('html', $c->getFormat());
|
||||
$this->assertEquals('foobar', $c->getRoute());
|
||||
$this->assertEquals(array('name' => $cloner->cloneVar(array('name' => 'foo'))->seek('name')), $c->getRouteParams());
|
||||
$this->assertEquals(array('name' => 'foo'), $c->getRouteParams());
|
||||
$this->assertSame(array(), $c->getSessionAttributes());
|
||||
$this->assertSame('en', $c->getLocale());
|
||||
$this->assertEquals($cloner->cloneVar($request->attributes->get('resource')), $attributes->get('resource'));
|
||||
$this->assertEquals($cloner->cloneVar($request->attributes->get('object')), $attributes->get('object'));
|
||||
$this->assertContains(__FILE__, $attributes->get('resource'));
|
||||
$this->assertSame('stdClass', $attributes->get('object')->getType());
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getResponseHeaders());
|
||||
$this->assertSame('OK', $c->getStatusText());
|
||||
@ -95,7 +95,7 @@ class RequestDataCollectorTest extends TestCase
|
||||
$this->injectController($c, $callable, $request);
|
||||
$c->collect($request, $response);
|
||||
|
||||
$this->assertSame($expected, $c->getController(), sprintf('Testing: %s', $name));
|
||||
$this->assertSame($expected, $c->getController()->getValue(true), sprintf('Testing: %s', $name));
|
||||
}
|
||||
|
||||
public function provideControllerCallables()
|
||||
|
@ -68,7 +68,7 @@ class MockCloner implements ClonerInterface
|
||||
{
|
||||
public function cloneVar($var)
|
||||
{
|
||||
return new Data(array($var.'-'));
|
||||
return new Data(array(array($var.'-')));
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,8 +76,6 @@ class MockDumper implements DataDumperInterface
|
||||
{
|
||||
public function dump(Data $data)
|
||||
{
|
||||
$rawData = $data->getRawData();
|
||||
|
||||
echo '+'.$rawData[0];
|
||||
echo '+'.$data->getValue();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
class ProfilerTest extends TestCase
|
||||
{
|
||||
@ -37,7 +36,7 @@ class ProfilerTest extends TestCase
|
||||
|
||||
$this->assertSame(204, $profile->getStatusCode());
|
||||
$this->assertSame('GET', $profile->getMethod());
|
||||
$this->assertInstanceOf(Data::class, $profiler->get('request')->getRequestQuery()->all()['foo']);
|
||||
$this->assertSame('bar', $profiler->get('request')->getRequestQuery()->all()['foo']->getValue());
|
||||
}
|
||||
|
||||
public function testFindWorksWithDates()
|
||||
|
@ -37,12 +37,13 @@
|
||||
"symfony/stopwatch": "~2.8|~3.0",
|
||||
"symfony/templating": "~2.8|~3.0",
|
||||
"symfony/translation": "~2.8|~3.0",
|
||||
"symfony/var-dumper": "~3.2",
|
||||
"symfony/var-dumper": "~3.3",
|
||||
"psr/cache": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<2.8",
|
||||
"symfony/dependency-injection": "<3.3"
|
||||
"symfony/dependency-injection": "<3.3",
|
||||
"symfony/var-dumper": "<3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/browser-kit": "",
|
||||
|
@ -44,6 +44,8 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto
|
||||
|
||||
$this->data = $this->computeCount($messages);
|
||||
$this->data['messages'] = $messages;
|
||||
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,12 +103,12 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto
|
||||
|
||||
if (!isset($result[$messageId])) {
|
||||
$message['count'] = 1;
|
||||
$message['parameters'] = !empty($message['parameters']) ? array($this->cloneVar($message['parameters'])) : array();
|
||||
$message['parameters'] = !empty($message['parameters']) ? array($message['parameters']) : array();
|
||||
$messages[$key]['translation'] = $this->sanitizeString($message['translation']);
|
||||
$result[$messageId] = $message;
|
||||
} else {
|
||||
if (!empty($message['parameters'])) {
|
||||
$result[$messageId]['parameters'][] = $this->cloneVar($message['parameters']);
|
||||
$result[$messageId]['parameters'][] = $message['parameters'];
|
||||
}
|
||||
|
||||
++$result[$messageId]['count'];
|
||||
|
@ -14,7 +14,6 @@ namespace Symfony\Component\Translation\Tests\DataCollector;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Translation\DataCollectorTranslator;
|
||||
use Symfony\Component\Translation\DataCollector\TranslationDataCollector;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
class TranslationDataCollectorTest extends TestCase
|
||||
{
|
||||
@ -36,13 +35,11 @@ class TranslationDataCollectorTest extends TestCase
|
||||
$this->assertEquals(0, $dataCollector->getCountMissings());
|
||||
$this->assertEquals(0, $dataCollector->getCountFallbacks());
|
||||
$this->assertEquals(0, $dataCollector->getCountDefines());
|
||||
$this->assertEquals(array(), $dataCollector->getMessages());
|
||||
$this->assertEquals(array(), $dataCollector->getMessages()->getValue());
|
||||
}
|
||||
|
||||
public function testCollect()
|
||||
{
|
||||
$cloner = new VarCloner();
|
||||
|
||||
$collectedMessages = array(
|
||||
array(
|
||||
'id' => 'foo',
|
||||
@ -119,9 +116,9 @@ class TranslationDataCollectorTest extends TestCase
|
||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||
'count' => 3,
|
||||
'parameters' => array(
|
||||
$cloner->cloneVar(array('%count%' => 3)),
|
||||
$cloner->cloneVar(array('%count%' => 3)),
|
||||
$cloner->cloneVar(array('%count%' => 4, '%foo%' => 'bar')),
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 3),
|
||||
array('%count%' => 4, '%foo%' => 'bar'),
|
||||
),
|
||||
'transChoiceNumber' => 3,
|
||||
),
|
||||
@ -136,7 +133,8 @@ class TranslationDataCollectorTest extends TestCase
|
||||
$this->assertEquals(1, $dataCollector->getCountMissings());
|
||||
$this->assertEquals(1, $dataCollector->getCountFallbacks());
|
||||
$this->assertEquals(1, $dataCollector->getCountDefines());
|
||||
$this->assertEquals($expectedMessages, array_values($dataCollector->getMessages()));
|
||||
|
||||
$this->assertEquals($expectedMessages, array_values($dataCollector->getMessages()->getValue(true)));
|
||||
}
|
||||
|
||||
private function getTranslator()
|
||||
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
* Helper for filtering out properties in casters.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class Caster
|
||||
{
|
||||
@ -38,14 +40,20 @@ class Caster
|
||||
/**
|
||||
* Casts objects to arrays and adds the dynamic property prefix.
|
||||
*
|
||||
* @param object $obj The object to cast
|
||||
* @param \ReflectionClass $reflector The class reflector to use for inspecting the object definition
|
||||
* @param object $obj The object to cast
|
||||
* @param string $class The class of the object
|
||||
* @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not
|
||||
*
|
||||
* @return array The array-cast of the object, with prefixed dynamic properties
|
||||
*/
|
||||
public static function castObject($obj, \ReflectionClass $reflector)
|
||||
public static function castObject($obj, $class, $hasDebugInfo = false)
|
||||
{
|
||||
if ($reflector->hasMethod('__debugInfo')) {
|
||||
if ($class instanceof \ReflectionClass) {
|
||||
@trigger_error(sprintf('Passing a ReflectionClass to %s() is deprecated since version 3.3 and will be unsupported in 4.0. Pass the class name as string instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
$hasDebugInfo = $class->hasMethod('__debugInfo');
|
||||
$class = $class->name;
|
||||
}
|
||||
if ($hasDebugInfo) {
|
||||
$a = $obj->__debugInfo();
|
||||
} elseif ($obj instanceof \Closure) {
|
||||
$a = array();
|
||||
@ -57,19 +65,22 @@ class Caster
|
||||
}
|
||||
|
||||
if ($a) {
|
||||
$combine = false;
|
||||
$p = array_keys($a);
|
||||
foreach ($p as $i => $k) {
|
||||
if (isset($k[0]) && "\0" !== $k[0] && !$reflector->hasProperty($k)) {
|
||||
$combine = true;
|
||||
$p[$i] = self::PREFIX_DYNAMIC.$k;
|
||||
$i = 0;
|
||||
$prefixedKeys = array();
|
||||
foreach ($a as $k => $v) {
|
||||
if (isset($k[0]) && "\0" !== $k[0] && !property_exists($class, $k)) {
|
||||
$prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
|
||||
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) {
|
||||
$combine = true;
|
||||
$p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0");
|
||||
$prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0");
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
if ($combine) {
|
||||
$a = array_combine($p, $a);
|
||||
if ($prefixedKeys) {
|
||||
$keys = array_keys($a);
|
||||
foreach ($prefixedKeys as $i => $k) {
|
||||
$keys[$i] = $k;
|
||||
}
|
||||
$a = array_combine($keys, $a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class ExceptionCaster
|
||||
if (isset($a[$xPrefix.'previous'], $a[$xPrefix.'trace'])) {
|
||||
$b = (array) $a[$xPrefix.'previous'];
|
||||
self::traceUnshift($b[$xPrefix.'trace'], get_class($a[$xPrefix.'previous']), $b[$prefix.'file'], $b[$prefix.'line']);
|
||||
$a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -1 - count($a[$xPrefix.'trace']->value));
|
||||
$a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -count($a[$xPrefix.'trace']->value));
|
||||
}
|
||||
|
||||
unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']);
|
||||
|
@ -31,13 +31,13 @@ class ReflectionCaster
|
||||
'isVariadic' => 'isVariadic',
|
||||
);
|
||||
|
||||
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
|
||||
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested, $filter = 0)
|
||||
{
|
||||
$prefix = Caster::PREFIX_VIRTUAL;
|
||||
$c = new \ReflectionFunction($c);
|
||||
|
||||
$stub->class = 'Closure'; // HHVM generates unique class names for closures
|
||||
$a = static::castFunctionAbstract($c, $a, $stub, $isNested);
|
||||
$a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
|
||||
|
||||
if (isset($a[$prefix.'parameters'])) {
|
||||
foreach ($a[$prefix.'parameters']->value as &$v) {
|
||||
@ -51,8 +51,9 @@ class ReflectionCaster
|
||||
unset($v->value['position'], $v->value['isVariadic'], $v->value['byReference'], $v);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
if ($f = $c->getFileName()) {
|
||||
if (!($filter & Caster::EXCLUDE_VERBOSE) && $f = $c->getFileName()) {
|
||||
$a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
|
||||
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
|
||||
}
|
||||
@ -199,7 +200,11 @@ class ReflectionCaster
|
||||
|
||||
if ($v = $c->getStaticVariables()) {
|
||||
foreach ($v as $k => &$v) {
|
||||
$a[$prefix.'use']['$'.$k] = &$v;
|
||||
if (is_object($v)) {
|
||||
$a[$prefix.'use']['$'.$k] = new CutStub($v);
|
||||
} else {
|
||||
$a[$prefix.'use']['$'.$k] = &$v;
|
||||
}
|
||||
}
|
||||
unset($v);
|
||||
$a[$prefix.'use'] = new EnumStub($a[$prefix.'use']);
|
||||
|
@ -45,7 +45,7 @@ class SplCaster
|
||||
} else {
|
||||
if (!($flags & \ArrayObject::STD_PROP_LIST)) {
|
||||
$c->setFlags(\ArrayObject::STD_PROP_LIST);
|
||||
$a = Caster::castObject($c, new \ReflectionClass($class));
|
||||
$a = Caster::castObject($c, $class);
|
||||
$c->setFlags($flags);
|
||||
}
|
||||
|
||||
|
@ -22,107 +22,107 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
|
||||
abstract class AbstractCloner implements ClonerInterface
|
||||
{
|
||||
public static $defaultCasters = array(
|
||||
'__PHP_Incomplete_Class' => 'Symfony\Component\VarDumper\Caster\Caster::castPhpIncompleteClass',
|
||||
'__PHP_Incomplete_Class' => array('Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'),
|
||||
|
||||
'Symfony\Component\VarDumper\Caster\CutStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
||||
'Symfony\Component\VarDumper\Caster\CutArrayStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castCutArray',
|
||||
'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
|
||||
'Symfony\Component\VarDumper\Caster\EnumStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castEnum',
|
||||
'Symfony\Component\VarDumper\Caster\CutStub' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'),
|
||||
'Symfony\Component\VarDumper\Caster\CutArrayStub' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'),
|
||||
'Symfony\Component\VarDumper\Caster\ConstStub' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'),
|
||||
'Symfony\Component\VarDumper\Caster\EnumStub' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'),
|
||||
|
||||
'Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
|
||||
'Generator' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castGenerator',
|
||||
'ReflectionType' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castType',
|
||||
'ReflectionGenerator' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflectionGenerator',
|
||||
'ReflectionClass' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClass',
|
||||
'ReflectionFunctionAbstract' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castFunctionAbstract',
|
||||
'ReflectionMethod' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castMethod',
|
||||
'ReflectionParameter' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castParameter',
|
||||
'ReflectionProperty' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castProperty',
|
||||
'ReflectionExtension' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castExtension',
|
||||
'ReflectionZendExtension' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castZendExtension',
|
||||
'Closure' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'),
|
||||
'Generator' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'),
|
||||
'ReflectionType' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'),
|
||||
'ReflectionGenerator' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'),
|
||||
'ReflectionClass' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'),
|
||||
'ReflectionFunctionAbstract' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'),
|
||||
'ReflectionMethod' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'),
|
||||
'ReflectionParameter' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'),
|
||||
'ReflectionProperty' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'),
|
||||
'ReflectionExtension' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'),
|
||||
'ReflectionZendExtension' => array('Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'),
|
||||
|
||||
'Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
|
||||
'Doctrine\Common\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castCommonProxy',
|
||||
'Doctrine\ORM\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castOrmProxy',
|
||||
'Doctrine\ORM\PersistentCollection' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castPersistentCollection',
|
||||
'Doctrine\Common\Persistence\ObjectManager' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'),
|
||||
'Doctrine\Common\Proxy\Proxy' => array('Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'),
|
||||
'Doctrine\ORM\Proxy\Proxy' => array('Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'),
|
||||
'Doctrine\ORM\PersistentCollection' => array('Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'),
|
||||
|
||||
'DOMException' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castException',
|
||||
'DOMStringList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||
'DOMNameList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||
'DOMImplementation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castImplementation',
|
||||
'DOMImplementationList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||
'DOMNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNode',
|
||||
'DOMNameSpaceNode' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNameSpaceNode',
|
||||
'DOMDocument' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocument',
|
||||
'DOMNodeList' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||
'DOMNamedNodeMap' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLength',
|
||||
'DOMCharacterData' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castCharacterData',
|
||||
'DOMAttr' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castAttr',
|
||||
'DOMElement' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castElement',
|
||||
'DOMText' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castText',
|
||||
'DOMTypeinfo' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castTypeinfo',
|
||||
'DOMDomError' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDomError',
|
||||
'DOMLocator' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castLocator',
|
||||
'DOMDocumentType' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castDocumentType',
|
||||
'DOMNotation' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castNotation',
|
||||
'DOMEntity' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castEntity',
|
||||
'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
|
||||
'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',
|
||||
'DOMException' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'),
|
||||
'DOMStringList' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'),
|
||||
'DOMNameList' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'),
|
||||
'DOMImplementation' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'),
|
||||
'DOMImplementationList' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'),
|
||||
'DOMNode' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'),
|
||||
'DOMNameSpaceNode' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'),
|
||||
'DOMDocument' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'),
|
||||
'DOMNodeList' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'),
|
||||
'DOMNamedNodeMap' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'),
|
||||
'DOMCharacterData' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'),
|
||||
'DOMAttr' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'),
|
||||
'DOMElement' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'),
|
||||
'DOMText' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'),
|
||||
'DOMTypeinfo' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'),
|
||||
'DOMDomError' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'),
|
||||
'DOMLocator' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'),
|
||||
'DOMDocumentType' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'),
|
||||
'DOMNotation' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'),
|
||||
'DOMEntity' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'),
|
||||
'DOMProcessingInstruction' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'),
|
||||
'DOMXPath' => array('Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'),
|
||||
|
||||
'XmlReader' => 'Symfony\Component\VarDumper\Caster\XmlReaderCaster::castXmlReader',
|
||||
'XmlReader' => array('Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'),
|
||||
|
||||
'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
|
||||
'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
|
||||
'Error' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castError',
|
||||
'Symfony\Component\DependencyInjection\ContainerInterface' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
|
||||
'Symfony\Component\DependencyInjection\LazyProxy\InheritanceProxyInterface' => 'Symfony\Component\VarDumper\Caster\SymfonyCaster::castInheritanceProxy',
|
||||
'Symfony\Component\HttpFoundation\Request' => 'Symfony\Component\VarDumper\Caster\SymfonyCaster::castRequest',
|
||||
'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castThrowingCasterException',
|
||||
'Symfony\Component\VarDumper\Caster\TraceStub' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castTraceStub',
|
||||
'Symfony\Component\VarDumper\Caster\FrameStub' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castFrameStub',
|
||||
'ErrorException' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'),
|
||||
'Exception' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'),
|
||||
'Error' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'),
|
||||
'Symfony\Component\DependencyInjection\ContainerInterface' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'),
|
||||
'Symfony\Component\DependencyInjection\LazyProxy\InheritanceProxyInterface' => array('Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castInheritanceProxy'),
|
||||
'Symfony\Component\HttpFoundation\Request' => array('Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'),
|
||||
'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'),
|
||||
'Symfony\Component\VarDumper\Caster\TraceStub' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'),
|
||||
'Symfony\Component\VarDumper\Caster\FrameStub' => array('Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'),
|
||||
|
||||
'PHPUnit_Framework_MockObject_MockObject' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
|
||||
'Prophecy\Prophecy\ProphecySubjectInterface' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
|
||||
'Mockery\MockInterface' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
|
||||
'PHPUnit_Framework_MockObject_MockObject' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'),
|
||||
'Prophecy\Prophecy\ProphecySubjectInterface' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'),
|
||||
'Mockery\MockInterface' => array('Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'),
|
||||
|
||||
'PDO' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdo',
|
||||
'PDOStatement' => 'Symfony\Component\VarDumper\Caster\PdoCaster::castPdoStatement',
|
||||
'PDO' => array('Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'),
|
||||
'PDOStatement' => array('Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'),
|
||||
|
||||
'AMQPConnection' => 'Symfony\Component\VarDumper\Caster\AmqpCaster::castConnection',
|
||||
'AMQPChannel' => 'Symfony\Component\VarDumper\Caster\AmqpCaster::castChannel',
|
||||
'AMQPQueue' => 'Symfony\Component\VarDumper\Caster\AmqpCaster::castQueue',
|
||||
'AMQPExchange' => 'Symfony\Component\VarDumper\Caster\AmqpCaster::castExchange',
|
||||
'AMQPEnvelope' => 'Symfony\Component\VarDumper\Caster\AmqpCaster::castEnvelope',
|
||||
'AMQPConnection' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'),
|
||||
'AMQPChannel' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'),
|
||||
'AMQPQueue' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'),
|
||||
'AMQPExchange' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'),
|
||||
'AMQPEnvelope' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'),
|
||||
|
||||
'ArrayObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castArrayObject',
|
||||
'SplDoublyLinkedList' => 'Symfony\Component\VarDumper\Caster\SplCaster::castDoublyLinkedList',
|
||||
'SplFileInfo' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFileInfo',
|
||||
'SplFileObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFileObject',
|
||||
'SplFixedArray' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFixedArray',
|
||||
'SplHeap' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
||||
'SplObjectStorage' => 'Symfony\Component\VarDumper\Caster\SplCaster::castObjectStorage',
|
||||
'SplPriorityQueue' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
|
||||
'OuterIterator' => 'Symfony\Component\VarDumper\Caster\SplCaster::castOuterIterator',
|
||||
'ArrayObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'),
|
||||
'SplDoublyLinkedList' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'),
|
||||
'SplFileInfo' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'),
|
||||
'SplFileObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'),
|
||||
'SplFixedArray' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'),
|
||||
'SplHeap' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'),
|
||||
'SplObjectStorage' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'),
|
||||
'SplPriorityQueue' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'),
|
||||
'OuterIterator' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'),
|
||||
|
||||
'MongoCursorInterface' => 'Symfony\Component\VarDumper\Caster\MongoCaster::castCursor',
|
||||
'MongoCursorInterface' => array('Symfony\Component\VarDumper\Caster\MongoCaster', 'castCursor'),
|
||||
|
||||
'Redis' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedis',
|
||||
'RedisArray' => 'Symfony\Component\VarDumper\Caster\RedisCaster::castRedisArray',
|
||||
'Redis' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'),
|
||||
'RedisArray' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'),
|
||||
|
||||
':curl' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castCurl',
|
||||
':dba' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||
':dba persistent' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castDba',
|
||||
':gd' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castGd',
|
||||
':mysql link' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castMysqlLink',
|
||||
':pgsql large object' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castLargeObject',
|
||||
':pgsql link' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castLink',
|
||||
':pgsql link persistent' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castLink',
|
||||
':pgsql result' => 'Symfony\Component\VarDumper\Caster\PgSqlCaster::castResult',
|
||||
':process' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castProcess',
|
||||
':stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
||||
':persistent stream' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStream',
|
||||
':stream-context' => 'Symfony\Component\VarDumper\Caster\ResourceCaster::castStreamContext',
|
||||
':xml' => 'Symfony\Component\VarDumper\Caster\XmlResourceCaster::castXml',
|
||||
':curl' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'),
|
||||
':dba' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'),
|
||||
':dba persistent' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'),
|
||||
':gd' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'),
|
||||
':mysql link' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'),
|
||||
':pgsql large object' => array('Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'),
|
||||
':pgsql link' => array('Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'),
|
||||
':pgsql link persistent' => array('Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'),
|
||||
':pgsql result' => array('Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'),
|
||||
':process' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'),
|
||||
':stream' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'),
|
||||
':persistent stream' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'),
|
||||
':stream-context' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'),
|
||||
':xml' => array('Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'),
|
||||
);
|
||||
|
||||
protected $maxItems = 2500;
|
||||
@ -161,7 +161,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
public function addCasters(array $casters)
|
||||
{
|
||||
foreach ($casters as $type => $callback) {
|
||||
$this->casters[strtolower($type)][] = $callback;
|
||||
$this->casters[strtolower($type)][] = is_string($callback) && false !== strpos($callback, '::') ? explode('::', $callback, 2) : $callback;
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,25 +249,37 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
$stub->class = get_parent_class($class).'@anonymous';
|
||||
}
|
||||
if (isset($this->classInfo[$class])) {
|
||||
$classInfo = $this->classInfo[$class];
|
||||
list($i, $parents, $hasDebugInfo) = $this->classInfo[$class];
|
||||
} else {
|
||||
$classInfo = array(
|
||||
new \ReflectionClass($class),
|
||||
array_reverse(array($class => $class) + class_parents($class) + class_implements($class) + array('*' => '*')),
|
||||
);
|
||||
$classInfo[1] = array_map('strtolower', $classInfo[1]);
|
||||
$i = 2;
|
||||
$parents = array(strtolower($class));
|
||||
$hasDebugInfo = method_exists($class, '__debugInfo');
|
||||
|
||||
$this->classInfo[$class] = $classInfo;
|
||||
foreach (class_parents($class) as $p) {
|
||||
$parents[] = strtolower($p);
|
||||
++$i;
|
||||
}
|
||||
foreach (class_implements($class) as $p) {
|
||||
$parents[] = strtolower($p);
|
||||
++$i;
|
||||
}
|
||||
$parents[] = '*';
|
||||
|
||||
$this->classInfo[$class] = array($i, $parents, $hasDebugInfo);
|
||||
}
|
||||
|
||||
$a = Caster::castObject($obj, $classInfo[0]);
|
||||
$a = Caster::castObject($obj, $class, $hasDebugInfo);
|
||||
|
||||
foreach ($classInfo[1] as $p) {
|
||||
if (!empty($this->casters[$p])) {
|
||||
foreach ($this->casters[$p] as $p) {
|
||||
$a = $this->callCaster($p, $obj, $a, $stub, $isNested);
|
||||
try {
|
||||
while ($i--) {
|
||||
if (!empty($this->casters[$p = $parents[$i]])) {
|
||||
foreach ($this->casters[$p] as $callback) {
|
||||
$a = $callback($obj, $a, $stub, $isNested, $this->filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$a = array((Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)) + $a;
|
||||
}
|
||||
|
||||
return $a;
|
||||
@ -287,33 +299,11 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
$res = $stub->value;
|
||||
$type = $stub->class;
|
||||
|
||||
if (!empty($this->casters[':'.$type])) {
|
||||
foreach ($this->casters[':'.$type] as $c) {
|
||||
$a = $this->callCaster($c, $res, $a, $stub, $isNested);
|
||||
}
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a custom caster.
|
||||
*
|
||||
* @param callable $callback The caster
|
||||
* @param object|resource $obj The object/resource being casted
|
||||
* @param array $a The result of the previous cast for chained casters
|
||||
* @param Stub $stub The Stub for the casted object/resource
|
||||
* @param bool $isNested True if $obj is nested in the dumped structure
|
||||
*
|
||||
* @return array The casted object/resource
|
||||
*/
|
||||
private function callCaster($callback, $obj, $a, $stub, $isNested)
|
||||
{
|
||||
try {
|
||||
$cast = call_user_func($callback, $obj, $a, $stub, $isNested, $this->filter);
|
||||
|
||||
if (is_array($cast)) {
|
||||
$a = $cast;
|
||||
if (!empty($this->casters[':'.$type])) {
|
||||
foreach ($this->casters[':'.$type] as $callback) {
|
||||
$a = $callback($res, $a, $stub, $isNested, $this->filter);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$a = array((Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)) + $a;
|
||||
|
@ -16,7 +16,7 @@ use Symfony\Component\VarDumper\Caster\Caster;
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class Data
|
||||
class Data implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
{
|
||||
private $data;
|
||||
private $position = 0;
|
||||
@ -33,11 +33,147 @@ class Data
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The type of the value.
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
$item = $this->data[$this->position][$this->key];
|
||||
|
||||
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
|
||||
$item = $item->value;
|
||||
}
|
||||
if (!$item instanceof Stub) {
|
||||
return gettype($item);
|
||||
}
|
||||
if (Stub::TYPE_STRING === $item->type) {
|
||||
return 'string';
|
||||
}
|
||||
if (Stub::TYPE_ARRAY === $item->type) {
|
||||
return 'array';
|
||||
}
|
||||
if (Stub::TYPE_OBJECT === $item->type) {
|
||||
return $item->class;
|
||||
}
|
||||
if (Stub::TYPE_RESOURCE === $item->type) {
|
||||
return $item->class.' resource';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $recursive Whether values should be resolved recursively or not.
|
||||
*
|
||||
* @return scalar|array|null|Data[] A native representation of the original value.
|
||||
*/
|
||||
public function getValue($recursive = false)
|
||||
{
|
||||
$item = $this->data[$this->position][$this->key];
|
||||
|
||||
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
|
||||
$item = $item->value;
|
||||
}
|
||||
if (!$item instanceof Stub) {
|
||||
return $item;
|
||||
}
|
||||
if (Stub::TYPE_STRING === $item->type) {
|
||||
return $item->value;
|
||||
}
|
||||
|
||||
$children = $item->position ? $this->data[$item->position] : array();
|
||||
|
||||
foreach ($children as $k => $v) {
|
||||
if ($recursive && !$v instanceof Stub) {
|
||||
continue;
|
||||
}
|
||||
$children[$k] = clone $this;
|
||||
$children[$k]->key = $k;
|
||||
$children[$k]->position = $item->position;
|
||||
|
||||
if ($recursive) {
|
||||
if ($v instanceof Stub && Stub::TYPE_REF === $v->type && $v->value instanceof Stub) {
|
||||
$recursive = (array) $recursive;
|
||||
if (isset($recursive[$v->value->position])) {
|
||||
continue;
|
||||
}
|
||||
$recursive[$v->value->position] = true;
|
||||
}
|
||||
$children[$k] = $children[$k]->getValue($recursive);
|
||||
}
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->getValue());
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
if (!is_array($value = $this->getValue())) {
|
||||
throw new \LogicException(sprintf('%s object holds non-iterable type "%s".', self::class, gettype($value)));
|
||||
}
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
yield $k => $v;
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if (null !== $data = $this->seek($key)) {
|
||||
$item = $data->data[$data->position][$data->key];
|
||||
|
||||
return $item instanceof Stub || array() === $item ? $data : $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return null !== $this->seek($key);
|
||||
}
|
||||
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return $this->__isset($key);
|
||||
}
|
||||
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->__get($key);
|
||||
}
|
||||
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
throw new \BadMethodCallException(self::class.' objects are immutable.');
|
||||
}
|
||||
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
throw new \BadMethodCallException(self::class.' objects are immutable.');
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$value = $this->getValue();
|
||||
|
||||
if (!is_array($value)) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return sprintf('%s (count=%d)', $this->getType(), count($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array The raw data structure
|
||||
*
|
||||
* @deprecated since version 3.3. Use array or object access instead.
|
||||
*/
|
||||
public function getRawData()
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the array or object access instead.', __METHOD__));
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
@ -97,6 +233,9 @@ class Data
|
||||
{
|
||||
$item = $this->data[$this->position][$this->key];
|
||||
|
||||
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
|
||||
$item = $item->value;
|
||||
}
|
||||
if (!$item instanceof Stub || !$item->position) {
|
||||
return;
|
||||
}
|
||||
|
115
src/Symfony/Component/VarDumper/Tests/Cloner/DataTest.php
Normal file
115
src/Symfony/Component/VarDumper/Tests/Cloner/DataTest.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests\Cloner;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\Caster\Caster;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
class DataTest extends TestCase
|
||||
{
|
||||
public function testBasicData()
|
||||
{
|
||||
$values = array(1 => 123, 4.5, 'abc', null, false);
|
||||
$data = $this->cloneVar($values);
|
||||
$clonedValues = array();
|
||||
|
||||
$this->assertInstanceOf(Data::class, $data);
|
||||
$this->assertCount(count($values), $data);
|
||||
$this->assertFalse(isset($data->{0}));
|
||||
$this->assertFalse(isset($data[0]));
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
$this->assertTrue(isset($data->{$k}));
|
||||
$this->assertTrue(isset($data[$k]));
|
||||
$this->assertSame(gettype($values[$k]), $data->seek($k)->getType());
|
||||
$this->assertSame($values[$k], $data->seek($k)->getValue());
|
||||
$this->assertSame($values[$k], $data->{$k});
|
||||
$this->assertSame($values[$k], $data[$k]);
|
||||
$this->assertSame((string) $values[$k], (string) $data->seek($k));
|
||||
|
||||
$clonedValues[$k] = $v->getValue();
|
||||
}
|
||||
|
||||
$this->assertSame($values, $clonedValues);
|
||||
}
|
||||
|
||||
public function testObject()
|
||||
{
|
||||
$data = $this->cloneVar(new \Exception('foo'));
|
||||
|
||||
$this->assertSame('Exception', $data->getType());
|
||||
|
||||
$this->assertSame('foo', $data->message);
|
||||
$this->assertSame('foo', $data->{Caster::PREFIX_PROTECTED.'message'});
|
||||
|
||||
$this->assertSame('foo', $data['message']);
|
||||
$this->assertSame('foo', $data[Caster::PREFIX_PROTECTED.'message']);
|
||||
|
||||
$this->assertStringMatchesFormat('Exception (count=%d)', (string) $data);
|
||||
}
|
||||
|
||||
public function testArray()
|
||||
{
|
||||
$values = array(array(), array(123));
|
||||
$data = $this->cloneVar($values);
|
||||
|
||||
$this->assertSame($values, $data->getValue(true));
|
||||
|
||||
$children = $data->getValue();
|
||||
|
||||
$this->assertInternalType('array', $children);
|
||||
|
||||
$this->assertInstanceOf(Data::class, $children[0]);
|
||||
$this->assertInstanceOf(Data::class, $children[1]);
|
||||
|
||||
$this->assertEquals($children[0], $data[0]);
|
||||
$this->assertEquals($children[1], $data[1]);
|
||||
|
||||
$this->assertSame($values[0], $children[0]->getValue(true));
|
||||
$this->assertSame($values[1], $children[1]->getValue(true));
|
||||
}
|
||||
|
||||
public function testStub()
|
||||
{
|
||||
$data = $this->cloneVar(array(new ClassStub('stdClass')));
|
||||
$data = $data[0];
|
||||
|
||||
$this->assertSame('string', $data->getType());
|
||||
$this->assertSame('stdClass', $data->getValue());
|
||||
$this->assertSame('stdClass', (string) $data);
|
||||
}
|
||||
|
||||
public function testHardRefs()
|
||||
{
|
||||
$values = array(array());
|
||||
$values[1] = &$values[0];
|
||||
$values[2][0] = &$values[2];
|
||||
|
||||
$data = $this->cloneVar($values);
|
||||
|
||||
$this->assertSame(array(), $data[0]->getValue());
|
||||
$this->assertSame(array(), $data[1]->getValue());
|
||||
$this->assertEquals(array($data[2]->getValue()), $data[2]->getValue(true));
|
||||
|
||||
$this->assertSame('array (count=3)', (string) $data);
|
||||
}
|
||||
|
||||
private function cloneVar($value)
|
||||
{
|
||||
$cloner = new VarCloner();
|
||||
|
||||
return $cloner->cloneVar($value);
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests;
|
||||
namespace Symfony\Component\VarDumper\Tests\Cloner;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
@ -9,7 +9,7 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests;
|
||||
namespace Symfony\Component\VarDumper\Tests\Dumper;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
@ -25,7 +25,7 @@ class CliDumperTest extends TestCase
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
require __DIR__.'/Fixtures/dumb-var.php';
|
||||
require __DIR__.'/../Fixtures/dumb-var.php';
|
||||
|
||||
$dumper = new CliDumper('php://output');
|
||||
$dumper->setColors(false);
|
||||
@ -75,8 +75,8 @@ array:24 [
|
||||
+"bar": "bar"
|
||||
}
|
||||
"closure" => Closure {{$r}
|
||||
class: "Symfony\Component\VarDumper\Tests\CliDumperTest"
|
||||
this: Symfony\Component\VarDumper\Tests\CliDumperTest {{$r} …}
|
||||
class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest"
|
||||
this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {{$r} …}
|
||||
parameters: {
|
||||
\$a: {}
|
||||
&\$b: {
|
||||
@ -297,7 +297,7 @@ EOTXT
|
||||
{
|
||||
$out = fopen('php://memory', 'r+b');
|
||||
|
||||
require_once __DIR__.'/Fixtures/Twig.php';
|
||||
require_once __DIR__.'/../Fixtures/Twig.php';
|
||||
$twig = new \__TwigTemplate_VarDumperFixture_u75a09(new \Twig_Environment(new \Twig_Loader_Filesystem()));
|
||||
|
||||
$dumper = new CliDumper();
|
@ -9,7 +9,7 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests;
|
||||
namespace Symfony\Component\VarDumper\Tests\Dumper;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
@ -22,7 +22,7 @@ class HtmlDumperTest extends TestCase
|
||||
{
|
||||
public function testGet()
|
||||
{
|
||||
require __DIR__.'/Fixtures/dumb-var.php';
|
||||
require __DIR__.'/../Fixtures/dumb-var.php';
|
||||
|
||||
$dumper = new HtmlDumper('php://output');
|
||||
$dumper->setDumpHeader('<foo></foo>');
|
||||
@ -76,9 +76,9 @@ class HtmlDumperTest extends TestCase
|
||||
+"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
|
||||
</samp>}
|
||||
"<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {{$r}<samp>
|
||||
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\HtmlDumperTest
|
||||
48 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests</span>\HtmlDumperTest</span>"
|
||||
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
|
||||
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest
|
||||
55 characters"><span class=sf-dump-ellipsis>Symfony\Component\VarDumper\Tests\Dumper</span>\HtmlDumperTest</span>"
|
||||
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
|
||||
<span class=sf-dump-meta>parameters</span>: {<samp>
|
||||
<span class=sf-dump-meta>\$a</span>: {}
|
||||
<span class=sf-dump-meta>&\$b</span>: {<samp>
|
Reference in New Issue
Block a user