Skip to content

Commit 67d4ea8

Browse files
authored
Merge pull request #644 from cosmocode/nestedlists
Nested Lists
2 parents 7d0142f + 4c31bcd commit 67d4ea8

34 files changed

+1744
-680
lines changed

_test/AggregationFilterTest.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace dokuwiki\plugin\struct\test;
4+
5+
6+
class AggregationFilterTest extends StructTest
7+
{
8+
protected $items = [
9+
[['green', 'yellow'], 'car', 'audi', 'a80'],
10+
[[], 'car', 'audi', 'a4'],
11+
[['red', 'black'], 'car', 'bmw', 'i3'],
12+
[['green', 'blue'], 'laptop', 'apple', 'pro 16'],
13+
[['blue', 'gray'], 'car', 'bmw', 'mini'],
14+
[['red', 'black'], 'car', 'bmw', 'z1'],
15+
[['red', 'blue'], 'laptop', 'apple', 'air'],
16+
[['black', 'red'], 'laptop', 'apple', 'm1'],
17+
[[], 'laptop', 'dell', 'xps'],
18+
[['black', 'green'], '', 'audi', 'quattro'],
19+
[['blue', 'yellow'], '', 'dell', 'inspiron'],
20+
[['gray', 'yellow'], 'laptop', 'dell', 'latitude'],
21+
];
22+
23+
public function testGetAllColumnValues()
24+
{
25+
$result = $this->createAggregationResult($this->items);
26+
$filter = new mock\AggregationFilter();
27+
$values = $filter->getAllColumnValues($result);
28+
29+
$this->assertCount(4, $values);
30+
31+
// we expect value => displayValue pairs, sorted by displayValue
32+
$this->assertSame(
33+
[
34+
'black' => 'black',
35+
'blue' => 'blue',
36+
'gray' => 'gray',
37+
'green' => 'green',
38+
'red' => 'red',
39+
'yellow' => 'yellow'
40+
],
41+
$values[0]['values']
42+
);
43+
44+
$this->assertEquals(
45+
'Label 1',
46+
$values[0]['label']
47+
);
48+
49+
$this->assertSame(
50+
[
51+
'car' => 'car',
52+
'laptop' => 'laptop'
53+
],
54+
$values[1]['values']
55+
);
56+
57+
$this->assertEquals(
58+
'Label 2',
59+
$values[1]['label']
60+
);
61+
}
62+
}

_test/ConfigParserTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public function test_simple()
2121
"cols : %pageid%, count",
2222
"sort : ^count",
2323
"sort : %pageid%, ^bam",
24-
"align : r,l,center,foo"
24+
"align : r,l,center,foo",
25+
"class : foo, bar",
2526
];
2627

2728
$configParser = new meta\ConfigParser($lines);
@@ -82,7 +83,10 @@ public function test_simple()
8283
],
8384
'csv' => true,
8485
'target' => '',
85-
'align' => ['right', 'left', 'center', null]
86+
'align' => ['right', 'left', 'center', null],
87+
'nesting' => 0,
88+
'index' => 0,
89+
'classes' => ['struct-custom-foo', 'struct-custom-bar'],
8690
];
8791

8892
$this->assertEquals($expected_config, $actual_config);

_test/InlineConfigParserTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ public function test_simple()
5151
'summarize' => false,
5252
'target' => '',
5353
'widths' => [],
54+
'nesting' => 0,
55+
'index' => 0,
56+
'classes' => [],
5457
];
5558

5659
$this->assertEquals($expected_config, $actual_config);

