diff --git a/lib/Service/AttachmentService.php b/lib/Service/AttachmentService.php index 2373dfb0a47..8ecc9f6a612 100755 --- a/lib/Service/AttachmentService.php +++ b/lib/Service/AttachmentService.php @@ -719,9 +719,18 @@ public function copyAttachmentsInFolder(Folder $sourceFolder, Folder $targetFold continue; } - if ($targetNode instanceof File && $targetAttachmentDir instanceof Folder) { + if ($targetNode instanceof File + && $sourceAttachmentDir instanceof Folder + && $targetAttachmentDir instanceof Folder) { + $fileIdMapping = []; + foreach ($sourceAttachmentDir->getDirectoryListing() as $sourceAttachment) { + if ($sourceAttachment instanceof File && $targetAttachmentDir->nodeExists($sourceAttachment->getName())) { + $fileIdMapping[] = [$sourceAttachment->getId(), $targetAttachmentDir->get($sourceAttachment->getName())->getId()]; + } + } $targetAttachmentDir->move($targetFolder->getPath() . '/' . $targetAttachmentDirName); self::replaceAttachmentFolderId($sourceNode, $targetNode); + self::replaceAttachmentFileIds($targetNode, $fileIdMapping); } } } diff --git a/tests/unit/Service/AttachmentServiceTest.php b/tests/unit/Service/AttachmentServiceTest.php index f915d658c31..2d9d70aca66 100755 --- a/tests/unit/Service/AttachmentServiceTest.php +++ b/tests/unit/Service/AttachmentServiceTest.php @@ -6,6 +6,14 @@ use OCA\Text\Service\AttachmentService; use OCP\Files\File; use OCP\Files\Folder; +use OCP\Files\IFilenameValidator; +use OCP\Files\IMimeTypeDetector; +use OCP\Files\IRootFolder; +use OCP\FilesMetadata\IFilesMetadataManager; +use OCP\IPreview; +use OCP\ISession; +use OCP\IURLGenerator; +use OCP\Share\IManager as ShareManager; use PHPUnit\Framework\TestCase; class AttachmentServiceTest extends TestCase { @@ -267,4 +275,62 @@ public function testReplaceAttachmentFileIdNoReplace(string $sourceContent): voi AttachmentService::replaceAttachmentFileIds($target, [[1, 2]]); $this->assertEquals($sourceContent, $replacedContent); } + + public function testCopyAttachmentsInFolderRewritesFolderAndFileIds(): void { + $service = new AttachmentService( + $this->createMock(IRootFolder::class), + $this->createMock(ShareManager::class), + $this->createMock(IPreview::class), + $this->createMock(IMimeTypeDetector::class), + $this->createMock(IURLGenerator::class), + $this->createMock(IFilenameValidator::class), + $this->createMock(IFilesMetadataManager::class), + $this->createMock(ISession::class), + ); + + $sourceMd = $this->createMock(File::class); + $sourceMd->method('getId')->willReturn(1); + $sourceMd->method('getName')->willReturn('page.md'); + $sourceMd->method('getMimeType')->willReturn('text/markdown'); + + $sourceAttachment = $this->createMock(File::class); + $sourceAttachment->method('getId')->willReturn(10); + $sourceAttachment->method('getName')->willReturn('board.whiteboard'); + + $sourceAttachmentDir = $this->createMock(Folder::class); + $sourceAttachmentDir->method('getDirectoryListing')->willReturn([$sourceAttachment]); + + $sourceFolder = $this->createMock(Folder::class); + $sourceFolder->method('getDirectoryListing')->willReturn([$sourceMd]); + $sourceFolder->method('get')->with('.attachments.1')->willReturn($sourceAttachmentDir); + + $content = "![a.png](.attachments.1/a.png)\n\n[board](https://localhost/f/10 (preview))\n"; + $targetMd = $this->createMock(File::class); + $targetMd->method('getId')->willReturn(2); + $targetMd->method('getContent')->willReturnCallback(function () use (&$content) { + return $content; + }); + $targetMd->method('putContent')->willReturnCallback(function (string $new) use (&$content): void { + $content = $new; + }); + + $targetAttachment = $this->createMock(File::class); + $targetAttachment->method('getId')->willReturn(20); + + $targetAttachmentDir = $this->createMock(Folder::class); + $targetAttachmentDir->method('nodeExists')->with('board.whiteboard')->willReturn(true); + $targetAttachmentDir->method('get')->with('board.whiteboard')->willReturn($targetAttachment); + $targetAttachmentDir->expects($this->once())->method('move')->with('/target/.attachments.2'); + + $targetFolder = $this->createMock(Folder::class); + $targetFolder->method('getPath')->willReturn('/target'); + $targetFolder->method('get')->willReturnMap([ + ['page.md', $targetMd], + ['.attachments.1', $targetAttachmentDir], + ]); + + $service->copyAttachmentsInFolder($sourceFolder, $targetFolder); + + $this->assertEquals("![a.png](.attachments.2/a.png)\n\n[board](https://localhost/f/20 (preview))\n", $content); + } }