Skip to content

Commit 534f96c

Browse files
committed
!!![TASK] Create Menus with a content of nodes instead of strings
This enables us to deal with menu types in both rst and md that do not fit in the current model.
1 parent bb3a291 commit 534f96c

File tree

9 files changed

+98
-28
lines changed

9 files changed

+98
-28
lines changed

packages/guides-restructured-text/src/RestructuredText/Directives/ContentsDirective.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace phpDocumentor\Guides\RestructuredText\Directives;
66

77
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
8+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
89
use phpDocumentor\Guides\Nodes\Node;
910
use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface;
1011
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
@@ -38,7 +39,7 @@ public function process(
3839
$blockContext->getDocumentParserContext()->getContext()->getCurrentFileName(),
3940
);
4041

41-
return (new ContentMenuNode([$absoluteUrl]))
42+
return (new ContentMenuNode([new ParsedMenuEntryNode($absoluteUrl)]))
4243
->withOptions($this->optionsToArray($options))
4344
->withCaption($directive->getDataNode());
4445
}

packages/guides-restructured-text/src/RestructuredText/Directives/MenuDirective.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace phpDocumentor\Guides\RestructuredText\Directives;
66

77
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
8+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
89
use phpDocumentor\Guides\Nodes\Node;
910
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
1011
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
@@ -48,7 +49,7 @@ public function process(
4849
$options,
4950
);
5051
if (count($toctreeFiles) === 0) {
51-
$toctreeFiles[] = '/*';
52+
$toctreeFiles[] = new ParsedMenuEntryNode('/*');
5253
}
5354

5455
return (new NavMenuNode($toctreeFiles))->withOptions($this->optionsToArray($options));

packages/guides-restructured-text/src/RestructuredText/Toc/ToctreeBuilder.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44

55
namespace phpDocumentor\Guides\RestructuredText\Toc;
66

7+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
78
use phpDocumentor\Guides\ParserContext;
89
use phpDocumentor\Guides\RestructuredText\Parser\LinesIterator;
910

10-
use function array_filter;
1111
use function array_map;
1212

1313
class ToctreeBuilder
1414
{
1515
/**
1616
* @param mixed[] $options
1717
*
18-
* @return string[]
18+
* @return ParsedMenuEntryNode[]
1919
*/
2020
public function buildToctreeFiles(
2121
ParserContext $parserContext,
@@ -31,12 +31,21 @@ public function buildToctreeFiles(
3131
return $toctreeFiles;
3232
}
3333

34-
/** @return string[] */
34+
/** @return ParsedMenuEntryNode[] */
3535
private function parseToctreeFiles(LinesIterator $lines): array
3636
{
37-
return array_filter(
38-
array_map('trim', $lines->toArray()),
39-
static fn (string $file): bool => $file !== '',
40-
);
37+
$linesArray = $lines->toArray();
38+
$trimmedLines = array_map('trim', $linesArray);
39+
40+
$result = [];
41+
foreach ($trimmedLines as $file) {
42+
if ($file === '') {
43+
continue;
44+
}
45+
46+
$result[] = new ParsedMenuEntryNode($file);
47+
}
48+
49+
return $result;
4150
}
4251
}

packages/guides/src/Compiler/NodeTransformers/MenuNodeAddEntryTransformer.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
1212
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
1313
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
14+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
1415
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1516
use phpDocumentor\Guides\Nodes\Node;
1617
use Psr\Log\LoggerInterface;
@@ -45,7 +46,7 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu
4546
return $node;
4647
}
4748

48-
$files = $node->getFiles();
49+
$parsedMenuEntryNodes = $node->getParsedMenuEntryNodes();
4950
$glob = $node->hasOption('glob');
5051
$globExclude = explode(',', $node->getOption('globExclude') . '');
5152

@@ -54,11 +55,11 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu
5455
$documentEntriesInTree = [];
5556
$menuEntries = [];
5657

