Completed
Push — master ( 3da3e5...9199f2 )
by
unknown
18:43
created

FileListController::addJumpToUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Filelist\Controller;
17
18
use Psr\Log\LoggerAwareInterface;
19
use Psr\Log\LoggerAwareTrait;
20
use TYPO3\CMS\Backend\Clipboard\Clipboard;
21
use TYPO3\CMS\Backend\Routing\UriBuilder;
22
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
23
use TYPO3\CMS\Backend\Utility\BackendUtility;
24
use TYPO3\CMS\Backend\View\BackendTemplateView;
25
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
26
use TYPO3\CMS\Core\Imaging\Icon;
27
use TYPO3\CMS\Core\Imaging\IconFactory;
28
use TYPO3\CMS\Core\Localization\LanguageService;
29
use TYPO3\CMS\Core\Messaging\FlashMessage;
30
use TYPO3\CMS\Core\Resource\DuplicationBehavior;
31
use TYPO3\CMS\Core\Resource\Exception;
32
use TYPO3\CMS\Core\Resource\Folder;
33
use TYPO3\CMS\Core\Resource\ResourceFactory;
34
use TYPO3\CMS\Core\Resource\Search\FileSearchDemand;
35
use TYPO3\CMS\Core\Resource\Utility\ListUtility;
36
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
37
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
use TYPO3\CMS\Core\Utility\MathUtility;
40
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
41
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
42
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
43
use TYPO3\CMS\Filelist\Configuration\ThumbnailConfiguration;
44
use TYPO3\CMS\Filelist\FileFacade;
45
use TYPO3\CMS\Filelist\FileList;
46
47
/**
48
 * Script Class for creating the list of files in the File > Filelist module
49
 * @internal this is a concrete TYPO3 controller implementation and solely used for EXT:filelist and not part of TYPO3's Core API.
50
 */
