-
Notifications
You must be signed in to change notification settings - Fork 139
feat: make preview conversion timeout and max file size configurable #5408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -66,16 +66,17 @@ public function convertFileTo(File $file, string $format) { | |||||||||||||||
| if ($stream === false) { | ||||||||||||||||
| throw new Exception('Failed to open stream'); | ||||||||||||||||
| } | ||||||||||||||||
| return $this->convertTo($file->getName(), $stream, $format); | ||||||||||||||||
| $timeout = $this->appConfig->getPreviewConversionTimeout(); | ||||||||||||||||
| return $this->convertTo($file->getName(), $stream, $format, [], $timeout); | ||||||||||||||||
|
||||||||||||||||
| return $this->convertTo($file->getName(), $stream, $format, [], $timeout); | |
| try { | |
| return $this->convertTo($file->getName(), $stream, $format, [], $timeout); | |
| } finally { | |
| fclose($stream); | |
| } |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convertFileTo() now unconditionally uses getPreviewConversionTimeout(). This method is also used outside the preview code path (e.g. via ConversionProvider::convertFile()), so changing it makes the preview timeout setting affect non-preview conversions as well, which is inconsistent with the config name/docs and can change behavior unexpectedly.
Consider keeping convertFileTo() on the default timeout and instead passing the preview timeout from Office::getThumbnail() (e.g. by adding an optional timeout parameter to convertFileTo() or introducing a dedicated preview-only method).
| $timeout = $this->appConfig->getPreviewConversionTimeout(); | |
| return $this->convertTo($file->getName(), $stream, $format, [], $timeout); | |
| } | |
| return $this->convertTo($file->getName(), $stream, $format); | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| namespace Tests\Richdocuments\Preview; | ||
|
|
||
| use OCA\Richdocuments\AppConfig; | ||
| use OCA\Richdocuments\Capabilities; | ||
| use OCA\Richdocuments\Preview\Office; | ||
| use OCA\Richdocuments\Service\RemoteService; | ||
| use OCP\Files\File; | ||
| use PHPUnit\Framework\MockObject\MockObject; | ||
| use PHPUnit\Framework\TestCase; | ||
juliusknorr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| use Psr\Log\LoggerInterface; | ||
|
|
||
| class OfficeTest extends TestCase { | ||
| private RemoteService&MockObject $remoteService; | ||
| private LoggerInterface&MockObject $logger; | ||
| private AppConfig&MockObject $appConfig; | ||
| private Capabilities&MockObject $capabilities; | ||
| private Office $provider; | ||
|
|
||
| protected function setUp(): void { | ||
| parent::setUp(); | ||
|
|
||
| $this->remoteService = $this->createMock(RemoteService::class); | ||
| $this->logger = $this->createMock(LoggerInterface::class); | ||
| $this->appConfig = $this->createMock(AppConfig::class); | ||
| $this->capabilities = $this->createMock(Capabilities::class); | ||
| $this->capabilities->method('getCapabilities')->willReturn(['richdocuments' => []]); | ||
|
|
||
| $this->provider = new class($this->remoteService, $this->logger, $this->appConfig, $this->capabilities) extends Office { | ||
| #[\Override] | ||
| public function getMimeType(): string { | ||
| return '/application\\/test/'; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| public function testGetThumbnailSkipsConversionWhenFileIsTooLarge(): void { | ||
| $file = $this->createMock(File::class); | ||
| $file->expects($this->once())->method('getSize')->willReturn(101 * 1024 * 1024); | ||
|
|
||
| $this->appConfig->expects($this->once()) | ||
| ->method('getPreviewConversionMaxFileSize') | ||
| ->willReturn(100 * 1024 * 1024); | ||
| $this->remoteService->expects($this->never())->method('convertFileTo'); | ||
|
|
||
| $result = $this->provider->getThumbnail($file, 64, 64); | ||
|
|
||
| $this->assertNull($result); | ||
| } | ||
|
|
||
| public function testGetThumbnailReturnsNullForEmptyFile(): void { | ||
| $file = $this->createMock(File::class); | ||
| $file->expects($this->once())->method('getSize')->willReturn(0); | ||
|
|
||
| $this->appConfig->expects($this->never())->method('getPreviewConversionMaxFileSize'); | ||
| $this->remoteService->expects($this->never())->method('convertFileTo'); | ||
|
|
||
| $result = $this->provider->getThumbnail($file, 64, 64); | ||
|
|
||
| $this->assertNull($result); | ||
| } | ||
|
|
||
| public function testGetThumbnailAttemptsConversionWhenFileSizeIsExactlyAtLimit(): void { | ||
| $file = $this->createMock(File::class); | ||
| $file->expects($this->once())->method('getSize')->willReturn(100 * 1024 * 1024); | ||
|
|
||
| $this->appConfig->expects($this->once()) | ||
| ->method('getPreviewConversionMaxFileSize') | ||
| ->willReturn(100 * 1024 * 1024); | ||
| // Conversion is attempted; throw to keep the test simple (image loading is not unit-tested here) | ||
| $this->remoteService->expects($this->once()) | ||
| ->method('convertFileTo') | ||
| ->with($file, 'png') | ||
| ->willThrowException(new \Exception('conversion failed')); | ||
|
|
||
| $result = $this->provider->getThumbnail($file, 64, 64); | ||
|
|
||
| $this->assertNull($result); | ||
| } | ||
|
|
||
| public function testGetThumbnailReturnsNullWhenConversionFails(): void { | ||
| $file = $this->createMock(File::class); | ||
| $file->expects($this->once())->method('getSize')->willReturn(1024); | ||
|
|
||
| $this->appConfig->expects($this->once()) | ||
| ->method('getPreviewConversionMaxFileSize') | ||
| ->willReturn(100 * 1024 * 1024); | ||
| $this->remoteService->expects($this->once()) | ||
| ->method('convertFileTo') | ||
| ->with($file, 'png') | ||
| ->willThrowException(new \Exception('conversion failed')); | ||
|
|
||
| $result = $this->provider->getThumbnail($file, 64, 64); | ||
|
|
||
| $this->assertNull($result); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new default entries use string literals (
'preview_conversion_timeout','preview_conversion_max_filesize') even though constants for these keys were introduced just above. Using the constants here would reduce the chance of typos/mismatches if the key names ever change.