Skip to content

Commit

Permalink
feat: introduce helper NodeTraverser for recursive operations on nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Jan 6, 2022
1 parent 2fd0bc1 commit cc1bc66
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/Mapper/Tree/NodeTraverser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace CuyZ\Valinor\Mapper\Tree;

/**
* @template T
*/
final class NodeTraverser
{
/** @var callable(Node): T */
private $callback;

/**
* @param callable(Node): T $callback
*/
public function __construct(callable $callback)
{
$this->callback = $callback;
}

/**
* @return iterable<T>
*/
public function traverse(Node $node): iterable
{
return $this->recurse($node);
}

/**
* @return iterable<T>
*/
private function recurse(Node $node): iterable
{
yield ($this->callback)($node);

foreach ($node->children() as $child) {
yield from $this->recurse($child);
}
}
}
29 changes: 29 additions & 0 deletions tests/Unit/Mapper/Tree/NodeTraverserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace CuyZ\Valinor\Tests\Unit\Mapper\Tree;

use CuyZ\Valinor\Mapper\Tree\Node;
use CuyZ\Valinor\Mapper\Tree\NodeTraverser;
use CuyZ\Valinor\Tests\Fake\Mapper\FakeNode;
use PHPUnit\Framework\TestCase;

final class NodeTraverserTest extends TestCase
{
public function test_nodes_are_visited(): void
{
$node = FakeNode::branch([
'foo' => [],
'bar' => [],
]);

$visited = [...(new NodeTraverser(
fn (Node $node) => $node
))->traverse($node)];

self::assertContains($node, $visited);
self::assertContains($node->children()['foo'], $visited);
self::assertContains($node->children()['bar'], $visited);
}
}

0 comments on commit cc1bc66

Please sign in to comment.