51
class FileListController extends ActionController implements LoggerAwareInterface
52
{
53
    use LoggerAwareTrait;
54
55
    public const UPLOAD_ACTION_REPLACE = 'replace';
56
    public const UPLOAD_ACTION_RENAME = 'rename';
57
    public const UPLOAD_ACTION_SKIP = 'cancel';
58
59
    /**
60
     * @var array
61
     */
62
    protected $MOD_MENU = [];
63
64
    /**
65
     * @var array
66
     */
67
    protected $MOD_SETTINGS = [];
68
69
    /**
70
     * "id" -> the path to list.
71
     *
72
     * @var string
73
     */
74
    protected $id;
75
76
    /**
77
     * @var Folder
78
     */
79
    protected $folderObject;
80
81
    /**
82
     * @var FlashMessage
83
     */
84
    protected $errorMessage;
85
86
    /**
87
     * Pointer to listing
88
     *
89
     * @var int
90
     */
91
    protected $pointer;
92
93
    /**
94
     * Thumbnail mode.
95
     *
96
     * @var string
97
     */
98
    protected $imagemode;
99
100
    /**
101
     * @var string
102
     */
103
    protected $cmd;
104
105
    /**
106
     * Defines behaviour when uploading files with names that already exist; possible values are
107
     * the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
108
     *
109
     * @var \TYPO3\CMS\Core\Resource\DuplicationBehavior
110
     */
111
    protected $overwriteExistingFiles;
112
113
    /**
114
     * The filelist object
115
     *
116
     * @var FileList
117
     */
118
    protected $filelist;
119
120
    /**
121
     * The name of the module
122
     *
123
     * @var string
124
     */
125
    protected $moduleName = 'file_list';
126
127
    /**
128
     * @var \TYPO3\CMS\Core\Resource\FileRepository
129
     */
130
    protected $fileRepository;
131
132
    /**
133
     * @var BackendTemplateView
134
     */
135
    protected $view;
136
137
    /**
138
     * BackendTemplateView Container
139
     *
140
     * @var string
141
     */
142
    protected $defaultViewObjectName = BackendTemplateView::class;
143
144
    /**
145
     * @param \TYPO3\CMS\Core\Resource\FileRepository $fileRepository
146
     */
147
    public function injectFileRepository(\TYPO3\CMS\Core\Resource\FileRepository $fileRepository)
148
    {
149
        $this->fileRepository = $fileRepository;
150
    }
151
152
    /**
153
     * Initialize variables, file object
154
     * Incoming GET vars include id, pointer, table, imagemode
155
     *
156
     * @throws \RuntimeException
157
     */
158
    public function initializeObject()
159
    {
160
        $this->getLanguageService()->includeLLFile('EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf');
161
        $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_misc.xlf');
162
163
        // Setting GPvars:
164
        $this->id = ($combinedIdentifier = GeneralUtility::_GP('id'));
165
        $this->pointer = GeneralUtility::_GP('pointer');
166
        $this->imagemode = GeneralUtility::_GP('imagemode');
167
        $this->cmd = GeneralUtility::_GP('cmd');
168
        $this->overwriteExistingFiles = DuplicationBehavior::cast(GeneralUtility::_GP('overwriteExistingFiles'));
169
170
        try {
171
            if ($combinedIdentifier) {
172
                /** @var ResourceFactory $resourceFactory */
173
                $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
174
                $storage = $resourceFactory->getStorageObjectFromCombinedIdentifier($combinedIdentifier);
175
                $identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1);
176
                if (!$storage->hasFolder($identifier)) {
177
                    $identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier);
178
                }
179
180
                $this->folderObject = $resourceFactory->getFolderObjectFromCombinedIdentifier($storage->getUid() . ':' . $identifier);
181
                // Disallow access to fallback storage 0
182
                if ($storage->getUid() === 0) {
183
                    throw new Exception\InsufficientFolderAccessPermissionsException(
184
                        'You are not allowed to access files outside your storages',
185
                        1434539815
186
                    );
187
                }
188
                // Disallow the rendering of the processing folder (e.g. could be called manually)
189
                if ($this->folderObject && $storage->isProcessingFolder($this->folderObject)) {
190
                    $this->folderObject = $storage->getRootLevelFolder();
191
                }
192
            } else {
193
                // Take the first object of the first storage
194
                $fileStorages = $this->getBackendUser()->getFileStorages();
195
                $fileStorage = reset($fileStorages);
196
                if ($fileStorage) {
197
                    $this->folderObject = $fileStorage->getRootLevelFolder();
198
                } else {
199
                    throw new \RuntimeException('Could not find any folder to be displayed.', 1349276894);
200
                }
201
            }
202
203
            if ($this->folderObject && !$this->folderObject->getStorage()->isWithinFileMountBoundaries($this->folderObject)) {
204
                throw new \RuntimeException('Folder not accessible.', 1430409089);
205
            }
206
        } catch (Exception\InsufficientFolderAccessPermissionsException $permissionException) {
207
            $this->folderObject = null;
208
            $this->errorMessage = GeneralUtility::makeInstance(
209
                FlashMessage::class,
210
                sprintf(
211
                    $this->getLanguageService()->getLL('missingFolderPermissionsMessage'),
212
                    $this->id
213
                ),
214
                $this->getLanguageService()->getLL('missingFolderPermissionsTitle'),
215
                FlashMessage::NOTICE
216
            );
217
        } catch (Exception $fileException) {
218
            // Set folder object to null and throw a message later on
219
            $this->folderObject = null;
220
            // Take the first object of the first storage
221
            $fileStorages = $this->getBackendUser()->getFileStorages();
222
            $fileStorage = reset($fileStorages);
223
            if ($fileStorage instanceof \TYPO3\CMS\Core\Resource\ResourceStorage) {
224
                $this->folderObject = $fileStorage->getRootLevelFolder();
225
                if (!$fileStorage->isWithinFileMountBoundaries($this->folderObject)) {
226
                    $this->folderObject = null;
227
                }
228
            }
229
            $this->errorMessage = GeneralUtility::makeInstance(
230
                FlashMessage::class,
231
                sprintf(
232
                    $this->getLanguageService()->getLL('folderNotFoundMessage'),
233
                    $this->id
234
                ),
235
                $this->getLanguageService()->getLL('folderNotFoundTitle'),
236
                FlashMessage::NOTICE
237
            );
238
        } catch (\RuntimeException $e) {
239
            $this->folderObject = null;
240
            $this->errorMessage = GeneralUtility::makeInstance(
241
                FlashMessage::class,
242
                $e->getMessage() . ' (' . $e->getCode() . ')',
243
                $this->getLanguageService()->getLL('folderNotFoundTitle'),
244
                FlashMessage::NOTICE
245
            );
246
        }
