Skip to content

Commit 1a6cc43

Browse files
committed
!!![TASK] Restructure Menu handling
1 parent ca75ddf commit 1a6cc43

File tree

21 files changed

+209
-390
lines changed

21 files changed

+209
-390
lines changed

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

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

77
use phpDocumentor\Guides\Nodes\Menu\ContentMenuNode;
8-
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
98
use phpDocumentor\Guides\Nodes\Menu\SectionMenuEntryNode;
109
use phpDocumentor\Guides\Nodes\Node;
1110
use phpDocumentor\Guides\ReferenceResolvers\DocumentNameResolverInterface;

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
use phpDocumentor\Guides\Nodes\Menu\ExternalMenuEntryNode;
88
use phpDocumentor\Guides\Nodes\Menu\GlobMenuEntryNode;
99
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
10-
use phpDocumentor\Guides\Nodes\Menu\MenuDefinitionLineNode;
1110
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
1211
use phpDocumentor\Guides\Nodes\TitleNode;
1312
use phpDocumentor\Guides\ParserContext;
1413
use phpDocumentor\Guides\RestructuredText\Parser\LinesIterator;
15-
use phpDocumentor\Guides\RestructuredText\Parser\Reference\EmbeddedReferenceParser;
14+
use phpDocumentor\Guides\RestructuredText\Parser\References\EmbeddedReferenceParser;
1615

1716
use function array_filter;
1817
use function array_map;
@@ -54,7 +53,7 @@ private function parseToctreeEntryLines(LinesIterator $lines): array
5453

