8000 [VarDumper] interface for dumping collected variables · symfony/symfony@1d5e3f4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1d5e3f4

Browse files
[VarDumper] interface for dumping collected variables
1 parent 0266072 commit 1d5e3f4

File tree

4 files changed

+331
-0
lines changed

4 files changed

+331
-0
lines changed

src/Symfony/Component/VarDumper/Cloner/Data.php

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Component\VarDumper\Cloner;
1313

14+
use Symfony\Component\VarDumper\Dumper\DumperInternalsInterface;
15+
use Symfony\Component\VarDumper\Dumper\Cursor;
16+
1417
/**
1518
* @author Nicolas Grekas <p@tchwork.com>
1619
*/
@@ -30,4 +33,169 @@ public function getRawData()
3033
{
3134
return $this->data;
3235
}
36+
37+
/**
38+
* Dumps data with a DumperInternalsInterface dumper.
39+
*/
40+
public function dump(DumperInternalsInterface $dumper)
41+
{
42+
$refs = array(0);
43+
$this->dumpItem($dumper, new Cursor, $refs, $this->data[0][0]);
44+
}
45+
46+
/**
47+
* Breadth-first dumping of items.
48+
*
49+
* @param DumperInternalsInterface $dumper The dumper being used for dumping.
50+
* @param Cursor $cursor A cursor used for tracking dumper state position.
51+
* @param array &$refs A map of all references discovered while dumping.
52+
* @param mixed $item A stub stdClass or the original value being dumped.
53+
*/
54+
private function dumpItem($dumper, $cursor, &$refs, $item)
55+
{
56+
$cursor->refIndex = $cursor->refTo = $cursor->refIsHard = false;
57+
58+
if ($item instanceof \stdClass) {
59+
if (property_exists($item, 'val')) {
60+
if (isset($item->ref)) {
61+
if (isset($refs[$r = $item->ref])) {
62+
$cursor->refTo = $refs[$r];
63+
$cursor->refIsHard = true;
64+
} else {
65+
$cursor->refIndex = $refs[$r] = ++$refs[0];
66+
}
67+
}
68+
$item = $item->val;
69+
}
70+
if (isset($item->ref)) {
71+
if (isset($refs[$r = $item->ref])) {
72+
if (false === $cursor->refTo) {
73+
$cursor->refTo = $refs[$r];
74+
$cursor->refIsHard = isset($item->count);
75+
}
76+
} elseif (false !== $cursor->refIndex) {
77+
$refs[$r] = $cursor->refIndex;
78+
} else {
79+
$cursor->refIndex = $refs[$r] = ++$refs[0];
80+
}
81+
}
82+
$cut = isset($item->cut) ? $item->cut : 0;
83+
84+
if (isset($item->pos) && false === $cursor->refTo) {
85+
$children = $this->data[$item->pos];
86+
87+
if ($cursor->stop) {
88+
if ($cut >= 0) {
89+
$cut += count($children);
90+
}
91+
$children = array();
92+
}
93+
} else {
94+
$children = array();
95+
}
96+
switch (true) {
97+
case isset($item->bin):
98+
$dumper->dumpString($cursor, $item->bin, true, $cut);
99+
100+
return;
101+
102+
case isset($item->str):
103+
$dumper->dumpString($cursor, $item->str, false, $cut);
104+
105+
return;
106+
107+
case isset($item->count):
108+
$dumper->enterArray($cursor, $item->count, !empty($item->indexed), (bool) $children);
109+
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, empty($item->indexed) ? $cursor::HASH_ASSOC : $cursor::HASH_INDEXED);
110+
$dumper->leaveArray($cursor, $item->count, !empty($item->indexed), (bool) $children, $cut);
111+
112+
return;
113+
114+
case isset($item->class):
115+
$dumper->enterObject($cursor, $item->class, (bool) $children);
116+
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_OBJECT);
117+
$dumper->leaveObject($cursor, $item->class, (bool) $children, $cut);
118+
119+
return;
120+
121+
case isset($item->res):
122+
$dumper->enterResource($cursor, $item->res, (bool) $children);
123+
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_RESOURCE);
124+
$dumper->leaveResource($cursor, $item->res, (bool) $children, $cut);
125+
126+
return;
127+
}
128+
}
129+
130+
if ('array' === $type = gettype($item)) {
131+
$dumper->enterArray($cursor, 0, true, 0, 0);
132+
$dumper->leaveArray($cursor, 0, true, 0, 0);
133+
} else {
134+
$dumper->dumpScalar($cursor, $type, $item);
135+
}
136+
}
137+
138+
/**
139+
* Dumps children of hash structures.
140+
*
141+
* @param DumperInternalsInterface $dumper
142+
* @param Cursor $parentCursor The cursor of the parent hash.
143+
* @param array &$refs A map of all references discovered while dumping.
144+
* @param array $children The children to dump.
145+
* @param int $hashCut The number of items removed from the original hash.
146+
* @param int $hashType A Cursor::HASH_* const.
147+
*
148+
* @return int The final number of removed items.
149+
*/
150+
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType)
151+
{
152+
if ($children) {
153+
$cursor = clone $parentCursor;
154+
++$cursor->depth;
155+
$cursor->hashType = $hashType;
156+
$cursor->hashIndex = 0;
157+
$cursor->hashLength = count($children);
158+
$cursor->hashCut = $hashCut;
159+
foreach ($children as $cursor->hashKey => $child) {
160+
$this->dumpItem($dumper, $cursor, $refs, $child);
161+
++$cursor->hashIndex;
162+
if ($cursor->stop) {
163+
$parentCursor->stop = true;
164+
165+
return $hashCut >= 0 ? $hashCut + $children - $cursor->hashIndex : $hashCut;
166+
}
167+
}
168+
}
169+
170+
return $hashCut;
171+
}
172+
173+
/**
174+
* Portable variant of utf8_encode()
175+
*
176+
* @param string $s
177+
*
178+
* @return string
179+
*
180+
* @internal
181+
*/
182+
public static function utf8Encode($s)
183+
{
184+
if (function_exists('iconv')) {
185+
return iconv('CP1252', 'UTF-8', $s);
186+
} else {
187+
$s .= $s;
188+
$len = strlen($s);
189+
190+
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
191+
switch (true) {
192+
case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
193+
case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
194+
default: $s[$j] = "\xC3"; $s[++$j] = chr(ord($s[$i]) - 64); break;
195+
}
196+
}
197+
198+
return substr($s, 0, $j);
199+
}
200+
}
33201
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Dumper;
13+
14+
/**
15+
* Represents the current state of a dumper while dumping.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class Cursor
20+
{
21+
const HASH_INDEXED = 'indexed-array';
22+
const HASH_ASSOC = 'associative-array';
23+
const HASH_OBJECT = 'object';
24+
const HASH_RESOURCE = 'resource';
25+
26+
public $depth = 0;
27+
public $refIndex = false;
28+
public $refTo = false;
29+
public $refIsHard = false;
30+
public $hashType;
31+
public $hashKey;
32+
public $hashIndex = 0;
33+
public $hashLength = 0;
34+
public $hashCut = 0;
35+
public $stop = false;
36+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Dumper;
13+
14+
use Symfony\Component\VarDumper\Cloner\Data;
15+
16+
/**
17+
* DataDumperInterface for dumping Data objects.
18+
*
19+
* @author Nicolas Grekas <p@tchwork.com>
20+
*/
21+
interface DataDumperInterface
22+
{
23+
/**
24+
* Dumps a Data object.
25+
*
26+
* @param Data $data A Data object.
27+
*/
28+
public function dump(Data $data);
29+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Dumper;
13+
14+
/**
15+
* DumperInterface used by Data objects.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
interface DumperInternalsInterface
20+
{
21+
/**
22+
* Dumps a scalar value.
23+
*
24+
* @param Cursor $cursor The Cursor position in the dump.
25+
* @param string $type The PHP type of the value being dumped.
26+
* @param scalar $value The scalar value being dumped.
27+
*/
28+
public function dumpScalar(Cursor $cursor, $type, $value);
29+
30+
/**
31+
* Dumps a string.
32+
*
33+
* @param Cursor $cursor The Cursor position in the dump.
34+
* @param string $str The string being dumped.
35+
* @param bool $bin Whether $str is UTF-8 or binary encoded.
36+
* @param int $cut The number of characters $str has been cut by.
37+
*/
38+
public function dumpString(Cursor $cursor, $str, $bin, $cut);
39+
40+
/**
41+
* Dumps while entering an array.
42+
*
43+
* @param Cursor $cursor The Cursor position in the dump.
44+
* @param int $count The number of items in the original array.
45+
* @param bool $indexed When the array is indexed or associative.
46+
* @param bool $hasChild When the dump of the array has child item.
47+
*/
48+
public function enterArray(Cursor $cursor, $count, $indexed, $hasChild);
49+
50+
/**
51+
* Dumps while leaving an array.
52+
*
53+
* @param Cursor $cursor The Cursor position in the dump.
54+
* @param int $count The number of items in the original array.
55+
* @param bool $indexed Whether the array is indexed or associative.
56+
* @param bool $hasChild When the dump of the array has child item.
57+
* @param int $cut The number of items the array has been cut by.
58+
*/
59+
public function leaveArray(Cursor $cursor, $count, $indexed, $hasChild, $cut);
60+
61+
/**
62+
* Dumps while entering an object.
63+
*
64+
* @param Cursor $cursor The Cursor position in the dump.
65+
* @param string $class The class of the object.
66+
* @param bool $hasChild When the dump of the object has child item.
67+
*/
68+
public function enterObject(Cursor $cursor, $class, $hasChild);
69+
70+
/**
71+
* Dumps while leaving an object.
72+
*
73+
* @param Cursor $cursor The Cursor position in the dump.
74+
* @param string $class The class of the object.
75+
* @param bool $hasChild When the dump of the object has child item.
76+
* @param int $cut The number of items the object has been cut by.
77+
*/
78+
public function leaveObject(Cursor $cursor, $class, $hasChild, $cut);
79+
80+
/**
81+
* Dumps while entering a resource.
82+
*
83+
* @param Cursor $cursor The Cursor position in the dump.
84+
* @param string $res The resource type.
85+
* @param bool $hasChild When the dump of the resource has child item.
86+
*/
87+
public function enterResource(Cursor $cursor, $res, $hasChild);
88+
89+
/**
90+
* Dumps while leaving a resource.
91+
*
92+
* @param Cursor $cursor The Cursor position in the dump.
93+
* @param string $res The resource type.
94+
* @param bool $hasChild When the dump of the resource has child item.
95+
* @param int $cut The number of items the resource has been cut by.
96+
*/
97+
public function leaveResource(Cursor $cursor, $res, $hasChild, $cut);
98+
}

0 commit comments

Comments
 (0)
0