Skip to content

Commit 85bea72

Browse files
committed
fix(files): conversion api simplification and conflict check
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
1 parent b2d1df7 commit 85bea72

File tree

10 files changed

+157
-93
lines changed

10 files changed

+157
-93
lines changed

apps/files/lib/Capabilities.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use OC\Files\FilenameValidator;
1111
use OCA\Files\Service\ChunkedUploadConfig;
1212
use OCP\Capabilities\ICapability;
13-
use OCP\Files\Conversion\ConversionMimeTuple;
13+
use OCP\Files\Conversion\ConversionMimeProvider;
1414
use OCP\Files\Conversion\IConversionManager;
1515

1616
class Capabilities implements ICapability {
@@ -24,7 +24,7 @@ public function __construct(
2424
/**
2525
* Return this classes capabilities
2626
*
27-
* @return array{files: array{'$comment': ?string, bigfilechunking: bool, blacklisted_files: list<mixed>, forbidden_filenames: list<string>, forbidden_filename_basenames: list<string>, forbidden_filename_characters: list<string>, forbidden_filename_extensions: list<string>, chunked_upload: array{max_size: int, max_parallel_count: int}, file_conversions: list<array{from: string, to: list<array{mime: string, name: string}>}>}}
27+
* @return array{files: array{'$comment': ?string, bigfilechunking: bool, blacklisted_files: list<mixed>, forbidden_filenames: list<string>, forbidden_filename_basenames: list<string>, forbidden_filename_characters: list<string>, forbidden_filename_extensions: list<string>, chunked_upload: array{max_size: int, max_parallel_count: int}, file_conversions: list<array{from: string, to: string, extension: string, displayName: string}>}}
2828
*/
2929
public function getCapabilities(): array {
3030
return [
@@ -42,9 +42,9 @@ public function getCapabilities(): array {
4242
'max_parallel_count' => ChunkedUploadConfig::getMaxParallelCount(),
4343
],
4444

45-
'file_conversions' => array_map(function (ConversionMimeTuple $mimeTuple) {
46-
return $mimeTuple->jsonSerialize();
47-
}, $this->fileConversionManager->getMimeTypes()),
45+
'file_conversions' => array_map(function (ConversionMimeProvider $mimeProvider) {
46+
return $mimeProvider->jsonSerialize();
47+
}, $this->fileConversionManager->getProviders()),
4848
],
4949
];
5050
}

apps/testing/lib/Conversion/ConversionProvider.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace OCA\Testing\Conversion;
1111

12-
use OCP\Files\Conversion\ConversionMimeTuple;
12+
use OCP\Files\Conversion\ConversionMimeProvider;
1313
use OCP\Files\Conversion\IConversionProvider;
1414
use OCP\Files\File;
1515
use OCP\IL10N;
@@ -22,19 +22,26 @@ public function __construct(
2222

2323
public function getSupportedMimeTypes(): array {
2424
return [
25-
new ConversionMimeTuple('image/jpeg', [
26-
['mime' => 'image/png', 'name' => $this->l10n->t('Image (.png)')],
27-
])
25+
new ConversionMimeProvider('image/jpeg', 'image/png', 'png', $this->l10n->t('Image (.png)')),
26+
new ConversionMimeProvider('image/jpeg', 'image/gif', 'gif', $this->l10n->t('Image (.gif)')),
2827
];
2928
}
3029

3130
public function convertFile(File $file, string $targetMimeType): mixed {
3231
$image = imagecreatefromstring($file->getContent());
33-
3432
imagepalettetotruecolor($image);
3533

34+
// Start output buffering
3635
ob_start();
37-
imagepng($image);
36+
37+
// Convert the image to the target format
38+
if ($targetMimeType === 'image/gif') {
39+
imagegif($image);
40+
} else {
41+
imagepng($image);
42+
}
43+
44+
// End and return the output buffer
3845
return ob_get_clean();
3946
}
4047
}

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@
377377
'OCP\\Files\\Config\\IRootMountProvider' => $baseDir . '/lib/public/Files/Config/IRootMountProvider.php',
378378
'OCP\\Files\\Config\\IUserMountCache' => $baseDir . '/lib/public/Files/Config/IUserMountCache.php',
379379
'OCP\\Files\\ConnectionLostException' => $baseDir . '/lib/public/Files/ConnectionLostException.php',
380-
'OCP\\Files\\Conversion\\ConversionMimeTuple' => $baseDir . '/lib/public/Files/Conversion/ConversionMimeTuple.php',
380+
'OCP\\Files\\Conversion\\ConversionMimeProvider' => $baseDir . '/lib/public/Files/Conversion/ConversionMimeProvider.php',
381381
'OCP\\Files\\Conversion\\IConversionManager' => $baseDir . '/lib/public/Files/Conversion/IConversionManager.php',
382382
'OCP\\Files\\Conversion\\IConversionProvider' => $baseDir . '/lib/public/Files/Conversion/IConversionProvider.php',
383383
'OCP\\Files\\DavUtil' => $baseDir . '/lib/public/Files/DavUtil.php',

lib/composer/composer/autoload_psr4.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
'OC\\' => array($baseDir . '/lib/private'),
1111
'OCP\\' => array($baseDir . '/lib/public'),
1212
'NCU\\' => array($baseDir . '/lib/unstable'),
13+
'Bamarni\\Composer\\Bin\\' => array($vendorDir . '/bamarni/composer-bin-plugin/src'),
1314
'' => array($baseDir . '/lib/private/legacy'),
1415
);

