Skip to content

Commit e4e66de

Browse files
committed
Add buildFromFinder + CS
1 parent 0f720a1 commit e4e66de

File tree

5 files changed

+155
-57
lines changed

5 files changed

+155
-57
lines changed

src/Symfony/Component/Console/Helper/Tree.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,54 @@ final class Tree implements \RecursiveIterator
2222
{
2323
private readonly TreeStyle $style;
2424

25-
private int $position = 0;
25+
private \Iterator $childrenIterator;
2626

2727
public function __construct(
2828
private readonly OutputInterface $output,
2929
private readonly TreeNode $node,
3030
?TreeStyle $style = null,
3131
) {
3232
$this->style = $style ?? TreeStyle::default();
33+
$this->childrenIterator = new \IteratorIterator($node->getChildren());
34+
$this->childrenIterator->rewind();
3335
}
3436

3537
public function current(): TreeNode
3638
{
37-
return $this->node->getChildren()[$this->position];
39+
return $this->childrenIterator->current();
3840
}
3941

4042
public function key(): int
4143
{
42-
return $this->position;
44+
return $this->childrenIterator->key();
4345
}
4446

4547
public function next(): void
4648
{
47-
++$this->position;
49+
$this->childrenIterator->next();
4850
}
4951

5052
public function rewind(): void
5153
{
52-
$this->position = 0;
54+
$this->childrenIterator->rewind();
5355
}
5456

5557
public function valid(): bool
5658
{
57-
return isset($this->node->getChildren()[$this->position]);
59+
return $this->childrenIterator->valid();
5860
}
5961

6062
public function hasChildren(): bool
6163
{
62-
return [] !== $this->current()->getChildren();
64+
if (null === $current = $this->current()) {
65+
return false;
66+
}
67+
68+
foreach ($current->getChildren() as $child) {
69+
return true;
70+
}
71+
72+
return false;
6373
}
6474

6575
public function getChildren(): \RecursiveIterator

src/Symfony/Component/Console/Helper/TreeBuilder.php

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

1212
namespace Symfony\Component\Console\Helper;
1313

14+
use Symfony\Component\Finder\Finder;
15+
1416
/**
1517
* @author Simon André <smn.andre@gmail.com>
1618
*/
@@ -58,6 +60,32 @@ public static function fromPaths(array $paths): TreeNode
5860
return $root;
5961
}
6062

