Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d6534f5

Browse filesBrowse files
[VarDumper] Added setMinDepth to VarCloner
This new function allows VarCloner users to specify a minimum tree depth that must be fully explored before we start limiting the number of cloned items via the existing setMaxItems functionality. It’s useful for dumping arguments from a backtrace to ensure some minimum level of detail, while keeping a very low setMaxItems value to ensure fast performance.
1 parent de5c60d commit d6534f5
Copy full SHA for d6534f5

File tree

4 files changed

+290
-5
lines changed
Filter options

4 files changed

+290
-5
lines changed

‎src/Symfony/Component/VarDumper/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.4.0
5+
-----
6+
7+
* added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth
8+
49
2.7.0
510
-----
611

‎src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
+13-1Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ abstract class AbstractCloner implements ClonerInterface
129129

130130
protected $maxItems = 2500;
131131
protected $maxString = -1;
132+
protected $minDepth = 1;
132133
protected $useExt;
133134

134135
private $casters = array();
@@ -168,7 +169,7 @@ public function addCasters(array $casters)
168169
}
169170

170171
/**
171-
* Sets the maximum number of items to clone past the first level in nested structures.
172+
* Sets the maximum number of items to clone past the minimum depth in nested structures.
172173
*
173174
* @param int $maxItems
174175
*/
@@ -187,6 +188,17 @@ public function setMaxString($maxString)
187188
$this->maxString = (int) $maxString;
188189
}
189190

