Completed
Push — master ( 6a91d9...e837e5 )
by
unknown
220:07 queued 201:54
created

FileListController::initClipboard()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 18
nc 8
nop 0
dl 0
loc 26
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace TYPO3\CMS\Filelist\Controller;
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
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 BackendTemplateView
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(
0 ignored issues
show
Bug introduced by
sprintf($this->getLangua...nsMessage'), $this->id) of type string is incompatible with the type array|array<mixed,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

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

210
                /** @scrutinizer ignore-type */ sprintf(
Loading history...
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/FileSearch');
296
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
297
        $this->registerDocHeaderButtons();
298
    }
299
300
    protected function initializeIndexAction()
301
    {
302
        // Apply predefined values for hidden checkboxes
303
        // Set predefined value for DisplayBigControlPanel:
304
        $backendUser = $this->getBackendUser();
305
        $userTsConfig = $backendUser->getTSConfig();
306
        if (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'activated') {
307
            $this->MOD_SETTINGS['bigControlPanel'] = true;
308
        } elseif (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'deactivated') {
309
            $this->MOD_SETTINGS['bigControlPanel'] = false;
310
        }
311
        // Set predefined value for DisplayThumbnails:
312
        if (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'activated') {
313
            $this->MOD_SETTINGS['displayThumbs'] = true;
314
        } elseif (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'deactivated') {
315
            $this->MOD_SETTINGS['displayThumbs'] = false;
316
        }
317
        // Set predefined value for Clipboard:
318
        if (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'activated') {
319
            $this->MOD_SETTINGS['clipBoard'] = true;
320
        } elseif (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'deactivated') {
321
            $this->MOD_SETTINGS['clipBoard'] = false;
322
        }
323
        // If user never opened the list module, set the value for displayThumbs
324
        if (!isset($this->MOD_SETTINGS['displayThumbs'])) {
325
            $this->MOD_SETTINGS['displayThumbs'] = $backendUser->uc['thumbnailsByDefault'];
326
        }
327
        if (!isset($this->MOD_SETTINGS['sort'])) {
328
            // Set default sorting
329
            $this->MOD_SETTINGS['sort'] = 'file';
330
            $this->MOD_SETTINGS['reverse'] = 0;
331
        }
332
    }
333
334
    protected function indexAction()
335
    {
336
        $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
337
        $pageRenderer->setTitle($this->getLanguageService()->getLL('files'));
338
339
        // There there was access to this file path, continue, make the list
340
        if ($this->folderObject) {
341
            $this->initClipboard();
342
            $userTsConfig = $this->getBackendUser()->getTSConfig();
343
            $this->filelist = GeneralUtility::makeInstance(FileList::class);
344
            $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
345
            $CB = GeneralUtility::_GET('CB');
346
            if ($this->cmd === 'setCB') {
347
                $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
348
                    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

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

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

815
        $this->filelist = GeneralUtility::makeInstance(FileList::class, /** @scrutinizer ignore-type */ $this);
Loading history...
816
        $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
817
        // Create clipboard object and initialize that
818
        $this->filelist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
819
        $this->filelist->clipObj->fileMode = true;
820
        $this->filelist->clipObj->initializeClipboard();
821
        $CB = GeneralUtility::_GET('CB');
822
        if ($this->cmd === 'setCB') {
823
            $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
824
                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

824
                /** @scrutinizer ignore-type */ GeneralUtility::_POST('CBH'),
Loading history...
825
                (array)GeneralUtility::_POST('CBC')
826
            ), '_FILE');
827
        }
828
        if (!$this->MOD_SETTINGS['clipBoard']) {
829
            $CB['setP'] = 'normal';
830
        }
831
        $this->filelist->clipObj->setCmd($CB);
832
        $this->filelist->clipObj->cleanCurrent();
833
        // Saves
834
        $this->filelist->clipObj->endClipboard();
835
836
        $this->view->assign('showClipBoard', (bool)$this->MOD_SETTINGS['clipBoard']);
837
        $this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard());
838
    }
839
840
    /**
841
     * add javascript jumpToUrl function
842
     */
843
    protected function addJumpToUrl(): void
844
    {
845
        $this->view->getModuleTemplate()->addJavaScriptCode(
846
            'FileListIndex',
847
            'if (top.fsMod) top.fsMod.recentIds["file"] = "' . rawurlencode($this->id) . '";
848
                '
849
        );
850
    }
851
}
852