Completed
Push — task/context-menu ( 799c34...14c51a )
by Frank
08:30 queued 03:12
created

AjaxController::getTreeFoldersAction()   A

Complexity

Conditions 6
Paths 21

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 21
nop 1
dl 0
loc 22
ccs 0
cts 10
cp 0
crap 42
rs 9.0777
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
/*
5
 * This file is part of the package lns/digital-asset-management.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE file that was distributed with this source code.
9
 */
10
11
namespace TYPO3\CMS\DigitalAssetManagement\Controller;
12
13
use Psr\Http\Message\ServerRequestInterface;
14
use TYPO3\CMS\Backend\Routing\UriBuilder;
15
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
16
use TYPO3\CMS\Core\Core\Environment;
17
use TYPO3\CMS\Core\Http\JsonResponse;
18
use TYPO3\CMS\Core\Http\Response;
19
use TYPO3\CMS\Core\Resource\Driver\LocalDriver;
20
use TYPO3\CMS\Core\Resource\DuplicationBehavior;
21
use TYPO3\CMS\Core\Resource\Exception as ResourceException;
22
use TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException;
23
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
24
use TYPO3\CMS\Core\Resource\FileInterface;
25
use TYPO3\CMS\Core\Resource\Folder;
26
use TYPO3\CMS\Core\Resource\ResourceFactory;
27
use TYPO3\CMS\Core\Utility\GeneralUtility;
28
use TYPO3\CMS\Core\Utility\PathUtility;
29
use TYPO3\CMS\Core\Utility\StringUtility;
30
use TYPO3\CMS\DigitalAssetManagement\Entity\FileMount;
31
use TYPO3\CMS\DigitalAssetManagement\Entity\FileOperationResult;
32
use TYPO3\CMS\DigitalAssetManagement\Entity\FolderItemFile;
33
use TYPO3\CMS\DigitalAssetManagement\Entity\FolderItemFolder;
34
use TYPO3\CMS\DigitalAssetManagement\Entity\FolderItemImage;
35
use TYPO3\CMS\DigitalAssetManagement\Entity\Storage;
36
use TYPO3\CMS\DigitalAssetManagement\Entity\TreeItemFolder;
37
use TYPO3\CMS\DigitalAssetManagement\Exception\ControllerException;
38
use TYPO3\CMS\DigitalAssetManagement\Http\FileExistsResponse;
39
use TYPO3\CMS\DigitalAssetManagement\Http\FileOperationResponse;
40
use TYPO3\CMS\DigitalAssetManagement\Http\FolderItemsResponse;
41
use TYPO3\CMS\DigitalAssetManagement\Http\JsonExceptionResponse;
42
use TYPO3\CMS\DigitalAssetManagement\Http\StoragesAndMountsResponse;
43
44
/**
45
 * Main API endpoint. These are ajax actions called by JS side.
46
 *
47
 * Look up the end points in Configuration/Backend/Routes.php: A typical
48
 * path is something like /ajax/dam/getStoragesAndMounts which maps to a method
49
 * with the same name plus word "Action": getStoragesAndMountsAction().
50
 *
51
 * All actions return a JsonResponse, if all is good, the return code is
52
 * 200. A different code, usually in 4xx range will be returned if the
53
 * client sent a bogus request, often with some exception details.
54
 */
