[TASK] Use BE Routing / PSR-7 instead of BackendUtility::getModuleUrl
[Packages/TYPO3.CMS.git] / typo3 / sysext / filelist / Classes / Controller / FileListController.php
1 <?php
2 namespace TYPO3\CMS\Filelist\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Clipboard\Clipboard;
18 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
19 use TYPO3\CMS\Backend\Template\DocumentTemplate;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Backend\View\BackendTemplateView;
22 use TYPO3\CMS\Core\Imaging\Icon;
23 use TYPO3\CMS\Core\Imaging\IconFactory;
24 use TYPO3\CMS\Core\Messaging\FlashMessage;
25 use TYPO3\CMS\Core\Resource\DuplicationBehavior;
26 use TYPO3\CMS\Core\Resource\Exception;
27 use TYPO3\CMS\Core\Resource\Folder;
28 use TYPO3\CMS\Core\Resource\ResourceFactory;
29 use TYPO3\CMS\Core\Resource\Utility\ListUtility;
30 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
31 use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33 use TYPO3\CMS\Core\Utility\MathUtility;
34 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
35 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
36 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
37 use TYPO3\CMS\Filelist\Configuration\ThumbnailConfiguration;
38 use TYPO3\CMS\Filelist\FileList;
39
40 /**
41 * Script Class for creating the list of files in the File > Filelist module
42 */
43 class FileListController extends ActionController
44 {
45 /**
46 * @var array
47 */
48 public $MOD_MENU = [];
49
50 /**
51 * @var array
52 */
53 public $MOD_SETTINGS = [];
54
55 /**
56 * Document template object
57 *
58 * @var DocumentTemplate
59 */
60 public $doc;
61
62 /**
63 * "id" -> the path to list.
64 *
65 * @var string
66 */
67 public $id;
68
69 /**
70 * @var Folder
71 */
72 protected $folderObject;
73
74 /**
75 * @var FlashMessage
76 */
77 protected $errorMessage;
78
79 /**
80 * Pointer to listing
81 *
82 * @var int
83 */
84 public $pointer;
85
86 /**
87 * "Table"
88 * @var string
89 */
90 public $table;
91
92 /**
93 * Thumbnail mode.
94 *
95 * @var string
96 */
97 public $imagemode;
98
99 /**
100 * @var string
101 */
102 public $cmd;
103
104 /**
105 * Defines behaviour when uploading files with names that already exist; possible values are
106 * the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
107 *
108 * @var \TYPO3\CMS\Core\Resource\DuplicationBehavior
109 */
110 protected $overwriteExistingFiles;
111
112 /**
113 * The filelist object
114 *
115 * @var FileList
116 */
117 public $filelist = null;
118
119 /**
120 * The name of the module
121 *
122 * @var string
123 */
124 protected $moduleName = 'file_list';
125
126 /**
127 * @var \TYPO3\CMS\Core\Resource\FileRepository
128 */
129 protected $fileRepository;
130
131 /**
132 * @var BackendTemplateView
133 */
134 protected $view;
135
136 /**
137 * BackendTemplateView Container
138 *
139 * @var BackendTemplateView
140 */
141 protected $defaultViewObjectName = BackendTemplateView::class;
142
143 /**
144 * @param \TYPO3\CMS\Core\Resource\FileRepository $fileRepository
145 */
146 public function injectFileRepository(\TYPO3\CMS\Core\Resource\FileRepository $fileRepository)
147 {
148 $this->fileRepository = $fileRepository;
149 }
150
151 /**
152 * Initialize variables, file object
153 * Incoming GET vars include id, pointer, table, imagemode
154 *
155 * @throws \RuntimeException
156 * @throws Exception\InsufficientFolderAccessPermissionsException
157 */
158 public function initializeObject()
159 {
160 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
161 $this->getLanguageService()->includeLLFile('EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf');
162 $this->getLanguageService()->includeLLFile('EXT:lang/Resources/Private/Language/locallang_misc.xlf');
163
164 // Setting GPvars:
165 $this->id = ($combinedIdentifier = GeneralUtility::_GP('id'));
166 $this->pointer = GeneralUtility::_GP('pointer');
167 $this->table = GeneralUtility::_GP('table');
168 $this->imagemode = GeneralUtility::_GP('imagemode');
169 $this->cmd = GeneralUtility::_GP('cmd');
170 $this->overwriteExistingFiles = DuplicationBehavior::cast(GeneralUtility::_GP('overwriteExistingFiles'));
171
172 try {
173 if ($combinedIdentifier) {
174 /** @var $resourceFactory ResourceFactory */
175 $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
176 $storage = $resourceFactory->getStorageObjectFromCombinedIdentifier($combinedIdentifier);
177 $identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1);
178 if (!$storage->hasFolder($identifier)) {
179 $identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier);
180 }
181
182 $this->folderObject = $resourceFactory->getFolderObjectFromCombinedIdentifier($storage->getUid() . ':' . $identifier);
183 // Disallow access to fallback storage 0
184 if ($storage->getUid() === 0) {
185 throw new Exception\InsufficientFolderAccessPermissionsException(
186 'You are not allowed to access files outside your storages',
187 1434539815
188 );
189 }
190 // Disallow the rendering of the processing folder (e.g. could be called manually)
191 if ($this->folderObject && $storage->isProcessingFolder($this->folderObject)) {
192 $this->folderObject = $storage->getRootLevelFolder();
193 }
194 } else {
195 // Take the first object of the first storage
196 $fileStorages = $this->getBackendUser()->getFileStorages();
197 $fileStorage = reset($fileStorages);
198 if ($fileStorage) {
199 $this->folderObject = $fileStorage->getRootLevelFolder();
200 } else {
201 throw new \RuntimeException('Could not find any folder to be displayed.', 1349276894);
202 }
203 }
204
205 if ($this->folderObject && !$this->folderObject->getStorage()->isWithinFileMountBoundaries($this->folderObject)) {
206 throw new \RuntimeException('Folder not accessible.', 1430409089);
207 }
208 } catch (Exception\InsufficientFolderAccessPermissionsException $permissionException) {
209 $this->folderObject = null;
210 $this->errorMessage = GeneralUtility::makeInstance(
211 FlashMessage::class,
212 sprintf(
213 $this->getLanguageService()->getLL('missingFolderPermissionsMessage'),
214 $this->id
215 ),
216 $this->getLanguageService()->getLL('missingFolderPermissionsTitle'),
217 FlashMessage::NOTICE
218 );
219 } catch (Exception $fileException) {
220 // Set folder object to null and throw a message later on
221 $this->folderObject = null;
222 // Take the first object of the first storage
223 $fileStorages = $this->getBackendUser()->getFileStorages();
224 $fileStorage = reset($fileStorages);
225 if ($fileStorage instanceof \TYPO3\CMS\Core\Resource\ResourceStorage) {
226 $this->folderObject = $fileStorage->getRootLevelFolder();
227 if (!$fileStorage->isWithinFileMountBoundaries($this->folderObject)) {
228 $this->folderObject = null;
229 }
230 }
231 $this->errorMessage = GeneralUtility::makeInstance(
232 FlashMessage::class,
233 sprintf(
234 $this->getLanguageService()->getLL('folderNotFoundMessage'),
235 $this->id
236 ),
237 $this->getLanguageService()->getLL('folderNotFoundTitle'),
238 FlashMessage::NOTICE
239 );
240 } catch (\RuntimeException $e) {
241 $this->folderObject = null;
242 $this->errorMessage = GeneralUtility::makeInstance(
243 FlashMessage::class,
244 $e->getMessage() . ' (' . $e->getCode() . ')',
245 $this->getLanguageService()->getLL('folderNotFoundTitle'),
246 FlashMessage::NOTICE
247 );
248 }
249
250 if ($this->folderObject && !$this->folderObject->getStorage()->checkFolderActionPermission(
251 'read',
252 $this->folderObject
253 )
254 ) {
255 $this->folderObject = null;
256 }
257
258 // Configure the "menu" - which is used internally to save the values of sorting, displayThumbs etc.
259 $this->menuConfig();
260 }
261
262 /**
263 * Setting the menu/session variables
264 */
265 public function menuConfig()
266 {
267 // MENU-ITEMS:
268 // If array, then it's a selector box menu
269 // If empty string it's just a variable, that will be saved.
270 // Values NOT in this array will not be saved in the settings-array for the module.
271 $this->MOD_MENU = [
272 'sort' => '',
273 'reverse' => '',
274 'displayThumbs' => '',
275 'clipBoard' => '',
276 'bigControlPanel' => ''
277 ];
278 // CLEANSE SETTINGS
279 $this->MOD_SETTINGS = BackendUtility::getModuleData(
280 $this->MOD_MENU,
281 GeneralUtility::_GP('SET'),
282 $this->moduleName
283 );
284 }
285
286 /**
287 * Initialize the view
288 *
289 * @param ViewInterface $view The view
290 */
291 public function initializeView(ViewInterface $view)
292 {
293 /** @var BackendTemplateView $view */
294 parent::initializeView($view);
295 $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
296 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation');
297 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileSearch');
298 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
299 $this->registerDocHeaderButtons();
300 }
301
302 /**
303 */
304 public function initializeIndexAction()
305 {
306 // Apply predefined values for hidden checkboxes
307 // Set predefined value for DisplayBigControlPanel:
308 $backendUser = $this->getBackendUser();
309 if ($backendUser->getTSConfigVal('options.file_list.enableDisplayBigControlPanel') === 'activated') {
310 $this->MOD_SETTINGS['bigControlPanel'] = true;
311 } elseif ($backendUser->getTSConfigVal('options.file_list.enableDisplayBigControlPanel') === 'deactivated') {
312 $this->MOD_SETTINGS['bigControlPanel'] = false;
313 }
314 // Set predefined value for DisplayThumbnails:
315 if ($backendUser->getTSConfigVal('options.file_list.enableDisplayThumbnails') === 'activated') {
316 $this->MOD_SETTINGS['displayThumbs'] = true;
317 } elseif ($backendUser->getTSConfigVal('options.file_list.enableDisplayThumbnails') === 'deactivated') {
318 $this->MOD_SETTINGS['displayThumbs'] = false;
319 }
320 // Set predefined value for Clipboard:
321 if ($backendUser->getTSConfigVal('options.file_list.enableClipBoard') === 'activated') {
322 $this->MOD_SETTINGS['clipBoard'] = true;
323 } elseif ($backendUser->getTSConfigVal('options.file_list.enableClipBoard') === 'deactivated') {
324 $this->MOD_SETTINGS['clipBoard'] = false;
325 }
326 // If user never opened the list module, set the value for displayThumbs
327 if (!isset($this->MOD_SETTINGS['displayThumbs'])) {
328 $this->MOD_SETTINGS['displayThumbs'] = $backendUser->uc['thumbnailsByDefault'];
329 }
330 if (!isset($this->MOD_SETTINGS['sort'])) {
331 // Set default sorting
332 $this->MOD_SETTINGS['sort'] = 'file';
333 $this->MOD_SETTINGS['reverse'] = 0;
334 }
335 }
336
337 /**
338 */
339 public function indexAction()
340 {
341 $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
342 $pageRenderer->setTitle($this->getLanguageService()->getLL('files'));
343
344 // There there was access to this file path, continue, make the list
345 if ($this->folderObject) {
346 // Create fileListing object
347 $this->filelist = GeneralUtility::makeInstance(FileList::class, $this);
348 $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
349 // Create clipboard object and initialize that
350 $this->filelist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
351 $this->filelist->clipObj->fileMode = true;
352 $this->filelist->clipObj->initializeClipboard();
353 $CB = GeneralUtility::_GET('CB');
354 if ($this->cmd === 'setCB') {
355 $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
356 GeneralUtility::_POST('CBH'),
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 // If the "cmd" was to delete files from the list (clipboard thing), do that:
368 if ($this->cmd === 'delete') {
369 $items = $this->filelist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), '_FILE', 1);
370 if (!empty($items)) {
371 // Make command array:
372 $FILE = [];
373 foreach ($items as $v) {
374 $FILE['delete'][] = ['data' => $v];
375 }
376 // Init file processing object for deleting and pass the cmd array.
377 /** @var ExtendedFileUtility $fileProcessor */
378 $fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
379 $fileProcessor->setActionPermissions();
380 $fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
381 $fileProcessor->start($FILE);
382 $fileProcessor->processData();
383 }
384 }
385 // Start up filelisting object, include settings.
386 $this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
387 $this->filelist->start(
388 $this->folderObject,
389 $this->pointer,
390 $this->MOD_SETTINGS['sort'],
391 $this->MOD_SETTINGS['reverse'],
392 $this->MOD_SETTINGS['clipBoard'],
393 $this->MOD_SETTINGS['bigControlPanel']
394 );
395 // Generate the list
396 $this->filelist->generateList();
397 // Set top JavaScript:
398 $this->view->getModuleTemplate()->addJavaScriptCode(
399 'FileListIndex',
400 'if (top.fsMod) top.fsMod.recentIds["file"] = "' . rawurlencode($this->id) . '";' . $this->filelist->CBfunctions() . '
401 function jumpToUrl(URL) {
402 window.location.href = URL;
403 return false;
404 }
405 '
406 );
407 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
408 $pageRenderer->addInlineLanguageLabelFile('EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
409
410 // Include DragUploader only if we have write access
411 if ($this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
412 && $this->folderObject->checkActionPermission('write')
413 ) {
414 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader');
415 $pageRenderer->addInlineLanguageLabelFile('EXT:lang/Resources/Private/Language/locallang_core.xlf', 'file_upload');
416 $pageRenderer->addInlineLanguageLabelArray([
417 'permissions.read' => $this->getLanguageService()->getLL('read'),
418 'permissions.write' => $this->getLanguageService()->getLL('write'),
419 ]);
420 }
421
422 // Setting up the buttons
423 $this->registerButtons();
424
425 $pageRecord = [
426 '_additional_info' => $this->filelist->getFolderInfo(),
427 'combined_identifier' => $this->folderObject->getCombinedIdentifier(),
428 ];
429 $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord);
430
431 $this->view->assign('headline', $this->getModuleHeadline());
432 $this->view->assign('listHtml', $this->filelist->HTMLcode);
433
434 $this->view->assign('checkboxes', [
435 'bigControlPanel' => [
436 'enabled' => $this->getBackendUser()->getTSConfigVal('options.file_list.enableDisplayBigControlPanel') === 'selectable',
437 'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
438 'html' => BackendUtility::getFuncCheck(
439 $this->id,
440 'SET[bigControlPanel]',
441 $this->MOD_SETTINGS['bigControlPanel'] ?? '',
442 '',
443 '',
444 'id="bigControlPanel"'
445 ),
446 ],
447 'displayThumbs' => [
448 'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->getBackendUser()->getTSConfigVal('options.file_list.enableDisplayThumbnails') === 'selectable',
449 'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
450 'html' => BackendUtility::getFuncCheck(
451 $this->id,
452 'SET[displayThumbs]',
453 $this->MOD_SETTINGS['displayThumbs'] ?? '',
454 '',
455 '',
456 'id="checkDisplayThumbs"'
457 ),
458 ],
459 'enableClipBoard' => [
460 'enabled' => $this->getBackendUser()->getTSConfigVal('options.file_list.enableClipBoard') === 'selectable',
461 'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')),
462 'html' => BackendUtility::getFuncCheck(
463 $this->id,
464 'SET[clipBoard]',
465 $this->MOD_SETTINGS['clipBoard'] ?? '',
466 '',
467 '',
468 'id="checkClipBoard"'
469 ),
470 ]
471 ]);
472 $this->view->assign('showClipBoard', (bool)$this->MOD_SETTINGS['clipBoard']);
473 $this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard());
474 $this->view->assign('folderIdentifier', $this->folderObject->getCombinedIdentifier());
475 $this->view->assign('fileDenyPattern', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']);
476 $this->view->assign('maxFileSize', GeneralUtility::getMaxUploadFileSize() * 1024);
477 } else {
478 $this->forward('missingFolder');
479 }
480 }
481
482 /**
483 */
484 public function missingFolderAction()
485 {
486 if ($this->errorMessage) {
487 $this->errorMessage->setSeverity(FlashMessage::ERROR);
488 $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage($this->errorMessage);
489 }
490 }
491
492 /**
493 * Search for files by name and pass them with a facade to fluid
494 *
495 * @param string $searchWord
496 */
497 public function searchAction($searchWord = '')
498 {
499 if (empty($searchWord)) {
500 $this->forward('index');
501 }
502
503 $fileFacades = [];
504 $files = $this->fileRepository->searchByName($this->folderObject, $searchWord);
505
506 if (empty($files)) {
507 $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage(
508 new FlashMessage(
509 LocalizationUtility::translate('flashmessage.no_results', 'filelist'),
510 '',
511 FlashMessage::INFO
512 )
513 );
514 } else {
515 foreach ($files as $file) {
516 $fileFacades[] = new \TYPO3\CMS\Filelist\FileFacade($file);
517 }
518 }
519
520 $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
521 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileList');
522
523 $thumbnailConfiguration = GeneralUtility::makeInstance(ThumbnailConfiguration::class);
524 $this->view->assign('thumbnail', [
525 'width' => $thumbnailConfiguration->getWidth(),
526 'height' => $thumbnailConfiguration->getHeight(),
527 ]);
528
529 $this->view->assign('searchWord', $searchWord);
530 $this->view->assign('files', $fileFacades);
531 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
532 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
533 $this->view->assign('deleteUrl', (string)$uriBuilder->buildUriFromRoute('tce_file'));
534 $this->view->assign('settings', [
535 'jsConfirmationDelete' => $this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)
536 ]);
537
538 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
539 $pageRenderer->addInlineLanguageLabelFile('EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
540 }
541
542 /**
543 * Get main headline based on active folder or storage for backend module
544 * Folder names are resolved to their special names like done in the tree view.
545 *
546 * @return string
547 */
548 protected function getModuleHeadline()
549 {
550 $name = $this->folderObject->getName();
551 if ($name === '') {
552 // Show storage name on storage root
553 if ($this->folderObject->getIdentifier() === '/') {
554 $name = $this->folderObject->getStorage()->getName();
555 }
556 } else {
557 $name = key(ListUtility::resolveSpecialFolderNames(
558 [$name => $this->folderObject]
559 ));
560 }
561 return $name;
562 }
563
564 /**
565 * Registers the Icons into the docheader
566 *
567 * @throws \InvalidArgumentException
568 */
569 protected function registerDocHeaderButtons()
570 {
571 /** @var ButtonBar $buttonBar */
572 $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
573
574 // CSH
575 $cshButton = $buttonBar->makeHelpButton()
576 ->setModuleName('xMOD_csh_corebe')
577 ->setFieldName('filelist_module');
578 $buttonBar->addButton($cshButton);
579 }
580
581 /**
582 * Create the panel of buttons for submitting the form or otherwise perform operations.
583 *
584 * @return array All available buttons as an assoc. array
585 */
586 protected function registerButtons()
587 {
588 /** @var ButtonBar $buttonBar */
589 $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
590
591 /** @var IconFactory $iconFactory */
592 $iconFactory = $this->view->getModuleTemplate()->getIconFactory();
593
594 /** @var $resourceFactory ResourceFactory */
595 $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
596
597 $lang = $this->getLanguageService();
598
599 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
600 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
601
602 // Refresh page
603 $refreshLink = GeneralUtility::linkThisScript(
604 [
605 'target' => rawurlencode($this->folderObject->getCombinedIdentifier()),
606 'imagemode' => $this->filelist->thumbs
607 ]
608 );
609 $refreshButton = $buttonBar->makeLinkButton()
610 ->setHref($refreshLink)
611 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.reload'))
612 ->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
613 $buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT);
614
615 // Level up
616 try {
617 $currentStorage = $this->folderObject->getStorage();
618 $parentFolder = $this->folderObject->getParentFolder();
619 if ($parentFolder->getIdentifier() !== $this->folderObject->getIdentifier()
620 && $currentStorage->isWithinFileMountBoundaries($parentFolder)
621 ) {
622 $levelUpClick = 'top.document.getElementsByName("navigation")[0].contentWindow.Tree.highlightActiveItem("file","folder'
623 . GeneralUtility::md5int($parentFolder->getCombinedIdentifier()) . '_"+top.fsMod.currentBank)';
624 $levelUpButton = $buttonBar->makeLinkButton()
625 ->setHref((string)$uriBuilder->buildUriFromRoute('file_FilelistList', ['id' => $parentFolder->getCombinedIdentifier()]))
626 ->setOnClick($levelUpClick)
627 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.upOneLevel'))
628 ->setIcon($iconFactory->getIcon('actions-view-go-up', Icon::SIZE_SMALL));
629 $buttonBar->addButton($levelUpButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
630 }
631 } catch (\Exception $e) {
632 }
633
634 // Shortcut
635 if ($this->getBackendUser()->mayMakeShortcut()) {
636 $shortCutButton = $buttonBar->makeShortcutButton()->setModuleName('file_FilelistList');
637 $buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT);
638 }
639
640 // Upload button (only if upload to this directory is allowed)
641 if ($this->folderObject && $this->folderObject->getStorage()->checkUserActionPermission(
642 'add',
643 'File'
644 ) && $this->folderObject->checkActionPermission('write')
645 ) {
646 $uploadButton = $buttonBar->makeLinkButton()
647 ->setHref((string)$uriBuilder->buildUriFromRoute(
648 'file_upload',
649 [
650 'target' => $this->folderObject->getCombinedIdentifier(),
651 'returnUrl' => $this->filelist->listURL(),
652 ]
653 ))
654 ->setClasses('t3js-drag-uploader-trigger')
655 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.upload'))
656 ->setIcon($iconFactory->getIcon('actions-edit-upload', Icon::SIZE_SMALL));
657 $buttonBar->addButton($uploadButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
658 }
659
660 // New folder button
661 if ($this->folderObject && $this->folderObject->checkActionPermission('write')
662 && ($this->folderObject->getStorage()->checkUserActionPermission(
663 'add',
664 'File'
665 ) || $this->folderObject->checkActionPermission('add'))
666 ) {
667 $newButton = $buttonBar->makeLinkButton()
668 ->setHref((string)$uriBuilder->buildUriFromRoute(
669 'file_newfolder',
670 [
671 'target' => $this->folderObject->getCombinedIdentifier(),
672 'returnUrl' => $this->filelist->listURL(),
673 ]
674 ))
675 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.new'))
676 ->setIcon($iconFactory->getIcon('actions-add', Icon::SIZE_SMALL));
677 $buttonBar->addButton($newButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
678 }
679
680 // Add paste button if clipboard is initialized
681 if ($this->filelist->clipObj instanceof Clipboard && $this->folderObject->checkActionPermission('write')) {
682 $elFromTable = $this->filelist->clipObj->elFromTable('_FILE');
683 if (!empty($elFromTable)) {
684 $addPasteButton = true;
685 $elToConfirm = [];
686 foreach ($elFromTable as $key => $element) {
687 $clipBoardElement = $resourceFactory->retrieveFileOrFolderObject($element);
688 if ($clipBoardElement instanceof Folder && $clipBoardElement->getStorage()->isWithinFolder(
689 $clipBoardElement,
690 $this->folderObject
691 )
692 ) {
693 $addPasteButton = false;
694 }
695 $elToConfirm[$key] = $clipBoardElement->getName();
696 }
697 if ($addPasteButton) {
698 $confirmText = $this->filelist->clipObj
699 ->confirmMsgText('_FILE', $this->folderObject->getReadablePath(), 'into', $elToConfirm);
700 $pasteButton = $buttonBar->makeLinkButton()
701 ->setHref($this->filelist->clipObj
702 ->pasteUrl('_FILE', $this->folderObject->getCombinedIdentifier()))
703 ->setClasses('t3js-modal-trigger')
704 ->setDataAttributes([
705 'severity' => 'warning',
706 'content' => $confirmText,
707 'title' => $lang->getLL('clip_paste')
708 ])
709 ->setTitle($lang->getLL('clip_paste'))
710 ->setIcon($iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));
711 $buttonBar->addButton($pasteButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
712 }
713 }
714 }
715 }
716
717 /**
718 * Returns an instance of LanguageService
719 *
720 * @return \TYPO3\CMS\Core\Localization\LanguageService
721 */
722 protected function getLanguageService()
723 {
724 return $GLOBALS['LANG'];
725 }
726
727 /**
728 * Returns the current BE user.
729 *
730 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
731 */
732 protected function getBackendUser()
733 {
734 return $GLOBALS['BE_USER'];
735 }
736 }