diff --git a/lib/Service/PageService.php b/lib/Service/PageService.php index 2b4360086..ba342f9ae 100644 --- a/lib/Service/PageService.php +++ b/lib/Service/PageService.php @@ -390,36 +390,62 @@ private function getIndexPageFile(Folder $folder): File { * @throws NotPermittedException */ 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)) { + $subPageInfos = []; + $folderNodes = $folder->getDirectoryListing(); + + $hasPages = false; + $pageFiles = []; + foreach ($folderNodes as $node) { + // Get page infos of subfolders + if ($recurse && $node instanceof Folder) { try { - $page = $this->getPageByFile($node, $folder); + array_push($subPageInfos, ...$this->getPagesFromFolder($collectiveId, $node, $userId, true)); } catch (NotFoundException) { - // If parent folder doesn't have an index page, it throws NotFoundException. Let's ignore it. - continue; + // If parent folder doesn't have an index page, `getPagesFromFolder()` throws NotFoundException even though having subpages. + $hasPages = true; } - if (NodeHelper::isIndexPage($node)) { - $indexPage = $page; - } else { - $pageInfos[] = $page; + } elseif ($node instanceof File && NodeHelper::isPage($node)) { + $hasPages = true; + $pageFiles[] = $node; + if (!isset($indexPage) && NodeHelper::isIndexPage($node)) { + $indexPage = $this->getPageByFile($node, $folder); } - } elseif ($recurse && $node instanceof Folder) { - array_push($pageInfos, ...$this->getPagesFromFolder($collectiveId, $node, $userId, true)); } } - if (!$indexPage) { - if (!$forceIndex && count($pageInfos) === 0) { + // One of the subfolders had a page + if (isset($subPageInfos[0])) { + $hasPages = true; + } + + if (!isset($indexPage)) { + if ($hasPages || $forceIndex) { + // Create missing index page if folder or subfolders have page files (or forceIndex) + $indexPage = $this->newPage($collectiveId, $folder, PageInfo::INDEX_PAGE_TITLE, $userId); + } else { + // Ignore folders without an index page return []; } - $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) { + if (NodeHelper::isIndexPage($pageFile)) { + continue; + } + + try { + $page = $this->getPageByFile($pageFile, $folder); + } catch (NotFoundException) { + // If parent folder doesn't have an index page, it throws NotFoundException. + continue; + } + + $folderPageInfos[] = $page; + } + + return array_merge([$indexPage], $folderPageInfos, $subPageInfos); } /** diff --git a/tests/Unit/Service/PageServiceTest.php b/tests/Unit/Service/PageServiceTest.php index e71caf5b9..f12b05c87 100644 --- a/tests/Unit/Service/PageServiceTest.php +++ b/tests/Unit/Service/PageServiceTest.php @@ -220,7 +220,7 @@ public function testGetPagesFromFolder(): void { $file->method('getMountPoint') ->willReturn($mountPoint); $file->method('getInternalPath') - ->willReturn('Collectives/testfolder/Readme.md'); + ->willReturn('Collectives/testfolder/' . $fileName); $file->method('getMTime') ->willReturn(0); $file->method('getSize') @@ -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';