55
class AjaxController
56
{
57
    /**
58
     * @return JsonResponse
59
     */
60
    public function getNewStorageUrlAction(): JsonResponse
61
    {
62
        $backendUser = $this->getBackendUser();
63
        if (!$backendUser->isAdmin()) {
64
            return new JsonExceptionResponse(new ControllerException('User is not admin', 1554380677));
65
        }
66
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
67
        $urlParameters = [
68
            'edit' => [
69
                'sys_file_storage' => [
70
                    0 => 'new',
71
                ],
72
            ],
73
            'returnUrl' => (string)$uriBuilder->buildUriFromRoute('file_DigitalAssetManagement'),
74
        ];
75
        return new JsonResponse([(string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters)]);
76
    }
77
78
    /**
79
     * @param ServerRequestInterface $request
80
     * @return Response
81
     */
82
    public function prepareDownloadAction(ServerRequestInterface $request): JsonResponse
83
    {
84
        $identifiers = $request->getQueryParams()['identifiers'] ?? '';
85
        try {
86
            if (empty($identifiers) || !is_array($identifiers)) {
87
                throw new ControllerException('List of files or folders needed', 1554375542);
88
            }
89
            // (Mis)-use the LocalDriver method to sanitize the filename prefix
90
            $archivePrefix = rtrim(
91
                GeneralUtility::makeInstance(LocalDriver::class)
92
                    ->sanitizeFileName($request->getQueryParams()['filenamePrefix'] ?? 'download'),
93
                '-'
94
            );
95
            $archiveFilename = Environment::getVarPath()
96
                . '/transient/'
97
                . $archivePrefix
98
                . '-'
99
                . GeneralUtility::hmac(StringUtility::getUniqueId(), 'damDownload')
100
                . '.zip';
101
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
102
            $zip = new \ZipArchive();
103
            $zip->open($archiveFilename, \ZipArchive::CREATE);
104
            foreach ($identifiers as $identifier) {
105
                $resource = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
106
                if ($resource instanceof FileInterface) {
107
                    /** @var FileInterface $resource */
108
                    $zip->addFile($resource->getForLocalProcessing(false), $resource->getName());
109
                } else {
110
                    /** @var Folder $resource */
111
                    $this->addFolderToArchiveRecursive($resource, $zip);
112
                }
113
                $zip->close();
114
            }
115
            GeneralUtility::fixPermissions($archiveFilename);
116
        } catch (ResourceException $e) {
117
            return new JsonExceptionResponse($e);
118
        } catch (ControllerException $e) {
119
            return new JsonExceptionResponse($e);
120
        }
121
        return new JsonResponse([ PathUtility::getAbsoluteWebPath($archiveFilename) ]);
122
    }
123
124
    /**
125
     * @param Folder $folder
126
     * @param \ZipArchive $zip
127
     * @param array $parentFolders
128
     */
129
    protected function addFolderToArchiveRecursive(Folder $folder, \ZipArchive $zip, array $parentFolders = []): void
130
    {
131
        $folderName = $folder->getName();
132
        $parentFolders[] = $folderName;
133
        $implodedParentFolders = implode('/', $parentFolders);
134
        $zip->addEmptyDir($implodedParentFolders);
135
        $files = $folder->getFiles();
136
        foreach ($files as $file) {
137
            $zip->addFile($file->getForLocalProcessing(false), $implodedParentFolders . '/' . $file->getName());
138
        }
139
        $subFolders = $folder->getSubfolders();
140
        foreach ($subFolders as $subFolder) {
141
            $this->addFolderToArchiveRecursive($subFolder, $zip, $parentFolders);
142
        }
143
    }
144
145
    /**
146
     * @return JsonResponse
147
     */
148
    public function damGetLogoutUrlAction(): JsonResponse
149
    {
150
        if (empty($this->getBackendUser()->user['uid'])) {
151
            return new JsonExceptionResponse(new ControllerException('User is not logged in', 1554380677));
152
        }
153
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
154
        return new JsonResponse([ (string)$uriBuilder->buildUriFromRoute('logout') ]);
155
    }
156
157
    /**
158
     * Set module state of BE user. Send a json array as ['data'] POST
159
     *
160
     * @param ServerRequestInterface $request
161
     * @return JsonResponse
162
     */
163
    public function setStateAction(ServerRequestInterface $request): JsonResponse
164
    {
165
        $backendUser = $this->getBackendUser();
166
        $backendUser->uc['digital_asset_management'] = $request->getParsedBody()['data'] ?? [];
167
        $backendUser->writeUC();
168
        return new JsonResponse();
169
    }
170
171
    /**
172
     * @return JsonResponse
173
     */
174
    public function getStateAction(): JsonResponse
175
    {
176
        return new JsonResponse([ 'data' => $this->getBackendUser()->uc['digital_asset_management'] ?? []]);
177
    }
178
179
    /**
180
     * @param ServerRequestInterface $request
181
     *
182
     * @return JsonResponse
183
     */
184
    public function createFolderAction(ServerRequestInterface $request): JsonResponse
185
    {
186
        $identifier = $request->getQueryParams()['identifier'] ?? '';
187
        if (empty($identifier)) {
188
            return new JsonExceptionResponse(new ControllerException('Identifier needed', 1554204780));
189
        }
190
        try {
191
            $folder = $this->createFolderRecursive($identifier);
192
            return new JsonResponse([new FolderItemFolder($folder)]);
193
        } catch (ResourceException $e) {
194
            return new JsonExceptionResponse($e);
195
        }
196
    }
197
198
    /**
199
     * @param ServerRequestInterface $request
200
     *
201
     * @return JsonResponse
202
     */
203
    public function fileUploadAction(ServerRequestInterface $request): JsonResponse
204
    {
205
        $identifier = $request->getQueryParams()['identifier'] ?? '';
206
        $conflictMode = $request->getQueryParams()['conflictMode'] ?? '';
207
        $tempFilename = '';
208
        try {
209
            if (empty($identifier)) {
210
                throw new ControllerException('Identifier needed', 1554132801);
211
            }
212
            if (empty($conflictMode) || !in_array($conflictMode, ['replace', 'cancel', 'rename'], true)) {
213
                throw new ControllerException('conflictMode must be one of "replace", "cancel", "rename"');
214
            }
215
            $folderIdentifier = dirname($identifier) . '/';
216
            $fileIdentifier = basename($identifier);
217
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
218
            try {
219
                $folder = $resourceFactory->retrieveFileOrFolderObject($folderIdentifier);
220
            } catch (ResourceDoesNotExistException $e) {
221
                $folder = $this->createFolderRecursive($folderIdentifier);
222
            }
223
            $tempFilename = tempnam(sys_get_temp_dir(), 'upload_');
224
            file_put_contents($tempFilename, $request->getBody());
225
            $file = $folder->addFile($tempFilename, $fileIdentifier, (string)DuplicationBehavior::cast($conflictMode));
226
            $fileExtension = strtolower($file->getExtension());
227
            if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)
228
                || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['mediafile_ext'], $fileExtension)
229
            ) {
230
                return new JsonResponse([new FolderItemImage($file)]);
231
            }
