8000 Add buildFromFinder + CS · symfony/symfony@e4e66de · GitHub
[go: up one dir, main page]

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

+17-7
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

+28
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

+28-26
10000
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

+60-19
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

+22-5
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)
0