1
|
|
|
<?php |
2
|
|
|
declare (strict_types = 1); |
3
|
|
|
/** |
4
|
|
|
* @copyright Copyright (c) 2018 John Molakvoæ <[email protected]> |
5
|
|
|
* |
6
|
|
|
* @author John Molakvoæ <[email protected]> |
7
|
|
|
* |
8
|
|
|
* @license GNU AGPL version 3 or any later version |
9
|
|
|
* |
10
|
|
|
* This program is free software: you can redistribute it and/or modify |
11
|
|
|
* it under the terms of the GNU Affero General Public License as |
12
|
|
|
* published by the Free Software Foundation, either version 3 of the |
13
|
|
|
* License, or (at your option) any later version. |
14
|
|
|
* |
15
|
|
|
* This program is distributed in the hope that it will be useful, |
16
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18
|
|
|
* GNU Affero General Public License for more details. |
19
|
|
|
* |
20
|
|
|
* You should have received a copy of the GNU Affero General Public License |
21
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
22
|
|
|
* |
23
|
|
|
*/ |
24
|
|
|
|
25
|
|
|
namespace OCA\Richdocuments; |
26
|
|
|
|
27
|
|
|
use OCP\Files\File; |
28
|
|
|
use OCP\Files\Folder; |
29
|
|
|
use OCP\Files\IRootFolder; |
30
|
|
|
use OCP\Files\Node; |
31
|
|
|
use OCP\Files\NotFoundException; |
32
|
|
|
use OCP\IConfig; |
33
|
|
|
use OCP\IL10N; |
34
|
|
|
use OCP\IPreview; |
35
|
|
|
use OCP\IURLGenerator; |
36
|
|
|
use OC\Files\AppData\Factory; |
37
|
|
|
|
38
|
|
|
class TemplateManager { |
39
|
|
|
|
40
|
|
|
/** @var string */ |
41
|
|
|
protected $appName; |
42
|
|
|
|
43
|
|
|
/** @var string */ |
44
|
|
|
protected $userId; |
45
|
|
|
|
46
|
|
|
/** @var IConfig */ |
47
|
|
|
private $config; |
48
|
|
|
|
49
|
|
|
/** @var IURLGenerator */ |
50
|
|
|
private $urlGenerator; |
51
|
|
|
|
52
|
|
|
/** @var IRootFolder */ |
53
|
|
|
private $rootFolder; |
54
|
|
|
|
55
|
|
|
/** @var IL10N */ |
56
|
|
|
private $l; |
57
|
|
|
|
58
|
|
|
/** Accepted templates mime types */ |
59
|
|
|
const MIMES_DOCUMENTS = [ |
60
|
|
|
'application/vnd.oasis.opendocument.text-template' |
61
|
|
|
]; |
62
|
|
|
const MIMES_SHEETS = [ |
63
|
|
|
'application/vnd.oasis.opendocument.spreadsheet-template' |
64
|
|
|
]; |
65
|
|
|
const MIMES_PRESENTATIONS = [ |
66
|
|
|
'application/vnd.oasis.opendocument.presentation-template' |
67
|
|
|
]; |
68
|
|
|
|
69
|
|
|
/** @var array Template mime types match */ |
70
|
|
|
static public $tplTypes = [ |
71
|
|
|
'document' => self::MIMES_DOCUMENTS, |
72
|
|
|
'spreadsheet' => self::MIMES_SHEETS, |
73
|
|
|
'presentation' => self::MIMES_PRESENTATIONS |
74
|
|
|
]; |
75
|
|
|
|
76
|
|
|
const EMPTY_TEMPLATE_ID_TYPE = [ |
77
|
|
|
-1 => 'document', |
78
|
|
|
-2 => 'spreadsheet', |
79
|
|
|
-3 => 'presentation', |
80
|
|
|
]; |
81
|
|
|
const EMPTY_TEMPLATE_TYPE_ID = [ |
82
|
|
|
'document' => -1, |
83
|
|
|
'spreadsheet' => -2, |
84
|
|
|
'presentation' => -3, |
85
|
|
|
]; |
86
|
|
|
const TYPE_EXTENTION = [ |
87
|
|
|
'document' => 'odt', |
88
|
|
|
'spreadsheet' => 'ods', |
89
|
|
|
'presentation' => 'odp', |
90
|
|
|
]; |
91
|
|
|
|
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Template manager |
95
|
|
|
* |
96
|
|
|
* @param string $appName |
97
|
|
|
* @param string $userId |
98
|
|
|
* @param IConfig $config |
99
|
|
|
* @param Factory $appDataFactory |
100
|
|
|
* @param IURLGenerator $urlGenerator |
101
|
|
|
* @param IRootFolder $rootFolder |
102
|
|
|
* @param IL10N $l |
103
|
|
|
* @throws \OCP\Files\NotPermittedException |
104
|
|
|
*/ |
105
|
|
|
public function __construct($appName, |
106
|
|
|
$userId, |
107
|
|
|
IConfig $config, |
108
|
|
|
Factory $appDataFactory, |
109
|
|
|
IURLGenerator $urlGenerator, |
110
|
|
|
IRootFolder $rootFolder, |
111
|
|
|
IL10N $l) { |
112
|
|
|
$this->appName = $appName; |
113
|
|
|
$this->userId = $userId; |
114
|
|
|
$this->config = $config; |
115
|
|
|
$this->rootFolder = $rootFolder; |
116
|
|
|
$this->urlGenerator = $urlGenerator; |
117
|
|
|
|
118
|
|
|
/* |
119
|
|
|
* Init the appdata folder |
120
|
|
|
* We need an actual folder for the fileid and previews. |
121
|
|
|
* TODO: Fix this at some point |
122
|
|
|
*/ |
123
|
|
|
$appData = $appDataFactory->get($appName); |
124
|
|
|
try { |
125
|
|
|
$appData->getFolder('templates'); |
126
|
|
|
} catch (NotFoundException $e) { |
|
|
|
|
127
|
|
|
$appData->newFolder('templates'); |
128
|
|
|
} |
129
|
|
|
try { |
130
|
|
|
$appData->getFolder('empty_templates'); |
131
|
|
|
} catch (NotFoundException $e) { |
|
|
|
|
132
|
|
|
$appData->newFolder('empty_templates'); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
$this->l = $l; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
public function setUserId($userId) { |
139
|
|
|
$this->userId = $userId; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Get template ISimpleFile|Node |
144
|
|
|
* |
145
|
|
|
* @param int $fileId |
146
|
|
|
* @return File |
147
|
|
|
*/ |
148
|
|
|
public function get($fileId) { |
149
|
|
|
// is this a global template ? |
150
|
|
|
$files = $this->getEmptyTemplateDir()->getDirectoryListing(); |
151
|
|
|
|
152
|
|
|
foreach ($files as $file) { |
153
|
|
|
if ($file->getId() === $fileId) { |
154
|
|
|
return $file; |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
// is this a global template ? |
159
|
|
|
$files = $this->getSystemTemplateDir()->getDirectoryListing(); |
160
|
|
|
|
161
|
|
|
foreach ($files as $file) { |
162
|
|
|
if ($file->getId() === $fileId) { |
163
|
|
|
return $file; |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$templateDir = $this->getUserTemplateDir(); |
168
|
|
|
// finally get the template file |
169
|
|
|
$files = $templateDir->getById($fileId); |
170
|
|
|
if ($files !== []) { |
171
|
|
|
return $files[0]; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
throw new NotFoundException(); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @param File[] $templates |
179
|
|
|
* @return File[] |
180
|
|
|
*/ |
181
|
|
|
private function filterTemplates($templates, $type = null) { |
182
|
|
|
return array_filter($templates, function (Node $templateFile) use ($type) { |
183
|
|
|
if (!($templateFile instanceof File)) { |
|
|
|
|
184
|
|
|
return false; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
if ($type !== null && !in_array($templateFile->getMimeType(), self::$tplTypes[$type])) { |
188
|
|
|
return false; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
//Todo validate mimetypes etc |
192
|
|
|
|
193
|
|
|
return true; |
194
|
|
|
}); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
private function getEmpty($type = null) { |
198
|
|
|
$folder = $this->getEmptyTemplateDir(); |
199
|
|
|
|
200
|
|
|
$templateFiles = $folder->getDirectoryListing(); |
201
|
|
|
|
202
|
|
|
if ($templateFiles === []) { |
203
|
|
|
// Empty so lets copy over the basic templates |
204
|
|
|
$templates = [ |
205
|
|
|
'document.ott', |
206
|
|
|
'spreadsheet.ots', |
207
|
|
|
'presentation.otp', |
208
|
|
|
]; |
209
|
|
|
|
210
|
|
|
foreach ($templates as $template) { |
211
|
|
|
$file = $folder->newFile($template); |
212
|
|
|
$file->putContent(file_get_contents(__DIR__ . '/../assets/' . $template)); |
213
|
|
|
$templateFiles[] = $file; |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
return $this->filterTemplates($templateFiles, $type); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Get all global templates |
222
|
|
|
* |
223
|
|
|
* @return File[] |
224
|
|
|
*/ |
225
|
|
|
public function getSystem($type = null) { |
226
|
|
|
$folder = $this->getSystemTemplateDir(); |
227
|
|
|
|
228
|
|
|
$templateFiles = $folder->getDirectoryListing(); |
229
|
|
|
return $this->filterTemplates($templateFiles, $type); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* @return array |
234
|
|
|
*/ |
235
|
|
|
public function getSystemFormatted($type = null) { |
236
|
|
|
$empty = $this->getEmpty($type); |
237
|
|
|
$system = $this->getSystem($type); |
238
|
|
|
|
239
|
|
|
$emptyFormatted = array_map(function(File $file) { |
240
|
|
|
return $this->formatEmpty($file); |
241
|
|
|
}, $empty); |
242
|
|
|
|
243
|
|
|
$systemFormatted = array_map(function(File $file) { |
244
|
|
|
return $this->formatNodeReturn($file); |
245
|
|
|
}, $system); |
246
|
|
|
|
247
|
|
|
return array_merge($emptyFormatted, $systemFormatted); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* Get all user templates |
252
|
|
|
* |
253
|
|
|
* @return File[] |
254
|
|
|
*/ |
255
|
|
|
public function getUser($type = null) { |
256
|
|
|
try { |
257
|
|
|
$templateDir = $this->getUserTemplateDir(); |
258
|
|
|
$templateFiles = $templateDir->getDirectoryListing(); |
259
|
|
|
|
260
|
|
|
return $this->filterTemplates($templateFiles, $type); |
261
|
|
|
} catch(NotFoundException $e) { |
|
|
|
|
262
|
|
|
return []; |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* @return array |
268
|
|
|
*/ |
269
|
|
|
public function getUserFormatted($type) { |
270
|
|
|
$templates = $this->getUser($type); |
271
|
|
|
|
272
|
|
|
return array_map(function(File $file) { |
273
|
|
|
return $this->formatNodeReturn($file); |
274
|
|
|
}, $templates); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Get all templates |
279
|
|
|
* |
280
|
|
|
* @return File[] |
281
|
|
|
*/ |
282
|
|
|
public function getAll($type = 'document') { |
283
|
|
|
$system = $this->getSystem(); |
284
|
|
|
$user = $this->getUser(); |
285
|
|
|
|
286
|
|
|
if (!array_key_exists($type, self::$tplTypes)) { |
287
|
|
|
return []; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
return array_values(array_filter(array_merge($user, $system), function (File $template) use ($type) { |
291
|
|
|
foreach (self::$tplTypes[$type] as $mime) { |
292
|
|
|
if ($template->getMimeType() === $mime) { |
293
|
|
|
return true; |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
return false; |
297
|
|
|
})); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
public function getAllFormatted($type) { |
301
|
|
|
if (!array_key_exists($type, self::$tplTypes)) { |
302
|
|
|
return []; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
$system = $this->getSystemFormatted($type); |
306
|
|
|
$user = $this->getUserFormatted($type); |
307
|
|
|
|
308
|
|
|
return array_merge($system, $user); |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Add a template to the global template folder |
313
|
|
|
* |
314
|
|
|
* @param string $templateName |
315
|
|
|
* @param string $templateFile |
316
|
|
|
* @return array |
317
|
|
|
*/ |
318
|
|
|
public function add($templateName, $templateFile) { |
319
|
|
|
$folder = $this->getSystemTemplateDir(); |
320
|
|
|
|
321
|
|
|
try { |
322
|
|
|
$template = $folder->get($templateName); |
323
|
|
|
} catch (NotFoundException $e) { |
|
|
|
|
324
|
|
|
$template = $folder->newFile($templateName); |
325
|
|
|
} |
326
|
|
|
$template->putContent($templateFile); |
327
|
|
|
|
328
|
|
|
return $this->formatNodeReturn($this->get($template->getId())); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Delete a template to the global template folder |
333
|
|
|
* |
334
|
|
|
* @param int $fileId |
335
|
|
|
* @return boolean |
336
|
|
|
* @throws NotFoundException |
337
|
|
|
*/ |
338
|
|
|
public function delete($fileId) { |
339
|
|
|
$files = $this->getSystemTemplateDir()->getDirectoryListing(); |
340
|
|
|
foreach ($files as $file) { |
341
|
|
|
if ($file->getId() === $fileId) { |
342
|
|
|
$file->delete(); |
343
|
|
|
return true; |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
throw new NotFoundException(); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Flip $tplTypes to retrieve types by mime |
352
|
|
|
* |
353
|
|
|
* @return array |
354
|
|
|
*/ |
355
|
|
|
private function flipTypes() { |
356
|
|
|
$result = []; |
357
|
|
|
foreach ($this::$tplTypes as $type => $mime) { |
358
|
|
|
$result = array_merge($result, array_fill_keys($mime, $type)); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
return $result; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Get the user template directory |
366
|
|
|
* |
367
|
|
|
* @return Folder |
368
|
|
|
* @throws NotFoundException |
369
|
|
|
*/ |
370
|
|
|
private function getUserTemplateDir() { |
371
|
|
|
if ($this->userId === null) { |
372
|
|
|
throw new NotFoundException('userId not set'); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// has the user manually set a directory as the default template dir ? |
376
|
|
|
$templateDirPath = $this->config->getUserValue($this->userId, $this->appName, 'templateFolder', false); |
377
|
|
|
$userFolder = $this->rootFolder->getUserFolder($this->userId); |
378
|
|
|
|
379
|
|
|
if ($templateDirPath !== false) { |
380
|
|
|
$templateDir = $userFolder->get($templateDirPath); |
381
|
|
|
} else { |
382
|
|
|
// fallback to default template dir |
383
|
|
|
try { |
384
|
|
|
$templateDir = $userFolder->get('Templates'); |
385
|
|
|
} catch (NotFoundException $e) { |
|
|
|
|
386
|
|
|
throw new NotFoundException($e->getMessage()); |
387
|
|
|
} |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
if (!($templateDir instanceof Folder)) { |
|
|
|
|
391
|
|
|
throw new NotFoundException('Template dir points to a file'); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
return $templateDir; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* @return Folder |
399
|
|
|
*/ |
400
|
|
|
private function getSystemTemplateDir() { |
401
|
|
|
return $this->rootFolder->get('appdata_' . $this->config->getSystemValue('instanceid', null)) |
402
|
|
|
->get('richdocuments') |
403
|
|
|
->get('templates'); |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
/** |
407
|
|
|
* @return Folder |
408
|
|
|
*/ |
409
|
|
|
private function getEmptyTemplateDir() { |
410
|
|
|
return $this->rootFolder->get('appdata_' . $this->config->getSystemValue('instanceid', null)) |
411
|
|
|
->get('richdocuments') |
412
|
|
|
->get('empty_templates'); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Format template file for json return object |
417
|
|
|
* |
418
|
|
|
* @param File $template |
419
|
|
|
* @return array |
420
|
|
|
*/ |
421
|
|
|
public function formatNodeReturn(File $template) { |
422
|
|
|
return [ |
423
|
|
|
'id' => $template->getId(), |
424
|
|
|
'name' => $template->getName(), |
425
|
|
|
'preview' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.templates.getPreview', ['fileId' => $template->getId()]), |
426
|
|
|
'type' => $this->flipTypes()[$template->getMimeType()], |
427
|
|
|
'delete' => $this->urlGenerator->linkToRouteAbsolute('richdocuments.templates.delete', ['fileId' => $template->getId()]), |
428
|
|
|
'extension' => self::TYPE_EXTENTION[$this->flipTypes()[$template->getMimeType()]], |
429
|
|
|
]; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
public function isTemplate($fileId) { |
433
|
|
|
$empty = $this->getEmpty(); |
434
|
|
|
$system = $this->getSystem(); |
435
|
|
|
$user = $this->getUser(); |
436
|
|
|
/** @var File[] $all */ |
437
|
|
|
$all = array_merge($empty, $system, $user); |
438
|
|
|
|
439
|
|
|
foreach ($all as $template) { |
440
|
|
|
if ($template->getId() === $fileId) { |
441
|
|
|
return true; |
442
|
|
|
} |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
return false; |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
public function formatEmpty(File $template) { |
449
|
|
|
return [ |
450
|
|
|
'id' => $template->getId(), |
451
|
|
|
'name' => $this->l->t('Empty'), |
452
|
|
|
'type' => $this->flipTypes()[$template->getMimeType()], |
453
|
|
|
'extension' => self::TYPE_EXTENTION[$this->flipTypes()[$template->getMimeType()]], |
454
|
|
|
]; |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.