Skip to content

Commit 51b934e

Browse files
committed
Don't loop infinitely with cyclic references.
Object chains can easily contain cycles, printing those values to HTML should not recurse infinitely. Refs #135
1 parent ec97965 commit 51b934e

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

Test/Case/View/Helper/HtmlToolbarHelperTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,37 @@ public function testMakeNeatArrayBasic() {
126126
$this->assertTags($result, $expected);
127127
}
128128

129+
/**
130+
* Test that cyclic references can be printed.
131+
*
132+
* @return void
133+
*/
134+
public function testMakeNeatArrayCyclicObjects() {
135+
$a = new StdClass;
136+
$b = new StdClass;
137+
$a->child = $b;
138+
$b->parent = $a;
139+
140+
$in = array('obj' => $a);
141+
$result = $this->Toolbar->makeNeatArray($in);
142+
$expected = array(
143+
array('ul' => array('class' => 'neat-array depth-0')),
144+
'<li', '<strong', 'obj', '/strong', '(object)',
145+
array('ul' => array('class' => 'neat-array depth-1')),
146+
'<li', '<strong', 'child', '/strong', '(object)',
147+
array('ul' => array('class' => 'neat-array depth-2')),
148+
'<li', '<strong', 'parent', '/strong',
149+
'(object) - recursion',
150+
'/li',
151+
'/ul',
152+
'/li',
153+
'/ul',
154+
'/li',
155+
'/ul'
156+
);
157+
$this->assertTags($result, $expected);
158+
}
159+
129160
/**
130161
* Test Neat Array formatting
131162
*

View/Helper/HtmlToolbarHelper.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class HtmlToolbarHelper extends ToolbarHelper {
5050
* @return string
5151
*/
5252
public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubleEncode = false) {
53+
static $printedObjects = null;
54+
if ($currentDepth === 0) {
55+
$printedObjects = new SplObjectStorage();
56+
}
5357
$className = "neat-array depth-$currentDepth";
5458
if ($openDepth > $currentDepth) {
5559
$className .= ' expanded';
@@ -90,12 +94,22 @@ public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubl
9094
$value = 'function';
9195
}
9296

97+
$isObject = is_object($value);
98+
if ($isObject && $printedObjects->contains($value)) {
99+
$isObject = false;
100+
$value = ' - recursion';
101+
}
102+
103+
if ($isObject) {
104+
$printedObjects->attach($value);
105+
}
106+
93107
if (
94108
(
95109
$value instanceof ArrayAccess ||
96110
$value instanceof Iterator ||
97111
is_array($value) ||
98-
is_object($value)
112+
$isObject
99113
) && !empty($value)
100114
) {
101115
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth, $doubleEncode);

0 commit comments

Comments
 (0)