e95450cfe72f7b3f7dbb516bd5a46ebaae44af71
[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:core/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 $userTsConfig = $backendUser->getTSConfig();
310 if ($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '' === 'activated') {
311 $this->MOD_SETTINGS['bigControlPanel'] = true;
312 } elseif ($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '' === 'deactivated') {
313 $this->MOD_SETTINGS['bigControlPanel'] = false;
314 }
315 // Set predefined value for DisplayThumbnails:
316 if ($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '' === 'activated') {
317 $this->MOD_SETTINGS['displayThumbs'] = true;
318 } elseif ($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '' === 'deactivated') {
319 $this->MOD_SETTINGS['displayThumbs'] = false;
320 }
321 // Set predefined value for Clipboard:
322 if ($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '' === 'activated') {
323 $this->MOD_SETTINGS['clipBoard'] = true;
324 } elseif ($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '' === 'deactivated') {
325 $this->MOD_SETTINGS['clipBoard'] = false;
326 }
327 // If user never opened the list module, set the value for displayThumbs
328 if (!isset($this->MOD_SETTINGS['displayThumbs'])) {
329 $this->MOD_SETTINGS['displayThumbs'] = $backendUser->uc['thumbnailsByDefault'];
330 }
331 if (!isset($this->MOD_SETTINGS['sort'])) {
332 // Set default sorting
333 $this->MOD_SETTINGS['sort'] = 'file';
334 $this->MOD_SETTINGS['reverse'] = 0;
335 }
336 }
337
338 /**
339 */
340 public function indexAction()
341 {
342 $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
343 $pageRenderer->setTitle($this->getLanguageService()->getLL('files'));
344
345 // There there was access to this file path, continue, make the list
346 if ($this->folderObject) {
347 $userTsConfig = $this->getBackendUser()->getTSConfig();
348 // Create fileListing object
349 $this->filelist = GeneralUtility::makeInstance(FileList::class, $this);
350 $this->filelist->thumbs = $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $this->MOD_SETTINGS['displayThumbs'];
351 // Create clipboard object and initialize that
352 $this->filelist->clipObj = GeneralUtility::makeInstance(Clipboard::class);
353 $this->filelist->clipObj->fileMode = true;
354 $this->filelist->clipObj->initializeClipboard();
355 $CB = GeneralUtility::_GET('CB');
356 if ($this->cmd === 'setCB') {
357 $CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge(
358 GeneralUtility::_POST('CBH'),
359 (array)GeneralUtility::_POST('CBC')
360 ), '_FILE');
361 }
362 if (!$this->MOD_SETTINGS['clipBoard']) {
363 $CB['setP'] = 'normal';
364 }
365 $this->filelist->clipObj->setCmd($CB);
366 $this->filelist->clipObj->cleanCurrent();
367 // Saves
368 $this->filelist->clipObj->endClipboard();
369 // If the "cmd" was to delete files from the list (clipboard thing), do that:
370 if ($this->cmd === 'delete') {
371 $items = $this->filelist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), '_FILE', 1);
372 if (!empty($items)) {
373 // Make command array:
374 $FILE = [];
375 foreach ($items as $v) {
376 $FILE['delete'][] = ['data' => $v];
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 }
386 }
387 // Start up filelisting object, include settings.
388 $this->pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
389 $this->filelist->start(
390 $this->folderObject,
391 $this->pointer,
392 $this->MOD_SETTINGS['sort'],
393 $this->MOD_SETTINGS['reverse'],
394 $this->MOD_SETTINGS['clipBoard'],
395 $this->MOD_SETTINGS['bigControlPanel']
396 );
397 // Generate the list
398 $this->filelist->generateList();
399 // Set top JavaScript:
400 $this->view->getModuleTemplate()->addJavaScriptCode(
401 'FileListIndex',
402 'if (top.fsMod) top.fsMod.recentIds["file"] = "' . rawurlencode($this->id) . '";' . $this->filelist->CBfunctions() . '
403 function jumpToUrl(URL) {
404 window.location.href = URL;
405 return false;
406 }
407 '
408 );
409 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
410 $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
411
412 // Include DragUploader only if we have write access
413 if ($this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
414 && $this->folderObject->checkActionPermission('write')
415 ) {
416 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader');
417 $pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_core.xlf', 'file_upload');
418 $pageRenderer->addInlineLanguageLabelArray([
419 'permissions.read' => $this->getLanguageService()->getLL('read'),
420 'permissions.write' => $this->getLanguageService()->getLL('write'),
421 ]);
422 }
423
424 // Setting up the buttons
425 $this->registerButtons();
426
427 $pageRecord = [
428 '_additional_info' => $this->filelist->getFolderInfo(),
429 'combined_identifier' => $this->folderObject->getCombinedIdentifier(),
430 ];
431 $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord);
432
433 $this->view->assign('headline', $this->getModuleHeadline());
434 $this->view->assign('listHtml', $this->filelist->HTMLcode);
435
436 $this->view->assign('checkboxes', [
437 'bigControlPanel' => [
438 'enabled' => $userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '' === 'selectable',
439 'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
440 'html' => BackendUtility::getFuncCheck(
441 $this->id,
442 'SET[bigControlPanel]',
443 $this->MOD_SETTINGS['bigControlPanel'] ?? '',
444 '',
445 '',
446 'id="bigControlPanel"'
447 ),
448 ],
449 'displayThumbs' => [
450 'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '' === 'selectable',
451 'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
452 'html' => BackendUtility::getFuncCheck(
453 $this->id,
454 'SET[displayThumbs]',
455 $this->MOD_SETTINGS['displayThumbs'] ?? '',
456 '',
457 '',
458 'id="checkDisplayThumbs"'
459 ),
460 ],
461 'enableClipBoard' => [
462 'enabled' => $userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '' === 'selectable',
463 'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')),
464 'html' => BackendUtility::getFuncCheck(
465 $this->id,
466 'SET[clipBoard]',
467 $this->MOD_SETTINGS['clipBoard'] ?? '',
468 '',
469 '',
470 'id="checkClipBoard"'
471 ),
472 ]
473 ]);
474 $this->view->assign('showClipBoard', (bool)$this->MOD_SETTINGS['clipBoard']);
475 $this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard());
476 $this->view->assign('folderIdentifier', $this->folderObject->getCombinedIdentifier());
477 $this->view->assign('fileDenyPattern', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern']);
478 $this->view->assign('maxFileSize', GeneralUtility::getMaxUploadFileSize() * 1024);
479 } else {
480 $this->forward('missingFolder');
481 }
482 }
483
484 /**
485 */
486 public function missingFolderAction()
487 {
488 if ($this->errorMessage) {
489 $this->errorMessage->setSeverity(FlashMessage::ERROR);
490 $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage($this->errorMessage);
491 }
492 }
493
494 /**
495 * Search for files by name and pass them with a facade to fluid
496 *
497 * @param string $searchWord
498 */
499 public function searchAction($searchWord = '')
500 {
501 if (empty($searchWord)) {
502 $this->forward('index');
503 }
504
505 $fileFacades = [];
506 $files = $this->fileRepository->searchByName($this->folderObject, $searchWord);
507
508 if (empty($files)) {
509 $this->controllerContext->getFlashMessageQueue('core.template.flashMessages')->addMessage(
510 new FlashMessage(
511 LocalizationUtility::translate('flashmessage.no_results', 'filelist'),
512 '',
513 FlashMessage::INFO
514 )
515 );
516 } else {
517 foreach ($files as $file) {
518 $fileFacades[] = new \TYPO3\CMS\Filelist\FileFacade($file);
519 }
520 }
521
522 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
523 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
524
525 $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
526 $pageRenderer->addInlineSetting('ShowItem', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('show_item'));
527 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileList');
528
529 $thumbnailConfiguration = GeneralUtility::makeInstance(ThumbnailConfiguration::class);
530 $this->view->assign('thumbnail', [
531 'width' => $thumbnailConfiguration->getWidth(),
532 'height' => $thumbnailConfiguration->getHeight(),
533 ]);
534
535 $this->view->assign('searchWord', $searchWord);
536 $this->view->assign('files', $fileFacades);
537 $this->view->assign('deleteUrl', (string)$uriBuilder->buildUriFromRoute('tce_file'));
538 $this->view->assign('settings', [
539 'jsConfirmationDelete' => $this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)
540 ]);
541
542 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
543 $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
544 }
545
546 /**
547 * Get main headline based on active folder or storage for backend module
548 * Folder names are resolved to their special names like done in the tree view.
549 *
550 * @return string
551 */
552 protected function getModuleHeadline()
553 {
554 $name = $this->folderObject->getName();
555 if ($name === '') {
556 // Show storage name on storage root
557 if ($this->folderObject->getIdentifier() === '/') {
558 $name = $this->folderObject->getStorage()->getName();
559 }
560 } else {
561 $name = key(ListUtility::resolveSpecialFolderNames(
562 [$name => $this->folderObject]
563 ));
564 }
565 return $name;
566 }
567
568 /**
569 * Registers the Icons into the docheader
570 *
571 * @throws \InvalidArgumentException
572 */
573 protected function registerDocHeaderButtons()
574 {
575 /** @var ButtonBar $buttonBar */
576 $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
577
578 // CSH
579 $cshButton = $buttonBar->makeHelpButton()
580 ->setModuleName('xMOD_csh_corebe')
581 ->setFieldName('filelist_module');
582 $buttonBar->addButton($cshButton);
583 }
584
585 /**
586 * Create the panel of buttons for submitting the form or otherwise perform operations.
587 *
588 * @return array All available buttons as an assoc. array
589 */
590 protected function registerButtons()
591 {
592 /** @var ButtonBar $buttonBar */
593 $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
594
595 /** @var IconFactory $iconFactory */
596 $iconFactory = $this->view->getModuleTemplate()->getIconFactory();
597
598 /** @var $resourceFactory ResourceFactory */
599 $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
600
601 $lang = $this->getLanguageService();
602
603 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
604 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
605
606 // Refresh page
607 $refreshLink = GeneralUtility::linkThisScript(
608 [
609 'target' => rawurlencode($this->folderObject->getCombinedIdentifier()),
610 'imagemode' => $this->filelist->thumbs
611 ]
612 );
613 $refreshButton = $buttonBar->makeLinkButton()
614 ->setHref($refreshLink)
615 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
616 ->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
617 $buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT);
618
619 // Level up
620 try {
621 $currentStorage = $this->folderObject->getStorage();
622 $parentFolder = $this->folderObject->getParentFolder();
623 if ($parentFolder->getIdentifier() !== $this->folderObject->getIdentifier()
624 && $currentStorage->isWithinFileMountBoundaries($parentFolder)
625 ) {
626 $levelUpClick = 'top.document.getElementsByName("nav_frame")[0].contentWindow.Tree.highlightActiveItem("file","folder'
627 . GeneralUtility::md5int($parentFolder->getCombinedIdentifier()) . '_"+top.fsMod.currentBank)';
628 $levelUpButton = $buttonBar->makeLinkButton()
629 ->setHref((string)$uriBuilder->buildUriFromRoute('file_FilelistList', ['id' => $parentFolder->getCombinedIdentifier()]))
630 ->setOnClick($levelUpClick)
631 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.upOneLevel'))
632 ->setIcon($iconFactory->getIcon('actions-view-go-up', Icon::SIZE_SMALL));
633 $buttonBar->addButton($levelUpButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
634 }
635 } catch (\Exception $e) {
636 }
637
638 // Shortcut
639 if ($this->getBackendUser()->mayMakeShortcut()) {
640 $shortCutButton = $buttonBar->makeShortcutButton()->setModuleName('file_FilelistList');
641 $buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT);
642 }
643
644 // Upload button (only if upload to this directory is allowed)
645 if ($this->folderObject && $this->folderObject->getStorage()->checkUserActionPermission(
646 'add',
647 'File'
648 ) && $this->folderObject->checkActionPermission('write')
649 ) {
650 $uploadButton = $buttonBar->makeLinkButton()
651 ->setHref((string)$uriBuilder->buildUriFromRoute(
652 'file_upload',
653 [
654 'target' => $this->folderObject->getCombinedIdentifier(),
655 'returnUrl' => $this->filelist->listURL(),
656 ]
657 ))
658 ->setClasses('t3js-drag-uploader-trigger')
659 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'))
660 ->setIcon($iconFactory->getIcon('actions-edit-upload', Icon::SIZE_SMALL));
661 $buttonBar->addButton($uploadButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
662 }
663
664 // New folder button
665 if ($this->folderObject && $this->folderObject->checkActionPermission('write')
666 && ($this->folderObject->getStorage()->checkUserActionPermission(
667 'add',
668 'File'
669 ) || $this->folderObject->checkActionPermission('add'))
670 ) {
671 $newButton = $buttonBar->makeLinkButton()
672 ->setHref((string)$uriBuilder->buildUriFromRoute(
673 'file_newfolder',
674 [
675 'target' => $this->folderObject->getCombinedIdentifier(),
676 'returnUrl' => $this->filelist->listURL(),
677 ]
678 ))
679 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.new'))
680 ->setIcon($iconFactory->getIcon('actions-add', Icon::SIZE_SMALL));
681 $buttonBar->addButton($newButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
682 }
683
684 // Add paste button if clipboard is initialized
685 if ($this->filelist->clipObj instanceof Clipboard && $this->folderObject->checkActionPermission('write')) {
686 $elFromTable = $this->filelist->clipObj->elFromTable('_FILE');
687 if (!empty($elFromTable)) {
688 $addPasteButton = true;
689 $elToConfirm = [];
690 foreach ($elFromTable as $key => $element) {
691 $clipBoardElement = $resourceFactory->retrieveFileOrFolderObject($element);
692 if ($clipBoardElement instanceof Folder && $clipBoardElement->getStorage()->isWithinFolder(
693 $clipBoardElement,
694 $this->folderObject
695 )
696 ) {
697 $addPasteButton = false;
698 }
699 $elToConfirm[$key] = $clipBoardElement->getName();
700 }
701 if ($addPasteButton) {
702 $confirmText = $this->filelist->clipObj
703 ->confirmMsgText('_FILE', $this->folderObject->getReadablePath(), 'into', $elToConfirm);
704 $pasteButton = $buttonBar->makeLinkButton()
705 ->setHref($this->filelist->clipObj
706 ->pasteUrl('_FILE', $this->folderObject->getCombinedIdentifier()))
707 ->setClasses('t3js-modal-trigger')
708 ->setDataAttributes([
709 'severity' => 'warning',
710 'content' => $confirmText,
711 'title' => $lang->getLL('clip_paste')
712 ])
713 ->setTitle($lang->getLL('clip_paste'))
714 ->setIcon($iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL));
715 $buttonBar->addButton($pasteButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
716 }
717 }
718 }
719 }
720
721 /**
722 * Returns an instance of LanguageService
723 *
724 * @return \TYPO3\CMS\Core\Localization\LanguageService
725 */
726 protected function getLanguageService()
727 {
728 return $GLOBALS['LANG'];
729 }
730
731 /**
732 * Returns the current BE user.
733 *
734 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
735 */
736 protected function getBackendUser()
737 {
738 return $GLOBALS['BE_USER'];
739 }
740 }