5554
$result = [];
5655
foreach ($linesArray as $line) {
57-
$referenceData = $this->extractEmbeddedUri($line);
56+
$referenceData = $this->extractEmbeddedReference($line);
5857
if (filter_var($referenceData->reference, FILTER_VALIDATE_URL) !== false) {
5958
$result[] = new ExternalMenuEntryNode($referenceData->reference, TitleNode::fromString($referenceData->text ?? $referenceData->reference));
6059
continue;

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/AbstractMenuEntryNodeTransformer.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
1313
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
1414
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
15-
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
1615
use phpDocumentor\Guides\Nodes\Menu\SectionMenuEntryNode;
17-
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1816
use phpDocumentor\Guides\Nodes\Node;
1917
use Psr\Log\LoggerInterface;
2018

2119
use function assert;
20+
use function count;
2221
use function sprintf;
2322
use function str_starts_with;
2423

@@ -57,7 +56,19 @@ public function leaveNode(Node $node, CompilerContext $compilerContext): Node|nu
5756

5857
$menuEntries = $this->handleMenuEntry($this->currentMenu, $node, $compilerContext);
5958

60-
return $menuEntries[0] ?? null;
59+
if (count($menuEntries) === 0) {
60+
return null;
61+
}
62+
63+
if (count($menuEntries) === 1) {
64+
return $menuEntries[0];
65+
}
66+
67+
foreach ($menuEntries as $menuEntry) {
68+
$compilerContext->getShadowTree()->getParent()?->addChild($menuEntry);
69+
}
70+
71+
return null;
6172
}
6273

6374
/** @return list<MenuEntryNode> */

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/ContentMenuNodeWithSectionEntryTransformer.php

Lines changed: 0 additions & 100 deletions
This file was deleted.

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/GlobMenuEntryNodeTransformer.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,26 @@
1212
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
1313
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1414
use phpDocumentor\Guides\Nodes\Node;
15-
use phpDocumentor\Guides\Nodes\TitleNode;
1615

1716
use function array_pop;
1817
use function assert;
1918
use function explode;
2019
use function implode;
2120
use function in_array;
22-
use function is_string;
2321
use function preg_match;
2422
use function str_replace;
2523
use function str_starts_with;
2624

2725
final class GlobMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
2826
{
27+
// Setting a default level prevents PHP errors in case of circular references
28+
private const DEFAULT_MAX_LEVELS = 10;
29+
30+
/** @return list<MenuEntryNode> */
2931
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, CompilerContext $compilerContext): array
3032
{
3133
assert($node instanceof GlobMenuEntryNode);
34+
$maxDepth = (int) $currentMenu->getOption('maxdepth', self::DEFAULT_MAX_LEVELS);
3235
$documentEntries = $compilerContext->getProjectNode()->getAllDocumentEntries();
3336
$currentPath = $compilerContext->getDocumentNode()->getFilePath();
3437
$globExclude = explode(',', $currentMenu->getOption('globExclude') . '');
@@ -46,10 +49,17 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, C
4649
continue;
4750
}
4851

52+
foreach ($currentMenu->getChildren() as $menuEntry) {
53+
if ($menuEntry instanceof InternalMenuEntryNode && $menuEntry->getUrl() === $documentEntry->getFile()) {
54+
// avoid duplicates
55+
continue 2;
56+
}
57+
}
58+
4959
$documentEntriesInTree[] = $documentEntry;
5060
$menuEntry = new InternalMenuEntryNode(
5161
$documentEntry->getFile(),
52-
is_string($node->getValue()) ? TitleNode::fromString($node->getValue()) : $documentEntry->getTitle(),
62+
$documentEntry->getTitle(),
5363
[],
5464
false,
5565
1,
@@ -58,7 +68,7 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, C
5868
$this->isCurrent($documentEntry, $currentPath),
5969
);
6070
if (!$currentMenu->hasOption('titlesonly')) {
61-
$this->addSubSectionsToMenuEntries($documentEntry, $menuEntry);
71+
$this->addSubSectionsToMenuEntries($documentEntry, $menuEntry, $maxDepth - 1);
6272
}
6373

6474
if ($currentMenu instanceof TocNode) {

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/InternalMenuEntryNodeTransformer.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
99
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
1010
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
11-
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
1211
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1312
use phpDocumentor\Guides\Nodes\Node;
1413
use Psr\Log\LoggerInterface;
@@ -20,6 +19,9 @@
2019

2120
class InternalMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
2221
{
22+
// Setting a default level prevents PHP errors in case of circular references
23+
private const DEFAULT_MAX_LEVELS = 10;
24+
2325
public function __construct(
2426
LoggerInterface $logger,
2527
) {
@@ -31,11 +33,13 @@ public function supports(Node $node): bool
3133
return $node instanceof MenuNode || $node instanceof InternalMenuEntryNode;
3234
}
3335

36+
/** @return list<MenuEntryNode> */
3437
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, CompilerContext $compilerContext): array
3538
{
3639
assert($node instanceof InternalMenuEntryNode);
3740
$documentEntries = $compilerContext->getProjectNode()->getAllDocumentEntries();
3841
$currentPath = $compilerContext->getDocumentNode()->getFilePath();
42+
$maxDepth = (int) $currentMenu->getOption('maxdepth', self::DEFAULT_MAX_LEVELS);
3943
foreach ($documentEntries as $documentEntry) {
4044
if (
4145
!self::isEqualAbsolutePath($documentEntry->getFile(), $node, $currentPath)
@@ -56,7 +60,7 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, C
5660
$this->isCurrent($documentEntry, $currentPath),
5761
);
5862
if (!$currentMenu->hasOption('titlesonly')) {
59-
$this->addSubSectionsToMenuEntries($documentEntry, $menuEntry);
63+
$this->addSubSectionsToMenuEntries($documentEntry, $menuEntry, $maxDepth - 1);
6064
}
6165

6266
if ($currentMenu instanceof TocNode) {

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/SectionMenuEntryNodeTransformer.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
46

57
use phpDocumentor\Guides\Compiler\CompilerContext;
6-
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
78
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
89
use phpDocumentor\Guides\Nodes\Menu\MenuNode;
910
use phpDocumentor\Guides\Nodes\Menu\SectionMenuEntryNode;
10-
use phpDocumentor\Guides\Nodes\Menu\TocNode;
1111
use phpDocumentor\Guides\Nodes\Node;
1212
use Psr\Log\LoggerInterface;
1313

14+
use function assert;
15+
16+
use const PHP_INT_MAX;
17+
1418
final class SectionMenuEntryNodeTransformer extends AbstractMenuEntryNodeTransformer
1519
{
1620
private const DEFAULT_MAX_LEVELS = PHP_INT_MAX;
21+
1722
public function __construct(
1823
LoggerInterface $logger,
1924
) {
@@ -25,6 +30,7 @@ public function supports(Node $node): bool
2530
return $node instanceof MenuNode || $node instanceof SectionMenuEntryNode;
2631
}
2732

33+
/** @return list<MenuEntryNode> */
2834
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, CompilerContext $compilerContext): array
2935
{
3036
assert($node instanceof SectionMenuEntryNode);
@@ -38,6 +44,7 @@ protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, C
3844
1,
3945
);
4046
$this->addSubSectionsToMenuEntries($documentEntry, $menuEntry, $depth);
47+
4148
return $menuEntry->getSections();
4249
}
4350

@@ -46,4 +53,4 @@ public function getPriority(): int
4653
// After DocumentEntryTransformer
4754
return 4500;
4855
}
49-
}
56+
}

packages/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/SubInternalMenuEntryNodeTransformer.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
66

7-
use Exception;
87
use phpDocumentor\Guides\Compiler\CompilerContext;
9-
use phpDocumentor\Guides\Compiler\NodeTransformer;
108
use phpDocumentor\Guides\Nodes\DocumentTree\DocumentEntryNode;
119
use phpDocumentor\Guides\Nodes\Menu\InternalMenuEntryNode;
1210
use phpDocumentor\Guides\Nodes\Menu\MenuEntryNode;
@@ -34,7 +32,7 @@ public function supports(Node $node): bool
3432
return $node instanceof TocNode || $node instanceof NavMenuNode || $node instanceof InternalMenuEntryNode;
3533
}
3634