247
248
        if ($this->folderObject && !$this->folderObject->getStorage()->checkFolderActionPermission(
249
            'read',
250
            $this->folderObject
251
        )
252
        ) {
253
            $this->folderObject = null;
254
        }
255
256
        // Configure the "menu" - which is used internally to save the values of sorting, displayThumbs etc.
257
        $this->menuConfig();
258
    }
259
260
    /**
261
     * Setting the menu/session variables
262
     */
263
    protected function menuConfig()
264
    {
265
        // MENU-ITEMS:
266
        // If array, then it's a selector box menu
267
        // If empty string it's just a variable, that will be saved.
268
        // Values NOT in this array will not be saved in the settings-array for the module.
269
        $this->MOD_MENU = [
270
            'sort' => '',
271
            'reverse' => '',
272
            'displayThumbs' => '',
273
            'clipBoard' => '',
274
            'bigControlPanel' => ''
275
        ];
276
        // CLEANSE SETTINGS
277
        $this->MOD_SETTINGS = BackendUtility::getModuleData(
278
            $this->MOD_MENU,
279
            GeneralUtility::_GP('SET'),
280
            $this->moduleName
281
        );
282
    }
283
284
    /**
285
     * Initialize the view
286
     *
287
     * @param ViewInterface $view The view
288
     */
289
    protected function initializeView(ViewInterface $view)
290
    {
291
        /** @var BackendTemplateView $view */
292
        parent::initializeView($view);
293
        $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
294
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation');
295
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileList');
296
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileSearch');
297
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
298
        $this->registerDocHeaderButtons();
299
        if ($this->folderObject instanceof Folder) {
0 ignored issues
show
introduced by
$this->folderObject is always a sub-type of TYPO3\CMS\Core\Resource\Folder.
Loading history...
300
            $view->assign(
301
                'currentFolderHash',
302
                'folder' . GeneralUtility::md5int($this->folderObject->getCombinedIdentifier())
303
            );
304
        }
305
        $view->assign('currentIdentifier', $this->id);
306
    }
307
308
    protected function initializeIndexAction()
309
    {
310
        // Apply predefined values for hidden checkboxes
311
        // Set predefined value for DisplayBigControlPanel:
312
        $backendUser = $this->getBackendUser();
313
        $userTsConfig = $backendUser->getTSConfig();
314
        if (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'activated') {
315
            $this->MOD_SETTINGS['bigControlPanel'] = true;
316
        } elseif (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'deactivated') {
317
            $this->MOD_SETTINGS['bigControlPanel'] = false;
318
        }
319
        // Set predefined value for DisplayThumbnails:
320
        if (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'activated') {
321
            $this->MOD_SETTINGS['displayThumbs'] = true;
322
        } elseif (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'deactivated') {
323
            $this->MOD_SETTINGS['displayThumbs'] = false;
324
        }
325
        // Set predefined value for Clipboard:
326
        if (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'activated') {
327
            $this->MOD_SETTINGS['clipBoard'] = true;
328
        } elseif (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'deactivated') {
329
            $this->MOD_SETTINGS['clipBoard'] = false;
330
        }
331
        // If user never opened the list module, set the value for displayThumbs
332
        if (!isset($this->MOD_SETTINGS['displayThumbs'])) {
333
            $this->MOD_SETTINGS['displayThumbs'] = $backendUser->uc['thumbnailsByDefault'];
334
        }
335
        if (!isset($this->MOD_SETTINGS['sort'])) {
336
            // Set default sorting
337
            $this->MOD_SETTINGS['sort'] = 'file';
338
            $this->MOD_SETTINGS['reverse'] = 0;
339
        }
340
    }