232
            return new JsonResponse([new FolderItemFile($file)]);
233
        } catch (ResourceException $e) {
234
            if (!empty($tempFilename) && file_exists($tempFilename)) {
235
                unlink($tempFilename);
236
            }
237
            return new JsonExceptionResponse($e);
238
        } catch (ControllerException $e) {
239
            return new JsonExceptionResponse($e);
240
        }
241
    }
242
243
    /**
244
     * @param string $folderIdentifier
245
     *
246
     * @return Folder
247
     */
248
    protected function createFolderRecursive(string $folderIdentifier): Folder
249
    {
250
        $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
251
        $stack = [];
252
        while (true) {
253
            $parentName = dirname($folderIdentifier);
254
            $folderName = basename($folderIdentifier);
255
            $stack[] = $folderName;
256
            try {
257
                $parentObject = $resourceFactory->retrieveFileOrFolderObject($parentName);
258
                break;
259
            } catch (ResourceDoesNotExistException $e) {
260
                $folderIdentifier = $parentName;
261
            }
262
        }
263
        while ($folderName = array_pop($stack)) {
264
            try {
265
                $parentObject = $parentObject->createFolder($folderName);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parentObject does not seem to be defined for all execution paths leading up to this point.
Loading history...
266
            } catch (ResourceException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
267
            }
268
        }
269
        return $parentObject;
270
    }
