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