341
342
    protected function indexAction()
343
    {
344
        $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
345
        $pageRenderer->setTitle($this->getLanguageService()->getLL('files'));
346
347
        // There there was access to this file path, continue, make the list
348
        if ($this->folderObject) {
349
            $this->initClipboard();
350
            $userTsConfig = $this->getBackendUser()->getTSConfig();
351
            $this->filelist = GeneralUtility::makeInstance(FileList::class);
352
            $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
353
            $CB = GeneralUtility::_GET('CB');
354
            if ($this->cmd === 'setCB') {
355
                $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
356
                    GeneralUtility::_POST('CBH'),
0 ignored issues
show
Bug introduced by
TYPO3\CMS\Core\Utility\G...alUtility::_POST('CBH') of type null|string is incompatible with the type array expected by parameter $array1 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

356
                    /** @scrutinizer ignore-type */ GeneralUtility::_POST('CBH'),
Loading history...
357
                    (array)GeneralUtility::_POST('CBC')
358
                ), '_FILE');
359
            }
360
            if (!$this->MOD_SETTINGS['clipBoard']) {
361
                $CB['setP'] = 'normal';
362
            }
363
            $this->filelist->clipObj->setCmd($CB);
364
            $this->filelist->clipObj->cleanCurrent();
365
            // Saves
366
            $this->filelist->clipObj->endClipboard();
367
368
            // If the "cmd" was to delete files from the list (clipboard thing), do that:
369
            if ($this->cmd === 'delete') {
370
                $items = $this->filelist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), '_FILE', 1);
371
                if (!empty($items)) {
372
                    // Make command array:
373
                    $FILE = [];
374
                    foreach ($items as $clipboardIdentifier => $combinedIdentifier) {
375
                        $FILE['delete'][] = ['data' => $combinedIdentifier];
376
                        $this->filelist->clipObj->removeElement($clipboardIdentifier);
377
                    }
378
                    // Init file processing object for deleting and pass the cmd array.
379
                    /** @var ExtendedFileUtility $fileProcessor */
380
                    $fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
381
                    $fileProcessor->setActionPermissions();
382
                    $fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
383
                    $fileProcessor->start($FILE);
384
                    $fileProcessor->processData();
385
                    // Clean & Save clipboard state
386
                    $this->filelist->clipObj->cleanCurrent();
387
                    $this->filelist->clipObj->endClipboard();
388
                }
389
            }
390
            // Start up filelisting object, include settings.
391
            $this->filelist->start(
392
                $this->folderObject,
393
                MathUtility::forceIntegerInRange($this->pointer, 0, 100000),
394
                $this->MOD_SETTINGS['sort'],
395
                (bool)$this->MOD_SETTINGS['reverse'],
396
                (bool)$this->MOD_SETTINGS['clipBoard'],
397
                (bool)$this->MOD_SETTINGS['bigControlPanel']
398
            );
399
            // Generate the list, if accessible
400
            if ($this->folderObject->getStorage()->isBrowsable()) {
401
                $this->view->assign('listHtml', $this->filelist->getTable());
402
            } else {
403
                $this->addFlashMessage(
404
                    $this->getLanguageService()->getLL('storageNotBrowsableMessage'),
405
                    $this->getLanguageService()->getLL('storageNotBrowsableTitle'),
406
                    FlashMessage::INFO
407
                );
408
            }
409
410
            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ClipboardComponent');
411
            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
412
            $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
413
414
            // Include DragUploader only if we have write access
415
            if ($this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
416
                && $this->folderObject->checkActionPermission('write')
417
            ) {
418
                $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader');
419
                $pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_core.xlf', 'file_upload');
420
                $pageRenderer->addInlineLanguageLabelArray([
421
                    'permissions.read' => $this->getLanguageService()->getLL('read'),
422
                    'permissions.write' => $this->getLanguageService()->getLL('write'),
423
                ]);
424
            }
425
426
            // Setting up the buttons
427
            $this->registerButtons();