271
272
    /**
273
     * @param ServerRequestInterface $request
274
     *
275
     * @return JsonResponse
276
     */
277
    public function fileExistsAction(ServerRequestInterface $request): JsonResponse
278
    {
279
        $identifier = $request->getQueryParams()['identifier'];
280
        if (empty($identifier)) {
281
            return new JsonExceptionResponse(new ControllerException('Identifier needed', 1554125449));
282
        }
283
        $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
284
        $folderIdentifier = dirname($identifier) . '/';
285
        $fileIdentifier = basename($identifier);
286
        try {
287
            $folder = $resourceFactory->retrieveFileOrFolderObject($folderIdentifier);
288
        } catch (ResourceDoesNotExistException $e) {
289
            return new FileExistsResponse(FileExistsResponse::PARENT_FOLDER_DOES_NOT_EXIST);
290
        }
291
        $fileName = $folder->getStorage()->sanitizeFileName($fileIdentifier, $folder);
292
        if ($folder->hasFile($fileName)) {
293
            $file = $resourceFactory->getFileObjectFromCombinedIdentifier($folderIdentifier . $fileName);
294
            // If file is an image or media, create image object, else file object
295
            $fileExtension = strtolower($file->getExtension());
296
            if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)
297
                || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['mediafile_ext'], $fileExtension)
298
            ) {
299
                return new JsonResponse([new FolderItemImage($file)]);
300
            }
301
            return new JsonResponse([new FolderItemFile($file)]);
302
        } else {
303
            return new FileExistsResponse(FileExistsResponse::FILE_DOES_NOT_EXIST);
304
        }
305
    }
306
307
    /**
308
     * Return item list (folders, files, images) of a storage:path
309
     * FAL folder identifier. GET request with identifier argument.
310
     *
311
     * @param ServerRequestInterface $request
312
     *
313
     * @return JsonResponse
314
     */
315
    public function getFolderItemsAction(ServerRequestInterface $request): JsonResponse
316
    {
317
        try {
318
            $identifier = $request->getQueryParams()['identifier'] ?? '';
319
            if (empty($identifier)) {
320
                throw new ControllerException('Identifier needed', 1553699828);
321
            }
322
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
323
            $folderObject = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
324
            if (!$folderObject instanceof Folder) {
325
                throw new ControllerException('Identifier is not a folder', 1553701684);
326
            }
327
            $subFolders = $folderObject->getSubfolders();
328
            $folders = [];
329
            foreach ($subFolders as $subFolder) {
330
                $folders[] = new FolderItemFolder($subFolder);
331
            }
332
            $allFiles = $folderObject->getFiles();
333
            $files = [];
334
            $images = [];
335
            foreach ($allFiles as $file) {
336
                // If file is an image or media, create image object, else file object
337
                $fileExtension = strtolower($file->getExtension());
338
                if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileExtension)
339
                    || GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['mediafile_ext'], $fileExtension)
340
                ) {
341
                    $images[] = new FolderItemImage($file);
342
                } else {
343
                    $files[] = new FolderItemFile($file);
344
                }
345
            }
346
            return new FolderItemsResponse($folders, $files, $images);
347
        } catch (ResourceException $e) {
348
            return new JsonExceptionResponse($e);
349
        } catch (ControllerException $e) {
350
            return new JsonExceptionResponse($e);
351
        }
352
    }
353
354
    /**
355
     * Returns list of storages (admins), or file mounts (non-admin). Admins
356
     * do NOT receive a list of file mounts, just the storages.
357
     *
358
     * Storages are returned in no particular order, file mounts are ordered
359
     * by 'sorting' DB field.
360
     *
361
     * Return structure is an array of Storage or FileMount objects.
362
     *
363
     * @return JsonResponse
364
     */