37-
35+
/** @return list<MenuEntryNode> */
3836
protected function handleMenuEntry(MenuNode $currentMenu, MenuEntryNode $node, CompilerContext $compilerContext): array
3937
{
4038
assert($node instanceof InternalMenuEntryNode);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers;
6+
7+
use phpDocumentor\Guides\Compiler\CompilerContext;
8+
use phpDocumentor\Guides\Compiler\NodeTransformer;
9+
use phpDocumentor\Guides\Nodes\Menu\TocNode;
10+
use phpDocumentor\Guides\Nodes\Node;
11+
12+
use function assert;
13+
14+
/** @implements NodeTransformer<TocNode> */
15+
final class TocNodeTransformer implements NodeTransformer
16+
{
17+
public function enterNode(Node $node, CompilerContext $compilerContext): Node
18+
{
19+
assert($node instanceof TocNode);
20+
$compilerContext->getDocumentNode()->addTocNode($node);
21+
22+
return $node;
23+
}
24+
25+
public function leaveNode(Node $node, CompilerContext $compilerContext): Node|null
26+
{
27+
return $node;
28+
}
29+
30+
public function supports(Node $node): bool
31+
{
32+
return $node instanceof TocNode;
33+
}
34+
35+
public function getPriority(): int
36+
{
37+
return 1000;
38+
}
39+
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ abstract class MenuNode extends CompoundNode
2828
private InlineCompoundNode|null $caption = null;
2929
protected const DEFAULT_DEPTH = PHP_INT_MAX;
3030

31-
/**
32-
* @param MenuEntryNode[] $menuEntries
33-
*/
31+
/** @param MenuEntryNode[] $menuEntries */
3432
public function __construct(array $menuEntries)
3533
{
3634
parent::__construct($menuEntries);

0 commit comments

Comments
 (0)