diff --git a/apps/files/lib/Capabilities.php b/apps/files/lib/Capabilities.php index 88efb4fcaf0c0..6b50e5807a5f6 100644 --- a/apps/files/lib/Capabilities.php +++ b/apps/files/lib/Capabilities.php @@ -10,7 +10,7 @@ use OC\Files\FilenameValidator; use OCA\Files\Service\ChunkedUploadConfig; use OCP\Capabilities\ICapability; -use OCP\Files\Conversion\ConversionMimeTuple; +use OCP\Files\Conversion\ConversionMimeProvider; use OCP\Files\Conversion\IConversionManager; class Capabilities implements ICapability { @@ -24,7 +24,7 @@ public function __construct( /** * Return this classes capabilities * - * @return array{files: array{'$comment': ?string, bigfilechunking: bool, blacklisted_files: list, forbidden_filenames: list, forbidden_filename_basenames: list, forbidden_filename_characters: list, forbidden_filename_extensions: list, chunked_upload: array{max_size: int, max_parallel_count: int}, file_conversions: list}>}} + * @return array{files: array{'$comment': ?string, bigfilechunking: bool, blacklisted_files: list, forbidden_filenames: list, forbidden_filename_basenames: list, forbidden_filename_characters: list, forbidden_filename_extensions: list, chunked_upload: array{max_size: int, max_parallel_count: int}, file_conversions: list}} */ public function getCapabilities(): array { return [ @@ -42,9 +42,9 @@ public function getCapabilities(): array { 'max_parallel_count' => ChunkedUploadConfig::getMaxParallelCount(), ], - 'file_conversions' => array_map(function (ConversionMimeTuple $mimeTuple) { - return $mimeTuple->jsonSerialize(); - }, $this->fileConversionManager->getMimeTypes()), + 'file_conversions' => array_map(function (ConversionMimeProvider $mimeProvider) { + return $mimeProvider->jsonSerialize(); + }, $this->fileConversionManager->getProviders()), ], ]; } diff --git a/apps/files/openapi.json b/apps/files/openapi.json index 015d4f42648ce..ddf3535c55f73 100644 --- a/apps/files/openapi.json +++ b/apps/files/openapi.json @@ -101,29 +101,22 @@ "type": "object", "required": [ "from", - "to" + "to", + "extension", + "displayName" ], "properties": { "from": { "type": "string" }, "to": { - "type": "array", - "items": { - "type": "object", - "required": [ - "mime", - "name" - ], - "properties": { - "mime": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } + "type": "string" + }, + "extension": { + "type": "string" + }, + "displayName": { + "type": "string" } } } diff --git a/apps/testing/lib/Conversion/ConversionProvider.php b/apps/testing/lib/Conversion/ConversionProvider.php index 15e468b07568a..b8d9342869464 100644 --- a/apps/testing/lib/Conversion/ConversionProvider.php +++ b/apps/testing/lib/Conversion/ConversionProvider.php @@ -9,7 +9,7 @@ namespace OCA\Testing\Conversion; -use OCP\Files\Conversion\ConversionMimeTuple; +use OCP\Files\Conversion\ConversionMimeProvider; use OCP\Files\Conversion\IConversionProvider; use OCP\Files\File; use OCP\IL10N; @@ -22,19 +22,26 @@ public function __construct( public function getSupportedMimeTypes(): array { return [ - new ConversionMimeTuple('image/jpeg', [ - ['mime' => 'image/png', 'name' => $this->l10n->t('Image (.png)')], - ]) + new ConversionMimeProvider('image/jpeg', 'image/png', 'png', $this->l10n->t('Image (.png)')), + new ConversionMimeProvider('image/jpeg', 'image/gif', 'gif', $this->l10n->t('Image (.gif)')), ]; } public function convertFile(File $file, string $targetMimeType): mixed { $image = imagecreatefromstring($file->getContent()); - imagepalettetotruecolor($image); + // Start output buffering ob_start(); - imagepng($image); + + // Convert the image to the target format + if ($targetMimeType === 'image/gif') { + imagegif($image); + } else { + imagepng($image); + } + + // End and return the output buffer return ob_get_clean(); } } diff --git a/lib/private/Files/Conversion/ConversionManager.php b/lib/private/Files/Conversion/ConversionManager.php index 37fc9a6c754c8..be6f01cacd012 100644 --- a/lib/private/Files/Conversion/ConversionManager.php +++ b/lib/private/Files/Conversion/ConversionManager.php @@ -11,7 +11,7 @@ use OC\AppFramework\Bootstrap\Coordinator; use OC\SystemConfig; -use OCP\Files\Conversion\ConversionMimeTuple; +use OCP\Files\Conversion\ConversionMimeProvider; use OCP\Files\Conversion\IConversionManager; use OCP\Files\Conversion\IConversionProvider; use OCP\Files\File; @@ -53,16 +53,28 @@ public function hasProviders(): bool { return !empty($context->getFileConversionProviders()); } - public function getMimeTypes(): array { - $mimeTypes = []; - - foreach ($this->getProviders() as $provider) { - $mimeTypes[] = $provider->getSupportedMimetypes(); + public function getProviders(): array { + $providers = []; + foreach ($this->getRegisteredProviders() as $provider) { + $providers = array_merge($providers, $provider->getSupportedMimeTypes()); } + return $providers; + } + + /** + * @param string $mime + * @return list + */ + private function getProvidersForMime(string $mime): array { + $mimeTypes = $this->getProviders(); + $filtered = array_filter( + $mimeTypes, + function (ConversionMimeProvider $mimeProvider) use ($mime) { + return $mimeProvider->getFrom() === $mime; + } + ); - /** @var list */ - $mimeTypes = array_merge(...$mimeTypes); - return $mimeTypes; + return array_values($filtered); } public function convert(File $file, string $targetMimeType, ?string $destination = null): string { @@ -80,24 +92,36 @@ public function convert(File $file, string $targetMimeType, ?string $destination $fileMimeType = $file->getMimetype(); $validProvider = $this->getValidProvider($fileMimeType, $targetMimeType); + $targetExtension = ''; + foreach ($this->getProvidersForMime($fileMimeType) as $mimeProvider) { + if ($mimeProvider->getTo() === $targetMimeType) { + $targetExtension = $mimeProvider->getExtension(); + break; + } + } + if ($validProvider !== null) { $convertedFile = $validProvider->convertFile($file, $targetMimeType); - if ($destination !== null) { - $convertedFile = $this->writeToDestination($destination, $convertedFile); - return $convertedFile->getPath(); + // If destination not provided, we use the same path + // as the original file, but with the new extension + if ($destination === null) { + $basename = pathinfo($file->getPath(), PATHINFO_FILENAME); + $parent = $file->getParent(); + $destination = $parent->getFullPath($basename . '.' . $targetExtension); } - $tmp = $this->tempManager->getTemporaryFile(); - file_put_contents($tmp, $convertedFile); - - return $tmp; + $convertedFile = $this->writeToDestination($destination, $convertedFile); + return $convertedFile->getPath(); } throw new RuntimeException('Could not convert file'); } - public function getProviders(): array { + /** + * @return list + */ + private function getRegisteredProviders(): array { if (count($this->providers) > 0) { return $this->providers; } @@ -125,28 +149,29 @@ public function getProviders(): array { } private function writeToDestination(string $destination, mixed $content): File { + if ($this->rootFolder->nodeExists($destination)) { + $file = $this->rootFolder->get($destination); + $parent = $file->getParent(); + if (!$parent->isCreatable()) { + throw new GenericFileException('Destination is not creatable'); + } + + $newName = $parent->getNonExistingName(basename($destination)); + $destination = $parent->getFullPath($newName); + } + return $this->rootFolder->newFile($destination, $content); } private function getValidProvider(string $fileMimeType, string $targetMimeType): ?IConversionProvider { - $validProvider = null; - foreach ($this->getProviders() as $provider) { - $suitableMimeTypes = array_filter( - $provider->getSupportedMimeTypes(), - function (ConversionMimeTuple $mimeTuple) use ($fileMimeType, $targetMimeType) { - ['from' => $from, 'to' => $to] = $mimeTuple->jsonSerialize(); - - $supportsTargetMimeType = in_array($targetMimeType, array_column($to, 'mime')); - return ($from === $fileMimeType) && $supportsTargetMimeType; + foreach ($this->getRegisteredProviders() as $provider) { + foreach ($provider->getSupportedMimeTypes() as $mimeProvider) { + if ($mimeProvider->getFrom() === $fileMimeType && $mimeProvider->getTo() === $targetMimeType) { + return $provider; } - ); - - if (!empty($suitableMimeTypes)) { - $validProvider = $provider; - break; } } - - return $validProvider; + + return null; } } diff --git a/lib/public/Files/Conversion/ConversionMimeProvider.php b/lib/public/Files/Conversion/ConversionMimeProvider.php new file mode 100644 index 0000000000000..0daf4a10648a4 --- /dev/null +++ b/lib/public/Files/Conversion/ConversionMimeProvider.php @@ -0,0 +1,66 @@ +from; + } + + public function getTo(): string { + return $this->to; + } + + public function getExtension(): string { + return $this->extension; + } + + public function getDisplayName(): string { + return $this->displayName; + } + + /** + * @return array{from: string, to: string, extension: string, displayName: string} + * + * @since 31.0.0 + */ + public function jsonSerialize(): array { + return [ + 'from' => $this->from, + 'to' => $this->to, + 'extension' => $this->extension, + 'displayName' => $this->displayName, + ]; + } +} diff --git a/lib/public/Files/Conversion/ConversionMimeTuple.php b/lib/public/Files/Conversion/ConversionMimeTuple.php deleted file mode 100644 index 0180f3311f33d..0000000000000 --- a/lib/public/Files/Conversion/ConversionMimeTuple.php +++ /dev/null @@ -1,44 +0,0 @@ - $to The desired MIME type for the file mapped to its translated name - * - * @since 31.0.0 - */ - public function __construct( - private string $from, - private array $to, - ) { - } - - /** - * @return array{from: string, to: list} - * - * @since 31.0.0 - */ - public function jsonSerialize(): array { - return [ - 'from' => $this->from, - 'to' => $this->to, - ]; - } -} diff --git a/lib/public/Files/Conversion/IConversionManager.php b/lib/public/Files/Conversion/IConversionManager.php index 59ff580fdf186..ed418129d3bc5 100644 --- a/lib/public/Files/Conversion/IConversionManager.php +++ b/lib/public/Files/Conversion/IConversionManager.php @@ -25,11 +25,11 @@ public function hasProviders(): bool; /** * Gets all supported MIME type conversions * - * @return list + * @return list * * @since 31.0.0 */ - public function getMimeTypes(): array; + public function getProviders(): array; /** * Convert a file to a given MIME type diff --git a/lib/public/Files/Conversion/IConversionProvider.php b/lib/public/Files/Conversion/IConversionProvider.php index b0a09fc93a433..3b5c5945c99b5 100644 --- a/lib/public/Files/Conversion/IConversionProvider.php +++ b/lib/public/Files/Conversion/IConversionProvider.php @@ -21,7 +21,7 @@ interface IConversionProvider { /** * Get an array of MIME type tuples this conversion provider supports * - * @return list + * @return list * * @since 31.0.0 */