428
429
            $pageRecord = [
430
                '_additional_info' => $this->filelist->getFolderInfo(),
431
                'combined_identifier' => $this->folderObject->getCombinedIdentifier(),
432
            ];
433
            $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord);
434
435
            $this->view->assign('headline', $this->getModuleHeadline());
436
437
            $this->view->assign('checkboxes', [
438
                'bigControlPanel' => [
439
                    'enabled' => ($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'selectable',
440
                    'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
441
                    'html' => BackendUtility::getFuncCheck(
442
                        $this->id,
443
                        'SET[bigControlPanel]',
444
                        $this->MOD_SETTINGS['bigControlPanel'] ?? '',
445
                        '',
446
                        '',
447
                        'id="bigControlPanel"'
448
                    ),
449
                ],
450
                'displayThumbs' => [
451
                    'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && ($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'selectable',
452
                    'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
453
                    'html' => BackendUtility::getFuncCheck(
454
                        $this->id,
455
                        'SET[displayThumbs]',
456
                        $this->MOD_SETTINGS['displayThumbs'] ?? '',
457
                        '',
458
                        '',
459
                        'id="checkDisplayThumbs"'
460
                    ),
461
                ],
462
                'enableClipBoard' => [
463
                    'enabled' => ($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'selectable',
464
                    'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')),
465
                    'html' => BackendUtility::getFuncCheck(
466
                        $this->id,
467
                        'SET[clipBoard]',
468
                        $this->MOD_SETTINGS['clipBoard'] ?? '',
469
                        '',
470
                        '',
471
                        'id="checkClipBoard"'
472
                    ),
473
                ]
474
            ]);
475
            $this->view->assign('showClipBoard', (bool)$this->MOD_SETTINGS['clipBoard']);
476
            $this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard());
477
            $this->view->assign('folderIdentifier', $this->folderObject->getCombinedIdentifier());
478
            $this->view->assign('fileDenyPattern', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']);
479
            $this->view->assign('maxFileSize', GeneralUtility::getMaxUploadFileSize() * 1024);
480
            $this->view->assign('defaultAction', $this->getDefaultAction());
481
            $this->buildListOptionCheckboxes();
482
        } else {
483
            $this->forward('missingFolder');
484
        }
485
    }
486
487
    protected function getDefaultAction(): string
488
    {
489
        $defaultAction = $this->getBackendUser()->getTSConfig()
490
            ['options.']['file_list.']['uploader.']['defaultAction'] ?? '';
491
492
        if ($defaultAction === '') {
493
            $defaultAction = self::UPLOAD_ACTION_SKIP;
494
        }
495
        if (!in_array($defaultAction, [
496
            self::UPLOAD_ACTION_REPLACE,
497
            self::UPLOAD_ACTION_RENAME,
498
            self::UPLOAD_ACTION_SKIP
499
        ], true)) {
500
            $this->logger->warning(sprintf(
501
                'TSConfig: options.file_list.uploader.defaultAction contains an invalid value ("%s"), fallback to default value: "%s"',
502
                $defaultAction,
503
                self::UPLOAD_ACTION_SKIP
504
            ));
505
            $defaultAction = self::UPLOAD_ACTION_SKIP;
506
        }
507
        return $defaultAction;
508
    }
509
510
    protected function missingFolderAction()
511
    {
512
        if ($this->errorMessage) {
513
            $this->errorMessage->setSeverity(FlashMessage::ERROR);
514
            $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage($this->errorMessage);
515
        }
516
    }
517
518
    /**
519
     * Search for files by name and pass them with a facade to fluid
520
     *
521
     * @param string $searchWord
522
     */
523
    protected function searchAction($searchWord = '')
