From f030169c1b577150f5541c2540f144844b706d67 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Fri, 11 Oct 2024 14:10:54 +0200 Subject: [PATCH] [FEATURE] Support automatically created multi-level menus Resolves https://github.com/phpDocumentor/guides/issues/1108 --- .../src/Compiler/Passes/AutomaticMenuPass.php | 55 +++++- .../src/Compiler/Passes/GlobalMenuPass.php | 15 +- .../expected/index.html | 31 +--- .../automatic-multilevel-menu/input/skip | 1 - .../expected/dir2/index.html | 167 +++++++++++++++++ .../expected/dir2/somePage.html | 168 ++++++++++++++++++ .../multi-nested-menu-md/expected/index.html | 166 +++++++++++++++++ .../multi-nested-menu-md/input/anotherPage.md | 3 + .../multi-nested-menu-md/input/dir1/index.md | 3 + .../multi-nested-menu-md/input/dir2/index.md | 3 + .../input/dir2/somePage.md | 4 + .../input/dir2/subdir1/index.md | 3 + .../input/dir2/subdir2/index.md | 3 + .../input/dir2/subdir2/somePage.md | 4 + .../input/dir2/subdir2/subsubdir1/index.md | 3 + .../input/dir2/yetAnotherPage.md | 3 + .../multi-nested-menu-md/input/guides.xml | 11 ++ .../multi-nested-menu-md/input/index.md | 3 + .../multi-nested-menu-md/input/somePage.md | 4 + .../input/yetAnotherPage.md | 3 + .../nested-menu-md/expected/dir2/index.html | 39 +++- .../expected/dir2/somePage.html | 46 +++-- .../nested-menu-md/expected/index.html | 41 +++-- .../markdown-full/nested-menu-md/input/skip | 1 - 24 files changed, 711 insertions(+), 69 deletions(-) delete mode 100644 tests/Integration/tests-full/automatic_menu/automatic-multilevel-menu/input/skip create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/expected/dir2/index.html create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/expected/dir2/somePage.html create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/expected/index.html create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/anotherPage.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir1/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/somePage.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/subdir1/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/subdir2/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/subdir2/somePage.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/subdir2/subsubdir1/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/dir2/yetAnotherPage.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/guides.xml create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/index.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/somePage.md create mode 100644 tests/Integration/tests-full/markdown-full/multi-nested-menu-md/input/yetAnotherPage.md delete mode 100644 tests/Integration/tests-full/markdown-full/nested-menu-md/input/skip diff --git a/packages/guides/src/Compiler/Passes/AutomaticMenuPass.php b/packages/guides/src/Compiler/Passes/AutomaticMenuPass.php index 8dee004fd..077578628 100644 --- a/packages/guides/src/Compiler/Passes/AutomaticMenuPass.php +++ b/packages/guides/src/Compiler/Passes/AutomaticMenuPass.php @@ -17,11 +17,20 @@ use phpDocumentor\Guides\Compiler\CompilerPass; use phpDocumentor\Guides\Nodes\DocumentNode; use phpDocumentor\Guides\Settings\SettingsManager; +use Psr\Log\LoggerInterface; + +use function array_pop; +use function count; +use function explode; +use function implode; +use function in_array; +use function sprintf; final class AutomaticMenuPass implements CompilerPass { public function __construct( private readonly SettingsManager $settingsManager, + private readonly LoggerInterface|null $logger = null, ) { } @@ -43,6 +52,7 @@ public function run(array $documents, CompilerContextInterface $compilerContext) $projectNode = $compilerContext->getProjectNode(); $rootDocumentEntry = $projectNode->getRootDocumentEntry(); + $indexNames = explode(',', $this->settingsManager->getProjectSettings()->getIndexName()); foreach ($documents as $documentNode) { if ($documentNode->isOrphan()) { // Do not add orphans to the automatic menu @@ -53,9 +63,48 @@ public function run(array $documents, CompilerContextInterface $compilerContext) continue; } - $documentEntry = $projectNode->getDocumentEntry($documentNode->getFilePath()); - $documentEntry->setParent($rootDocumentEntry); - $rootDocumentEntry->addChild($documentEntry); + $filePath = $documentNode->getFilePath(); + $pathParts = explode('/', $filePath); + $documentEntry = $projectNode->getDocumentEntry($filePath); + if (count($pathParts) === 1 || count($pathParts) === 2 && in_array($pathParts[1], $indexNames, true)) { + $documentEntry->setParent($rootDocumentEntry); + $rootDocumentEntry->addChild($documentEntry); + continue; + } + + $fileName = array_pop($pathParts); + $path = implode('/', $pathParts); + if (in_array($fileName, $indexNames, true)) { + array_pop($pathParts); + $path = implode('/', $pathParts); + } + + $parentFound = false; + foreach ($indexNames as $indexName) { + $indexFile = $path . '/' . $indexName; + $parentEntry = $projectNode->findDocumentEntry($indexFile); + if ($parentEntry === null) { + continue; + } + + $documentEntry->setParent($parentEntry); + $parentEntry->addChild($documentEntry); + $parentFound = true; + break; + } + + if ($parentFound) { + continue; + } + + $parentEntry = $projectNode->findDocumentEntry($path); + if ($parentEntry === null) { + $this->logger?->warning(sprintf('No parent found for file "%s/%s" attaching it to the document root instead. ', $path, $fileName)); + continue; + } + + $documentEntry->setParent($parentEntry); + $parentEntry->addChild($documentEntry); } return $documents; diff --git a/packages/guides/src/Compiler/Passes/GlobalMenuPass.php b/packages/guides/src/Compiler/Passes/GlobalMenuPass.php index 13ec50799..bdbabff9a 100644 --- a/packages/guides/src/Compiler/Passes/GlobalMenuPass.php +++ b/packages/guides/src/Compiler/Passes/GlobalMenuPass.php @@ -90,14 +90,23 @@ public function run(array $documents, CompilerContextInterface $compilerContext) private function getNavMenuNodeFromDocumentEntries(CompilerContextInterface $compilerContext): NavMenuNode { - $menuEntries = []; $rootDocumentEntry = $compilerContext->getProjectNode()->getRootDocumentEntry(); + $menuEntries = $this->getMenuEntriesFromDocumentEntries($rootDocumentEntry); + + return new NavMenuNode($menuEntries); + } + + /** @return InternalMenuEntryNode[] */ + public function getMenuEntriesFromDocumentEntries(DocumentEntryNode $rootDocumentEntry): array + { + $menuEntries = []; foreach ($rootDocumentEntry->getChildren() as $documentEntryNode) { - $newMenuEntry = new InternalMenuEntryNode($documentEntryNode->getFile(), $documentEntryNode->getTitle(), [], false, 1); + $children = $this->getMenuEntriesFromDocumentEntries($documentEntryNode); + $newMenuEntry = new InternalMenuEntryNode($documentEntryNode->getFile(), $documentEntryNode->getTitle(), $children, false, 1); $menuEntries[] = $newMenuEntry; } - return new NavMenuNode($menuEntries); + return $menuEntries; } private function getNavMenuNodefromTocNode(CompilerContextInterface $compilerContext, TocNode $tocNode, string|null $menuType = null): NavMenuNode diff --git a/tests/Integration/tests-full/automatic_menu/automatic-multilevel-menu/expected/index.html b/tests/Integration/tests-full/automatic_menu/automatic-multilevel-menu/expected/index.html index 407d880ed..2a663cebf 100644 --- a/tests/Integration/tests-full/automatic_menu/automatic-multilevel-menu/expected/index.html +++ b/tests/Integration/tests-full/automatic_menu/automatic-multilevel-menu/expected/index.html @@ -52,11 +52,11 @@
  • Another Page -