191+
/**
192+
* Sets the minimum tree depth where we are guaranteed to clone all the items. After this
193+
* depth is reached, only setMaxItems items will be cloned.
194+
*
195+
* @param int $minDepth
196+
*/
197+
public function setMinDepth($minDepth)
198+
{
199+
$this->minDepth = (int) $minDepth;
200+
}
201+
190202
/**
191203
* Clones a PHP variable.
192204
*

‎src/Symfony/Component/VarDumper/Cloner/VarCloner.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Cloner/VarCloner.php
+17-4Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected function doClone($var)
2626
{
2727
$useExt = $this->useExt;
2828
$len = 1; // Length of $queue
29-
$pos = 0; // Number of cloned items past the first level
29+
$pos = 0; // Number of cloned items past the minimum depth
3030
$refsCounter = 0; // Hard references counter
3131
$queue = array(array($var)); // This breadth-first queue is the return value
3232
$arrayRefs = array(); // Map of queue indexes to stub array objects
@@ -36,6 +36,10 @@ protected function doClone($var)
3636
$values = array(); // Map of stub objects' hashes to original values
3737
$maxItems = $this->maxItems;
3838
$maxString = $this->maxString;
39+
$minDepth = $this->minDepth;
40+
$currentDepth = 0; // Current tree depth
41+
$currentDepthFinalIndex = 0; // Final $queue index for current tree depth
42+
$minimumDepthReached = $minDepth === 0; // Becomes true when minimum tree depth has been reached
3943
$cookie = (object) array(); // Unique object used to detect hard references
4044
$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable
4145
$a = null; // Array cast for nested structures
@@ -57,6 +61,15 @@ protected function doClone($var)
5761
$hashOffset = self::$hashOffset;
5862

5963
for ($i = 0; $i < $len; ++$i) {
64+
// Detect when we move on to the next tree depth
65+
if ($i > $currentDepthFinalIndex) {
66+
++$currentDepth;
67+
$currentDepthFinalIndex = $len - 1;
68+
if ($currentDepth >= $minDepth) {
69+
$minimumDepthReached = true;
70+
}
71+
}
72+
6073
$indexed = true; // Whether the currently iterated array is numerically indexed or not
6174
$j = -1; // Position in the currently iterated array
6275
$fromObjCast = array_keys($queue[$i]);
@@ -166,7 +179,7 @@ protected function doClone($var)
166179
$stub->handle = $h;
167180
}
168181
$stub->value = null;
169-
if (0 <= $maxItems && $maxItems <= $pos) {
182+
if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
170183
$stub->cut = count($a);
171184
$a = null;
172185
}
@@ -193,7 +206,7 @@ protected function doClone($var)
193206
$stub->handle = $h;
194207
$a = $this->castResource($stub, 0 < $i);
195208
$stub->value = null;
196-
if (0 <= $maxItems && $maxItems <= $pos) {
209+
if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
197210
$stub->cut = count($a);
198211
$a = null;
199212
}
@@ -226,7 +239,7 @@ protected function doClone($var)
226239
}
227240

228241
if ($a) {
229-
if ($i && 0 <= $maxItems) {
242+
if ($minimumDepthReached && 0 <= $maxItems) {
230243
$k = count($a);
231244
if ($pos < $maxItems) {
232245
if ($maxItems < $pos += $k) {

‎src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php
+255Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,261 @@ public function testClone()
152152
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
153153
)
154154
155+
EOTXT;
156+
$this->assertStringMatchesFormat($expected, print_r($clone, true));
157+
}
158+
159+
public function testLimits()
160+
{
161+
// Level 0:
162+
$data = array(
163+
// Level 1:
164+
array(
165+
// Level 2:
166+
array(
167+
// Level 3:
168+
'Level 3 Item 0',
169+
'Level 3 Item 1',
170+
'Level 3 Item 2',
171+
'Level 3 Item 3',
172+
),
173+
array(
174+
'Level 3 Item 4',
175+
'Level 3 Item 5',
176+
'Level 3 Item 6',
177+
),
178+
array(
179+
'Level 3 Item 7',
180+
),
181+
),
182+
array(
183+
array(
184+
'Level 3 Item 8',
185+
),
186+
'Level 2 Item 0',
187+
),
188+
array(
189+
'Level 2 Item 1',
190+
),
191+
'Level 1 Item 0',
192+
array(
193+
// Test setMaxString:
194+
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
195+
'SHORT',
196+
),
197+
);
198+
199+
$cloner = new VarCloner();
200+
$cloner->setMinDepth(2);
201+
$cloner->setMaxItems(5);
202+
$cloner->setMaxString(20);
203+
$clone = $cloner->cloneVar($data);
204+
205+
$expected = <<<EOTXT
206+
Symfony\Component\VarDumper\Cloner\Data Object
207+
(
208+
[data:Symfony\Component\VarDumper\Cloner\Data:private] => Array
209+
(
210+
[0] => Array
211+
(
212+
[0] => Symfony\Component\VarDumper\Cloner\Stub Object
213+
(
214+
[type] => array
215+
[class] => indexed
216+
[value] => 5
217+
[cut] => 0
218+
[handle] => 0
219+
[refCount] => 0
220+
[position] => 1
221+
[attr] => Array
222+
(
223+
)
224+
225+
)
226+
227+
)
228+
229+
[1] => Array
230+
(
231+
[0] => Symfony\Component\VarDumper\Cloner\Stub Object
232+
(
233+
[type] => array
234+
[class] => indexed
235+
[value] => 3
236+
[cut] => 0
237+
[handle] => 0
238+
[refCount] => 0
239+
[position] => 2
240+
[attr] => Array
241+
(
242+
)
243+
244+
)
245+
246+
[1] => Symfony\Component\VarDumper\Cloner\Stub Object
247+
(
248+
[type] => array
249+
[class] => indexed
250+
[value] => 2
251+
[cut] => 0
252+
[handle] => 0
253+
[refCount] => 0
254+
[position] => 3
255+
[attr] => Array
256+
(
257+
)
258+
259+
)
260+
261+
[2] => Symfony\Component\VarDumper\Cloner\Stub Object
262+
(
263+
[type] => array
264+
[class] => indexed
265+
[value] => 1
266+
[cut] => 0
267+
[handle] => 0
268+
[refCount] => 0
269+
[position] => 4
270+
[attr] => Array
271+
(
272+
)
273+
274+
)
275+
276+
[3] => Level 1 Item 0
277+
[4] => Symfony\Component\VarDumper\Cloner\Stub Object
278+
(
279+
[type] => array
280+
[class] => indexed
281+
[value] => 2
282+
[cut] => 0
283+
[handle] => 0
284+
[refCount] => 0
285+
[position] => 5
286+
[attr] => Array
287+
(
288+
)
289+
290+
)
291+
292+
)
293+
294+
[2] => Array
295+
(
296+
[0] => Symfony\Component\VarDumper\Cloner\Stub Object
297+
(
298+
[type] => array
299+
[class] => indexed
300+
[value] => 4
301+
[cut] => 0
302+
[handle] => 0
303+
[refCount] => 0
304+
[position] => 6
305+
[attr] => Array
306+
(
307+
)
308+
309+
)
310+
311+
[1] => Symfony\Component\VarDumper\Cloner\Stub Object
312+
(
313+
[type] => array
314+
[class] => indexed
315+
[value] => 3
316+
[cut] => 2
317+
[handle] => 0
318+
[refCount] => 0
319+
[position] => 7
320+
[attr] => Array
321+
(
322+
)
323+
324+
)
325+
326+
[2] => Symfony\Component\VarDumper\Cloner\Stub Object
327+
(
328+
[type] => array
329+
[class] => assoc
330+
[value] => 1
331+
[cut] => 1
332+
[handle] => 0
333+
[refCount] => 0
334+
[position] => 0
335+
[attr] => Array
336+
(
337+
)
338+
339+
)
340+
341+
)
342+
343+
[3] => Array
344+
(
345+
[0] => Symfony\Component\VarDumper\Cloner\Stub Object
346+
(
347+
[type] => array
348+
[class] => assoc
349+
[value] => 1
350+
[cut] => 1
351+
[handle] => 0
352+
[refCount] => 0
353+
[position] => 0
354+
[attr] => Array
355+
(
356+
)
357+
358+
)
359+
360+
[1] => Level 2 Item 0
361+
)
362+
363+
[4] => Array
364+
(
365+
[0] => Level 2 Item 1
366+
)
367+
368+
[5] => Array
369+
(
370+
[0] => Symfony\Component\VarDumper\Cloner\Stub Object
371+
(
372+
[type] => string
373+
[class] => utf8
374+
[value] => ABCDEFGHIJKLMNOPQRST
375+
[cut] => 6
376+
[handle] => 0
377+
[refCount] => 0
378+
[position] => 0
379+
[attr] => Array
380+
(
381+
)
382+
383+
)
384+
385+
[1] => SHORT
386+
)
387+
388+
[6] => Array
389+
(
390+
[0] => Level 3 Item 0
391+
[1] => Level 3 Item 1
392+
[2] => Level 3 Item 2
393+
[3] => Level 3 Item 3
394+
)
395+
396+
[7] => Array
397+
(
398+
[0] => Level 3 Item 4
399+
)
400+
401+
)
402+
403+
[position:Symfony\Component\VarDumper\Cloner\Data:private] => 0
404+
[key:Symfony\Component\VarDumper\Cloner\Data:private] => 0
405+
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
406+
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
407+
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
408+
)
409+
155410
EOTXT;
156411
$this->assertStringMatchesFormat($expected, print_r($clone, true));
157412
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.