63+
public static function buildFromFinder(Finder $finder): TreeNode
64+
{
65+
$root = new TreeNode('Root');
66+
$root->addChild(function () use ($finder) {
67+
foreach ($finder as $item) {
68+
if ($item->isDir()) {
69+
$dirNode = new TreeNode($item->getFilename());
70+
$dirNode->addChild(function () use ($item) {
71+
$subFinder = new Finder();
72+
$subFinder->in($item->getRealPath())->depth('== 0')->sortByName();
73+
yield from self::buildFromFinder($subFinder);
74+
});
75+
yield $dirNode;
76+
} else {
77+
$filename = $item->getFilename();
78+
if (stripos($filename, 'er.php') !== false) {
79+
$filename = "<fg=red>$filename</>";
80+
}
81+
yield new TreeNode($filename);
82+
}
83+
}
84+
});
85+
86+
return $root;
87+
}
88+
6189
private static function buildTree(TreeNode $node, array $array): TreeNode
6290
{
6391
foreach ($array as $key => $value) {

src/Symfony/Component/Console/Helper/TreeNode.php

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,73 +18,75 @@
1818
*/
1919
final class TreeNode implements \Countable, \IteratorAggregate
2020
{
21-
private readonly string $value;
22-
2321
/**
24-
* @var array<self>
22+
* @var array<TreeNode|callable(): \Generator>
2523
*/
26-
private array $children;
24+
private array $children = [];
2725

2826
public function __construct(
29-
?string $value = null,
27+
private readonly string $value = '',
3028
?self $parent = null,
31-
array $children = [],
29+
iterable $children = [],
3230
) {
33-
$this->value = $value ?? '';
3431
if ($parent) {
3532
$parent->addChild($this);
3633
}
34+
3735
foreach ($children as $child) {
3836
$this->addChild($child);
3937
}
40-
$this->children = $children;
4138
}
4239

4340
public function getValue(): string
4441
{
4542
return $this->value;
4643
}
4744

48-
public function addChild(self|string $node): self
45+
public function addChild(self|string|callable $node): self
4946
{
5047
if (\is_string($node)) {
5148
$node = new self($node, $this);
5249
}
5350

54-
$this->children[] = $node;
51+
if (\is_callable($node)) {
52+
$this->children[] = $node;
53+
} else {
54+
$this->children[] = $node;
55+
}
5556

5657
return $this;
5758
}
5859

5960
/**
60-
* @return iterable<TreeNode>
61+
* @return \Traversable<TreeNode>
6162
*/
6263
public function getChildren(): iterable
6364
{
64-
return $this->children;
65+
foreach ($this->children as $child) {
66+
if (\is_callable($child)) {
67+
yield from $child();
68+
} elseif ($child instanceof self) {
69+
yield $child;
70+
}
71+
}
6572
}
6673

6774
/**
68-
* @return \RecursiveArrayIterator<TreeNode>
75+
* @return \Traversable<TreeNode>
6976
*/
70-
public function getIterator(): \RecursiveArrayIterator
77+
public function getIterator(): \Traversable
7178
{
72-
return new class($this->children) extends \RecursiveArrayIterator {
73-
public function hasChildren(): bool
74-
{
75-
return !$this->current()->hasChildren();
76-
}
77-
78-
public function getChildren(): self
79-
{
80-
return new self($this->current()->getChildren());
81-
}
82-
};
79+
return $this->getChildren();
8380
}
8481

8582
public function count(): int
8683
{
87-
return \count($this->children);
84+
$count = 0;
85+
foreach ($this->getChildren() as $child) {
86+
++$count;
87+
}
88+
89+
return $count;
8890
}
8991

9092
public function __toString(): string

src/Symfony/Component/Console/Tests/Helper/TreeBuilderTest.php

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Helper\TreeBuilder;
16+
use Symfony\Component\Finder\Finder;
1617

1718
class TreeBuilderTest extends TestCase
1819
{
@@ -27,37 +28,37 @@ public function testFromArray()
2728

2829
$root = TreeBuilder::fromArray($array);
2930

30-
$this->assertCount(2, $root->getChildren());
31+
$this->assertSame(2, iterator_count($root->getChildren()));
3132

3233
$root = TreeBuilder::fromArray($array, '');
3334
$this->assertSame('', $root->getValue());
3435

3536
$root = TreeBuilder::fromArray($array, '**');
3637
$this->assertSame('**', $root->getValue());
3738

38-
$child1 = $root->getChildren()[0];
39+
$child1 = iterator_to_array($root->getChildren())[0];
3940
$this->assertSame('Child 1', $child1->getValue());
40-
$this->assertCount(1, $child1->getChildren());
41+
$this->assertSame(1, iterator_count($child1->getChildren()));
4142

42-
$leaf1 = $child1->getChildren()[0];
43+
$leaf1 = iterator_to_array($child1->getChildren())[0];
4344
$this->assertSame('Leaf 1', $leaf1->getValue());
4445

45-
$child2 = $root->getChildren()[1];
46+
$child2 = iterator_to_array($root->getChildren())[1];
4647
$this->assertSame('Child 2', $child2->getValue());
47-
$this->assertEmpty($child2->getChildren());
48+
$this->assertSame(0, iterator_count($child2->getChildren()));
4849
}
4950

5051
public function testFromArrayWithEmptyArray()
5152
{
5253
$root = TreeBuilder::fromArray([]);
53-
$this->assertEmpty($root->getChildren());
54+
$this->assertSame(0, iterator_count($root->getChildren()));
5455
}
5556

5657
public function testBuildWithRootValue()
5758
{
5859
$tree = TreeBuilder::fromArray([], 'Foo');
59-
$this->assertEmpty($tree->getChildren());
60-
$this->assertEquals('Foo', (string) $tree);
60+
$this->assertSame(0, iterator_count($tree->getChildren()));
61+
$this->assertSame('Foo', (string) $tree);
6162
}
6263

6364
public function testFromPaths()
@@ -69,18 +70,20 @@ public function testFromPaths()
6970

7071
$root = TreeBuilder::fromPaths($paths);
7172

72-
$this->assertCount(2, $root->getChildren());
73+
$this->assertSame(2, iterator_count($root->getChildren()));
7374

74-
$child1 = $root->getChildren()[0];
75+
$children = iterator_to_array($root->getChildren());
76+
77+
$child1 = $children[0];
7578
$this->assertSame('Child 1', $child1->getValue());
76-
$this->assertCount(1, $child1->getChildren());
79+
$this->assertSame(1, iterator_count($child1->getChildren()));
7780

78-
$leaf1 = $child1->getChildren()[0];
81+
$leaf1 = iterator_to_array($child1->getChildren())[0];
7982
$this->assertSame('Leaf 1', $leaf1->getValue());
8083

81-
$child2 = $root->getChildren()[1];
84+
$child2 = $children[1];
8285
$this->assertSame('Child 2', $child2->getValue());
83-
$this->assertEmpty($child2->getChildren());
86+
$this->assertSame(0, iterator_count($child2->getChildren()));
8487
}
8588

8689
public function testFromRecursiveIterator()
@@ -94,9 +97,47 @@ public function testFromRecursiveIterator()
9497

9598
$root = TreeBuilder::fromIterator($recursiveIterator);
9699

97-
$this->assertCount(2, $root->getChildren());
98-
$this->assertSame('Child 1', $root->getChildren()[0]->getValue());
99-
$this->assertSame('Child 2', $root->getChildren()[1]->getValue());
100-
$this->assertSame('Leaf 1', $root->getChildren()[0]->getChildren()[0]->getValue());
100+
$this->assertSame(2, iterator_count($root->getChildren()));
101+
$this->assertSame('Child 1', iterator_to_array($root->getChildren())[0]->getValue());
102+
$this->assertSame('Child 2', iterator_to_array($root->getChildren())[1]->getValue());
103+
}
104+
105+
public function testFromFinder()
106+
{
107+
$tempDir = sys_get_temp_dir().'/test_tree_builder/'.rand(0, 999999);
108+
mkdir($tempDir.'/dir1', 0777, true);
109+
mkdir($tempDir.'/dir2', 0777, true);
110+
111+
file_put_contents($tempDir.'/file1.php', '');
112+
file_put_contents($tempDir.'/dir1/file2er.php', '');
113+
file_put_contents($tempDir.'/dir2/file3.php', '');
114+
115+
$finder = new Finder();
116+
$finder->in($tempDir)->depth('== 0')->sortByName();
117+
118+
$root = TreeBuilder::buildFromFinder($finder);
119+
120+
$this->assertSame('Root', $root->getValue());
121+
$children = iterator_to_array($root->getChildren());
122+
$this->assertCount(3, $children);
123+
$this->assertSame('dir1', $children[0]->getValue());
124+
$this->assertSame('dir2', $children[1]->getValue());
125+
$this->assertSame('file1.php', $children[2]->getValue());
126+
127+
$dir1Children = iterator_to_array($children[0]->getChildren());
128+
$this->assertCount(1, $dir1Children);
129+
$this->assertSame('<fg=red>file2er.php</>', $dir1Children[0]->getValue());
130+
131+
$dir2Children = iterator_to_array($children[1]->getChildren());
132+
$this->assertCount(1, $dir2Children);
133+
$this->assertSame('file3.php', $dir2Children[0]->getValue());
134+
135+
// Clean up
136+
array_map('unlink', glob("$tempDir/*.*"));
137+
array_map('unlink', glob("$tempDir/dir1/*.*"));
138+
array_map('unlink', glob("$tempDir/dir2/*.*"));
139+
rmdir($tempDir.'/dir1');
140+
rmdir($tempDir.'/dir2');
141+
rmdir($tempDir);
101142
}
102143
}

