From 56211128e82365411060d4703e888f8c84ac7a7c Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 6 Nov 2024 15:21:09 +0100 Subject: [PATCH] fix(PageService): Create index page if folder or subfolders have pages Fixes the scenario where a folder is missing the index page but one of its subfolders contains pages. Signed-off-by: Jonas --- lib/Service/PageService.php | 61 +++++++++++++-------- tests/Unit/Service/PageServiceTest.php | 73 ++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/lib/Service/PageService.php b/lib/Service/PageService.php index 2b4360086..00803a8de 100644 --- a/lib/Service/PageService.php +++ b/lib/Service/PageService.php @@ -391,35 +391,50 @@ private function getIndexPageFile(Folder $folder): File { */ public function getPagesFromFolder(int $collectiveId, Folder $folder, string $userId, bool $recurse = false, bool $forceIndex = false): array { $pageInfos = []; - $indexPage = null; - - // Add subpages and recurse over subfolders - foreach ($folder->getDirectoryListing() as $node) { - if ($node instanceof File && NodeHelper::isPage($node)) { - try { - $page = $this->getPageByFile($node, $folder); - } catch (NotFoundException) { - // If parent folder doesn't have an index page, it throws NotFoundException. Let's ignore it. - continue; - } - if (NodeHelper::isIndexPage($node)) { - $indexPage = $page; - } else { - $pageInfos[] = $page; - } - } elseif ($recurse && $node instanceof Folder) { - array_push($pageInfos, ...$this->getPagesFromFolder($collectiveId, $node, $userId, true)); + $folderNodes = $folder->getDirectoryListing(); + + // Get page infos of subfolders + if ($recurse) { + $subfolders = array_filter($folderNodes, static function (Node $node) { + return $node instanceof Folder; + }); + foreach ($subfolders as $subfolder) { + array_push($pageInfos, ...$this->getPagesFromFolder($collectiveId, $subfolder, $userId, true)); } } - if (!$indexPage) { - if (!$forceIndex && count($pageInfos) === 0) { - return []; - } + $pageFiles = array_filter($folderNodes, static function (Node $node) { + return $node instanceof File && NodeHelper::isPage($node); + }); + + // Create missing index file if folder or subfolders have page files (or forceIndex) + $hasIndexFile = (bool)array_filter($folderNodes, static function (Node $node) { + return $node instanceof File && NodeHelper::isIndexPage($node); + }); + $hasPages = count($pageFiles) > 0 || count($pageInfos) > 0; + if (!$hasIndexFile && ($hasPages || $forceIndex)) { $indexPage = $this->newPage($collectiveId, $folder, PageInfo::INDEX_PAGE_TITLE, $userId); } - return array_merge([$indexPage], $pageInfos); + // Add markdown files from this folder + $folderPageInfos = []; + foreach ($pageFiles as $pageFile) { + try { + $page = $this->getPageByFile($pageFile, $folder); + } catch (NotFoundException) { + // If parent folder doesn't have an index page, it throws NotFoundException. + continue; + } + + if (NodeHelper::isIndexPage($pageFile)) { + $indexPage = $page; + } else { + $folderPageInfos[] = $page; + } + array_unshift($folderPageInfos, $indexPage); + } + + return array_merge($folderPageInfos, $pageInfos); } /** diff --git a/tests/Unit/Service/PageServiceTest.php b/tests/Unit/Service/PageServiceTest.php index e71caf5b9..1dff3e139 100644 --- a/tests/Unit/Service/PageServiceTest.php +++ b/tests/Unit/Service/PageServiceTest.php @@ -251,6 +251,79 @@ public function testGetPagesFromFolder(): void { self::assertEquals($pageInfos, $this->service->getPagesFromFolder($this->collectiveId, $folder, $this->userId, true)); } + public function testGetPagesFromFolderWithMissingIndex(): void { + $files = []; + $pageInfos = []; + + $mountPoint = $this->getMockBuilder(MountPoint::class) + ->disableOriginalConstructor() + ->getMock(); + $mountPoint->method('getMountPoint')->willReturn('/files/user/Collectives/collective/'); + + $folder = $this->createMock(Folder::class); + $folder->method('getParent') + ->willReturn($folder); + $folder->method('getName') + ->willReturn('testfolder'); + + $file1Name = 'page1.md'; + $file1 = $this->getMockBuilder(File::class) + ->disableOriginalConstructor() + ->getMock(); + $file1->method('getId') + ->willReturn(1); + $file1->method('getName') + ->willReturn($file1Name); + $file1->method('getParent') + ->willReturn($folder); + $file1->method('getMountPoint') + ->willReturn($mountPoint); + $file1->method('getInternalPath') + ->willReturn('Collectives/testfolder/' . $file1Name); + $file1->method('getMTime') + ->willReturn(0); + $file1->method('getSize') + ->willReturn(0); + $files[] = $file1; + + $folder->method('getDirectoryListing') + ->willReturn($files); + + $pageInfo1 = new PageInfo(); + $pageInfo1->fromFile($file1, 1); + $pageInfo1->setParentId(101); + $pageInfos[] = $pageInfo1; + + $indexFile = $this->createMock(File::class); + $indexFile->method('getId') + ->willReturn(101); + $indexFile->method('getName') + ->willReturn('Readme.md'); + $folder->method('get') + ->willReturn($indexFile); + $indexFile->method('getParent') + ->willReturn($folder); + $indexFile->method('getMountPoint') + ->willReturn($mountPoint); + $indexFile->method('getInternalPath') + ->willReturn('Collectives/testfolder/Readme.md'); + $indexFile->method('getMTime') + ->willReturn(0); + $indexFile->method('getSize') + ->willReturn(0); + $folder->method('newFile') + ->willReturn($indexFile); + + $indexPageInfo = new PageInfo(); + $indexPageInfo->fromFile($indexFile, 1); + $indexPageInfo->setParentId(101); + $indexPageInfo->setTitle('testfolder'); + $indexPageInfo->setLastUserId('jane'); + array_unshift($pageInfos, $indexPageInfo); + + self::assertEquals($pageInfos, $this->service->getPagesFromFolder($this->collectiveId, $folder, $this->userId, true)); + } + public function testGetPageLink(): void { $collectiveName = 'My Collective';