57-
foreach ($files as $file) {
58+
foreach ($parsedMenuEntryNodes as $parsedMenuEntryNode) {
5859
foreach ($documentEntries as $documentEntry) {
5960
if (
60-
!self::isEqualAbsolutePath($documentEntry->getFile(), $file, $currentPath, $glob, $globExclude)
61-
&& !self::isEqualRelativePath($documentEntry->getFile(), $file, $currentPath, $glob, $globExclude)
61+
!self::isEqualAbsolutePath($documentEntry->getFile(), $parsedMenuEntryNode, $currentPath, $glob, $globExclude)
62+
&& !self::isEqualRelativePath($documentEntry->getFile(), $parsedMenuEntryNode, $currentPath, $glob, $globExclude)
6263
) {
6364
continue;
6465
}
@@ -136,8 +137,9 @@ public function getPriority(): int
136137
}
137138

138139
/** @param String[] $globExclude */
139-
private static function isEqualAbsolutePath(string $actualFile, string $expectedFile, string $currentFile, bool $glob, array $globExclude): bool
140+
private static function isEqualAbsolutePath(string $actualFile, ParsedMenuEntryNode $parsedMenuEntryNode, string $currentFile, bool $glob, array $globExclude): bool
140141
{
142+
$expectedFile = $parsedMenuEntryNode->getReference();
141143
if (!self::isAbsoluteFile($expectedFile)) {
142144
return false;
143145
}
@@ -150,8 +152,9 @@ private static function isEqualAbsolutePath(string $actualFile, string $expected
150152
}
151153

152154
/** @param String[] $globExclude */
153-
private static function isEqualRelativePath(string $actualFile, string $expectedFile, string $currentFile, bool $glob, array $globExclude): bool
155+
private static function isEqualRelativePath(string $actualFile, ParsedMenuEntryNode $parsedMenuEntryNode, string $currentFile, bool $glob, array $globExclude): bool
154156
{
157+
$expectedFile = $parsedMenuEntryNode->getReference();
155158
if (self::isAbsoluteFile($expectedFile)) {
156159
return false;
157160
}

packages/guides/src/Compiler/Passes/GlobalMenuPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function run(array $documents, CompilerContext $compilerContext): array
7171

7272
private function getNavMenuNodefromTocNode(CompilerContext $compilerContext, TocNode $tocNode, string|null $menuType = null): NavMenuNode
7373
{
74-
$node = new NavMenuNode($tocNode->getFiles());
74+
$node = new NavMenuNode($tocNode->getParsedMenuEntryNodes());
7575
$self = $this;
7676
$menuEntries = array_map(static function (MenuEntryNode $tocEntry) use ($compilerContext, $self) {
7777
return $self->getMenuEntryWithChildren($compilerContext, $tocEntry);

packages/guides/src/Nodes/Menu/MenuNode.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ abstract class MenuNode extends CompoundNode
3232
/** @var MenuEntryNode[] */
3333
private array $menuEntries = [];
3434

35-
/** @param string[] $files */
36-
public function __construct(private readonly array $files)
35+
/** @param ParsedMenuEntryNode[] $parsedMenuEntryNodes */
36+
public function __construct(private readonly array $parsedMenuEntryNodes)
3737
{
3838
parent::__construct();
3939
}
4040

41-
/** @return string[] */
42-
public function getFiles(): array
41+
/** @return ParsedMenuEntryNode[] */
42+
public function getParsedMenuEntryNodes(): array
4343
{
44-
return $this->files;
44+
return $this->parsedMenuEntryNodes;
4545
}
4646

4747
abstract public function getDepth(): int;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Nodes\Menu;
6+
7+
use phpDocumentor\Guides\Nodes\AbstractNode;
8+
use Stringable;
9+
10+
/**
11+
* This node contains the result of parsing the menu entries for a menu.
12+
*
13+
* @extends AbstractNode<String>
14+
*/
15+
final class ParsedMenuEntryNode extends AbstractNode implements Stringable
16+
{
17+
public function __construct(
18+
private readonly string $reference,
19+
private readonly string|null $title = null,
20+
private readonly string|null $interlink = null,
21+
) {
22+
$this->value = $reference;
23+
}
24+
25+
public function getReference(): string
26+
{
27+
return $this->reference;
28+
}
29+
30+
public function getTitle(): string|null
31+
{
32+
return $this->title;
33+
}
34+
35+
public function getInterlink(): string|null
36+
{
37+
return $this->interlink;
38+
}
39+
40+
public function __toString(): string
41+
{
42+
return $this->reference;
43+
}
44+
}

packages/guides/tests/unit/Compiler/DocumentNodeTraverserTest.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use phpDocumentor\Guides\Compiler\NodeTransformers\CustomNodeTransformerFactory;
88
use phpDocumentor\Guides\Nodes\DocumentNode;
99
use phpDocumentor\Guides\Nodes\InlineCompoundNode;
10+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
1011
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1112
use phpDocumentor\Guides\Nodes\Node;
1213
use phpDocumentor\Guides\Nodes\ProjectNode;
@@ -19,7 +20,7 @@ final class DocumentNodeTraverserTest extends TestCase
1920
public function testRemoveNodeFromDocument(): void
2021
{
2122
$document = new DocumentNode('foo', '/index.rst');
22-
$document->addChildNode(new TocNode(['/readme.rst']));
23+
$document->addChildNode(new TocNode([new ParsedMenuEntryNode('/readme.rst')]));
2324
$document->addChildNode(new SectionNode(new TitleNode(InlineCompoundNode::getPlainTextInlineNode('Foo'), 1, 'foo')));
2425

2526
$traverser = new DocumentNodeTraverser(new CustomNodeTransformerFactory([
@@ -59,10 +60,10 @@ public function getPriority(): int
5960
public function testReplaceInEnterNode(): void
6061
{
6162
$document = new DocumentNode('foo', '/index.rst');
62-
$document->addChildNode(new TocNode(['/readme.rst']));
63+
$document->addChildNode(new TocNode([new ParsedMenuEntryNode('/readme.rst')]));
6364
$document->addChildNode(new SectionNode(new TitleNode(InlineCompoundNode::getPlainTextInlineNode('Foo'), 1, 'foo')));
6465

65-
$replacement = new TocNode(['/foo.rst']);
66+
$replacement = new TocNode([new ParsedMenuEntryNode('/foo.rst')]);
6667

6768

6869
/** @var iterable<NodeTransformer<Node>> $transformers */
@@ -112,10 +113,10 @@ public function getPriority(): int
112113
public function testReplaceInLeaveNode(): void
113114
{
114115
$document = new DocumentNode('foo', '/index.rst');
115-
$document->addChildNode(new TocNode(['/readme.rst']));
116+
$document->addChildNode(new TocNode([new ParsedMenuEntryNode('/readme.rst')]));
116117
$document->addChildNode(new SectionNode(new TitleNode(InlineCompoundNode::getPlainTextInlineNode('Foo'), 1, 'foo')));
117118

118-
$replacement = new TocNode(['/foo.rst']);
119+
$replacement = new TocNode([new ParsedMenuEntryNode('/foo.rst')]);
119120

120121

121122
/** @var iterable<NodeTransformer<Node>> $transformers */

packages/guides/tests/unit/Compiler/NodeTransformers/MenuNodeAddSubDocumentsTransformerTest.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
use phpDocumentor\Guides\Nodes\DocumentNode;
99
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
1010
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
11+
use phpDocumentor\Guides\Nodes\Menu\ParsedMenuEntryNode;
1112
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1213
use phpDocumentor\Guides\Nodes\ProjectNode;
1314
use phpDocumentor\Guides\Nodes\TitleNode;
1415
use PHPUnit\Framework\Attributes\DataProvider;
1516
use PHPUnit\Framework\TestCase;
1617
use Psr\Log\LoggerInterface;
1718

19+
use function array_map;
20+
1821
class MenuNodeAddSubDocumentsTransformerTest extends TestCase
1922
{
2023
/** @param string[] $paths */
@@ -44,7 +47,11 @@ public function testTocTreeEntryCount(string $currentPath, array $paths, array $
4447
{
4548
$context = self::getCompilerContext($currentPath, $paths);
4649

47-
$node = new TocNode($tocFiles);
50+
$parsedMenuEntryNodes = array_map(static function ($file) {
51+
return new ParsedMenuEntryNode($file);
52+
}, $tocFiles);
53+
54+
$node = new TocNode($parsedMenuEntryNodes);
4855
if ($glob) {
4956
$node = $node->withOptions(['glob' => true]);
5057
}
@@ -149,7 +156,11 @@ public function testNavMenuTreeEntryCount(string $currentPath, array $paths, arr
149156
{
150157
$context = self::getCompilerContext($currentPath, $paths);
151158

152-
$node = new NavMenuNode($tocFiles);
159+
$parsedMenuEntryNodes = array_map(static function ($file) {
160+
return new ParsedMenuEntryNode($file);
161+
}, $tocFiles);
162+
163+
$node = new NavMenuNode($parsedMenuEntryNodes);
153164
if ($glob) {
154165
$node = $node->withOptions(['glob' => true]);
155166
}

0 commit comments

Comments
 (0)