rootFolder = $this->createMock(IRootFolder::class); $this->userFolder = $this->createMock(Folder::class); $this->user = $this->createMock(IUser::class); $this->user->method('getUID')->willReturn('admin'); $this->rootFolder->method('getUserFolder')->with('admin')->willReturn($this->userFolder); $this->service = new ShortcutService($this->rootFolder); } public function testCreateWritesBareFileId(): void { $target = $this->createMock(File::class); $target->method('getId')->willReturn(320); $target->method('getName')->willReturn('main.tex'); $target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $target->method('getMimeType')->willReturn('application/x-tex'); $destination = $this->createMock(Folder::class); $destination->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $destination->method('nodeExists')->with('main.tex.nextcloudshortcut')->willReturn(false); $created = $this->createMock(File::class); $created->method('getId')->willReturn(999); $created->method('getName')->willReturn('main.tex.nextcloudshortcut'); $created->method('getPath')->willReturn('/admin/files/test/main.tex.nextcloudshortcut'); $destination->expects($this->once()) ->method('newFile') ->with('main.tex.nextcloudshortcut', '320') ->willReturn($created); $this->userFolder->method('getFirstNodeById')->with(320)->willReturn($target); $this->userFolder->method('get')->with('/test')->willReturn($destination); $this->userFolder->method('getRelativePath') ->with('/admin/files/test/main.tex.nextcloudshortcut') ->willReturn('/test/main.tex.nextcloudshortcut'); $result = $this->service->create($this->user, 320, '/test'); $this->assertSame(999, $result['fileId']); $this->assertSame(320, $result['targetFileId']); $this->assertSame('file', $result['targetType']); $this->assertSame('main.tex.nextcloudshortcut', $result['name']); } public function testCreateConflict(): void { $target = $this->createMock(File::class); $target->method('getId')->willReturn(1); $target->method('getName')->willReturn('a.txt'); $target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $target->method('getMimeType')->willReturn('text/plain'); $this->userFolder->method('getFirstNodeById')->willReturn($target); $this->userFolder->method('get')->with('/')->willReturn($this->userFolder); $this->userFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $this->userFolder->method('nodeExists')->with('a.txt.nextcloudshortcut')->willReturn(true); $this->expectException(ConflictException::class); $this->service->create($this->user, 1, '/'); } public function testResolveFile(): void { $shortcut = $this->createMock(File::class); $shortcut->method('getId')->willReturn(50); $shortcut->method('getName')->willReturn('main.tex.nextcloudshortcut'); $shortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $shortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut'); $shortcut->method('getContent')->willReturn("320\n"); $target = $this->createMock(File::class); $target->method('getId')->willReturn(320); $target->method('getName')->willReturn('main.tex'); $target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $target->method('getMimeType')->willReturn('application/x-tex'); $target->method('getPath')->willReturn('/admin/files/docs/main.tex'); $parent = $this->createMock(Folder::class); $parent->method('getPath')->willReturn('/admin/files/docs'); $target->method('getParent')->willReturn($parent); $this->userFolder->method('getFirstNodeById')->willReturnMap([ [50, $shortcut], [320, $target], ]); $this->userFolder->method('getRelativePath')->willReturnMap([ ['/admin/files/docs/main.tex', '/docs/main.tex'], ['/admin/files/docs', '/docs'], ]); $result = $this->service->resolve($this->user, 50); $this->assertSame(320, $result['targetFileId']); $this->assertSame('file', $result['targetType']); $this->assertSame('/docs/main.tex', $result['path']); $this->assertSame('/docs', $result['dirname']); } public function testResolveInvalidContents(): void { $shortcut = $this->createMock(File::class); $shortcut->method('getName')->willReturn('bad.nextcloudshortcut'); $shortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $shortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut'); $shortcut->method('getContent')->willReturn('not-an-id'); $this->userFolder->method('getFirstNodeById')->willReturn($shortcut); $this->expectException(InvalidPathException::class); $this->service->resolve($this->user, 1); } public function testCreateCanonicalizesShortcutTarget(): void { $innerShortcut = $this->createMock(File::class); $innerShortcut->method('getId')->willReturn(10); $innerShortcut->method('getName')->willReturn('a.nextcloudshortcut'); $innerShortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $innerShortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut'); $innerShortcut->method('getContent')->willReturn('320'); $realTarget = $this->createMock(File::class); $realTarget->method('getId')->willReturn(320); $realTarget->method('getName')->willReturn('main.tex'); $realTarget->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $realTarget->method('getMimeType')->willReturn('application/x-tex'); $created = $this->createMock(File::class); $created->method('getId')->willReturn(11); $created->method('getName')->willReturn('main.tex.nextcloudshortcut'); $created->method('getPath')->willReturn('/admin/files/main.tex.nextcloudshortcut'); $this->userFolder->method('getFirstNodeById')->willReturnMap([ [10, $innerShortcut], [320, $realTarget], ]); $this->userFolder->method('get')->with('/')->willReturn($this->userFolder); $this->userFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $this->userFolder->method('nodeExists')->with('main.tex.nextcloudshortcut')->willReturn(false); $this->userFolder->expects($this->once()) ->method('newFile') ->with('main.tex.nextcloudshortcut', '320') ->willReturn($created); $this->userFolder->method('getRelativePath')->willReturn('/main.tex.nextcloudshortcut'); $result = $this->service->create($this->user, 10, '/'); $this->assertSame(320, $result['targetFileId']); $this->assertSame(11, $result['fileId']); } }