Skip to content

Commit 45da421

Browse files
committed
First pre-release ready.
1 parent b8645db commit 45da421

File tree

5 files changed

+197
-95
lines changed

5 files changed

+197
-95
lines changed

README.md

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,25 @@ composer require smoren/tree-tools
2121
| [`traverseDepthFirst`](#Traverse-Depth-First) | Iterates a tree using depth-first search | `TreeWalker::traverseDepthFirst($data, $childrenContainerKey)` |
2222
| [`traverseBreadthFirst`](#Traverse-Breadth-First) | Iterates a tree using breadth-first search | `TreeWalker::traverseBreadthFirst($data, $childrenContainerKey)` |
2323

24+
#### Tree Builder
25+
| Reducer | Description | Code Snippet |
26+
|-------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------|
27+
| [`build`](#Build) | Builds a tree from given flat collection | `TreeBuilder::build($collection, $idField, $parentIdField, $childrenContainerField, $itemContainerField)` |
28+
2429
## Usage
2530

2631
### Tree Walker
2732

28-
#### Traverse-Depth-First
33+
#### Traverse Depth First
2934

3035
Iterates a tree like a flat collection using depth-first traversal.
3136

37+
```TreeWalker::traverseDepthFirst(iterable $data, ?string $childrenContainerKey = null): Generator```
38+
3239
If `$childrenContainerKey` is not null looks for children items using by this key only.
3340

3441
Otherwise, considers any subarray to contain children.
3542

36-
```TreeWalker::traverseDepthFirst(iterable $data, ?string $childrenContainerKey = null): Generator```
37-
3843
```php
3944
use Smoren\TreeTools\TreeWalker;
4045

@@ -70,16 +75,16 @@ var_dump($result);
7075
// [1, 11, 12, 121, 122, 2, 21, 3]
7176
```
7277

73-
#### Traverse-Breadth-First
78+
#### Traverse Breadth First
7479

7580
Iterates a tree like a flat collection using depth-breadth traversal.
7681

82+
```TreeWalker::traverseBreadthFirst(iterable $data, ?string $childrenContainerKey = null): Generator```
83+
7784
If `$childrenContainerKey` is not null looks for children items using by this key only.
7885

7986
Otherwise, considers any subarray to contain children.
8087

81-
```TreeWalker::traverseBreadthFirst(iterable $data, ?string $childrenContainerKey = null): Generator```
82-
8388
```php
8489
use Smoren\TreeTools\TreeWalker;
8590

@@ -115,6 +120,96 @@ var_dump($result);
115120
// [1, 2, 3, 11, 12, 21, 121, 122]
116121
```
117122

123+
### Tree Builder
124+
125+
#### Build
126+
127+
Builds a tree from given flat collection of items with relations.
128+
129+
```
130+
TreeBuilder::build(
131+
iterable $collection,
132+
string $idField = 'id',
133+
string $parentIdField = 'parent_id',
134+
string $childrenContainerField = 'children',
135+
string $itemContainerField = 'item'
136+
): array
137+
```
138+
139+
```php
140+
use Smoren\TreeTools\TreeBuilder;
141+
142+
$input = [
143+
['id' => 1, 'name' => 'Item 1', 'parent_id' => null],
144+
['id' => 2, 'name' => 'Item 1.1', 'parent_id' => 1],
145+
['id' => 3, 'name' => 'Item 1.2', 'parent_id' => 1],
146+
['id' => 4, 'name' => 'Item 1.1.1', 'parent_id' => 2],
147+
['id' => 5, 'name' => 'Item 2', 'parent_id' => null],
148+
['id' => 6, 'name' => 'Item 3', 'parent_id' => null],
149+
['id' => 7, 'name' => 'Item 3.1', 'parent_id' => 6],
150+
['id' => 8, 'name' => 'Item 3.2', 'parent_id' => 6],
151+
];
152+
153+
$tree = TreeBuilder::build($input);
154+
print_r($tree);
155+
/*
156+
[
157+
[
158+
'id' => 1,
159+
'name' => 'Item 1',
160+
'parent_id' => null,
161+
'children' => [
162+
[
163+
'id' => 2,
164+
'name' => 'Item 1.1',
165+
'parent_id' => 1,
166+
'children' => [
167+
[
168+
'id' => 4,
169+
'name' => 'Item 1.1.1',
170+
'parent_id' => 2,
171+
'children' => [],
172+
]
173+
],
174+
],
175+
[
176+
'id' => 3,
177+
'name' => 'Item 1.2',
178+
'parent_id' => 1,
179+
'children' => [],
180+
],
181+
],
182+
],
183+
[
184+
'id' => 5,
185+
'name' => 'Item 2',
186+
'parent_id' => null,
187+
'children' => [],
188+
],
189+
[
190+
'id' => 6,
191+
'name' => 'Item 3',
192+
'parent_id' => null,
193+
'children' => [
194+
[
195+
'id' => 7,
196+
'name' => 'Item 3.1',
197+
'parent_id' => 6,
198+
'children' => [],
199+
],
200+
[
201+
'id' => 8,
202+
'name' => 'Item 3.2',
203+
'parent_id' => 6,
204+
'children' => [],
205+
],
206+
]
207+
],
208+
]
209+
*/
210+
211+
```
212+
118213
## Unit testing
119214
```
120215
composer install

src/TreeMaker.php renamed to src/TreeBuilder.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,23 @@
55
namespace Smoren\TreeTools;
66

77
use Smoren\TypeTools\MapAccess;
8-
use ArrayAccess;
98
use stdClass;
109

11-
class TreeMaker
10+
class TreeBuilder
1211
{
1312
/**
14-
* @param iterable<mixed> $list
13+
* Builds a tree from given flat collection of items with relations.
14+
*
15+
* @param iterable<mixed> $collection
1516
* @param string $idField
1617
* @param string $parentIdField
1718
* @param string $childrenContainerField
1819
* @param string $itemContainerField
1920
*
2021
* @return array<mixed>
2122
*/
22-
public static function fromList(
23-
iterable $list,
23+
public static function build(
24+
iterable $collection,
2425
string $idField = 'id',
2526
string $parentIdField = 'parent_id',
2627
string $childrenContainerField = 'children',
@@ -29,7 +30,7 @@ public static function fromList(
2930
$result = [];
3031
$map = [];
3132

32-
foreach($list as $item) {
33+
foreach($collection as $item) {
3334
$map[MapAccess::get($item, $idField)] = static::wrapItem(
3435
$item,
3536
$childrenContainerField,
@@ -50,6 +51,8 @@ public static function fromList(
5051
}
5152

5253
/**
54+
* Returns value of parent relation.
55+
*
5356
* @param mixed $item
5457
* @param string $parentIdField
5558
* @param string $itemContainerField
@@ -69,6 +72,8 @@ protected static function getParentId($item, string $parentIdField, string $item
6972
}
7073

7174
/**
75+
* Returns children container of given item.
76+
*
7277
* @param mixed $item
7378
* @param string $childrenContainerField
7479
*
@@ -84,6 +89,8 @@ protected static function &getChildrenContainer(&$item, string $childrenContaine
8489
}
8590

8691
/**
92+
* Wraps collection item for tree representation.
93+
*
8794
* @param mixed $item
8895
* @param string $childrenContainerField
8996
* @param string $itemContainerField

tests/unit/TreeMaker/ArrayTest.php renamed to tests/unit/TreeBuilder/ArrayTest.php

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?php
22

3-
namespace Smoren\TreeTools\Tests\Unit\TreeMaker;
3+
namespace Smoren\TreeTools\Tests\Unit\TreeBuilder;
44

5-
use Smoren\TreeTools\TreeMaker;
5+
use Smoren\TreeTools\TreeBuilder;
66

77
class ArrayTest extends \Codeception\Test\Unit
88
{
@@ -15,7 +15,7 @@ class ArrayTest extends \Codeception\Test\Unit
1515
public function testWithoutParentIds(array $input, array $expected): void
1616
{
1717
// When
18-
$result = TreeMaker::fromList($input);
18+
$result = TreeBuilder::build($input);
1919

2020
// Then
2121
$this->assertEquals($expected, $result);
@@ -33,59 +33,59 @@ public function dataProviderForWithoutParentIds(): array
3333
],
3434
[
3535
[
36-
['id' => 1, 'name' => 'Элемент 1'],
37-
['id' => 2, 'name' => 'Элемент 1.1', 'parent_id' => 1],
38-
['id' => 3, 'name' => 'Элемент 1.2', 'parent_id' => 1],
39-
['id' => 4, 'name' => 'Элемент 1.1.1', 'parent_id' => 2],
40-
['id' => 5, 'name' => 'Элемент 2'],
41-
['id' => 6, 'name' => 'Элемент 3'],
42-
['id' => 7, 'name' => 'Элемент 3.1', 'parent_id' => 6],
43-
['id' => 8, 'name' => 'Элемент 3.2', 'parent_id' => 6],
36+
['id' => 1, 'name' => 'Item 1'],
37+
['id' => 2, 'name' => 'Item 1.1', 'parent_id' => 1],
38+
['id' => 3, 'name' => 'Item 1.2', 'parent_id' => 1],
39+
['id' => 4, 'name' => 'Item 1.1.1', 'parent_id' => 2],
40+
['id' => 5, 'name' => 'Item 2'],
41+
['id' => 6, 'name' => 'Item 3'],
42+
['id' => 7, 'name' => 'Item 3.1', 'parent_id' => 6],
43+
['id' => 8, 'name' => 'Item 3.2', 'parent_id' => 6],
4444
],
4545
[
4646
[
4747
'id' => 1,
48-
'name' => 'Элемент 1',
48+
'name' => 'Item 1',
4949
'children' => [
5050
[
5151
'id' => 2,
52-
'name' => 'Элемент 1.1',
52+
'name' => 'Item 1.1',
5353
'parent_id' => 1,
5454
'children' => [
5555
[
5656
'id' => 4,
57-
'name' => 'Элемент 1.1.1',
57+
'name' => 'Item 1.1.1',
5858
'parent_id' => 2,
5959
'children' => [],
6060
]
6161
],
6262
],
6363
[
6464
'id' => 3,
65-
'name' => 'Элемент 1.2',
65+
'name' => 'Item 1.2',
6666
'parent_id' => 1,
6767
'children' => [],
6868
],
6969
]
7070
],
7171
[
7272
'id' => 5,
73-
'name' => 'Элемент 2',
73+
'name' => 'Item 2',
7474
'children' => [],
7575
],
7676
[
7777
'id' => 6,
78-
'name' => 'Элемент 3',
78+
'name' => 'Item 3',
7979
'children' => [
8080
[
8181
'id' => 7,
82-
'name' => 'Элемент 3.1',
82+
'name' => 'Item 3.1',
8383
'parent_id' => 6,
8484
'children' => [],
8585
],
8686
[
8787
'id' => 8,
88-
'name' => 'Элемент 3.2',
88+
'name' => 'Item 3.2',
8989
'parent_id' => 6,
9090
'children' => [],
9191
],
@@ -105,7 +105,7 @@ public function dataProviderForWithoutParentIds(): array
105105
public function testWithNullableParentIds(array $input, array $expected): void
106106
{
107107
// When
108-
$result = TreeMaker::fromList($input);
108+
$result = TreeBuilder::build($input);
109109

110110
// Then
111111
$this->assertEquals($expected, $result);
@@ -123,62 +123,62 @@ public function dataProviderForWithNullableParentIds(): array
123123
],
124124
[
125125
[
126-
['id' => 1, 'name' => 'Элемент 1', 'parent_id' => null],
127-
['id' => 2, 'name' => 'Элемент 1.1', 'parent_id' => 1],
128-
['id' => 3, 'name' => 'Элемент 1.2', 'parent_id' => 1],
129-
['id' => 4, 'name' => 'Элемент 1.1.1', 'parent_id' => 2],
130-
['id' => 5, 'name' => 'Элемент 2', 'parent_id' => null],
131-
['id' => 6, 'name' => 'Элемент 3', 'parent_id' => null],
132-
['id' => 7, 'name' => 'Элемент 3.1', 'parent_id' => 6],
133-
['id' => 8, 'name' => 'Элемент 3.2', 'parent_id' => 6],
126+
['id' => 1, 'name' => 'Item 1', 'parent_id' => null],
127+
['id' => 2, 'name' => 'Item 1.1', 'parent_id' => 1],
128+
['id' => 3, 'name' => 'Item 1.2', 'parent_id' => 1],
129+
['id' => 4, 'name' => 'Item 1.1.1', 'parent_id' => 2],
130+
['id' => 5, 'name' => 'Item 2', 'parent_id' => null],
131+
['id' => 6, 'name' => 'Item 3', 'parent_id' => null],
132+
['id' => 7, 'name' => 'Item 3.1', 'parent_id' => 6],
133+
['id' => 8, 'name' => 'Item 3.2', 'parent_id' => 6],
134134
],
135135
[
136136
[
137137
'id' => 1,
138-
'name' => 'Элемент 1',
138+
'name' => 'Item 1',
139139
'parent_id' => null,
140140
'children' => [
141141
[
142142
'id' => 2,
143-
'name' => 'Элемент 1.1',
143+
'name' => 'Item 1.1',
144144
'parent_id' => 1,
145145
'children' => [
146146
[
147147
'id' => 4,
148-
'name' => 'Элемент 1.1.1',
148+
'name' => 'Item 1.1.1',
149149
'parent_id' => 2,
150150
'children' => [],
151151
]
152152
],
153153
],
154154
[
155155
'id' => 3,
156-
'name' => 'Элемент 1.2',
156+
'name' => 'Item 1.2',
157157
'parent_id' => 1,
158158
'children' => [],
159159
],
160160
],
161161
],
162162
[
163163
'id' => 5,
164-
'name' => 'Элемент 2',
164+
'name' => 'Item 2',
165165
'parent_id' => null,
166166
'children' => [],
167167
],
168168
[
169169
'id' => 6,
170-
'name' => 'Элемент 3',
170+
'name' => 'Item 3',
171171
'parent_id' => null,
172172
'children' => [
173173
[
174174
'id' => 7,
175-
'name' => 'Элемент 3.1',
175+
'name' => 'Item 3.1',
176176
'parent_id' => 6,
177177
'children' => [],
178178
],
179179
[
180180
'id' => 8,
181-
'name' => 'Элемент 3.2',
181+
'name' => 'Item 3.2',
182182
'parent_id' => 6,
183183
'children' => [],
184184
],

0 commit comments

Comments
 (0)