_test/NestedResultTest.php

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
<?php
2+
3+
namespace dokuwiki\plugin\struct\test;
4+
5+
use dokuwiki\plugin\struct\meta\Column;
6+
use dokuwiki\plugin\struct\meta\NestedResult;
7+
use dokuwiki\plugin\struct\meta\Value;
8+
use dokuwiki\plugin\struct\types\Text;
9+
10+
/**
11+
* Tests for the NestedResult class
12+
*
13+
* @group plugin_struct
14+
* @group plugins
15+
*
16+
*/
17+
class NestedResultTest extends StructTest
18+
{
19+
protected $simpleItems = [
20+
['car', 'audi', 'a80'],
21+
['car', 'audi', 'a4'],
22+
['car', 'audi', 'quattro'],
23+
['car', 'bmw', 'i3'],
24+
['car', 'bmw', 'mini'],
25+
['car', 'bmw', 'z1'],
26+
['laptop', 'apple', 'pro 16'],
27+
['laptop', 'apple', 'air'],
28+
['laptop', 'apple', 'm1'],
29+
['laptop', 'dell', 'inspiron'],
30+
['laptop', 'dell', 'latitude'],
31+
['laptop', 'bmw', 'latitude'],
32+
];
33+
34+
protected $multiItems = [
35+
[['green', 'yellow'], 'car', 'audi', 'a80'],
36+
[['yellow', 'blue'], 'car', 'audi', 'a4'],
37+
[['black', 'green'], 'car', 'audi', 'quattro'],
38+
[['red', 'black'], 'car', 'bmw', 'i3'],
39+
[['blue', 'gray'], 'car', 'bmw', 'mini'],
40+
[['red', 'black'], 'car', 'bmw', 'z1'],
41+
[['green', 'blue'], 'laptop', 'apple', 'pro 16'],
42+
[['red', 'blue'], 'laptop', 'apple', 'air'],
43+
[['black', 'red'], 'laptop', 'apple', 'm1'],
44+
[['gray', 'green'], 'laptop', 'dell', 'xps'],
45+
[['blue', 'yellow'], 'laptop', 'dell', 'inspiron'],
46+
[['gray', 'yellow'], 'laptop', 'dell', 'latitude'],
47+
];
48+
49+
protected $multiHoleItems = [
50+
[['green', 'yellow'], 'car', 'audi', 'a80'],
51+
[[], 'car', 'audi', 'a4'],
52+
[['black', 'green'], '', 'audi', 'quattro'],
53+
[['red', 'black'], 'car', 'bmw', 'i3'],
54+
[['blue', 'gray'], 'car', 'bmw', 'mini'],
55+
[['red', 'black'], 'car', 'bmw', 'z1'],
56+
[['green', 'blue'], 'laptop', 'apple', 'pro 16'],
57+
[['red', 'blue'], 'laptop', 'apple', 'air'],
58+
[['black', 'red'], 'laptop', 'apple', 'm1'],
59+
[[], 'laptop', 'dell', 'xps'],
60+
[['blue', 'yellow'], '', 'dell', 'inspiron'],
61+
[['gray', 'yellow'], 'laptop', 'dell', 'latitude'],
62+
];
63+
64+
protected $multiMultiItems = [
65+
[['metal', 'wood'], ['green', 'yellow'], 'car', 'audi', 'a80'],
66+
[['metal', 'wood', 'plastic'], ['yellow', 'blue'], 'car', 'audi', 'a4'],
67+
[['plastic', 'metal'], ['red', 'blue'], 'laptop', 'apple', 'pro 16'],
68+
[['metal', 'plastic'], ['black', 'red'], 'laptop', 'apple', 'air'],
69+
];
70+
71+
/**
72+
* Don't nest at all
73+
*/
74+
public function testSimpleZeroLevel()
75+
{
76+
$result = $this->createAggregationResult($this->simpleItems);
77+
$nestedResult = new NestedResult($result);
78+
$root = $nestedResult->getRoot(0);
79+
80+
$this->assertCount(0, $root->getChildren(true), 'no children expected');
81+
$this->assertCount(12, $root->getResultRows(), '12 result rows expected');
82+
}
83+
84+
/**
85+
* Nest by the first level, no multi values
86+
*/
87+
public function testSimpleOneLevel()
88+
{
89+
$result = $this->createAggregationResult($this->simpleItems);
90+
$nestedResult = new NestedResult($result);
91+
$root = $nestedResult->getRoot(1);
92+
$tree = $root->getChildren(true);
93+
94+
$this->assertCount(2, $tree, '2 root nodes expected');
95+
$this->assertEquals('car', $tree[0]->getValueObject()->getValue());
96+
$this->assertEquals('laptop', $tree[1]->getValueObject()->getValue());
97+
98+
$this->assertCount(0, $tree[0]->getChildren(true), 'no children expected');
99+
$this->assertCount(0, $tree[1]->getChildren(true), 'no children expected');
100+
101+
$this->assertCount(6, $tree[0]->getResultRows(), 'result rows');
102+
$this->assertCount(6, $tree[1]->getResultRows(), 'result rows');
103+
104+
$this->assertEquals('a80', $tree[0]->getResultRows()[0][1]->getValue(), 'Audi 80 expected');
105+
$this->assertEquals('pro 16', $tree[1]->getResultRows()[0][1]->getValue(), 'Mac Pro 16 expected');
106+
}
107+
108+
109+
/**
110+
* Nest by two levels, no multi values
111+
*/
112+
public function testSimpleTwoLevels()
113+
{
114+
$result = $this->createAggregationResult($this->simpleItems);
115+
$nestedResult = new NestedResult($result);
116+
$root = $nestedResult->getRoot(2);
117+
$tree = $root->getChildren(true);
118+
119+
$this->assertCount(2, $tree, '2 root nodes expected');
120+
$this->assertEquals('car', $tree[0]->getValueObject()->getValue());
121+
$this->assertEquals('laptop', $tree[1]->getValueObject()->getValue());
122+
123+
$this->assertCount(2, $tree[0]->getChildren(true), '2 car brands expected');
124+
$this->assertCount(3, $tree[1]->getChildren(true), '3 laptop brands expected');
125+
126+
$this->assertCount(3, $tree[0]->getChildren(true)[0]->getResultRows(), '3 audis expected');
127+
$this->assertCount(3, $tree[0]->getChildren(true)[1]->getResultRows(), '3 bmw expected');
128+
$this->assertCount(3, $tree[1]->getChildren(true)[0]->getResultRows(), '3 apple expected');
129+
$this->assertCount(1, $tree[1]->getChildren(true)[1]->getResultRows(), '1 bmw expected');
130+
$this->assertCount(2, $tree[1]->getChildren(true)[2]->getResultRows(), '2 dell expected');
131+
132+
133+
$this->assertEquals('a80', $tree[0]->getChildren(true)[0]->getResultRows()[0][0]->getValue(), 'Audi 80 expected');
134+
$this->assertEquals('pro 16', $tree[1]->getChildren(true)[0]->getResultRows()[0][0]->getValue(), 'Mac Pro 16 expected');
135+
}
136+
137+
/**
138+
* Nest by three levels, the first one being multi-value
139+
*/
140+
public function testMultiThreeLevels()
141+
{
142+
$result = $this->createAggregationResult($this->multiItems);
143+
$nestedResult = new NestedResult($result);
144+
$root = $nestedResult->getRoot(3);
145+
$tree = $root->getChildren(true); // nest: color, type, brand -> model
146+
147+
$this->assertCount(6, $tree, '6 root nodes of colors expected');
148+
149+
// Values on the first level will be multi-values, thus returning arrays
150+
$this->assertEquals('black', $tree[0]->getValueObject()->getValue()[0]);
151+
$this->assertEquals('blue', $tree[1]->getValueObject()->getValue()[0]);
152+
$this->assertEquals('gray', $tree[2]->getValueObject()->getValue()[0]);
153+
$this->assertEquals('green', $tree[3]->getValueObject()->getValue()[0]);
154+
$this->assertEquals('red', $tree[4]->getValueObject()->getValue()[0]);
155+
$this->assertEquals('yellow', $tree[5]->getValueObject()->getValue()[0]);
156+
157+
// Results should now show up under multiple top-level nodes
158+
$this->assertEquals('a80',
159+
$tree[3] // green
160+
->getChildren(true)[0] // car
161+
->getChildren(true)[0] // audi
162+
->getResultRows()[0][0] // a80
163+
->getValue(),
164+
'green car audi a80 expected'
165+
);
166+
$this->assertEquals('a80',
167+
$tree[5] // yellow
168+
->getChildren(true)[0] // car
169+
->getChildren(true)[0] // audi
170+
->getResultRows()[0][0] // a80
171+
->getValue(),
172+
'yellow car audi a80 expected'
173+
);
174+
}
175+
176+
public function testMultiHoles()
177+
{
178+
$result = $this->createAggregationResult($this->multiHoleItems);
179+
$nestedResult = new NestedResult($result);
180+
$root = $nestedResult->getRoot(3);
181+
$tree = $root->getChildren(true); // nest: color, type, brand -> model
182+
$this->assertCount(7, $tree, '6 root nodes of colors + 1 n/a expected'); // should have one n/a node
183+
$this->assertCount(2, $tree[6]->getChildren(true), 'top n/a node should have car, laptop');
184+
$this->assertCount(3, $tree[0]->getChildren(true), 'black should have car,laptop,n/a');
185+
}
186+
187+
/**
188+
* Nest by two multi value levels
189+
*/
190+
public function testMultiMultiTwoLevels()
191+
{
192+
$result = $this->createAggregationResult($this->multiMultiItems);
193+
$nestedResult = new NestedResult($result);
194+
$root = $nestedResult->getRoot(2);
195+
$tree = $root->getChildren(true); // nest: material, color, *
196+
197+
$this->assertCount(3, $tree, '3 root nodes of material expected');
198+
$this->assertCount(1, $tree[0]->getChildren(true)[0]->getResultRows(), '1 metal black row expected');
199+
}
200+
201+
/**
202+
* Nest by two multi value levels with indexing
203+
*/
204+
public function testMultiMultiTwoLevelsIndex()
205+
{
206+
$result = $this->createAggregationResult($this->multiMultiItems);
207+
$nestedResult = new NestedResult($result);
208+
$root = $nestedResult->getRoot(2, 1);
209+
$tree = $root->getChildren(true); // nest: index, material, color, *
210+
211+
$this->assertCount(3, $tree, '3 root index nodes expected');
212+
$this->assertEquals('M', $tree[0]->getValueObject()->getValue(), 'M expected');
213+
$this->assertCount(1, $tree[0]->getChildren(true), '1 metal sub node under M expected');
214+
}
215+
216+
/**
217+
* Index a flat result with no multi values
218+
*/
219+
public function testSimpleIndex()
220+
{
221+
$result = $this->createAggregationResult($this->simpleItems);
222+
$nestedResult = new NestedResult($result);
223+
$root = $nestedResult->getRoot(0, 2);
224+
$tree = $root->getChildren(true);
225+
226+
$this->assertCount(2, $tree, '2 root index nodes expected');
227+
$this->assertEquals('CA', $tree[0]->getValueObject()->getValue(), 'CA(r) index expected');
228+
$this->assertEquals('LA', $tree[1]->getValueObject()->getValue(), 'LA(ptop) index expected');
229+
230+
$this->assertCount(6, $tree[0]->getResultRows(), '6 rows under CA expected');
231+
}
232+
233+
234+
/**
235+
* Index a flat result with multi values
236+
*/
237+
public function testMultiIndex()
238+
{
239+
$result = $this->createAggregationResult($this->multiItems);
240+
$nestedResult = new NestedResult($result);
241+
$root = $nestedResult->getRoot(0, 2);
242+
$tree = $root->getChildren(true);
243+
244+
$this->assertCount(4, $tree, '4 root index nodes expected');
245+
$this->assertEquals('BL', $tree[0]->getValueObject()->getValue(), 'BL(ack|blue) index expected');
246+
247+
$this->assertCount(4, $tree[0]->getResultRows(), '4 rows under BL expected');
248+
}
249+
}

0 commit comments

Comments
 (0)