524
    {
525
        if (empty($searchWord)) {
526
            $this->forward('index');
527
        }
528
        $searchDemand = FileSearchDemand::createForSearchTerm($searchWord)->withRecursive();
529
        $files = $this->folderObject->searchFiles($searchDemand);
530
531
        $fileFacades = [];
532
        if (count($files) === 0) {
533
            $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage(
534
                new FlashMessage(
535
                    LocalizationUtility::translate('flashmessage.no_results', 'filelist'),
536
                    '',
537
                    FlashMessage::INFO
538
                )
539
            );
540
        } else {
541
            foreach ($files as $file) {
542
                $fileFacades[] = new FileFacade($file);
543
            }
544
        }
545
546
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
547
548
        $thumbnailConfiguration = GeneralUtility::makeInstance(ThumbnailConfiguration::class);
549
        $this->view->assign('thumbnail', [
550
            'width' => $thumbnailConfiguration->getWidth(),
551
            'height' => $thumbnailConfiguration->getHeight(),
552
        ]);
553
554
        $this->view->assign('searchWord', $searchWord);
555
        $this->view->assign('files', $fileFacades);
556
        $this->view->assign('deleteUrl', (string)$uriBuilder->buildUriFromRoute('tce_file'));
557
        $this->view->assign('settings', [
558
            'jsConfirmationDelete' => $this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)
559
        ]);
560
        $this->view->assign('moduleSettings', $this->MOD_SETTINGS);
561
562
        $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
563
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
564
        $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
565
566
        $this->initClipboard();
567
        $this->buildListOptionCheckboxes($searchWord);
568
    }
569
570
    /**
571
     * Get main headline based on active folder or storage for backend module
572
     * Folder names are resolved to their special names like done in the tree view.
573
     *
574
     * @return string
575
     */
576
    protected function getModuleHeadline()
577
    {
578
        $name = $this->folderObject->getName();
579
        if ($name === '') {
580
            // Show storage name on storage root
581
            if ($this->folderObject->getIdentifier() === '/') {
582
                $name = $this->folderObject->getStorage()->getName();
583
            }
584
        } else {
585
            $name = key(ListUtility::resolveSpecialFolderNames(
586
                [$name => $this->folderObject]
587
            ));
588
        }
589
        return $name;
590
    }
591
592
    /**
593
     * Registers the Icons into the docheader
594
     *
595
     * @throws \InvalidArgumentException
596
     */
597
    protected function registerDocHeaderButtons()
598
    {
599
        /** @var ButtonBar $buttonBar */
600
        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
601
602
        // CSH
603
        $cshButton = $buttonBar->makeHelpButton()
604
            ->setModuleName('xMOD_csh_corebe')
605
            ->setFieldName('filelist_module');
606
        $buttonBar->addButton($cshButton);
607
    }
608
609
    /**
610
     * Create the panel of buttons for submitting the form or otherwise perform operations.
611
     */
612
    protected function registerButtons()
613
    {
614
        /** @var ButtonBar $buttonBar */
615
        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
616
617
        /** @var IconFactory $iconFactory */
618
        $iconFactory = $this->view->getModuleTemplate()->getIconFactory();
619
620
        $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
621
622
        $lang = $this->getLanguageService();
623
624
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
625
626
        // Refresh page
627
        $refreshLink = GeneralUtility::linkThisScript(
628
            [
629
                'target' => rawurlencode($this->folderObject->getCombinedIdentifier()),
630
                'imagemode' => $this->filelist->thumbs
631
            ]
632
        );
633
        $refreshButton = $buttonBar->makeLinkButton()
634
            ->setHref($refreshLink)
635
            ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
636
            ->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
637
        $buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT);
638
639
        // Level up
640
        try {
641
            $currentStorage = $this->folderObject->getStorage();
642
            $parentFolder = $this->folderObject->getParentFolder();
643
            if ($parentFolder->getIdentifier() !== $this->folderObject->getIdentifier()
644
                && $currentStorage->isWithinFileMountBoundaries($parentFolder)
645
            ) {
646
                $levelUpButton = $buttonBar->makeLinkButton()
647
                    ->setDataAttributes([
648
                        'tree-update-request' => htmlspecialchars('folder' . GeneralUtility::md5int($parentFolder->getCombinedIdentifier())),
649
                    ])
650
                    ->setHref((string)$uriBuilder->buildUriFromRoute('file_FilelistList', ['id' => $parentFolder->getCombinedIdentifier()]))
651
                    ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.upOneLevel'))
652
                    ->setIcon($iconFactory->getIcon('actions-view-go-up', Icon::SIZE_SMALL));
653
                $buttonBar->addButton($levelUpButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
654
            }
655
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
656
        }
657
658
        // Shortcut
659
        if ($this->getBackendUser()->mayMakeShortcut()) {
660
            $shortCutButton = $buttonBar->makeShortcutButton()->setModuleName('file_FilelistList');
661
            $buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT);
662
        }
