‪TYPO3CMS  ‪main
FileListController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
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 
19 
20 use Psr\Http\Message\ResponseFactoryInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
23 use Psr\Log\LoggerAwareInterface;
24 use Psr\Log\LoggerAwareTrait;
39 use TYPO3\CMS\Core\Imaging\IconSize;
64 
70 #[Controller]
71 class ‪FileListController implements LoggerAwareInterface
72 {
73  use LoggerAwareTrait;
74 
75  protected string ‪$id = '';
76  protected string ‪$cmd = '';
77  protected string ‪$searchTerm = '';
78  protected int ‪$currentPage = 1;
79 
80  protected ?‪Folder ‪$folderObject = null;
82  protected ?‪ModuleTemplate ‪$view = null;
83  protected ?‪FileList ‪$filelist = null;
84  protected ?‪ModuleData ‪$moduleData = null;
85 
86  public function ‪__construct(
87  protected readonly ‪UriBuilder $uriBuilder,
88  protected readonly ‪PageRenderer $pageRenderer,
89  protected readonly ‪IconFactory $iconFactory,
90  protected readonly ‪ResourceFactory $resourceFactory,
91  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
92  protected readonly ‪BackendViewFactory $viewFactory,
93  protected readonly ResponseFactoryInterface $responseFactory,
94  ) {
95  }
96 
97  public function ‪handleRequest(ServerRequestInterface $request): ResponseInterface
98  {
99  $lang = $this->‪getLanguageService();
100  $backendUser = $this->‪getBackendUser();
101 
102  $this->moduleData = $request->getAttribute('moduleData');
103 
104  $this->view = $this->moduleTemplateFactory->create($request);
105  $this->view->setTitle($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:mlang_tabs_tab'));
106 
107  $queryParams = $request->getQueryParams();
108  $parsedBody = $request->getParsedBody();
109 
110  $this->id = (string)($parsedBody['id'] ?? $queryParams['id'] ?? '');
111  $this->cmd = (string)($parsedBody['cmd'] ?? $queryParams['cmd'] ?? '');
112  $this->searchTerm = (string)trim($parsedBody['searchTerm'] ?? $queryParams['searchTerm'] ?? '');
113  $this->currentPage = (int)($parsedBody['currentPage'] ?? $queryParams['currentPage'] ?? 1);
114  $this->overwriteExistingFiles = ‪DuplicationBehavior::cast(
115  $parsedBody['overwriteExistingFiles'] ?? $queryParams['overwriteExistingFiles'] ?? null
116  );
117 
118  try {
119  if ($this->id !== '') {
120  $backendUser->evaluateUserSpecificFileFilterSettings();
121  $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByCombinedIdentifier($this->id);
122  if ($storage !== null) {
123  ‪$identifier = substr($this->id, strpos($this->id, ':') + 1);
124  if (!$storage->hasFolder(‪$identifier)) {
125  ‪$identifier = $storage->getFolderIdentifierFromFileIdentifier(‪$identifier);
126  }
127  $this->folderObject = $storage->getFolder(‪$identifier);
128  // Disallow access to fallback storage 0
129  if ($storage->getUid() === 0) {
131  'You are not allowed to access files outside your storages',
132  1434539815
133  );
134  }
135  // Disallow the rendering of the processing folder (e.g. could be called manually)
136  if ($this->folderObject instanceof ‪Folder && $storage->isProcessingFolder($this->folderObject)) {
137  $this->folderObject = $storage->getRootLevelFolder();
138  }
139  }
140  } else {
141  // Take the first object of the first storage
142  $fileStorages = $backendUser->getFileStorages();
143  $fileStorage = reset($fileStorages);
144  if ($fileStorage) {
145  $this->folderObject = $fileStorage->getRootLevelFolder();
146  } else {
147  throw new \RuntimeException('Could not find any folder to be displayed.', 1349276894);
148  }
149  }
150 
151  if ($this->folderObject && !$this->folderObject->getStorage()->isWithinFileMountBoundaries($this->folderObject)) {
152  throw new \RuntimeException('Folder not accessible.', 1430409089);
153  }
154  } catch (‪InsufficientFolderAccessPermissionsException $permissionException) {
155  $this->folderObject = null;
156  $this->‪addFlashMessage(
157  sprintf($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:missingFolderPermissionsMessage'), $this->id),
158  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:missingFolderPermissionsTitle'),
159  ContextualFeedbackSeverity::ERROR
160  );
161  } catch (‪Exception $fileException) {
162  $this->folderObject = null;
163  // Take the first object of the first storage
164  $fileStorages = $backendUser->getFileStorages();
165  $fileStorage = reset($fileStorages);
166  if ($fileStorage instanceof ‪ResourceStorage) {
167  $this->folderObject = $fileStorage->getRootLevelFolder();
168  if (!$fileStorage->isWithinFileMountBoundaries($this->folderObject)) {
169  $this->folderObject = null;
170  }
171  }
172  if (!$this->folderObject) {
173  $this->‪addFlashMessage(
174  sprintf($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:folderNotFoundMessage'), $this->id),
175  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:folderNotFoundTitle'),
176  ContextualFeedbackSeverity::ERROR
177  );
178  }
179  } catch (\RuntimeException $e) {
180  $this->folderObject = null;
181  $this->‪addFlashMessage(
182  $e->getMessage() . ' (' . $e->getCode() . ')',
183  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:folderNotFoundTitle'),
184  ContextualFeedbackSeverity::ERROR
185  );
186  }
187 
188  if ($this->folderObject
189  && !$this->folderObject->getStorage()->checkFolderActionPermission('read', $this->folderObject)
190  ) {
191  $this->folderObject = null;
192  }
193 
194  $this->view->assign('currentIdentifier', $this->folderObject ? $this->folderObject->getCombinedIdentifier() : '');
195  $javaScriptRenderer = $this->pageRenderer->getJavaScriptRenderer();
196  $javaScriptRenderer->addJavaScriptModuleInstruction(
197  ‪JavaScriptModuleInstruction::create('@typo3/filelist/file-list.js')->instance()
198  );
199 
200  $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-list-dragdrop.js');
201  $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-list-transfer-handler.js');
202  $this->pageRenderer->addInlineLanguageLabelFile('EXT:filelist/Resources/Private/Language/locallang_transfer_handler.xlf');
203 
204  $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-list-actions.js');
205  $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-list-rename-handler.js');
206  $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-delete.js');
207  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/context-menu.js');
208  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/clipboard-panel.js');
209  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/multi-record-selection.js');
210  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/column-selector-button.js');
211 
212  $this->pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
213 
214  $this->‪initializeModule($request);
215 
216  // In case the folderObject is NULL, the request is either invalid or the user
217  // does not have necessary permissions. Just render and return the "empty" view.
218  if ($this->folderObject === null) {
219  return $this->view->renderResponse('File/List');
220  }
221 
222  return $this->‪processRequest($request);
223  }
224 
225  protected function ‪processRequest(ServerRequestInterface $request): ResponseInterface
226  {
227  $lang = $this->‪getLanguageService();
228 
229  // Initialize FileList, including the clipboard actions
230  $this->‪initializeFileList($request);
231 
232  // Generate the file listing markup
233  $this->‪generateFileList($request);
234 
235  // Generate the clipboard, if enabled
236  $this->view->assign('showClipboardPanel', (bool)$this->moduleData->get('clipBoard'));
237 
238  // Register drag-uploader
239  $this->‪registerDragUploader();
240 
241  // Register the display thumbnails / show clipboard checkboxes
243 
244  // Register additional doc header buttons
245  $this->‪registerAdditionalDocHeaderButtons($request);
246 
247  // Add additional view variables
248  $this->view->assignMultiple([
249  'headline' => $this->‪getModuleHeadline(),
250  'folderIdentifier' => $this->folderObject->getCombinedIdentifier(),
251  'searchTerm' => $this->searchTerm,
252  ]);
253 
254  // Overwrite the default module title, adding the specific module headline (the folder name)
255  $this->view->setTitle(
256  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:mlang_tabs_tab'),
257  $this->getModuleHeadline()
258  );
259 
260  // Additional doc header information: current path and folder info
261  $this->view->getDocHeaderComponent()->setMetaInformation([
262  '_additional_info' => $this->filelist->getFolderInfo(),
263  ]);
264  $this->view->getDocHeaderComponent()->setMetaInformationForResource($this->folderObject);
265 
266  return $this->view->renderResponse('File/List');
267  }
268 
269  protected function ‪initializeModule(ServerRequestInterface $request): void
270  {
271  $userTsConfig = $this->‪getBackendUser()->getTSConfig();
272 
273  // Set predefined value for DisplayThumbnails:
274  if (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'activated') {
275  $this->moduleData->set('displayThumbs', true);
276  } elseif (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'deactivated') {
277  $this->moduleData->set('displayThumbs', false);
278  }
279  // Set predefined value for Clipboard:
280  if (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'activated') {
281  $this->moduleData->set('clipBoard', true);
282  } elseif (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'deactivated') {
283  $this->moduleData->set('clipBoard', false);
284  }
285  }
286 
287  protected function ‪initializeFileList(ServerRequestInterface $request): void
288  {
289  // Create the file list
290  $this->filelist = GeneralUtility::makeInstance(FileList::class, $request);
291  $this->filelist->viewMode = ViewMode::tryFrom($this->moduleData->get('viewMode')) ?? ‪ViewMode::TILES;
292  $this->filelist->thumbs = (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] ?? false) && $this->moduleData->get('displayThumbs');
293 
294  // Create clipboard object and initialize it
295  $CB = array_replace_recursive($request->getQueryParams()['CB'] ?? [], $request->getParsedBody()['CB'] ?? []);
296  if (($this->cmd === 'copyMarked' || $this->cmd === 'removeMarked')) {
297  // Get CBC from request, and map the element values, since they must either be the file identifier,
298  // in case the element should be transferred to the clipboard, or false if it should be removed.
299  $CBC = array_map(fn ($item) => $this->cmd === 'copyMarked' ? $item : false, (array)($request->getParsedBody()['CBC'] ?? []));
300  // Cleanup CBC
301  $CB['el'] = $this->filelist->clipObj->cleanUpCBC($CBC, '_FILE');
302  }
303  if (!$this->moduleData->get('clipBoard')) {
304  $CB['setP'] = 'normal';
305  }
306  $this->filelist->clipObj->setCmd($CB);
307  $this->filelist->clipObj->cleanCurrent();
308  $this->filelist->clipObj->endClipboard();
309 
310  // If the "cmd" was to delete files from the list, do that:
311  if ($this->cmd === 'delete') {
312  $items = $this->filelist->clipObj->cleanUpCBC(
313  (array)($request->getParsedBody()['CBC'] ?? []),
314  '_FILE',
315  true
316  );
317  if (!empty($items)) {
318  // Make command array:
319  $FILE = [];
320  foreach ($items as $clipboardIdentifier => $combinedIdentifier) {
321  $FILE['delete'][] = ['data' => $combinedIdentifier];
322  $this->filelist->clipObj->removeElement($clipboardIdentifier);
323  }
324  // Init file processing object for deleting and pass the cmd array.
325  $fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
326  $fileProcessor->setActionPermissions();
327  $fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
328  $fileProcessor->start($FILE);
329  $fileProcessor->processData();
330  // Clean & Save clipboard state
331  $this->filelist->clipObj->cleanCurrent();
332  $this->filelist->clipObj->endClipboard();
333  }
334  }
335 
336  // Start up the file list by including processed settings.
337  $this->filelist->start(
338  $this->folderObject,
339  ‪MathUtility::forceIntegerInRange($this->currentPage, 1, 100000),
340  (string)$this->moduleData->get('sort'),
341  (bool)$this->moduleData->get('reverse')
342  );
343  $this->filelist->setColumnsToRender($this->‪getBackendUser()->getModuleData('list/displayFields')['_FILE'] ?? []);
344 
345  $resourceSelectableMatcher = GeneralUtility::makeInstance(Matcher::class);
346  $resourceSelectableMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFileTypeMatcher::class));
347  $resourceSelectableMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFolderTypeMatcher::class));
348  $this->filelist->setResourceSelectableMatcher($resourceSelectableMatcher);
349 
350  $resourceDownloadMatcher = GeneralUtility::makeInstance(Matcher::class);
351  $resourceDownloadMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFileTypeMatcher::class));
352  $resourceDownloadMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFolderTypeMatcher::class));
353  $this->filelist->setResourceDownloadMatcher($resourceDownloadMatcher);
354  }
355 
356  protected function ‪generateFileList(ServerRequestInterface $request): void
357  {
358  $lang = $this->‪getLanguageService();
359 
360  // If a searchTerm is provided, create the searchDemand object
361  $searchDemand = $this->searchTerm !== ''
362  ? ‪FileSearchDemand::createForSearchTerm($this->searchTerm)->withRecursive()
363  : null;
364 
365  // Generate the list, if accessible
366  if ($this->folderObject->getStorage()->isBrowsable()) {
367  $fileListView = $this->viewFactory->create($request);
368  $this->view->assignMultiple([
369  'listHtml' => $this->filelist->render($searchDemand, $fileListView),
370  'listUrl' => $this->filelist->createModuleUri(),
371  'fileUploadUrl' => $this->getFileUploadUrl(),
372  'totalItems' => $this->filelist->totalItems,
373  ]);
374  // Assign meta information for the multi record selection
375  $this->view->assignMultiple([
376  'editActionConfiguration' => GeneralUtility::jsonEncodeForHtmlAttribute([
377  'idField' => 'filelistMetaUid',
378  'table' => 'sys_file_metadata',
379  'returnUrl' => $this->filelist->createModuleUri(),
380  ], true),
381  'deleteActionConfiguration' => GeneralUtility::jsonEncodeForHtmlAttribute([
382  'ok' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete'),
383  'title' => $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_deleteMarked'),
384  'content' => $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_deleteMarkedWarning'),
385  ], true),
386  ]);
387 
388  // Add download button configuration, if file download is enabled
389  if ($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.']['enabled'] ?? true) {
390  $this->view->assign(
391  'downloadActionConfiguration',
392  GeneralUtility::jsonEncodeForHtmlAttribute([
393  'downloadUrl' => (string)$this->uriBuilder->buildUriFromRoute('file_download'),
394  ], true)
395  );
396  }
397  } else {
398  $this->‪addFlashMessage(
399  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:storageNotBrowsableMessage'),
400  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:storageNotBrowsableTitle')
401  );
402  }
403  }
404 
405  protected function ‪registerDragUploader(): void
406  {
407  // Include DragUploader only if we have write access
408  if ($this->folderObject->checkActionPermission('write')
409  && $this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
410  ) {
411  $lang = $this->‪getLanguageService();
412  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/drag-uploader.js');
413  $this->pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_core.xlf', 'file_upload');
414  $this->pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_core.xlf', 'file_download');
415  $this->pageRenderer->addInlineLanguageLabelArray([
416  'type.file' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:file'),
417  'permissions.read' => $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read'),
418  'permissions.write' => $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write'),
419  'online_media.update.success' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.update.success'),
420  'online_media.update.error' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.update.error'),
421  ]);
422  $this->view->assign('dragUploader', [
423  'fileDenyPattern' => ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] ?? null,
424  'maxFileSize' => GeneralUtility::getMaxUploadFileSize() * 1024,
425  'defaultDuplicationBehaviourAction' => $this->‪getDefaultDuplicationBehaviourAction(),
426  ]);
427  }
428  }
429 
430  protected function ‪registerFileListCheckboxes(): void
431  {
432  $lang = $this->‪getLanguageService();
433  $userTsConfig = $this->‪getBackendUser()->getTSConfig();
434 
435  $this->view->assign('enableClipBoard', [
436  'enabled' => ($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'selectable',
437  'label' => htmlspecialchars($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clipBoard')),
438  'mode' => $this->filelist->clipObj->current,
439  ]);
440  }
441 
445  protected function ‪registerAdditionalDocHeaderButtons(ServerRequestInterface $request): void
446  {
447  $lang = $this->‪getLanguageService();
448  $buttonBar = $this->view->getDocHeaderComponent()->getButtonBar();
449 
450  // Refresh
451  $refreshButton = $buttonBar->makeLinkButton()
452  ->setHref($request->getAttribute('normalizedParams')->getRequestUri())
453  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
454  ->setIcon($this->iconFactory->getIcon('actions-refresh', IconSize::SMALL));
455  $buttonBar->addButton($refreshButton, ‪ButtonBar::BUTTON_POSITION_RIGHT);
456 
457  // ViewMode
458  $viewModeItems = [];
459  $viewModeItems[] = GeneralUtility::makeInstance(DropDownRadio::class)
460  ->setActive($this->moduleData->get('viewMode') === ‪ViewMode::TILES->value)
461  ->setHref($this->filelist->createModuleUri(['viewMode' => ‪ViewMode::TILES->value]))
462  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.tiles'))
463  ->setIcon($this->iconFactory->getIcon('actions-viewmode-tiles'));
464  $viewModeItems[] = GeneralUtility::makeInstance(DropDownRadio::class)
465  ->setActive($this->moduleData->get('viewMode') === ‪ViewMode::LIST->value)
466  ->setHref($this->filelist->createModuleUri(['viewMode' => ‪ViewMode::LIST->value]))
467  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.list'))
468  ->setIcon($this->iconFactory->getIcon('actions-viewmode-list'));
469  $viewModeItems[] = GeneralUtility::makeInstance(DropDownDivider::class);
470  if (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && ($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'selectable') {
471  $viewModeItems[] = GeneralUtility::makeInstance(DropDownToggle::class)
472  ->setActive((bool)$this->moduleData->get('displayThumbs'))
473  ->setHref($this->filelist->createModuleUri(['displayThumbs' => $this->moduleData->get('displayThumbs') ? 0 : 1]))
474  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.showThumbnails'))
475  ->setIcon($this->iconFactory->getIcon('actions-image'));
476  }
477  $viewModeItems[] = GeneralUtility::makeInstance(DropDownToggle::class)
478  ->setActive((bool)$this->moduleData->get('clipBoard'))
479  ->setHref($this->filelist->createModuleUri(['clipBoard' => $this->moduleData->get('clipBoard') ? 0 : 1]))
480  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.showClipboard'))
481  ->setIcon($this->iconFactory->getIcon('actions-clipboard'));
482  if (($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['displayColumnSelector'] ?? true)
483  && $this->moduleData->get('viewMode') === ‪ViewMode::LIST->value) {
484  $viewModeItems[] = GeneralUtility::makeInstance(DropDownDivider::class);
485  $viewModeItems[] = GeneralUtility::makeInstance(DropDownItem::class)
486  ->setTag('typo3-backend-column-selector-button')
487  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.selectColumns'))
488  ->setAttributes([
489  'data-url' => $this->uriBuilder->buildUriFromRoute(
490  'ajax_show_columns_selector',
491  ['id' => $this->id, 'table' => '_FILE']
492  ),
493  'data-target' => $this->filelist->createModuleUri(),
494  'data-title' => sprintf(
495  $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:showColumnsSelection'),
496  $lang->sL(‪$GLOBALS['TCA']['sys_file']['ctrl']['title'] ?? ''),
497  ),
498  'data-button-ok' => $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:updateColumnView'),
499  'data-button-close' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.cancel'),
500  'data-error-message' => $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:updateColumnView.error'),
501  ])
502  ->setIcon($this->iconFactory->getIcon('actions-options'));
503  }
504  $viewModeButton = $buttonBar->makeDropDownButton()
505  ->setLabel($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view'))
506  ->setShowLabelText(true);
507  foreach ($viewModeItems as $viewModeItem) {
508  $viewModeButton->addItem($viewModeItem);
509  }
510  $buttonBar->addButton($viewModeButton, ‪ButtonBar::BUTTON_POSITION_RIGHT, 2);
511 
512  // Level up
513  try {
514  $currentStorage = $this->folderObject->getStorage();
515  $parentFolder = $this->folderObject->getParentFolder();
516  if ($currentStorage->isWithinFileMountBoundaries($parentFolder)
517  && $parentFolder->getIdentifier() !== $this->folderObject->getIdentifier()
518  && $parentFolder instanceof ‪Folder
519  ) {
520  $levelUpButton = $buttonBar->makeLinkButton()
521  ->setDataAttributes([
522  'tree-update-request' => htmlspecialchars('folder' . ‪GeneralUtility::md5int($parentFolder->getCombinedIdentifier())),
523  ])
524  ->setHref(
525  (string)$this->uriBuilder->buildUriFromRoute(
526  'media_management',
527  ['id' => $parentFolder->getCombinedIdentifier()]
528  )
529  )
530  ->setShowLabelText(true)
531  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.upOneLevel'))
532  ->setIcon($this->iconFactory->getIcon('actions-view-go-up', IconSize::SMALL));
533  $buttonBar->addButton($levelUpButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 1);
534  }
535  } catch (\‪Exception $e) {
536  }
537 
538  // Shortcut
539  $shortCutButton = $buttonBar->makeShortcutButton()
540  ->setRouteIdentifier('media_management')
541  ->setDisplayName(sprintf(
542  '%s: %s',
543  $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:mlang_tabs_tab'),
544  $this->folderObject->getName() ?: $this->folderObject->getIdentifier()
545  ))
546  ->setArguments(array_filter([
547  'id' => $this->id,
548  'searchTerm' => $this->searchTerm,
549  ]));
550  $buttonBar->addButton($shortCutButton, ‪ButtonBar::BUTTON_POSITION_RIGHT);
551 
552  // Upload button (only if upload to this directory is allowed)
553  if ($this->folderObject
554  && $this->folderObject->checkActionPermission('write')
555  && $this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
556  ) {
557  $uploadButton = $buttonBar->makeLinkButton()
558  ->setHref($this->‪getFileUploadUrl())
559  ->setClasses('t3js-drag-uploader-trigger')
560  ->setShowLabelText(true)
561  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'))
562  ->setIcon($this->iconFactory->getIcon('actions-edit-upload', IconSize::SMALL));
563  $buttonBar->addButton($uploadButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 2);
564  }
565 
566  // New folder button
567  if ($this->folderObject && $this->folderObject->checkActionPermission('write') && $this->folderObject->checkActionPermission('add')) {
568  $newButton = $buttonBar->makeLinkButton()
569  ->setClasses('t3js-element-browser')
570  ->setHref((string)$this->uriBuilder->buildUriFromRoute('wizard_element_browser'))
571  ->setDataAttributes([
572  'identifier' => $this->folderObject->getCombinedIdentifier(),
574  ])
575  ->setShowLabelText(true)
576  ->setTitle($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:actions.create_folder'))
577  ->setIcon($this->iconFactory->getIcon('actions-folder-add', IconSize::SMALL));
578  $buttonBar->addButton($newButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 3);
579  }
580 
581  // New file button
582  if ($this->folderObject && $this->folderObject->checkActionPermission('write')
583  && $this->folderObject->getStorage()->checkUserActionPermission('add', 'File')
584  ) {
585  $newButton = $buttonBar->makeLinkButton()
586  ->setHref((string)$this->uriBuilder->buildUriFromRoute(
587  'file_create',
588  [
589  'target' => $this->folderObject->getCombinedIdentifier(),
590  'returnUrl' => $this->filelist->createModuleUri(),
591  ]
592  ))
593  ->setShowLabelText(true)
594  ->setTitle($lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:actions.create_file'))
595  ->setIcon($this->iconFactory->getIcon('actions-file-add', IconSize::SMALL));
596  $buttonBar->addButton($newButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 4);
597  }
598 
599  // Add paste button if clipboard is initialized
600  if ($this->filelist->clipObj instanceof ‪Clipboard && $this->folderObject->checkActionPermission('write')) {
601  $elFromTable = $this->filelist->clipObj->elFromTable('_FILE');
602  if (!empty($elFromTable)) {
603  $addPasteButton = true;
604  $elToConfirm = [];
605  foreach ($elFromTable as $key => $element) {
606  $clipBoardElement = $this->resourceFactory->retrieveFileOrFolderObject($element);
607  if ($clipBoardElement instanceof ‪Folder && $clipBoardElement->‪getStorage()->isWithinFolder(
608  $clipBoardElement,
609  $this->folderObject
610  )
611  ) {
612  $addPasteButton = false;
613  }
614  $elToConfirm[$key] = $clipBoardElement->getName();
615  }
616  if ($addPasteButton) {
617  $confirmText = $this->filelist->clipObj
618  ->confirmMsgText('_FILE', $this->folderObject->getReadablePath(), 'into', $elToConfirm);
619  $pastButtonTitle = $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_paste');
620  $pasteButton = $buttonBar->makeLinkButton()
621  ->setHref($this->filelist->clipObj
622  ->pasteUrl('_FILE', $this->folderObject->getCombinedIdentifier()))
623  ->setClasses('t3js-modal-trigger')
624  ->setDataAttributes([
625  'severity' => 'warning',
626  'bs-content' => $confirmText,
627  'title' => $pastButtonTitle,
628  ])
629  ->setShowLabelText(true)
630  ->setTitle($pastButtonTitle)
631  ->setIcon($this->iconFactory->getIcon('actions-document-paste-into', IconSize::SMALL));
632  $buttonBar->addButton($pasteButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 10);
633  }
634  }
635  }
636  }
637 
642  protected function ‪getModuleHeadline(): string
643  {
644  $name = $this->folderObject->getName();
645  if ($name === '') {
646  // Show storage name on storage root
647  if ($this->folderObject->getIdentifier() === '/') {
648  $name = $this->folderObject->getStorage()->getName();
649  }
650  } else {
651  $name = key(ListUtility::resolveSpecialFolderNames(
652  [$name => $this->folderObject]
653  ));
654  }
655  return (string)$name;
656  }
657 
661  protected function ‪getDefaultDuplicationBehaviourAction(): string
662  {
663  $defaultAction = $this->‪getBackendUser()->getTSConfig()
664  ['options.']['file_list.']['uploader.']['defaultAction'] ?? '';
665 
666  if ($defaultAction === '') {
668  }
669 
670  if (!in_array($defaultAction, [
674  ], true)) {
675  $this->logger->warning('TSConfig: options.file_list.uploader.defaultAction contains an invalid value ("{value}"), fallback to default value: "{default}"', [
676  'value' => $defaultAction,
677  'default' => ‪DuplicationBehavior::CANCEL,
678  ]);
679  $defaultAction = ‪DuplicationBehavior::CANCEL;
680  }
681  return $defaultAction;
682  }
683 
687  protected function ‪htmlResponse(string $html): ResponseInterface
688  {
689  $response = $this->responseFactory
690  ->createResponse()
691  ->withHeader('Content-Type', 'text/html; charset=utf-8');
692 
693  $response->getBody()->write($html);
694  return $response;
695  }
696 
700  protected function ‪addFlashMessage(string $message, string $title = '', ‪ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::INFO): void
701  {
702  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $title, $severity, true);
703  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
704  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
705  $defaultFlashMessageQueue->enqueue($flashMessage);
706  }
707 
711  protected function ‪getFileUploadUrl(): string
712  {
713  return (string)$this->uriBuilder->buildUriFromRoute(
714  'file_upload',
715  [
716  'target' => $this->folderObject->getCombinedIdentifier(),
717  'returnUrl' => $this->filelist->createModuleUri(),
718  ]
719  );
720  }
721 
723  {
724  return ‪$GLOBALS['LANG'];
725  }
726 
728  {
729  return ‪$GLOBALS['BE_USER'];
730  }
731 }
‪TYPO3\CMS\Filelist\Controller\FileListController\getModuleHeadline
‪getModuleHeadline()
Definition: FileListController.php:642
‪TYPO3\CMS\Filelist\Matcher\ResourceFolderTypeMatcher
Definition: ResourceFolderTypeMatcher.php:27
‪TYPO3\CMS\Scheduler\LIST
‪@ LIST
Definition: SchedulerManagementAction.php:28
‪TYPO3\CMS\Filelist\Controller\FileListController\initializeFileList
‪initializeFileList(ServerRequestInterface $request)
Definition: FileListController.php:287
‪TYPO3\CMS\Filelist\Controller\FileListController\processRequest
‪processRequest(ServerRequestInterface $request)
Definition: FileListController.php:225
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:37
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:33
‪TYPO3\CMS\Core\Resource\DuplicationBehavior
Definition: DuplicationBehavior.php:24
‪TYPO3\CMS\Core\Resource\DuplicationBehavior\CANCEL
‪const CANCEL
Definition: DuplicationBehavior.php:46
‪TYPO3\CMS\Filelist\Controller\FileListController\__construct
‪__construct(protected readonly UriBuilder $uriBuilder, protected readonly PageRenderer $pageRenderer, protected readonly IconFactory $iconFactory, protected readonly ResourceFactory $resourceFactory, protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly BackendViewFactory $viewFactory, protected readonly ResponseFactoryInterface $responseFactory,)
Definition: FileListController.php:86
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:24
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Backend\View\BackendViewFactory
Definition: BackendViewFactory.php:35
‪TYPO3\CMS\Filelist\Controller\FileListController\$view
‪ModuleTemplate $view
Definition: FileListController.php:82
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\Filelist\Controller\FileListController\getFileUploadUrl
‪getFileUploadUrl()
Definition: FileListController.php:711
‪TYPO3\CMS\Filelist\Controller\FileListController\$filelist
‪FileList $filelist
Definition: FileListController.php:83
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪TYPO3\CMS\Backend\Module\ModuleData
Definition: ModuleData.php:30
‪TYPO3\CMS\Filelist\Controller\FileListController\initializeModule
‪initializeModule(ServerRequestInterface $request)
Definition: FileListController.php:269
‪TYPO3\CMS\Filelist\Matcher\Matcher
Definition: Matcher.php:24
‪TYPO3\CMS\Backend\Attribute\Controller
Definition: Controller.php:25
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Core\Resource\Utility\ListUtility
Definition: ListUtility.php:26
‪TYPO3\CMS\Filelist\Controller\FileListController\getLanguageService
‪getLanguageService()
Definition: FileListController.php:722
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownToggle
Definition: DropDownToggle.php:39
‪TYPO3\CMS\Filelist\Controller\FileListController\getDefaultDuplicationBehaviourAction
‪getDefaultDuplicationBehaviourAction()
Definition: FileListController.php:661
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownDivider
Definition: DropDownDivider.php:27
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
Definition: ExtendedFileUtility.php:77
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:46
‪TYPO3\CMS\Filelist\Controller
‪TYPO3\CMS\Filelist\FileList
Definition: FileList.php:75
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownRadio
Definition: DropDownRadio.php:54
‪TYPO3\CMS\Filelist\Controller\FileListController\htmlResponse
‪htmlResponse(string $html)
Definition: FileListController.php:687
‪TYPO3\CMS\Filelist\Controller\FileListController
Definition: FileListController.php:72
‪TYPO3\CMS\Filelist\Controller\FileListController\$searchTerm
‪string $searchTerm
Definition: FileListController.php:77
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand
Definition: FileSearchDemand.php:26
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Resource\DuplicationBehavior\RENAME
‪const RENAME
Definition: DuplicationBehavior.php:32
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪getStorage()
Definition: Folder.php:138
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:64
‪TYPO3\CMS\Filelist\ElementBrowser\CreateFolderBrowser\IDENTIFIER
‪const IDENTIFIER
Definition: CreateFolderBrowser.php:35
‪TYPO3\CMS\Filelist\Controller\FileListController\$moduleData
‪ModuleData $moduleData
Definition: FileListController.php:84
‪TYPO3\CMS\Filelist\Controller\FileListController\$id
‪string $id
Definition: FileListController.php:75
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Filelist\Controller\FileListController\getBackendUser
‪getBackendUser()
Definition: FileListController.php:727
‪TYPO3\CMS\Filelist\Controller\FileListController\addFlashMessage
‪addFlashMessage(string $message, string $title='', ContextualFeedbackSeverity $severity=ContextualFeedbackSeverity::INFO)
Definition: FileListController.php:700
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:127
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:27
‪TYPO3\CMS\Filelist\Controller\FileListController\registerFileListCheckboxes
‪registerFileListCheckboxes()
Definition: FileListController.php:430
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Filelist\Controller\FileListController\registerDragUploader
‪registerDragUploader()
Definition: FileListController.php:405
‪TYPO3\CMS\Filelist\Controller\FileListController\registerAdditionalDocHeaderButtons
‪registerAdditionalDocHeaderButtons(ServerRequestInterface $request)
Definition: FileListController.php:445
‪TYPO3\CMS\Filelist\Type\TILES
‪@ TILES
Definition: ViewMode.php:26
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Filelist\Controller\FileListController\handleRequest
‪handleRequest(ServerRequestInterface $request)
Definition: FileListController.php:97
‪TYPO3\CMS\Core\Resource\DuplicationBehavior\REPLACE
‪const REPLACE
Definition: DuplicationBehavior.php:39
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility\md5int
‪static int md5int($str)
Definition: GeneralUtility.php:463
‪TYPO3\CMS\Filelist\Controller\FileListController\generateFileList
‪generateFileList(ServerRequestInterface $request)
Definition: FileListController.php:356
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange(mixed $theInt, int $min, int $max=2000000000, int $defaultValue=0)
Definition: MathUtility.php:34
‪TYPO3\CMS\Filelist\Controller\FileListController\$cmd
‪string $cmd
Definition: FileListController.php:76
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\createForSearchTerm
‪static createForSearchTerm(string $searchTerm)
Definition: FileSearchDemand.php:70
‪TYPO3\CMS\Filelist\Type\ViewMode
‪ViewMode
Definition: ViewMode.php:24
‪TYPO3\CMS\Filelist\ElementBrowser\CreateFolderBrowser
Definition: CreateFolderBrowser.php:34
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_RIGHT
‪const BUTTON_POSITION_RIGHT
Definition: ButtonBar.php:42
‪TYPO3\CMS\Filelist\Matcher\ResourceFileTypeMatcher
Definition: ResourceFileTypeMatcher.php:27
‪TYPO3\CMS\Filelist\Controller\FileListController\$currentPage
‪int $currentPage
Definition: FileListController.php:78
‪TYPO3\CMS\Filelist\Controller\FileListController\$overwriteExistingFiles
‪DuplicationBehavior $overwriteExistingFiles
Definition: FileListController.php:81
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownItem
Definition: DropDownItem.php:34
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Filelist\Controller\FileListController\$folderObject
‪Folder $folderObject
Definition: FileListController.php:80