src/Symfony/Component/Console/Tests/Helper/TreeNodeTest.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function testNodeInitialization()
2020
{
2121
$node = new TreeNode('Root');
2222
$this->assertSame('Root', $node->getValue());
23-
$this->assertEmpty($node->getChildren());
23+
$this->assertSame(0, iterator_count($node->getChildren()));
2424
}
2525

2626
public function testAddingChildren()
@@ -30,8 +30,25 @@ public function testAddingChildren()
3030

3131
$root->addChild($child);
3232

33-
$this->assertCount(1, $root->getChildren());
34-
$this->assertSame($child, $root->getChildren()[0]);
33+
$this->assertSame(1, iterator_count($root->getChildren()));
34+
$this->assertSame($child, iterator_to_array($root->getChildren())[0]);
35+
}
36+
37+
public function testAddingChildrenWithGenerators()
38+
{
39+
$root = new TreeNode('Root');
40+
41+
$root->addChild(function () {
42+
yield new TreeNode('Generated Child 1');
43+
yield new TreeNode('Generated Child 2');
44+
});
45+
46+
$this->assertSame(2, iterator_count($root->getChildren()));
47+
48+
$children = iterator_to_array($root->getChildren());
49+
50+
$this->assertSame('Generated Child 1', $children[0]->getValue());
51+
$this->assertSame('Generated Child 2', $children[1]->getValue());
3552
}
3653

3754
public function testRecursiveStructure()
@@ -45,7 +62,7 @@ public function testRecursiveStructure()
4562
$root->addChild($child1);
4663
$root->addChild($child2);
4764

48-
$this->assertCount(2, $root->getChildren());
49-
$this->assertSame($leaf1, $child1->getChildren()[0]);
65+
$this->assertSame(2, iterator_count($root->getChildren()));
66+
$this->assertSame($leaf1, iterator_to_array($child1->getChildren())[0]);
5067
}
5168
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy