Skip to content

Commit cc1b9f2

Browse files
committed
feat: register conversion provider
Signed-off-by: Elizabeth Danzberger <[email protected]>
1 parent d495a66 commit cc1b9f2

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed

lib/AppInfo/Application.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use OCA\Files_Sharing\Event\ShareLinkAccessedEvent;
1212
use OCA\Richdocuments\Capabilities;
13+
use OCA\Richdocuments\Conversion\ConversionProvider;
1314
use OCA\Richdocuments\Db\WopiMapper;
1415
use OCA\Richdocuments\Listener\AddContentSecurityPolicyListener;
1516
use OCA\Richdocuments\Listener\AddFeaturePolicyListener;
@@ -81,6 +82,7 @@ public function register(IRegistrationContext $context): void {
8182
$context->registerPreviewProvider(OOXML::class, OOXML::MIMETYPE_REGEX);
8283
$context->registerPreviewProvider(OpenDocument::class, OpenDocument::MIMETYPE_REGEX);
8384
$context->registerPreviewProvider(Pdf::class, Pdf::MIMETYPE_REGEX);
85+
$context->registerFileConversionProvider(ConversionProvider::class);
8486
$context->registerNotifierService(Notifier::class);
8587
}
8688

lib/Conversion/ConversionProvider.php

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
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 OCA\Richdocuments\Conversion;
11+
12+
use OCA\Richdocuments\Service\RemoteService;
13+
use OCP\Files\Conversion\ConversionMimeProvider;
14+
use OCP\Files\Conversion\IConversionProvider;
15+
use OCP\Files\File;
16+
use OCP\IL10N;
17+
use OCP\L10N\IFactory;
18+
use Psr\Log\LoggerInterface;
19+
20+
class ConversionProvider implements IConversionProvider {
21+
private IL10N $l10n;
22+
23+
private const MIME_TYPES = [
24+
'documents' => [
25+
'doc' => 'application/msword',
26+
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
27+
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
28+
'ott' => 'application/vnd.oasis.opendocument.text-template',
29+
'odt' => 'application/vnd.oasis.opendocument.text',
30+
],
31+
'sheets' => [
32+
'xls' => 'application/vnd.ms-excel',
33+
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
34+
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
35+
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
36+
'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
37+
],
38+
'presentations' => [
39+
'ppt' => 'application/vnd.ms-powerpoint',
40+
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
41+
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
42+
'odp' => 'application/vnd.oasis.opendocument.presentation',
43+
'otp' => 'application/vnd.oasis.opendocument.presentation-template',
44+
],
45+
'drawings' => [
46+
'vsdx' => 'application/vnd.visio',
47+
'odg' => 'application/vnd.oasis.opendocument.graphics',
48+
'otg' => 'application/vnd.oasis.opendocument.graphics-template',
49+
],
50+
];
51+
52+
public function __construct(
53+
private RemoteService $remoteService,
54+
private LoggerInterface $logger,
55+
IFactory $l10nFactory,
56+
) {
57+
$this->l10n = $l10nFactory->get('richdocuments');
58+
}
59+
60+
public function getSupportedMimeTypes(): array {
61+
$documents = self::MIME_TYPES['documents'];
62+
$sheets = self::MIME_TYPES['sheets'];
63+
$presentations = self::MIME_TYPES['presentations'];
64+
$drawings = self::MIME_TYPES['drawings'];
65+
66+
$pdfConversions = array_merge(
67+
[],
68+
self::MIME_TYPES['documents'],
69+
self::MIME_TYPES['sheets'],
70+
self::MIME_TYPES['presentations'],
71+
self::MIME_TYPES['drawings'],
72+
);
73+
74+
$documentConversions = [
75+
// OpenDocument Text to Word Document
76+
'docx' => [$documents['odt']],
77+
78+
// Word Document to OpenDocument Text
79+
'odt' => [$documents['doc'], $documents['docx']],
80+
81+
// Documents to Rich Text Format
82+
'rtf' => [$documents['odt'], $documents['doc'], $documents['docx']],
83+
84+
// Documents to text
85+
'txt' => [$documents['odt'], $documents['doc'], $documents['docx']],
86+
];
87+
88+
$spreadsheetConversions = [
89+
// OpenDocument Spreadsheet to Excel Workbook
90+
'xlsx' => [$sheets['ods']],
91+
92+
// Excel Workbook to OpenDocument Spreadsheet
93+
'ods' => [$sheets['xls'], $sheets['xlsx']],
94+
];
95+
96+
$presentationConversions = [
97+
// OpenDocument Presentation to PowerPoint Presentation
98+
'pptx' => [$presentations['odp']],
99+
100+
// PowerPoint Presentation to OpenDocument Presentation
101+
'odp' => [$presentations['ppt'], $presentations['pptx']],
102+
];
103+
104+
$drawingConversions = [
105+
// OpenDocument Drawing to Portable Network Graphics
106+
'png' => [$drawings['odg']],
107+
108+
// OpenDocument Drawing to Scalable Vector Graphics
109+
'svg' => [$drawings['odg']],
110+
];
111+
112+
return [
113+
// PDF conversions
114+
...$this->getMimeProvidersFor($pdfConversions, 'application/pdf'),
115+
116+
// Document conversions
117+
...$this->getMimeProvidersFor($documentConversions['docx'], $documents['docx']),
118+
...$this->getMimeProvidersFor($documentConversions['odt'], $documents['odt']),
119+
...$this->getMimeProvidersFor($documentConversions['rtf'], 'application/rtf'),
120+
...$this->getMimeProvidersFor($documentConversions['txt'], 'text/plain'),
121+
122+
// Spreadsheet conversions
123+
...$this->getMimeProvidersFor($spreadsheetConversions['xlsx'], $sheets['xlsx']),
124+
...$this->getMimeProvidersFor($spreadsheetConversions['ods'], $sheets['ods']),
125+
126+
// Presentation conversions
127+
...$this->getMimeProvidersFor($presentationConversions['pptx'], $presentations['pptx']),
128+
...$this->getMimeProvidersFor($presentationConversions['odp'], $presentations['odp']),
129+
130+
// Drawing conversions
131+
...$this->getMimeProvidersFor($drawingConversions['png'], 'image/png'),
132+
...$this->getMimeProvidersFor($drawingConversions['svg'], 'image/svg+xml'),
133+
];
134+
}
135+
136+
public function convertFile(File $file, string $targetMimeType): mixed {
137+
$targetFileExtension = $this->getExtensionForMimeType($targetMimeType);
138+
if ($targetFileExtension === null) {
139+
throw new \Exception($this->l10n->t(
140+
'Unable to determine the proper file extension for %1$s',
141+
[$targetMimeType]
142+
));
143+
}
144+
145+
return $this->remoteService->convertFileTo($file, $targetFileExtension);
146+
}
147+
148+
private function getMimeProvidersFor(array $inputMimeTypes, string $outputMimeType): array {
149+
$outputMimeInfo = $this->getMimeInfoFor($outputMimeType);
150+
if ($outputMimeInfo === null) {
151+
$this->logger->error($this->l10n->t('Unable to fetch information on $s', [$outputMimeType]));
152+
throw new \Exception();
153+
}
154+
155+
$conversionMimeProviders = [];
156+
foreach ($inputMimeTypes as $mimeType) {
157+
$conversionMimeProviders[] = new ConversionMimeProvider(
158+
$mimeType,
159+
...$outputMimeInfo
160+
);
161+
}
162+
163+
return $conversionMimeProviders;
164+
}
165+
166+
private function getMimeInfoFor(string $targetMimeType): ?array {
167+
foreach ($this->getTargetMimeTypes() as $mimeType => $mimeInfo) {
168+
if ($mimeType === $targetMimeType) {
169+
return [
170+
'to' => $mimeType,
171+
...$mimeInfo,
172+
];
173+
}
174+
}
175+
176+
return null;
177+
}
178+
179+
private function getTargetMimeTypes(): array {
180+
$documents = self::MIME_TYPES['documents'];
181+
$sheets = self::MIME_TYPES['sheets'];
182+
$presentations = self::MIME_TYPES['presentations'];
183+
184+
return [
185+
'application/pdf' => [
186+
'extension' => 'pdf',
187+
'displayName' => $this->l10n->t('Portable Document Format (.pdf)'),
188+
],
189+
'image/png' => [
190+
'extension' => 'png',
191+
'displayName' => $this->l10n->t('Image (.png)'),
192+
],
193+
'image/svg+xml' => [
194+
'extension' => 'svg',
195+
'displayName' => $this->l10n->t('Image (.svg)'),
196+
],
197+
'application/rtf' => [
198+
'extension' => 'rtf',
199+
'displayName' => $this->l10n->t('Text (.rtf)'),
200+
],
201+
'text/plain' => [
202+
'extension' => 'txt',
203+
'displayName' => $this->l10n->t('Text (.txt)'),
204+
],
205+
$documents['docx'] => [
206+
'extension' => 'docx',
207+
'displayName' => $this->l10n->t('Word Document (.docx)'),
208+
],
209+
$documents['odt'] => [
210+
'extension' => 'odt',
211+
'displayName' => $this->l10n->t('OpenDocument Text (.odt)'),
212+
],
213+
$sheets['xlsx'] => [
214+
'extension' => 'xlsx',
215+
'displayName' => $this->l10n->t('Excel Workbook (.xlsx)'),
216+
],
217+
$sheets['ods'] => [
218+
'extension' => 'ods',
219+
'displayName' => $this->l10n->t('OpenDocument Spreadsheet (.ods)'),
220+
],
221+
$presentations['pptx'] => [
222+
'extension' => 'pptx',
223+
'displayName' => $this->l10n->t('PowerPoint Presentation (.pptx)'),
224+
],
225+
$presentations['odp'] => [
226+
'extension' => 'odp',
227+
'displayName' => $this->l10n->t('OpenDocument Presentation (.odp)'),
228+
],
229+
];
230+
}
231+
232+
private function getExtensionForMimeType(string $mimeType): ?string {
233+
foreach ($this->getTargetMimeTypes() as $targetMimeType => $targetMimeInfo) {
234+
if ($targetMimeType === $mimeType) {
235+
return $targetMimeInfo['extension'];
236+
}
237+
}
238+
239+
return null;
240+
}
241+
}

0 commit comments

Comments
 (0)