663
664
        // Upload button (only if upload to this directory is allowed)
665
        if ($this->folderObject && $this->folderObject->getStorage()->checkUserActionPermission(
666
            'add',
667
            'File'
668
        ) && $this->folderObject->checkActionPermission('write')
669
        ) {
670
            $uploadButton = $buttonBar->makeLinkButton()
671
                ->setHref((string)$uriBuilder->buildUriFromRoute(
672
                    'file_upload',
673
                    [
674
                        'target' => $this->folderObject->getCombinedIdentifier(),
675
                        'returnUrl' => $this->filelist->listURL(),
676
                    ]
677
                ))
678
                ->setClasses('t3js-drag-uploader-trigger')
679
                ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'))
680
                ->setIcon($iconFactory->getIcon('actions-edit-upload', Icon::SIZE_SMALL));
681
            $buttonBar->addButton($uploadButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
682
        }
683
684
        // New folder button
685
        if ($this->folderObject && $this->folderObject->checkActionPermission('write')
686
            && ($this->folderObject->getStorage()->checkUserActionPermission(
687
                'add',
688
                'File'
689
            ) || $this->folderObject->checkActionPermission('add'))
690
        ) {
691
            $newButton = $buttonBar->makeLinkButton()
692
                ->setHref((string)$uriBuilder->buildUriFromRoute(
693
                    'file_newfolder',
694
                    [
695
                        'target' => $this->folderObject->getCombinedIdentifier(),
696
                        'returnUrl' => $this->filelist->listURL(),
697
                    ]
698
                ))
699
                ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.new'))
700
                ->setIcon($iconFactory->getIcon('actions-add', Icon::SIZE_SMALL));
701
            $buttonBar->addButton($newButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
702
        }
703
704
        // Add paste button if clipboard is initialized
705
        if ($this->filelist->clipObj instanceof Clipboard && $this->folderObject->checkActionPermission('write')) {
706
            $elFromTable = $this->filelist->clipObj->elFromTable('_FILE');
707
            if (!empty($elFromTable)) {
708
                $addPasteButton = true;
709
                $elToConfirm = [];
710
                foreach ($elFromTable as $key => $element) {
711
                    $clipBoardElement = $resourceFactory->retrieveFileOrFolderObject($element);
712
                    if ($clipBoardElement instanceof Folder && $clipBoardElement->getStorage()->isWithinFolder(
713
                        $clipBoardElement,
714
                        $this->folderObject
715
                    )
716
                    ) {
717
                        $addPasteButton = false;
718
                    }
719
                    $elToConfirm[$key] = $clipBoardElement->getName();
720
                }
721
                if ($addPasteButton) {
722
                    $confirmText = $this->filelist->clipObj
723
                        ->confirmMsgText('_FILE', $this->folderObject->getReadablePath(), 'into', $elToConfirm);
724
                    $pasteButton = $buttonBar->makeLinkButton()
725
                        ->setHref($this->filelist->clipObj
726
                            ->pasteUrl('_FILE', $this->folderObject->getCombinedIdentifier()))
727
                        ->setClasses('t3js-modal-trigger')
728
                        ->setDataAttributes([
729
                            'severity' => 'warning',
730
                            'content' => $confirmText,
731
                            'title' => $lang->getLL('clip_paste')
732
                        ])
733
                        ->setTitle($lang->getLL('clip_paste'))
734
                        ->setIcon($iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));
735
                    $buttonBar->addButton($pasteButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
736
                }
737
            }
738
        }
739
    }
740
741
    /**
742
     * Returns an instance of LanguageService
743
     *
744
     * @return LanguageService
745
     */
746
    protected function getLanguageService(): LanguageService
747
    {
748
        return $GLOBALS['LANG'];
749
    }
750
751
    /**
752
     * Returns the current BE user.
753
     *
754
     * @return BackendUserAuthentication
755
     */
756
    protected function getBackendUser(): BackendUserAuthentication
757
    {
758
        return $GLOBALS['BE_USER'];
759
    }
760
761
    /**
762
     * build option checkboxes for filelist
763
     */
764
    protected function buildListOptionCheckboxes(string $searchWord = ''): void
765
    {
766
        $backendUser = $this->getBackendUser();
767
        $userTsConfig = $backendUser->getTSConfig();
768
769
        $addParams = '';
770
        if ($searchWord) {
771
            $addParams = '&tx_filelist_file_filelistlist%5Baction%5D=search';
772
            $addParams .= '&tx_filelist_file_filelistlist%5Bcontroller%5D=FileList';
773
            $addParams .= '&tx_filelist_file_filelistlist%5BsearchWord%5D=' . htmlspecialchars($searchWord);
774
        }
775
        $this->view->assign('checkboxes', [
776
            'bigControlPanel' => [
777
                'enabled' => $userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] === 'selectable',
778
                'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
779
                'html' => BackendUtility::getFuncCheck(
780
                    $this->id,
781
                    'SET[bigControlPanel]',
782
                    $this->MOD_SETTINGS['bigControlPanel'] ?? '',
783
                    '',
784
                    $addParams,
785
                    'id="bigControlPanel"'
786
                ),
787
            ],
788
            'displayThumbs' => [
789
                'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] === 'selectable',
790
                'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
791
                'html' => BackendUtility::getFuncCheck(
792
                    $this->id,
793
                    'SET[displayThumbs]',
794
                    $this->MOD_SETTINGS['displayThumbs'] ?? '',
795
                    '',
796
                    $addParams,
797
                    'id="checkDisplayThumbs"'
798
                ),
799
            ],
800
            'enableClipBoard' => [
801
                'enabled' => $userTsConfig['options.']['file_list.']['enableClipBoard'] === 'selectable',
802
                'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')),
803
                'html' => BackendUtility::getFuncCheck(
804
                    $this->id,
805
                    'SET[clipBoard]',
806
                    $this->MOD_SETTINGS['clipBoard'] ?? '',
807
                    '',
808
                    $addParams,
809
                    'id="checkClipBoard"'
810
                ),
811
            ]
812
        ]);