365
    public function getStoragesAndMountsAction(): JsonResponse
366
    {
367
        $backendUser = $this->getBackendUser();
368
        $storages = $backendUser->getFileStorages();
369
        $entities = [];
370
        if ($backendUser->isAdmin()) {
371
            foreach ($storages as $storage) {
372
                $entities[] = new Storage($storage);
373
            }
374
        } else {
375
            foreach ($storages as $storage) {
376
                $fileMounts = $storage->getFileMounts();
377
                foreach ($fileMounts as $fileMount) {
378
                    $entities[] = new FileMount($storage, $fileMount);
379
                }
380
            }
381
        }
382
        return new StoragesAndMountsResponse($entities);
383
    }
384
385
    /**
386
     * Returns list of folders only. No files, no images
387
     * Result is sorted by name
388
     *
389
     * Return structure is an array of TreeItemFolder objects.
390
     *
391
     * @param ServerRequestInterface $request
392
     *
393
     * @return JsonResponse
394
     */
395
    public function getTreeFoldersAction(ServerRequestInterface $request): JsonResponse
396
    {
397
        try {
398
            $identifier = $request->getQueryParams()['identifier'] ?? '';
399
            if (empty($identifier)) {
400
                throw new ControllerException('Identifier needed', 1553699828);
401
            }
402
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
403
            $folderObject = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
404
            if (!$folderObject instanceof Folder) {
405
                throw new ControllerException('Identifier is not a folder', 1553701684);
406
            }
407
            $subFolders = $folderObject->getSubfolders();
408
            $folders = [];
409
            foreach ($subFolders as $subFolder) {
410
                $folders[] = new TreeItemFolder($subFolder);
411
            }
412
            return new JsonResponse($folders);
413
        } catch (ResourceException $e) {
414
            return new JsonExceptionResponse($e);
415
        } catch (ControllerException $e) {
416
            return new JsonExceptionResponse($e);
417
        }
418
    }
419
420
    /**
421
     * Copy files or folders
422
     * Query parameters
423
     *  'identifiers' array of identifier to copy
424
     *  'targetFolderIdentifier' string the target identifier. Must be a folder.
425
     *  'conflictMode' string one of: "replace", "cancel", "rename", as defined in \TYPO3\CMS\Core\Resource\DuplicationBehavior
426
     *
427
     * @param ServerRequestInterface $request
428
     *
429
     * @return JsonResponse
430
     */
431
    public function copyResourcesAction(ServerRequestInterface $request): JsonResponse
432
    {
433
        try {
434
            $identifiers = $request->getQueryParams()['identifiers'];
435
            $conflictMode = $request->getQueryParams()['conflictMode'] ?? '';
436
            $targetFolderIdentifier = $request->getQueryParams()['targetFolderIdentifier'];
437
            if (empty($identifiers)) {
438
                throw new ControllerException('Identifiers needed', 1553699828);
439
            }
440
            if (empty($conflictMode) || !in_array($conflictMode, ['replace', 'cancel', 'rename'], true)) {
441
                throw new ControllerException('conflictMode must be one of "replace", "cancel", "rename"');
442
            }
443
            if (empty($targetFolderIdentifier)) {
444
                throw new ControllerException(
445
                    'Target folder identifier needed',
446
                    1554122023
447
                );
448
            }
449
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
450
            $targetFolderObject = $resourceFactory->getObjectFromCombinedIdentifier($targetFolderIdentifier);
451
            if (!$targetFolderObject instanceof Folder) {
452
                throw new ControllerException('Target identifier is not a folder', 1553701684);
453
            }
454
        } catch (ResourceException $e) {
455
            return new JsonExceptionResponse($e);
456
        } catch (ControllerException $e) {
457
            return new JsonExceptionResponse($e);
458
        }
459
        $resources = [];
460
        foreach ($identifiers as $identifier) {
461
            $state = FileOperationResult::FAILED;
462
            $message = '';
463
            $resultEntity = null;
464
            try {
465
                $sourceObject = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
466
                if ($resultObject = $sourceObject->copyTo($targetFolderObject, null, (string)DuplicationBehavior::cast($conflictMode))) {
467
                    if ($resultObject instanceof Folder) {
468
                        $resultEntity = new FolderItemFolder($resultObject);
469
                    } else {
470
                        $resultEntity = new FolderItemFile($resultObject);
471
                    }
472
                    $state = FileOperationResult::COPIED;
473
                }
474
            } catch (InvalidTargetFolderException $e) {
475
                $message = $e->getMessage();
476
            } catch (ResourceException $e) {
477
                $message = $e->getMessage();
478
            }
479
            $resources[] = new FileOperationResult($identifier, $state, $message, $resultEntity);
480
        }
481
        return new FileOperationResponse($resources);
482
    }
