diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index a92238fb591ac..3434a2430071b 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -11,12 +11,16 @@ namespace Symfony\Component\VarDumper\Cloner; +use Symfony\Component\VarDumper\Caster\Caster; + /** * @author Nicolas Grekas
*/ class Data { private $data; + private $position = 0; + private $key = 0; private $maxDepth = 20; private $maxItemsPerDepth = -1; private $useRefHandles = -1; @@ -82,13 +86,57 @@ public function withRefHandles($useRefHandles) return $data; } + /** + * Seeks to a specific key in nested data structures. + * + * @param string|int $key The key to seek to + * + * @return self|null A clone of $this of null if the key is not set + */ + public function seek($key) + { + $item = $this->data[$this->position][$this->key]; + + if (!$item instanceof Stub || !$item->position) { + return; + } + $keys = array($key); + + switch ($item->type) { + case Stub::TYPE_OBJECT: + $keys[] = Caster::PREFIX_DYNAMIC.$key; + $keys[] = Caster::PREFIX_PROTECTED.$key; + $keys[] = Caster::PREFIX_VIRTUAL.$key; + $keys[] = "\0$item->class\0$key"; + case Stub::TYPE_ARRAY: + case Stub::TYPE_RESOURCE: + break; + default: + return; + } + + $data = null; + $children = $this->data[$item->position]; + + foreach ($keys as $key) { + if (isset($children[$key]) || array_key_exists($key, $children)) { + $data = clone $this; + $data->key = $key; + $data->position = $item->position; + break; + } + } + + return $data; + } + /** * Dumps data with a DumperInterface dumper. */ public function dump(DumperInterface $dumper) { $refs = array(0); - $this->dumpItem($dumper, new Cursor(), $refs, $this->data[0][0]); + $this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]); } /** diff --git a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php index a6ec9eab8ee12..52b3010e9a56a 100644 --- a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php +++ b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php @@ -29,7 +29,7 @@ public function assertDumpMatchesFormat($dump, $data, $message = '') $this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message); } - protected function getDump($data) + protected function getDump($data, $key = null) { $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; @@ -39,7 +39,11 @@ protected function getDump($data) $cloner->setMaxItems(-1); $dumper = new CliDumper($h, null, $flags); $dumper->setColors(false); - $dumper->dump($cloner->cloneVar($data)->withRefHandles(false)); + $data = $cloner->cloneVar($data)->withRefHandles(false); + if (null !== $key && null === $data = $data->seek($key)) { + return; + } + $dumper->dump($data); $data = stream_get_contents($h, -1, 0); fclose($h); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 7eb3ee94def17..8d9cf1efbf708 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -59,6 +59,31 @@ public function testDefaultSettings() $this->assertDumpMatchesFormat($expectedDump, $e); } + public function testSeek() + { + $e = $this->getTestException(2); + + $expectedDump = <<<'EODUMP' +{ + %d. %sExceptionCasterTest.php:23: { + 22: { + 23: return new \Exception('foo'); + 24: } + } + %d. %sExceptionCasterTest.php:%d: { + %d: { + %d: $e = $this->getTestException(2); + %d: + args: { + 2 + } + } +%A +EODUMP; + + $this->assertStringMatchesFormat($expectedDump, $this->getDump($e, 'trace')); + } + public function testNoArgs() { $e = $this->getTestException(1); diff --git a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php index 1184f2c76a255..83accce2d9dd7 100644 --- a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php @@ -52,6 +52,8 @@ public function testMaxIntBoundary() ) + [position:Symfony\Component\VarDumper\Cloner\Data:private] => 0 + [key:Symfony\Component\VarDumper\Cloner\Data:private] => 0 [maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20 [maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1 [useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1 @@ -126,6 +128,8 @@ public function testClone() ) + [position:Symfony\Component\VarDumper\Cloner\Data:private] => 0 + [key:Symfony\Component\VarDumper\Cloner\Data:private] => 0 [maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20 [maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1 [useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1 @@ -143,7 +147,7 @@ public function testJsonCast() $clone = $cloner->cloneVar($data); $expected = <<<'EOTXT' -object(Symfony\Component\VarDumper\Cloner\Data)#%i (4) { +object(Symfony\Component\VarDumper\Cloner\Data)#%i (6) { ["data":"Symfony\Component\VarDumper\Cloner\Data":private]=> array(2) { [0]=> @@ -187,6 +191,10 @@ public function testJsonCast() } } } + ["position":"Symfony\Component\VarDumper\Cloner\Data":private]=> + int(0) + ["key":"Symfony\Component\VarDumper\Cloner\Data":private]=> + int(0) ["maxDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=> int(20) ["maxItemsPerDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=> @@ -242,6 +250,8 @@ public function testCaster() ) + [position:Symfony\Component\VarDumper\Cloner\Data:private] => 0 + [key:Symfony\Component\VarDumper\Cloner\Data:private] => 0 [maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20 [maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1 [useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1