lib/composer/composer/autoload_static.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
2121
array (
2222
'NCU\\' => 4,
2323
),
24+
'B' =>
25+
array (
26+
'Bamarni\\Composer\\Bin\\' => 21,
27+
),
2428
);
2529

2630
public static $prefixDirsPsr4 = array (
@@ -40,6 +44,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
4044
array (
4145
0 => __DIR__ . '/../../..' . '/lib/unstable',
4246
),
47+
'Bamarni\\Composer\\Bin\\' =>
48+
array (
49+
0 => __DIR__ . '/..' . '/bamarni/composer-bin-plugin/src',
50+
),
4351
);
4452

4553
public static $fallbackDirsPsr4 = array (
@@ -418,7 +426,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
418426
'OCP\\Files\\Config\\IRootMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IRootMountProvider.php',
419427
'OCP\\Files\\Config\\IUserMountCache' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IUserMountCache.php',
420428
'OCP\\Files\\ConnectionLostException' => __DIR__ . '/../../..' . '/lib/public/Files/ConnectionLostException.php',
421-
'OCP\\Files\\Conversion\\ConversionMimeTuple' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/ConversionMimeTuple.php',
429+
'OCP\\Files\\Conversion\\ConversionMimeProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/ConversionMimeProvider.php',
422430
'OCP\\Files\\Conversion\\IConversionManager' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/IConversionManager.php',
423431
'OCP\\Files\\Conversion\\IConversionProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/IConversionProvider.php',
424432
'OCP\\Files\\DavUtil' => __DIR__ . '/../../..' . '/lib/public/Files/DavUtil.php',

lib/private/Files/Conversion/ConversionManager.php

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212
use OC\AppFramework\Bootstrap\Coordinator;
1313
use OC\SystemConfig;
14-
use OCP\Files\Conversion\ConversionMimeTuple;
14+
use OCP\Files\Conversion\ConversionMimeProvider;
1515
use OCP\Files\Conversion\IConversionManager;
1616
use OCP\Files\Conversion\IConversionProvider;
1717
use OCP\Files\File;
18+
use OCP\Files\Folder;
1819
use OCP\Files\GenericFileException;
1920
use OCP\Files\IRootFolder;
2021
use OCP\ITempManager;
@@ -53,16 +54,28 @@ public function hasProviders(): bool {
5354
return !empty($context->getFileConversionProviders());
5455
}
5556

56-
public function getMimeTypes(): array {
57-
$mimeTypes = [];
58-
59-
foreach ($this->getProviders() as $provider) {
60-
$mimeTypes[] = $provider->getSupportedMimetypes();
57+
public function getProviders(): array {
58+
$providers = [];
59+
foreach ($this->getRegisteredProviders() as $provider) {
60+
$providers = array_merge($providers, $provider->getSupportedMimeTypes());
6161
}
62+
return $providers;
63+
}
64+
65+
/**
66+
* @param string $mime
67+
* @return list<ConversionMimeProvider>
68+
*/
69+
private function getProvidersForMime(string $mime): array {
70+
$mimeTypes = $this->getProviders();
71+
$filtered = array_filter(
72+
$mimeTypes,
73+
function (ConversionMimeProvider $mimeProvider) use ($mime) {
74+
return $mimeProvider->getFrom() === $mime;
75+
}
76+
);
6277

63-
/** @var list<ConversionMimeTuple> */
64-
$mimeTypes = array_merge(...$mimeTypes);
65-
return $mimeTypes;
78+
return array_values($filtered);
6679
}
6780

6881
public function convert(File $file, string $targetMimeType, ?string $destination = null): string {
@@ -80,24 +93,36 @@ public function convert(File $file, string $targetMimeType, ?string $destination
8093
$fileMimeType = $file->getMimetype();
8194
$validProvider = $this->getValidProvider($fileMimeType, $targetMimeType);
8295

96+
$targetExtension = '';
97+
foreach ($this->getProvidersForMime($fileMimeType) as $mimeProvider) {
98+
if ($mimeProvider->getTo() === $targetMimeType) {
99+
$targetExtension = $mimeProvider->getExtension();
100+
break;
101+
}
102+
}
103+
83104
if ($validProvider !== null) {
84105
$convertedFile = $validProvider->convertFile($file, $targetMimeType);
85106

86-
if ($destination !== null) {
87-
$convertedFile = $this->writeToDestination($destination, $convertedFile);
88-
return $convertedFile->getPath();
107+
// If destination not provided, we use the same path
108+
// as the original file, but with the new extension
109+
if ($destination === null) {
110+
$basename = pathinfo($file->getPath(), PATHINFO_FILENAME);
111+
$parent = $file->getParent();
112+
$destination = $parent->getFullPath($basename . '.' . $targetExtension);
89113
}
90114

91-
$tmp = $this->tempManager->getTemporaryFile();
92-
file_put_contents($tmp, $convertedFile);
93-
94-
return $tmp;
115+
$convertedFile = $this->writeToDestination($destination, $convertedFile);
116+
return $convertedFile->getPath();
95117
}
96118

97119
throw new RuntimeException('Could not convert file');
98120
}
99121

100-
public function getProviders(): array {
122+
/**
123+
* @return IConversionProvider[]
124+
*/
125+
private function getRegisteredProviders(): array {
101126
if (count($this->providers) > 0) {
102127
return $this->providers;
103128
}
@@ -125,28 +150,29 @@ public function getProviders(): array {
125150
}
126151

127152
private function writeToDestination(string $destination, mixed $content): File {
153+
if ($this->rootFolder->nodeExists($destination)) {
154+
$file = $this->rootFolder->get($destination);
155+
$parent = $file->getParent();
156+
if (!$parent->isCreatable()) {
157+
throw new GenericFileException('Destination is not creatable');
158+
}
159+
160+
$newName = $parent->getNonExistingName(basename($destination));
161+
$destination = $parent->getFullPath($newName);
162+
}
163+
128164
return $this->rootFolder->newFile($destination, $content);
129165
}
130166

131167
private function getValidProvider(string $fileMimeType, string $targetMimeType): ?IConversionProvider {
132-
$validProvider = null;
133-
foreach ($this->getProviders() as $provider) {
134-
$suitableMimeTypes = array_filter(
135-
$provider->getSupportedMimeTypes(),
136-
function (ConversionMimeTuple $mimeTuple) use ($fileMimeType, $targetMimeType) {
137-
['from' => $from, 'to' => $to] = $mimeTuple->jsonSerialize();
138-
139-
$supportsTargetMimeType = in_array($targetMimeType, array_column($to, 'mime'));
140-
return ($from === $fileMimeType) && $supportsTargetMimeType;
168+
foreach ($this->getRegisteredProviders() as $provider) {
169+
foreach ($provider->getSupportedMimeTypes() as $mimeProvider) {
170+
if ($mimeProvider->getFrom() === $fileMimeType && $mimeProvider->getTo() === $targetMimeType) {
171+
return $provider;
141172
}
142-
);
143-
144-
if (!empty($suitableMimeTypes)) {
145-
$validProvider = $provider;
146-
break;
147173
}
148174
}
149-
150-
return $validProvider;
175+
176+
return null;
151177
}
152178
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCP\Files\Conversion;
11+
12+
use JsonSerializable;
13+
14+
/**
15+
* A tuple-like object representing both an original and target
16+
* MIME type for a file conversion
17+
*
18+
* @since 31.0.0
19+
*/
20+
class ConversionMimeProvider implements JsonSerializable {
21+
/**
22+
* @param string $from The source MIME type of a file
23+
* @param string $to The target MIME type for the file
24+
* @param string $extension The file extension for the target MIME type (e.g. 'png')
25+
* @param string $displayName The human-readable name of the target MIME type (e.g. 'Image (.png)')
26+
*
27+
* @since 31.0.0
28+
*/
29+
public function __construct(
30+
private string $from,
31+
private string $to,
32+
private string $extension,
33+
private string $displayName,
34+
) {
35+
}
36+
37+
public function getFrom(): string {
38+
return $this->from;
39+
}
40+
41+
public function getTo(): string {
42+
return $this->to;
43+
}
44+
45+
public function getExtension(): string {
46+
return $this->extension;
47+
}
48+
49+
public function getDisplayName(): string {
50+
return $this->displayName;
51+
}
52+
53+
/**
54+
* @return array{from: string, to: string, extension: string, displayName: string}
55+
*
56+
* @since 31.0.0
57+
*/
58+
public function jsonSerialize(): array {
59+
return [
60+
'from' => $this->from,
61+
'to' => $this->to,
62+
'extension' => $this->extension,
63+
'displayName' => $this->displayName,
64+
];
65+
}
66+
}

lib/public/Files/Conversion/ConversionMimeTuple.php

Lines changed: 0 additions & 44 deletions
This file was deleted.

lib/public/Files/Conversion/IConversionManager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ public function hasProviders(): bool;
2525
/**
2626
* Gets all supported MIME type conversions
2727
*
28-
* @return list<ConversionMimeTuple>
28+
* @return list<ConversionMimeProvider>
2929
*
3030
* @since 31.0.0
3131
*/
32-
public function getMimeTypes(): array;
32+
public function getProviders(): array;
3333

3434
/**
3535
* Convert a file to a given MIME type

lib/public/Files/Conversion/IConversionProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ interface IConversionProvider {
2121
/**
2222
* Get an array of MIME type tuples this conversion provider supports
2323
*
24-
* @return list<ConversionMimeTuple>
24+
* @return list<ConversionMimeProvider>
2525
*
2626
* @since 31.0.0
2727
*/

0 commit comments

Comments
 (0)