483
484
    /**
485
     * Move files or folders
486
     * Query parameters
487
     *  'identifiers' array of identifier to move
488
     *  'targetFolderIdentifier' string the target identifier. Must be a folder.
489
     *  'conflictMode' string one of: "replace", "cancel", "rename", as defined in \TYPO3\CMS\Core\Resource\DuplicationBehavior
490
     *
491
     * @param ServerRequestInterface $request
492
     *
493
     * @return JsonResponse
494
     */
495
    public function moveResourcesAction(ServerRequestInterface $request): JsonResponse
496
    {
497
        try {
498
            $identifiers = $request->getQueryParams()['identifiers'];
499
            $conflictMode = $request->getQueryParams()['conflictMode'] ?? '';
500
            $targetFolderIdentifier = $request->getQueryParams()['targetFolderIdentifier'];
501
            if (empty($identifiers)) {
502
                throw new ControllerException('Identifiers needed', 1553699828);
503
            }
504
            if (empty($conflictMode) || !in_array($conflictMode, ['replace', 'cancel', 'rename'], true)) {
505
                throw new ControllerException('conflictMode must be one of "replace", "cancel", "rename"');
506
            }
507
            if (empty($targetFolderIdentifier)) {
508
                throw new ControllerException('Target folder identifier needed', 1554122023);
509
            }
510
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
511
            $targetFolderObject = $resourceFactory->getObjectFromCombinedIdentifier($targetFolderIdentifier);
512
            if (!$targetFolderObject instanceof Folder) {
513
                throw new ControllerException('Target identifier is not a folder', 1553701684);
514
            }
515
        } catch (ResourceException $e) {
516
            return new JsonExceptionResponse($e);
517
        } catch (ControllerException $e) {
518
            return new JsonExceptionResponse($e);
519
        }
520
        $resources = [];
521
        foreach ($identifiers as $identifier) {
522
            $state = FileOperationResult::FAILED;
523
            $message = '';
524
            $resultEntity = null;
525
            try {
526
                $sourceObject = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
527
                if ($resultObject = $sourceObject->moveTo($targetFolderObject, null, (string)DuplicationBehavior::cast($conflictMode))) {
528
                    if ($resultObject instanceof Folder) {
529
                        $resultEntity = new FolderItemFolder($resultObject);
530
                    } else {
531
                        $resultEntity = new FolderItemFile($resultObject);
532
                    }
533
                    $state = FileOperationResult::MOVED;
534
                }
535
            } catch (InvalidTargetFolderException $e) {
536
                $message = $e->getMessage();
537
            } catch (ResourceException $e) {
538
                $message = $e->getMessage();
539
            }
540
            $resources[] = new FileOperationResult($identifier, $state, $message, $resultEntity);
541
        }
542
        return new FileOperationResponse($resources);
543
    }
544
545
    /**
546
     * rename file or folder
547
     * Query parameters
548
     *  'identifier' string identifier to rename
549
     *  'targetName' string The new name of file or folder.
550
     *  'conflictMode' string one of: "replace", "cancel", "rename"
551
     *
552
     * @param ServerRequestInterface $request
553
     *
554
     * @return JsonResponse
555
     */
