Skip to content

Commit a454da1

Browse files
committed
[FEATURE] Add traverseStatementsWithCallable
1 parent 78bedd9 commit a454da1

File tree

7 files changed

+118
-6
lines changed

7 files changed

+118
-6
lines changed

packages/fractor-typoscript/src/AbstractTypoScriptFractor.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use a9f\Fractor\Application\ValueObject\AppliedRule;
88
use a9f\Fractor\Application\ValueObject\File;
99
use a9f\FractorTypoScript\Contract\TypoScriptFractor;
10+
use a9f\FractorTypoScript\NodeTraverser\SimpleCallableStatementTraverser;
1011
use Helmich\TypoScriptParser\Parser\AST\Statement;
1112

1213
abstract class AbstractTypoScriptFractor implements TypoScriptFractor
@@ -15,6 +16,11 @@ abstract class AbstractTypoScriptFractor implements TypoScriptFractor
1516

1617
protected bool $hasChanged = false;
1718

19+
public function __construct(
20+
private readonly SimpleCallableStatementTraverser $simpleCallableStatementTraverser
21+
) {
22+
}
23+
1824
/**
1925
* @param list<Statement> $statements
2026
*/
@@ -23,7 +29,7 @@ final public function beforeTraversal(File $file, array $statements): void
2329
$this->file = $file;
2430
}
2531

26-
final public function enterNode(Statement $node): Statement|int
32+
final public function enterNode(Statement $node): Statement|int|null
2733
{
2834
$result = $this->refactor($node);
2935

@@ -37,8 +43,9 @@ final public function enterNode(Statement $node): Statement|int
3743
return $result;
3844
}
3945

40-
final public function leaveNode(Statement $node): void
46+
final public function leaveNode(Statement $node): int|Statement|null
4147
{
48+
return null;
4249
}
4350

4451
/**
@@ -47,4 +54,9 @@ final public function leaveNode(Statement $node): void
4754
final public function afterTraversal(array $statements): void
4855
{
4956
}
57+
58+
protected function traverseStatementsWithCallable(?Statement $statement, callable $callable): void
59+
{
60+
$this->simpleCallableStatementTraverser->traverseNodesWithCallable($statement, $callable);
61+
}
5062
}

packages/fractor-typoscript/src/Contract/TypoScriptNodeVisitor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ interface TypoScriptNodeVisitor
1717
*/
1818
public function beforeTraversal(File $file, array $statements): void;
1919

20-
public function enterNode(Statement $node): Statement|int;
20+
public function enterNode(Statement $node): Statement|int|null;
2121

22-
public function leaveNode(Statement $node): void;
22+
public function leaveNode(Statement $node): Statement|int|null;
2323

2424
/**
2525
* @param list<Statement> $statements
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorTypoScript\NodeTraverser;
6+
7+
use a9f\Fractor\Application\ValueObject\File;
8+
use a9f\FractorTypoScript\NodeVisitor\CallableStatementVisitor;
9+
use a9f\FractorTypoScript\TypoScriptStatementsIterator;
10+
use Helmich\TypoScriptParser\Parser\AST\Statement;
11+
12+
final class SimpleCallableStatementTraverser
13+
{
14+
public function traverseNodesWithCallable(?Statement $statement, callable $callable): void
15+
{
16+
if ($statement === null) {
17+
return;
18+
}
19+
$callableStatementVisitor = new CallableStatementVisitor($callable);
20+
21+
$nodeTraverser = new TypoScriptStatementsIterator([$callableStatementVisitor]);
22+
$nodeTraverser->traverseDocument(new File('', ''), [$statement]);
23+
}
24+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorTypoScript\NodeVisitor;
6+
7+
use a9f\FractorTypoScript\TypoScriptStatementsIterator;
8+
use Helmich\TypoScriptParser\Parser\AST\Statement;
9+
10+
final class CallableStatementVisitor extends StatementVisitorAbstract
11+
{
12+
/**
13+
* @var callable(Statement): (Statement|int|null)
14+
*/
15+
private $callable;
16+
17+
private ?int $statementIdToRemove = null;
18+
19+
public function __construct(callable $callable)
20+
{
21+
$this->callable = $callable;
22+
}
23+
24+
public function enterNode(Statement $node): int|null|Statement
25+
{
26+
$originalStatement = $node;
27+
$callable = $this->callable;
28+
/** @var int|Statement|null $newStatement */
29+
$newStatement = $callable($node);
30+
if ($newStatement === TypoScriptStatementsIterator::REMOVE_NODE) {
31+
$this->statementIdToRemove = \spl_object_id($originalStatement);
32+
return $originalStatement;
33+
}
34+
return $newStatement;
35+
}
36+
37+
public function leaveNode(Statement $node): int|Statement
38+
{
39+
if ($this->statementIdToRemove !== null && $this->statementIdToRemove === \spl_object_id($node)) {
40+
$this->statementIdToRemove = null;
41+
return TypoScriptStatementsIterator::REMOVE_NODE;
42+
}
43+
return $node;
44+
}
45+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace a9f\FractorTypoScript\NodeVisitor;
6+
7+
use a9f\Fractor\Application\ValueObject\File;
8+
use a9f\FractorTypoScript\Contract\TypoScriptNodeVisitor;
9+
use Helmich\TypoScriptParser\Parser\AST\Statement;
10+
11+
abstract class StatementVisitorAbstract implements TypoScriptNodeVisitor
12+
{
13+
public function beforeTraversal(File $file, array $statements): void
14+
{
15+
}
16+
17+
public function enterNode(Statement $node): int|null|Statement
18+
{
19+
return null;
20+
}
21+
22+
public function leaveNode(Statement $node): int|null|Statement
23+
{
24+
return null;
25+
}
26+
27+
public function afterTraversal(array $statements): void
28+
{
29+
}
30+
}

packages/fractor-typoscript/src/TypoScriptStatementsIterator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private function processStatementList(array $statements): array
6969
return array_merge(...$resultingStatements);
7070
}
7171

72-
private function traverseNode(Statement $node): int|Statement
72+
private function traverseNode(Statement $node): int|Statement|null
7373
{
7474
$lastCalledVisitor = null;
7575
$result = $node;

packages/fractor-typoscript/tests/TypoScriptStatementsIterator/Fixture/StatementCollectingVisitor.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ public function enterNode(Statement $node): Statement|int
3333
return $node;
3434
}
3535

36-
public function leaveNode(Statement $node): void
36+
public function leaveNode(Statement $node): int|Statement|null
3737
{
3838
$this->calls[] = sprintf('%s:leaveNode:%s:l-%d', $this->visitorName, $node::class, $node->sourceLine);
39+
return $node;
3940
}
4041

4142
/**

0 commit comments

Comments
 (0)