813
    }
814
815
    /**
816
     * init and assign clipboard to view
817
     */
818
    protected function initClipboard(): void
819
    {
820
        // Create fileListing object
821
        $this->filelist = GeneralUtility::makeInstance(FileList::class, $this);
822
        $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
823
        // Create clipboard object and initialize that
824
        $this->filelist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
825
        $this->filelist->clipObj->fileMode = true;
826
        $this->filelist->clipObj->initializeClipboard();
827
        $CB = GeneralUtility::_GET('CB');
828
        if ($this->cmd === 'setCB') {
829
            $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
830
                GeneralUtility::_POST('CBH'),
0 ignored issues
show
Bug introduced by
TYPO3\CMS\Core\Utility\G...alUtility::_POST('CBH') of type null|string is incompatible with the type array expected by parameter $array1 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

830
                /** @scrutinizer ignore-type */ GeneralUtility::_POST('CBH'),
Loading history...
831
                (array)GeneralUtility::_POST('CBC')
832
            ), '_FILE');
833
        }
834
        if (!$this->MOD_SETTINGS['clipBoard']) {
835
            $CB['setP'] = 'normal';
836
        }
837
        $this->filelist->clipObj->setCmd($CB);
838
        $this->filelist->clipObj->cleanCurrent();
839
        // Saves
840
        $this->filelist->clipObj->endClipboard();
841
842
        $this->view->assign('showClipBoard', (bool)$this->MOD_SETTINGS['clipBoard']);
843
        $this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard());
844
    }
845
}
846