556
    public function renameResourcesAction(ServerRequestInterface $request): JsonResponse
557
    {
558
        try {
559
            $identifier = $request->getQueryParams()['identifier'];
560
            $targetName = $request->getQueryParams()['targetName'];
561
            $conflictMode = $request->getQueryParams()['conflictMode'] ?? '';
562
            if (empty($identifier)) {
563
                throw new ControllerException('Identifier needed', 1553699828);
564
            }
565
            if (empty($conflictMode) || !in_array($conflictMode, ['replace', 'cancel', 'rename'], true)) {
566
                throw new ControllerException('conflictMode must be one of "replace", "cancel", "rename"');
567
            }
568
            if (empty($targetName)) {
569
                throw new ControllerException('Target name needed', 1554193259);
570
            }
571
            $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
572
            $fileOrFolder = $resourceFactory->retrieveFileOrFolderObject($identifier);
573
        } catch (ResourceException $e) {
574
            return new JsonExceptionResponse($e);
575
        } catch (ControllerException $e) {
576
            return new JsonExceptionResponse($e);
577
        }
578
        $resources = [];
579
        $state = FileOperationResult::FAILED;
580
        $resultEntity = null;
581
        try {
582
            if ($fileOrFolder === null) {
583
                throw new ResourceException\ResourceDoesNotExistException('Resource does not exist');
584
            } else {
585
                $resultObject = $fileOrFolder->rename($targetName, (string)DuplicationBehavior::cast($conflictMode));
586
                if ($resultObject instanceof Folder) {
587
                    $resultEntity = new FolderItemFolder($resultObject);
588
                    $message = 'Folder was successfully renamed';
589
                } else {
590
                    $resultEntity = new FolderItemFile($resultObject);
591
                    $message = 'File was successfully renamed';
592
                }
593
                $state = FileOperationResult::RENAMED;
594
            }
595
        } catch (ResourceException $e) {
596
            $message = $e->getMessage();
597
        }
598
        $resources[] = new FileOperationResult($identifier, $state, $message, $resultEntity);
599
        return new JsonResponse($resources);
600
    }
601
602
    /**
603
     * delete file or folder
604
     * Query parameters
605
     *  'identifiers' array of strings identifier of file or folder to delete
606
     *
607
     * @param ServerRequestInterface $request
608
     *
609
     * @return JsonResponse
610
     */
611
    public function deleteResourcesAction(ServerRequestInterface $request): JsonResponse
612
    {
613
        try {
614
            $identifiers = $request->getQueryParams()['identifiers'];
615
            if (empty($identifiers)) {
616
                throw new ControllerException('Identifiers needed', 1553699828);
617
            }
618
        } catch (ControllerException $e) {
619
            return new JsonExceptionResponse($e);
620
        }
621
        $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
622
        $resources = [];
623
        foreach ($identifiers as $identifier) {
624
            try {
625
                $sourceObject = $resourceFactory->getObjectFromCombinedIdentifier($identifier);
626
                if ($sourceObject->delete(true)) {
627
                    $state = FileOperationResult::DELETED;
628
                    $message = 'Resource deleted';
629
                } else {
630
                    $state = FileOperationResult::FAILED;
631
                    $message = 'Resource could not be deleted';
632
                }
633
            } catch (ResourceException $e) {
634
                $state = FileOperationResult::FAILED;
635
                $message = $e->getMessage();
636
            }
637
            $resources[] = new FileOperationResult($identifier, $state, $message, null);
638
        }
639
        return new FileOperationResponse($resources);
640
    }
641
642
    /**
643
     * @return BackendUserAuthentication
644
     */
645
    protected function getBackendUser(): BackendUserAuthentication
646
    {
647
        return $GLOBALS['BE_USER'];
648
    }
649
}
650