‪TYPO3CMS  ‪main
FileList.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Filelist;
17 
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Http\Message\ServerRequestInterface;
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
37 use TYPO3\CMS\Core\Imaging\IconSize;
67 
74 {
75  public ‪Mode ‪$mode = Mode::MANAGE;
77 
81  public int ‪$itemsPerPage = 40;
82 
86  public int ‪$currentPage = 1;
87 
91  public int ‪$totalbytes = 0;
92 
96  public int ‪$totalItems = 0;
97 
101  public string ‪$sort = '';
102 
106  public bool ‪$sortRev = true;
107 
111  public bool ‪$thumbs = false;
112 
116  public int ‪$maxTitleLength = 30;
117 
121  public array ‪$fieldArray = [];
122 
128  public array ‪$addElement_tdCssClass = [
129  '_CONTROL_' => 'col-control',
130  '_SELECTOR_' => 'col-checkbox',
131  'icon' => 'col-icon',
132  'name' => 'col-title col-responsive',
133  ];
134 
138  protected ‪$folderObject;
139 
143  public ‪$clipObj;
144 
145  // Evaluates if a resource can be downloaded
147  // Evaluates if a resource can be displayed
149  // Evaluates if a resource can be selected
151  // Evaluates if a resource is currently selected
153 
155  protected EventDispatcherInterface ‪$eventDispatcher;
156  protected ServerRequestInterface ‪$request;
162 
163  public function ‪__construct(ServerRequestInterface ‪$request)
164  {
165  $this->request = ‪$request;
166 
167  // Setting the maximum length of the filenames to the user's settings or minimum 30 (= $this->maxTitleLength)
168  $this->maxTitleLength = max($this->maxTitleLength, (int)($this->‪getBackendUser()->uc['titleLen'] ?? 1));
169  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
170  $this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
171  $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
172  $this->itemsPerPage = ‪MathUtility::forceIntegerInRange(
173  $this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['filesPerPage'] ?? $this->itemsPerPage,
174  1
175  );
176  // Create clipboard object and initialize that
177  $this->clipObj = GeneralUtility::makeInstance(Clipboard::class);
178  $this->clipObj->initializeClipboard(‪$request);
179  $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
180  $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
181  $this->onlineMediaHelperRegistry = GeneralUtility::makeInstance(OnlineMediaHelperRegistry::class);
182 
183  // Initialize Resource Download
184  $this->resourceDownloadMatcher = GeneralUtility::makeInstance(Matcher::class);
185  $this->resourceDownloadMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFolderTypeMatcher::class));
186 
187  // Create filter for file extensions
188  $fileExtensionMatcher = GeneralUtility::makeInstance(ResourceFileExtensionMatcher::class);
189  $fileDownloadConfiguration = (array)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.'] ?? []);
190  if ($fileDownloadConfiguration !== []) {
191  $allowedExtensions = ‪GeneralUtility::trimExplode(',', (string)($fileDownloadConfiguration['allowedFileExtensions'] ?? ''), true);
192  $disallowedExtensions = ‪GeneralUtility::trimExplode(',', (string)($fileDownloadConfiguration['disallowedFileExtensions'] ?? ''), true);
193  $fileExtensionMatcher = GeneralUtility::makeInstance(ResourceFileExtensionMatcher::class);
194  $fileExtensionMatcher->setExtensions($allowedExtensions);
195  $fileExtensionMatcher->setIgnoredExtensions($disallowedExtensions);
196  } else {
197  $fileExtensionMatcher->addExtension('*');
198  }
199  $this->resourceDownloadMatcher->addMatcher($fileExtensionMatcher);
200  }
201 
202  public function ‪setResourceDownloadMatcher(?‪Matcher $matcher): self
203  {
204  $this->resourceDownloadMatcher = $matcher;
205  return $this;
206  }
207 
208  public function ‪setResourceDisplayMatcher(?‪Matcher $matcher): self
209  {
210  $this->resourceDisplayMatcher = $matcher;
211  return $this;
212  }
213 
214  public function ‪setResourceSelectableMatcher(?‪Matcher $matcher): self
215  {
216  $this->resourceSelectableMatcher = $matcher;
217  return $this;
218  }
219 
220  public function ‪setResourceSelectedMatcher(?‪Matcher $matcher): self
221  {
222  $this->resourceSelectedMatcher = $matcher;
223  return $this;
224  }
225 
235  public function ‪start(Folder ‪$folderObject, int ‪$currentPage, string ‪$sort, bool ‪$sortRev, ‪Mode ‪$mode = Mode::MANAGE)
236  {
237  $this->folderObject = ‪$folderObject;
238  $this->currentPage = ‪MathUtility::forceIntegerInRange(‪$currentPage, 1, 100000);
239  $this->sort = ‪$sort;
240  $this->sortRev = ‪$sortRev;
241  $this->totalbytes = 0;
242  $this->resourceDownloadMatcher = null;
243  $this->resourceDisplayMatcher = null;
244  $this->resourceSelectableMatcher = null;
245  $this->‪setMode($mode);
246  }
247 
248  public function ‪setMode(‪Mode ‪$mode)
249  {
250  $this->mode = ‪$mode;
251  $this->‪fieldArray = $mode->fieldArray();
252  }
253 
254  public function ‪setColumnsToRender(array $additionalFields = []): void
255  {
256  $this->‪fieldArray = array_unique(array_merge($this->‪fieldArray, $additionalFields));
257  }
258 
262  protected function ‪renderTiles(ResourceCollectionPaginator $paginator, array $resourceViews, ViewInterface $view): string
263  {
264  $view->assign('displayThumbs', $this->thumbs);
265  $view->assign('displayCheckbox', $this->resourceSelectableMatcher ? true : false);
266  $view->assign('defaultLanguageAccess', $this->‪getBackendUser()->checkLanguageAccess(0));
267  $view->assign('pagination', [
268  'backward' => $this->‪getPaginationLinkForDirection($paginator, ‪NavigationDirection::BACKWARD),
269  'forward' => $this->‪getPaginationLinkForDirection($paginator, NavigationDirection::FORWARD),
270  ]);
271  $view->assign('resources', $resourceViews);
272 
273  return $view->render('Filelist/Tiles');
274  }
275 
279  protected function ‪renderList(ResourceCollectionPaginator $paginator, array $resourceViews, ViewInterface $view): string
280  {
281  $view->assign('tableHeader', $this->‪renderListTableHeader());
282  $view->assign('tableBackwardNavigation', $this->‪renderListTableForwardBackwardNavigation($paginator, ‪NavigationDirection::BACKWARD));
283  $view->assign('tableBody', $this->‪renderListTableBody($resourceViews));
284  $view->assign('tableForwardNavigation', $this->‪renderListTableForwardBackwardNavigation($paginator, NavigationDirection::FORWARD));
285 
286  return $view->render('Filelist/List');
287  }
288 
289  public function ‪render(?‪FileSearchDemand ‪$searchDemand, ‪ViewInterface $view): string
290  {
291  $storage = $this->folderObject->getStorage();
292  $storage->resetFileAndFolderNameFiltersToDefault();
293  if (!$this->folderObject->getStorage()->isBrowsable()) {
294  return '';
295  }
296 
297  if (‪$searchDemand !== null) {
298  $this->searchDemand = ‪$searchDemand;
300  $folders = [];
301  // Add special "Path" field for the search result
302  array_splice($this->‪fieldArray, 3, 0, '_PATH_');
303  } else {
304  $folders = $storage->getFoldersInFolder($this->folderObject);
305  }
306  $files = iterator_to_array($this->folderObject->searchFiles(‪$searchDemand));
307  } else {
308  $folders = $storage->getFoldersInFolder($this->folderObject);
309  $files = $this->folderObject->getFiles();
310  }
311 
312  // Cleanup field array
313  $this->‪fieldArray = array_filter($this->‪fieldArray, function (string $fieldName) {
314  if ($fieldName === '_SELECTOR_' && $this->resourceSelectableMatcher === null) {
315  return false;
316  }
317  return true;
318  });
319 
320  // Remove processing folders
321  $folders = array_filter($folders, function (Folder $folder) {
322  return $folder->getRole() !== ‪FolderInterface::ROLE_PROCESSING;
323  });
324 
325  // Apply filter
326  $resources = array_filter($folders + $files, function (ResourceInterface $resource) {
327  return $this->resourceDisplayMatcher === null || $this->resourceDisplayMatcher->match($resource);
328  });
329 
330  $resourceCollection = new ResourceCollection($resources);
331  $this->totalItems = $resourceCollection->getTotalCount();
332  $this->totalbytes = $resourceCollection->getTotalBytes();
333 
334  // Sort the files before sending it to the renderer
335  if (trim($this->sort) !== '') {
336  $resourceCollection->setResources($this->‪sortResources($resourceCollection->getResources(), $this->sort));
337  }
338 
339  $paginator = new ResourceCollectionPaginator($resourceCollection, $this->currentPage, $this->itemsPerPage);
340 
341  // Prepare Resources for View
342  $resourceViews = [];
343  $userPermissions = $this->‪getUserPermissions();
344  foreach ($paginator->getPaginatedItems() as $resource) {
345  $resourceView = new ResourceView(
346  $resource,
347  $userPermissions,
348  $this->iconFactory->getIconForResource($resource, IconSize::SMALL)
349  );
350  $resourceView->moduleUri = $this->‪createModuleUriForResource($resource);
351  $resourceView->editDataUri = $this->‪createEditDataUriForResource($resource);
352  $resourceView->editContentUri = $this->‪createEditContentUriForResource($resource);
353  $resourceView->replaceUri = $this->‪createReplaceUriForResource($resource);
354 
355  $resourceView->isDownloadable = $this->resourceDownloadMatcher !== null && $this->resourceDownloadMatcher->match($resource);
356  $resourceView->isSelectable = $this->resourceSelectableMatcher !== null && $this->resourceSelectableMatcher->match($resource);
357  if ($this->mode === Mode::BROWSE && $resource instanceof File) {
358  $resourceView->isSelectable = $this->eventDispatcher->dispatch(new IsFileSelectableEvent($resource))->isFileSelectable();
359  }
360  $resourceView->isSelected = $this->resourceSelectedMatcher !== null && $this->resourceSelectedMatcher->match($resource);
361 
362  $resourceViews[] = $resourceView;
363  }
364 
365  if ($this->viewMode === ‪ViewMode::TILES) {
366  return $this->‪renderTiles($paginator, $resourceViews, $view);
367  }
368 
369  return $this->‪renderList($paginator, $resourceViews, $view);
370  }
371 
382  public function ‪addElement(array $data, array $attributes = [], bool $isTableHeader = false): string
383  {
384  // Initialize rendering.
385  $cols = [];
386  $colType = $isTableHeader ? 'th' : 'td';
387  // Traverse field array which contains the data to present:
388  foreach ($this->‪fieldArray as $fieldName) {
389  $cellAttributes = [];
390  $cellAttributes['class'] = $this->addElement_tdCssClass[$fieldName] ?? 'col-nowrap';
391 
392  // Special handling to combine icon and name column
393  if ($isTableHeader && $fieldName === 'icon') {
394  continue;
395  }
396  if ($isTableHeader && $fieldName === 'name') {
397  $cellAttributes['colspan'] = 2;
398  }
399 
400  $cols[] = '<' . $colType . ' ' . GeneralUtility::implodeAttributes($cellAttributes, true) . '>' . ($data[$fieldName] ?? '') . '</' . $colType . '>';
401  }
402 
403  // Add the table row
404  return '
405  <tr ' . GeneralUtility::implodeAttributes($attributes, true) . '>
406  ' . implode(PHP_EOL, $cols) . '
407  </tr>';
408  }
409 
413  public function ‪getFolderInfo(): string
414  {
415  if ($this->totalItems == 1) {
416  $fileLabel = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:file');
417  } else {
418  $fileLabel = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:files');
419  }
420  return $this->totalItems . ' ' . htmlspecialchars($fileLabel) . ', ' . GeneralUtility::formatSize(
421  $this->totalbytes,
422  htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits'))
423  );
424  }
425 
426  protected function ‪renderListTableHeader(): string
427  {
428  $data = [];
429  foreach ($this->‪fieldArray as $field) {
430  switch ($field) {
431  case 'icon':
432  $data[$field] = '';
433  break;
434  case '_SELECTOR_':
435  $data[$field] = $this->‪renderCheckboxActions();
436  break;
437  default:
438  $data[$field] = $this->‪renderListTableFieldHeader($field);
439  break;
440  }
441  }
442 
443  return $this->‪addElement($data, [], true);
444  }
445 
446  protected function ‪renderListTableFieldHeader(string $field): string
447  {
448  $label = $this->‪getFieldLabel($field);
449  if (in_array($field, ['_SELECTOR_', '_CONTROL_', '_PATH_'])) {
450  return $label;
451  }
452 
453  $params = ['sort' => $field, 'currentPage' => 0];
454  if ($this->sort === $field) {
455  // Check reverse sorting
456  $params['reverse'] = ($this->sortRev ? '0' : '1');
457  } else {
458  $params['reverse'] = 0;
459  }
460 
461  $icon = $this->sort === $field
462  ? $this->iconFactory->getIcon('actions-sort-amount-' . ($this->sortRev ? 'down' : 'up'), IconSize::SMALL)->‪render()
463  : $this->iconFactory->getIcon('actions-sort-amount', IconSize::SMALL)->render();
464 
465  $attributes = [
466  'class' => 'table-sorting-button ' . ($this->sort === $field ? 'table-sorting-button-active' : ''),
467  'href' => $this->‪createModuleUri($params),
468  ];
469 
470  return '<a ' . GeneralUtility::implodeAttributes($attributes, true) . '>
471  <span class="table-sorting-label">' . htmlspecialchars($label) . '</span>
472  <span class="table-sorting-icon">' . $icon . '</span>
473  </a>';
474 
475  }
476 
480  protected function ‪renderListTableBody(array $resourceViews): string
481  {
482  $output = '';
483  foreach ($resourceViews as $resourceView) {
484  $data = [];
485  $attributes = [
486  'class' => $resourceView->isSelected ? 'selected' : '',
487  'data-filelist-element' => 'true',
488  'data-filelist-type' => $resourceView->getType(),
489  'data-filelist-identifier' => $resourceView->getIdentifier(),
490  'data-filelist-name' => htmlspecialchars($resourceView->getName()),
491  'data-filelist-icon' => $resourceView->getIconIdentifier(),
492  'data-filelist-thumbnail' => $resourceView->getThumbnailUri(),
493  'data-filelist-uid' => $resourceView->getUid(),
494  'data-filelist-meta-uid' => $resourceView->getMetaDataUid(),
495  'data-filelist-selectable' => $resourceView->isSelectable ? 'true' : 'false',
496  'data-filelist-selected' => $resourceView->isSelected ? 'true' : 'false',
497  'data-multi-record-selection-element' => 'true',
498  'draggable' => $resourceView->canMove() ? 'true' : 'false',
499  ];
500  if ($this->‪getBackendUser()->checkLanguageAccess(0)) {
501  $attributes['data-default-language-access'] = 'true';
502  }
503  foreach ($this->‪fieldArray as $field) {
504  switch ($field) {
505  case 'icon':
506  $data[$field] = $this->‪renderIcon($resourceView);
507  break;
508  case 'name':
509  $data[$field] = $this->‪renderName($resourceView)
510  . $this->‪renderThumbnail($resourceView);
511  break;
512  case 'size':
513  $data[$field] = $this->‪renderSize($resourceView);
514  break;
515  case 'rw':
516  $data[$field] = $this->‪renderPermission($resourceView);
517  break;
518  case 'record_type':
519  $data[$field] = $this->‪renderType($resourceView);
520  break;
521  case 'crdate':
522  $data[$field] = $this->‪renderCreationTime($resourceView);
523  break;
524  case 'tstamp':
525  $data[$field] = $this->‪renderModificationTime($resourceView);
526  break;
527  case '_SELECTOR_':
528  $data[$field] = $this->‪renderSelector($resourceView);
529  break;
530  case '_PATH_':
531  $data[$field] = $this->‪renderPath($resourceView);
532  break;
533  case '_REF_':
534  $data[$field] = $this->‪renderReferenceCount($resourceView);
535  break;
536  case '_CONTROL_':
537  $data[$field] = $this->‪renderControl($resourceView);
538  break;
539  default:
540  $data[$field] = $this->‪renderField($resourceView, $field);
541  }
542  }
543  $output .= $this->‪addElement($data, $attributes);
544  }
545 
546  return $output;
547  }
548 
551  ‪NavigationDirection $direction
552  ): string {
553  if (!$link = $this->‪getPaginationLinkForDirection($paginator, $direction)) {
554  return '';
555  }
556 
557  $iconIdentifier = match ($direction) {
558  ‪NavigationDirection::BACKWARD => 'actions-move-up',
559  NavigationDirection::FORWARD => 'actions-move-down',
560  };
561 
562  $markup = [];
563  $markup[] = '<tr>';
564  $markup[] = ' <td colspan="' . count($this->‪fieldArray) . '">';
565  $markup[] = ' <a href="' . htmlspecialchars($link->uri) . '">';
566  $markup[] = ' ' . $this->iconFactory->getIcon($iconIdentifier, IconSize::SMALL)->render();
567  $markup[] = ' <i>[' . $link->label . ']</i>';
568  $markup[] = ' </a>';
569  $markup[] = ' </td>';
570  $markup[] = '</tr>';
571 
572  return implode(PHP_EOL, $markup);
573  }
574 
581  protected function getTranslationsForMetaData($metaDataRecord)
582  {
583  $languageField = ‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? '';
584  $languageParentField = ‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['transOrigPointerField'] ?? '';
585 
586  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_metadata');
587  $queryBuilder->getRestrictions()->removeAll();
588  ‪$translationRecords = $queryBuilder->select('*')
589  ->from('sys_file_metadata')
590  ->where(
591  $queryBuilder->expr()->eq(
592  $languageParentField,
593  $queryBuilder->createNamedParameter($metaDataRecord['uid'] ?? 0, ‪Connection::PARAM_INT)
594  ),
595  $queryBuilder->expr()->gt(
596  $languageField,
597  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
598  )
599  )
600  ->executeQuery()
601  ->fetchAllAssociative();
602 
603  ‪$translations = [];
604  foreach (‪$translationRecords as ‪$record) {
605  $languageId = ‪$record[$languageField];
606  ‪$translations[$languageId] = ‪$record;
607  }
608  return ‪$translations;
609  }
610 
614  protected function ‪renderIcon(ResourceView $resourceView): string
615  {
616  return $this->mode === Mode::BROWSE
617  ? $resourceView->getIconSmall()->render()
618  : BackendUtility::wrapClickMenuOnIcon($resourceView->getIconSmall()->render(), 'sys_file', $resourceView->getIdentifier());
619  }
620 
624  protected function ‪renderName(ResourceView $resourceView): string
625  {
626  $resourceName = htmlspecialchars($resourceView->getName());
627  if ($resourceView->resource instanceof Folder
628  && $resourceView->resource->getRole() !== ‪FolderInterface::ROLE_DEFAULT) {
629  $resourceName = '<strong>' . $resourceName . '</strong>';
630  }
631 
632  $attributes = [];
633  $attributes['title'] = $resourceView->getName();
634  $attributes['type'] = 'button';
635  $attributes['class'] = 'btn btn-link p-0';
636  $attributes['data-filelist-action'] = 'primary';
637 
638  $output = '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>' . $resourceName . '</button>';
639  if ($resourceView->isMissing()) {
640  $label = htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing'));
641  $output = '<span class="badge badge-danger">' . $label . '</span> ' . $output;
642  }
643 
644  return $output;
645  }
646 
650  protected function ‪renderThumbnail(ResourceView $resourceView): string
651  {
652  if ($this->thumbs === false
653  || $resourceView->getPreview() === null
654  || !($resourceView->getPreview()->isImage() || $resourceView->getPreview()->isMediaFile())
655  ) {
656  return '';
657  }
658 
659  $processedFile = $resourceView->getPreview()->process(
661  [
662  'width' => (int)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['thumbnail.']['width'] ?? 64),
663  'height' => (int)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['thumbnail.']['height'] ?? 64),
664  ]
665  );
666 
667  if (($thumbnailUrl = ($processedFile->getPublicUrl() ?? '')) === '') {
668  // Prevent rendering of a "img" tag with an empty "src" attribute
669  return '';
670  }
671 
672  if (‪PathUtility::isAbsolutePath($thumbnailUrl)) {
673  $thumbnailUrl .= '?' . filemtime($processedFile->getForLocalProcessing(false));
674  }
675 
676  return '<br><img src="' . htmlspecialchars($thumbnailUrl) . '" ' .
677  'width="' . htmlspecialchars($processedFile->getProperty('width')) . '" ' .
678  'height="' . htmlspecialchars($processedFile->getProperty('height')) . '" ' .
679  'title="' . htmlspecialchars($resourceView->getName()) . '" ' .
680  'loading="lazy" ' .
681  'alt="" />';
682  }
683 
687  protected function ‪renderType(ResourceView $resourceView): string
688  {
689  $type = $resourceView->getType();
690  $content = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:' . $type);
691  if ($resourceView->resource instanceof File && $resourceView->resource->getExtension() !== '') {
692  $content .= ' (' . strtoupper($resourceView->resource->getExtension()) . ')';
693  }
694 
695  return htmlspecialchars($content);
696  }
697 
701  protected function ‪renderCreationTime(ResourceView $resourceView): string
702  {
703  if ($resourceView->resource instanceof File) {
704  $timestamp = $resourceView->getCreatedAt();
705  } elseif ($resourceView->resource instanceof Folder) {
706  $timestamp = $resourceView->resource->getCreationTime();
707  } else {
708  $timestamp = null;
709  }
710 
711  return $timestamp ? BackendUtility::datetime($timestamp) : '';
712  }
713 
717  protected function ‪renderModificationTime(ResourceView $resourceView): string
718  {
719  if ($resourceView->resource instanceof File) {
720  $timestamp = $resourceView->getUpdatedAt();
721  } elseif ($resourceView->resource instanceof Folder) {
722  $timestamp = $resourceView->resource->getModificationTime();
723  } else {
724  $timestamp = null;
725  }
726 
727  return $timestamp ? BackendUtility::datetime($timestamp) : '';
728  }
729 
733  protected function ‪renderSize(ResourceView $resourceView): string
734  {
735  if ($resourceView->resource instanceof File) {
736  return GeneralUtility::formatSize((int)$resourceView->resource->getSize(), htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')));
737  }
738 
739  if ($resourceView->resource instanceof Folder) {
740  try {
741  $numFiles = $resourceView->resource->getFileCount();
742  } catch (InsufficientFolderAccessPermissionsException $e) {
743  $numFiles = 0;
744  }
745  if ($numFiles === 1) {
746  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:file'));
747  }
748  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:files'));
749  }
750 
751  return '';
752  }
753 
757  protected function ‪renderPermission(ResourceView $resourceView): string
758  {
759  return '<strong class="text-danger">'
760  . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read'))
761  . ($resourceView->canWrite() ? htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write')) : '')
762  . '</strong>';
763  }
764 
768  protected function ‪renderField(ResourceView $resourceView, string $field): string
769  {
770  if ($resourceView->resource instanceof File && $resourceView->resource->hasProperty($field)) {
771  if ($field === 'storage') {
772  // Fetch storage name of the current file
773  $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$resourceView->resource->getProperty($field));
774  if ($storage !== null) {
775  return htmlspecialchars($storage->getName());
776  }
777  } else {
778  return htmlspecialchars(
779  (string)BackendUtility::getProcessedValueExtra(
780  $this->‪getConcreteTableName($field),
781  $field,
782  $resourceView->resource->getProperty($field),
783  $this->maxTitleLength,
784  $resourceView->resource->getMetaData()->offsetGet('uid')
785  )
786  );
787  }
788  }
789 
790  return '';
791  }
792 
796  protected function ‪renderSelector(ResourceView $resourceView): string
797  {
798  $checkboxConfig = $resourceView->getCheckboxConfig();
799  if ($checkboxConfig === null) {
800  return '';
801  }
802  if (!$resourceView->isSelectable) {
803  return '';
804  }
805 
806  $attributes = [
807  'class' => 'form-check-input ' . $checkboxConfig['class'],
808  'type' => 'checkbox',
809  'name' => $checkboxConfig['name'],
810  'value' => $checkboxConfig['value'],
811  'checked' => $checkboxConfig['checked'],
812  ];
813 
814  return '<span class="form-check form-check-type-toggle">'
815  . '<input ' . GeneralUtility::implodeAttributes($attributes, true) . ' />'
816  . '</span>';
817  }
818 
822  protected function ‪renderPath(ResourceView $resourceView): string
823  {
824  return htmlspecialchars($resourceView->getPath());
825  }
826 
831  protected function ‪renderReferenceCount(ResourceView $resourceView): string
832  {
833  if (!$resourceView->resource instanceof File) {
834  return '-';
835  }
836 
837  $referenceCount = $this->‪getFileReferenceCount($resourceView->resource);
838  if (!$referenceCount) {
839  return '-';
840  }
841 
842  $attributes = [
843  'type' => 'button',
844  'class' => 'btn btn-sm btn-link',
845  'data-filelist-action' => 'show',
846  'title' => $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references') . ' (' . $referenceCount . ')',
847  ];
848 
849  return '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>' . $referenceCount . '</button>';
850  }
851 
855  protected function ‪renderControl(ResourceView $resourceView): string
856  {
857  return match ($this->mode) {
858  Mode::MANAGE => $this->‪renderControlManage($resourceView),
859  Mode::BROWSE => $this->‪renderControlBrowse($resourceView),
860  };
861  }
862 
866  protected function ‪renderControlManage(ResourceView $resourceView): string
867  {
868  if (!$resourceView->resource instanceof File && !$resourceView->resource instanceof Folder) {
869  return '';
870  }
871 
872  // primary actions
873  $primaryActions = ['view', 'metadata', 'translations', 'delete'];
874  $userTsConfig = $this->‪getBackendUser()->getTSConfig();
875  if ($userTsConfig['options.']['file_list.']['primaryActions'] ?? false) {
876  $primaryActions = ‪GeneralUtility::trimExplode(',', $userTsConfig['options.']['file_list.']['primaryActions']);
877  // Always add "translations" as this action has an own dropdown container and therefore cannot be a secondary action
878  if (!in_array('translations', $primaryActions, true)) {
879  $primaryActions[] = 'translations';
880  }
881  }
882 
883  $actions = [
884  'edit' => $this->‪createControlEditContent($resourceView),
885  'metadata' => $this->‪createControlEditMetaData($resourceView),
886  'translations' => $this->‪createControlTranslation($resourceView),
887  'view' => $this->‪createControlView($resourceView),
888  'replace' => $this->‪createControlReplace($resourceView),
889  'rename' => $this->‪createControlRename($resourceView),
890  'download' => $this->‪createControlDownload($resourceView),
891  'upload' => $this->‪createControlUpload($resourceView),
892  'info' => $this->‪createControlInfo($resourceView),
893  'delete' => $this->‪createControlDelete($resourceView),
894  'copy' => $this->‪createControlCopy($resourceView),
895  'cut' => $this->‪createControlCut($resourceView),
896  'paste' => $this->‪createControlPaste($resourceView),
897  'updateOnlineMedia' => $this->‪createControlUpdateOnlineMedia($resourceView),
898  ];
899 
900  $event = new ProcessFileListActionsEvent($resourceView->resource, $actions);
901  $event = $this->eventDispatcher->dispatch($event);
902  $actions = $event->getActionItems();
903 
904  // Remove empty actions
905  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
906 
907  // Compile items into a dropdown
908  $cellOutput = '';
909  $output = '';
910  foreach ($actions as $key => $action) {
911  if (in_array($key, $primaryActions, true)) {
912  $output .= $action;
913  continue;
914  }
915  // This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12.
916  $action = str_replace('btn btn-sm btn-default', 'dropdown-item dropdown-item-spaced', $action);
917  $title = [];
918  preg_match('/title="([^"]*)"/', $action, $title);
919  if (empty($title)) {
920  preg_match('/aria-label="([^"]*)"/', $action, $title);
921  }
922  if (!empty($title[1])) {
923  $action = str_replace(
924  [
925  '</a>',
926  '</button>',
927  ],
928  [
929  ' ' . $title[1] . '</a>',
930  ' ' . $title[1] . '</button>',
931  ],
932  $action
933  );
934  // In case we added the title as tag content, we can remove the attribute,
935  // since this is duplicated and would trigger a tooltip with the same content.
936  if (!empty($title[0])) {
937  $action = str_replace($title[0], '', $action);
938  }
939  $cellOutput .= '<li>' . $action . '</li>';
940  }
941  }
942 
943  if ($cellOutput !== '') {
944  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.more');
945  $output .= '<div class="btn-group dropdown" title="' . htmlspecialchars($title) . '" >'
946  . '<a href="#actions_' . $resourceView->resource->getHashedIdentifier() . '" class="btn btn-sm btn-default dropdown-toggle dropdown-toggle-no-chevron" data-bs-toggle="dropdown" data-bs-boundary="window" aria-expanded="false">'
947  . $this->iconFactory->getIcon('actions-menu-alternative', IconSize::SMALL)->render()
948  . '</a>'
949  . '<ul id="actions_' . $resourceView->resource->getHashedIdentifier() . '" class="dropdown-menu">' . $cellOutput . '</ul>'
950  . '</div>';
951  }
952 
953  return '<div class="btn-group">' . $output . '</div>';
954  }
955 
959  protected function ‪renderControlBrowse(ResourceView $resourceView): string
960  {
961  $fileOrFolderObject = $resourceView->resource;
962  if (!$fileOrFolderObject instanceof File && !$fileOrFolderObject instanceof Folder) {
963  return '';
964  }
965 
966  $actions = [
967  'select' => $this->‪createControlSelect($resourceView),
968  'info' => $this->‪createControlInfo($resourceView),
969  ];
970 
971  // Remove empty actions
972  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
973  if (empty($actions)) {
974  return '';
975  }
976 
977  return '<div class="btn-group">' . implode(' ', $actions) . '</div>';
978  }
979 
980  protected function ‪createControlSelect(‪ResourceView $resourceView): ?‪ButtonInterface
981  {
982  if (!$resourceView->isSelectable) {
983  return null;
984  }
985 
986  $title = sprintf(
987  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.selectFile'),
988  $resourceView->‪getName(),
989  );
990  $button = GeneralUtility::makeInstance(GenericButton::class);
991  $button->setTitle($title);
992  $button->setAttributes([
993  'type' => 'button',
994  'data-filelist-action' => 'select',
995  'aria-label' => $title,
996  ]);
997  $button->setIcon($this->iconFactory->getIcon('actions-plus', IconSize::SMALL));
998 
999  return $button;
1000  }
1001 
1002  protected function ‪createControlEditContent(‪ResourceView $resourceView): ?‪ButtonInterface
1003  {
1004  if (!($resourceView->resource instanceof ‪File && $resourceView->resource->isTextFile())
1005  || !$resourceView->‪canWrite()) {
1006  return null;
1007  }
1008 
1009  $button = GeneralUtility::makeInstance(LinkButton::class);
1010  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent'));
1011  $button->setHref($resourceView->editContentUri);
1012  $button->setIcon($this->iconFactory->getIcon('actions-page-open', IconSize::SMALL));
1013 
1014  return $button;
1015  }
1016 
1017  protected function ‪createControlEditMetaData(‪ResourceView $resourceView): ?‪ButtonInterface
1018  {
1019  if (!$resourceView->‪getMetaDataUid() || !$this->getBackendUser()->checkLanguageAccess(0)) {
1020  return null;
1021  }
1022 
1023  $button = GeneralUtility::makeInstance(LinkButton::class);
1024  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editMetadata'));
1025  $button->setHref($resourceView->editDataUri);
1026  $button->setIcon($this->iconFactory->getIcon('actions-open', IconSize::SMALL));
1027 
1028  return $button;
1029  }
1030 
1031  protected function ‪createControlView(‪ResourceView $resourceView): ?‪ButtonInterface
1032  {
1033  if (!$resourceView->‪getPublicUrl()) {
1034  return null;
1035  }
1036 
1037  $button = GeneralUtility::makeInstance(GenericButton::class);
1038  $button->setTag('a');
1039  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.view'));
1040  $button->setHref($resourceView->‪getPublicUrl());
1041  $button->setAttributes(['target' => '_blank']);
1042  $button->setIcon($this->iconFactory->getIcon('actions-document-view', IconSize::SMALL));
1043 
1044  return $button;
1045  }
1046 
1047  protected function ‪createControlReplace(‪ResourceView $resourceView): ?‪ButtonInterface
1048  {
1049  if (!$resourceView->replaceUri) {
1050  return null;
1051  }
1052 
1053  $button = GeneralUtility::makeInstance(LinkButton::class);
1054  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace'));
1055  $button->setHref($resourceView->replaceUri);
1056  $button->setIcon($this->iconFactory->getIcon('actions-edit-replace', IconSize::SMALL));
1057 
1058  return $button;
1059  }
1060 
1061  protected function ‪createControlRename(‪ResourceView $resourceView): ?‪ButtonInterface
1062  {
1063  if (!$resourceView->‪canRename()) {
1064  return null;
1065  }
1066 
1067  $button = GeneralUtility::makeInstance(GenericButton::class);
1068  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename'));
1069  $button->setAttributes(['type' => 'button', 'data-filelist-action' => 'rename']);
1070  $button->setIcon($this->iconFactory->getIcon('actions-edit-rename', IconSize::SMALL));
1071 
1072  return $button;
1073  }
1074 
1075  protected function ‪createControlDownload(‪ResourceView $resourceView): ?‪ButtonInterface
1076  {
1077  if (!$resourceView->‪canRead() || !(bool)($this->getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.']['enabled'] ?? true)) {
1078  return null;
1079  }
1080 
1081  if (!$resourceView->isDownloadable) {
1082  return null;
1083  }
1084 
1085  $button = GeneralUtility::makeInstance(GenericButton::class);
1086  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:download'));
1087  $button->setAttributes([
1088  'type' => 'button',
1089  'data-filelist-action' => 'download',
1090  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_download'),
1091  ]);
1092  $button->setIcon($this->iconFactory->getIcon('actions-download', IconSize::SMALL));
1093 
1094  return $button;
1095  }
1096 
1097  protected function ‪createControlUpload(‪ResourceView $resourceView): ?‪ButtonInterface
1098  {
1099  if (!$resourceView->resource->getStorage()->checkUserActionPermission('add', 'File')
1100  || !$resourceView->resource instanceof ‪Folder
1101  || !$resourceView->‪canWrite()) {
1102  return null;
1103  }
1104 
1105  $button = GeneralUtility::makeInstance(LinkButton::class);
1106  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'));
1107  $button->setHref($this->uriBuilder->buildUriFromRoute('file_upload', ['target' => $resourceView->‪getIdentifier(), 'returnUrl' => $this->createModuleUri()]));
1108  $button->setIcon($this->iconFactory->getIcon('actions-edit-upload', IconSize::SMALL));
1109 
1110  return $button;
1111  }
1112 
1113  protected function ‪createControlInfo(‪ResourceView $resourceView): ?‪ButtonInterface
1114  {
1115  if (!$resourceView->‪canRead()) {
1116  return null;
1117  }
1118 
1119  $button = GeneralUtility::makeInstance(GenericButton::class);
1120  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info'));
1121  $button->setAttributes([
1122  'type' => 'button',
1123  'data-filelist-action' => 'show',
1124  ]);
1125  $button->setIcon($this->iconFactory->getIcon('actions-document-info', IconSize::SMALL));
1126 
1127  return $button;
1128  }
1129 
1130  protected function ‪createControlDelete(‪ResourceView $resourceView): ?‪ButtonInterface
1131  {
1132  if (!$resourceView->‪canDelete()) {
1133  return null;
1134  }
1135  $recordInfo = $resourceView->‪getName();
1136  $referenceCountText = '';
1137  if ($resourceView->resource instanceof Folder) {
1138  ‪$identifier = $resourceView->‪getIdentifier();
1139  $deleteType = 'delete_folder';
1140  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1141  $recordInfo .= ' [' . ‪$identifier . ']';
1142  }
1143  } else {
1144  $referenceCountText = BackendUtility::referenceCount('sys_file', (int)$resourceView->‪getUid(), LF . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToFile'));
1145  $deleteType = 'delete_file';
1146  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1147  $recordInfo .= ' [sys_file:' . $resourceView->‪getUid() . ']';
1148  }
1149  }
1150 
1151  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete');
1152  $button = GeneralUtility::makeInstance(GenericButton::class);
1153  $button->setLabel($title);
1154  $button->setIcon($this->iconFactory->getIcon('actions-edit-delete', IconSize::SMALL));
1155  $button->setAttributes([
1156  'type' => 'button',
1157  'data-title' => $title,
1158  'data-bs-content' => sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete'), trim($recordInfo)) . $referenceCountText,
1159  'data-filelist-action' => 'delete',
1160  'data-filelist-delete' => 'true',
1161  'data-filelist-delete-identifier' => $resourceView->‪getIdentifier(),
1162  'data-filelist-delete-url' => $this->uriBuilder->buildUriFromRoute('tce_file'),
1163  'data-filelist-delete-type' => $deleteType,
1164  'data-filelist-delete-check' => $this->getBackendUser()->jsConfirmation(‪JsConfirmation::DELETE) ? '1' : '0',
1165  ]);
1166 
1167  return $button;
1168  }
1169 
1176  protected function ‪createControlTranslation(ResourceView $resourceView): ?ButtonInterface
1177  {
1178  if (!$resourceView->resource instanceof File) {
1179  return null;
1180  }
1181 
1182  $backendUser = $this->‪getBackendUser();
1183 
1184  // Fetch all system languages except "default (0)" and "all languages (-1)"
1185  $systemLanguages = array_filter(
1186  $this->translateTools->getSystemLanguages(),
1187  static fn(array $languageRecord): bool => $languageRecord['uid'] > 0 && $backendUser->checkLanguageAccess($languageRecord['uid'])
1188  );
1189 
1190  if ($systemLanguages === []
1191  || !(‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? false)
1192  || !$resourceView->resource->isIndexed()
1193  || !$resourceView->resource->checkActionPermission('editMeta')
1194  || !$backendUser->check('tables_modify', 'sys_file_metadata')
1195  ) {
1196  // Early return in case no system languages exists or metadata
1197  // of this file can not be created / edited by the current user.
1198  return null;
1199  }
1200 
1201  $dropdownItems = [];
1202  $metaDataRecord = $resourceView->resource->getMetaData()->get();
1203  $existingTranslations = $this->getTranslationsForMetaData($metaDataRecord);
1204 
1205  foreach ($systemLanguages as $languageId => $language) {
1206  if (!isset($existingTranslations[$languageId]) && !($metaDataRecord['uid'] ?? false)) {
1207  // Skip if neither a translation nor the metadata uid exists
1208  continue;
1209  }
1210 
1211  if (isset($existingTranslations[$languageId])) {
1212  // Set options for edit action of an existing translation
1213  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:editMetadataForLanguage'), $language['title']);
1214  $actionType = 'edit';
1215  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1216  'record_edit',
1217  [
1218  'edit' => [
1219  'sys_file_metadata' => [
1220  $existingTranslations[$languageId]['uid'] => 'edit',
1221  ],
1222  ],
1223  'returnUrl' => $this->createModuleUri(),
1224  ]
1225  );
1226  } else {
1227  // Set options for "create new" action of a new translation
1228  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:createMetadataForLanguage'), $language['title']);
1229  $actionType = 'new';
1230  $metaDataRecordId = (int)($metaDataRecord['uid'] ?? 0);
1231  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1232  'tce_db',
1233  [
1234  'cmd' => [
1235  'sys_file_metadata' => [
1236  $metaDataRecordId => [
1237  'localize' => $languageId,
1238  ],
1239  ],
1240  ],
1241  'redirect' => (string)$this->uriBuilder->buildUriFromRoute(
1242  'record_edit',
1243  [
1244  'justLocalized' => 'sys_file_metadata:' . $metaDataRecordId . ':' . $languageId,
1245  'returnUrl' => $this->‪createModuleUri(),
1246  ]
1247  ),
1248  ]
1249  );
1250  }
1251 
1252  $dropdownItem = GeneralUtility::makeInstance(DropDownItem::class);
1253  $dropdownItem->setLabel($title);
1254  $dropdownItem->setHref(‪$url);
1255  $dropdownItem->setIcon($this->iconFactory->getIcon($language['flagIcon'], IconSize::SMALL, 'overlay-' . $actionType));
1256  $dropdownItems[] = $dropdownItem;
1257  }
1258 
1259  if (empty($dropdownItems)) {
1260  return null;
1261  }
1262 
1263  $dropdownButton = GeneralUtility::makeInstance(DropDownButton::class);
1264  $dropdownButton->setLabel($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:translations'));
1265  $dropdownButton->setIcon($this->iconFactory->getIcon('actions-translate', IconSize::SMALL));
1266  foreach ($dropdownItems as $dropdownItem) {
1267  $dropdownButton->addItem($dropdownItem);
1268  }
1269 
1270  return $dropdownButton;
1271  }
1272 
1273  protected function ‪createControlCopy(‪ResourceView $resourceView): ?‪ButtonInterface
1274  {
1275  if (!$resourceView->‪canRead() || !$resourceView->‪canCopy()) {
1276  return null;
1277  }
1278 
1279  if ($this->clipObj->current === 'normal') {
1280  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1281  $button = GeneralUtility::makeInstance(LinkButton::class);
1282  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'copy' ? 'copyrelease' : 'copy')));
1283  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), true, $isSelected === 'copy'));
1284  $button->setIcon($this->iconFactory->getIcon($isSelected === 'copy' ? 'actions-edit-copy-release' : 'actions-edit-copy', IconSize::SMALL));
1285  return $button;
1286  }
1287 
1288  return null;
1289  }
1290 
1291  protected function ‪createControlCut(‪ResourceView $resourceView): ?‪ButtonInterface
1292  {
1293  if (!$resourceView->‪canRead() || !$resourceView->‪canMove()) {
1294  return null;
1295  }
1296 
1297  if ($this->clipObj->current === 'normal') {
1298  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1299  $button = GeneralUtility::makeInstance(LinkButton::class);
1300  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'cut' ? 'cutrelease' : 'cut')));
1301  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), false, $isSelected === 'cut'));
1302  $button->setIcon($this->iconFactory->getIcon($isSelected === 'cut' ? 'actions-edit-cut-release' : 'actions-edit-cut', IconSize::SMALL));
1303 
1304  return $button;
1305  }
1306 
1307  return null;
1308  }
1309 
1310  protected function ‪createControlPaste(‪ResourceView $resourceView): ?‪ButtonInterface
1311  {
1312  $permission = ($this->clipObj->clipData[$this->clipObj->current]['mode'] ?? '') === 'copy' ? 'copy' : 'move';
1313  $addPasteButton = $this->folderObject->checkActionPermission($permission);
1314  $elementFromTable = $this->clipObj->elFromTable('_FILE');
1315  if ($elementFromTable === []
1316  || !$addPasteButton
1317  || !$resourceView->‪canRead()
1318  || !$resourceView->‪canWrite()
1319  || !$resourceView->resource instanceof ‪Folder) {
1320  return null;
1321  }
1322 
1323  $elementsToConfirm = [];
1324  foreach ($elementFromTable as $key => $element) {
1325  $clipBoardElement = $this->resourceFactory->retrieveFileOrFolderObject($element);
1326  if ($clipBoardElement instanceof Folder
1327  && $clipBoardElement->getStorage()->isWithinFolder($clipBoardElement, $resourceView->resource)
1328  ) {
1329  // In case folder is already present in the target folder, return actions without paste button
1330  return null;
1331  }
1332  $elementsToConfirm[$key] = $clipBoardElement->getName();
1333  }
1334 
1335  $pasteTitle = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_pasteInto');
1336  $button = GeneralUtility::makeInstance(LinkButton::class);
1337  $button->setTitle($pasteTitle);
1338  $button->setHref($this->clipObj->pasteUrl('_FILE', $resourceView->‪getIdentifier()));
1339  $button->setDataAttributes([
1340  'title' => $pasteTitle,
1341  'bs-content' => $this->clipObj->confirmMsgText('_FILE', $resourceView->‪getName(), 'into', $elementsToConfirm),
1342  ]);
1343  $button->setIcon($this->iconFactory->getIcon('actions-document-paste-into', IconSize::SMALL));
1344 
1345  return $button;
1346  }
1347 
1348  protected function ‪createControlUpdateOnlineMedia(‪ResourceView $resourceView): ?‪ButtonInterface
1349  {
1350  if (!($resourceView->resource instanceof ‪File)
1351  || !$resourceView->‪canEditMetadata()
1352  || !$this->getBackendUser()->checkLanguageAccess(0)
1353  || !$this->onlineMediaHelperRegistry->hasOnlineMediaHelper($resourceView->resource->getExtension())
1354  ) {
1355  return null;
1356  }
1357 
1358  $title = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:reloadMetadata');
1359  $button = GeneralUtility::makeInstance(GenericButton::class);
1360  $button->setLabel($title);
1361  $button->setIcon($this->iconFactory->getIcon('actions-refresh', IconSize::SMALL));
1362  $button->setAttributes([
1363  'type' => 'button',
1364  'data-title' => $title,
1365  'data-filelist-action' => 'updateOnlineMedia',
1366  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_update_online_media'),
1367  ]);
1368 
1369  return $button;
1370  }
1371 
1372  protected function ‪isEditMetadataAllowed(‪File $file): bool
1373  {
1374  return $file->‪isIndexed()
1375  && $file->‪checkActionPermission('editMeta')
1376  && $this->‪getUserPermissions()->editMetaData;
1377  }
1378 
1384  protected function ‪renderCheckboxActions(): string
1385  {
1386  // Early return in case there are no items
1387  if (!$this->totalItems) {
1388  return '';
1389  }
1390 
1391  $lang = $this->‪getLanguageService();
1392 
1393  $dropdownItems['checkAll'] = '
1394  <li>
1395  <button type="button" class="dropdown-item disabled" data-multi-record-selection-check-action="check-all" title="' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll')) . '">
1396  <span class="dropdown-item-columns">
1397  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1398  ' . $this->iconFactory->getIcon('actions-selection-elements-all', IconSize::SMALL)->render() . '
1399  </span>
1400  <span class="dropdown-item-column dropdown-item-column-title">
1401  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll')) . '
1402  </span>
1403  </span>
1404  </button>
1405  </li>';
1406 
1407  $dropdownItems['checkNone'] = '
1408  <li>
1409  <button type="button" class="dropdown-item disabled" data-multi-record-selection-check-action="check-none" title="' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll')) . '">
1410  <span class="dropdown-item-columns">
1411  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1412  ' . $this->iconFactory->getIcon('actions-selection-elements-none', IconSize::SMALL)->render() . '
1413  </span>
1414  <span class="dropdown-item-column dropdown-item-column-title">
1415  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll')) . '
1416  </span>
1417  </span>
1418  </button>
1419  </li>';
1420 
1421  $dropdownItems['toggleSelection'] = '
1422  <li>
1423  <button type="button" class="dropdown-item" data-multi-record-selection-check-action="toggle" title="' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection')) . '">
1424  <span class="dropdown-item-columns">
1425  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1426  ' . $this->iconFactory->getIcon('actions-selection-elements-invert', IconSize::SMALL)->render() . '
1427  </span>
1428  <span class="dropdown-item-column dropdown-item-column-title">
1429  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection')) . '
1430  </span>
1431  </span>
1432  </button>
1433  </li>';
1434 
1435  return '
1436  <div class="btn-group dropdown">
1437  <button type="button" class="dropdown-toggle dropdown-toggle-link t3js-multi-record-selection-check-actions-toggle" data-bs-toggle="dropdown" data-bs-boundary="window" aria-expanded="false" aria-label="' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.openSelectionOptions')) . '">
1438  ' . $this->iconFactory->getIcon('actions-selection', IconSize::SMALL) . '
1439  </button>
1440  <ul class="dropdown-menu t3js-multi-record-selection-check-actions">
1441  ' . implode(PHP_EOL, $dropdownItems) . '
1442  </ul>
1443  </div>';
1444  }
1445 
1450  protected function ‪getConcreteTableName(string $fieldName): string
1451  {
1452  return (‪$GLOBALS['TCA']['sys_file']['columns'][$fieldName] ?? false) ? 'sys_file' : 'sys_file_metadata';
1453  }
1454 
1456  {
1457  $currentPagination = new ‪SimplePagination($paginator);
1458  $targetPage = null;
1459  switch ($direction) {
1461  $targetPage = $currentPagination->getPreviousPageNumber();
1462  break;
1463  case NavigationDirection::FORWARD:
1464  $targetPage = $currentPagination->getNextPageNumber();
1465  break;
1466  }
1467 
1468  return $this->‪getPaginationLinkForPage($paginator, $targetPage);
1469  }
1470 
1471  protected function ‪getPaginationLinkForPage(‪ResourceCollectionPaginator $paginator, ?int $targetPage = null): ?‪PaginationLink
1472  {
1473  if ($targetPage === null) {
1474  return null;
1475  }
1476  if ($targetPage > $paginator->‪getNumberOfPages()) {
1477  return null;
1478  }
1479  if ($targetPage < 1) {
1480  return null;
1481  }
1482 
1483  $targetPaginator = $paginator->‪withCurrentPageNumber($targetPage);
1484  $targetPagination = new SimplePagination($targetPaginator);
1485 
1486  $uri = new Uri($this->request->getAttribute('normalizedParams')->getRequestUri());
1487  parse_str($uri->getQuery(), $queryParameters);
1488  unset($queryParameters['contentOnly']);
1489  $queryParameters = array_merge($queryParameters, ['currentPage' => $targetPage]);
1490  if ($this->searchDemand) {
1491  $queryParameters['searchTerm'] = $this->searchDemand->getSearchTerm() ?? '';
1492  }
1493  $uri = $uri->withQuery(‪HttpUtility::buildQueryString($queryParameters, '&'));
1494 
1495  return new PaginationLink(
1496  $targetPagination->getStartRecordNumber() . '-' . $targetPagination->getEndRecordNumber(),
1497  (string)$uri,
1498  );
1499  }
1500 
1504  public function ‪createModuleUri(array $params = []): ?string
1505  {
1507  $queryParams = ‪$request->getQueryParams();
1508  $parsedBody = ‪$request->getParsedBody();
1509 
1510  $route = ‪$request->getAttribute('route');
1511  if (!$route instanceof Route) {
1512  return null;
1513  }
1514 
1515  $baseParams = [
1516  'currentPage' => ‪$this->currentPage,
1517  'id' => $this->folderObject->getCombinedIdentifier(),
1518  'searchTerm' => $this->searchDemand ? $this->searchDemand->getSearchTerm() : '',
1519  ];
1520 
1521  // Keep ElementBrowser Settings
1522  if (‪$mode = $parsedBody['mode'] ?? $queryParams['mode'] ?? null) {
1523  $baseParams['mode'] = ‪$mode;
1524  }
1525  if ($bparams = $parsedBody['bparams'] ?? $queryParams['bparams'] ?? null) {
1526  $baseParams['bparams'] = $bparams;
1527  }
1528 
1529  // Keep LinkHandler Settings
1530  if ($act = ($parsedBody['act'] ?? $queryParams['act'] ?? null)) {
1531  $baseParams['act'] = $act;
1532  }
1533  if ($linkHandlerParams = ($parsedBody['P'] ?? $queryParams['P'] ?? null)) {
1534  $baseParams['P'] = $linkHandlerParams;
1535  }
1536 
1537  $params = array_replace_recursive($baseParams, $params);
1538 
1539  // Expanded folder is used in the element browser.
1540  // We always map it to the id here.
1541  $params['expandFolder'] = $params['id'];
1542  $params = array_filter($params, static function ($value) {
1543  return (is_array($value) && $value !== []) || (trim((string)$value) !== '');
1544  });
1545 
1546  return (string)$this->uriBuilder->buildUriFromRequest(‪$request, $params);
1547  }
1548 
1549  protected function ‪createEditDataUriForResource(‪ResourceInterface $resource): ?string
1550  {
1551  if ($resource instanceof ‪File
1552  && $this->‪isEditMetadataAllowed($resource)
1553  && ($metaDataUid = $resource->getMetaData()->offsetGet('uid'))
1554  ) {
1555  $parameter = [
1556  'edit' => ['sys_file_metadata' => [$metaDataUid => 'edit']],
1557  'returnUrl' => $this->‪createModuleUri(),
1558  ];
1559  return (string)$this->uriBuilder->buildUriFromRoute('record_edit', $parameter);
1560  }
1561 
1562  return null;
1563  }
1564 
1565  protected function ‪createEditContentUriForResource(‪ResourceInterface $resource): ?string
1566  {
1567  if ($resource instanceof ‪File
1568  && $resource->checkActionPermission('write')
1569  && $resource->isTextFile()
1570  ) {
1571  $parameter = [
1572  'target' => $resource->getCombinedIdentifier(),
1573  'returnUrl' => $this->‪createModuleUri(),
1574  ];
1575  return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $parameter);
1576  }
1577 
1578  return null;
1579  }
1580 
1581  protected function ‪createModuleUriForResource(‪ResourceInterface $resource): ?string
1582  {
1583  if ($resource instanceof ‪Folder) {
1584  $parameter = [
1585  'id' => $resource->getCombinedIdentifier(),
1586  'searchTerm' => '',
1587  'currentPage' => 1,
1588  ];
1589  return (string)$this->‪createModuleUri($parameter);
1590  }
1591 
1592  if ($resource instanceof File) {
1593  return $this->‪createEditDataUriForResource($resource);
1594  }
1595 
1596  return null;
1597  }
1598 
1599  protected function ‪createReplaceUriForResource(‪ResourceInterface $resource): ?string
1600  {
1601  if ($resource instanceof ‪File
1602  && $resource->checkActionPermission('replace')
1603  ) {
1604  $parameter = [
1605  'target' => $resource->getCombinedIdentifier(),
1606  'uid' => $resource->getUid(),
1607  'returnUrl' => $this->‪createModuleUri(),
1608  ];
1609  return (string)$this->uriBuilder->buildUriFromRoute('file_replace', $parameter);
1610  }
1611  return null;
1612  }
1613 
1617  protected function ‪sortResources(array $resources, string $sortField): array
1618  {
1619  $collator = new \Collator((string)($this->‪getLanguageService()->getLocale() ?? 'en'));
1620  if ($sortField === 'size') {
1621  $collator->setAttribute(\Collator::NUMERIC_COLLATION, \Collator::ON);
1622  }
1623  uksort($resources, function (int $index1, int $index2) use ($sortField, $resources, $collator) {
1624  $resource1 = $resources[$index1];
1625  $resource2 = $resources[$index2];
1626 
1627  // Folders are always prioritized above files
1628  if ($resource1 instanceof File && $resource2 instanceof Folder) {
1629  return 1;
1630  }
1631  if ($resource1 instanceof Folder && $resource2 instanceof File) {
1632  return -1;
1633  }
1634 
1635  return (int)$collator->compare(
1636  $this->getSortingValue($resource1, $sortField) . $index1,
1637  $this->getSortingValue($resource2, $sortField) . $index2
1638  );
1639  });
1640 
1641  if ($this->sortRev) {
1642  $resources = array_reverse($resources);
1643  }
1644 
1645  return $resources;
1646  }
1647 
1648  protected function ‪getSortingValue(‪ResourceInterface $resource, string $sortField): string
1649  {
1650  if ($resource instanceof ‪File) {
1651  return $this->‪getSortingValueForFile($resource, $sortField);
1652  }
1653  if ($resource instanceof Folder) {
1654  return $this->‪getSortingValueForFolder($resource, $sortField);
1655  }
1656 
1657  return '';
1658  }
1659 
1660  protected function ‪getSortingValueForFile(‪File $resource, string $sortField): string
1661  {
1662  switch ($sortField) {
1663  case 'fileext':
1664  return $resource->‪getExtension();
1665  case 'size':
1666  return $resource->getSize() . 's';
1667  case 'rw':
1668  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1669  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1670  case '_REF_':
1671  return $this->‪getFileReferenceCount($resource) . 'ref';
1672  case 'tstamp':
1673  return $resource->‪getModificationTime() . 't';
1674  case 'crdate':
1675  return $resource->‪getCreationTime() . 'c';
1676  default:
1677  return $resource->‪hasProperty($sortField) ? (string)$resource->‪getProperty($sortField) : '';
1678  }
1679  }
1680 
1681  protected function ‪getSortingValueForFolder(‪Folder $resource, string $sortField): string
1682  {
1683  switch ($sortField) {
1684  case 'size':
1685  try {
1686  $fileCount = $resource->‪getFileCount();
1688  $fileCount = 0;
1689  }
1690  return '0' . $fileCount . 's';
1691  case 'rw':
1692  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1693  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1694  case 'name':
1695  return $resource->‪getName();
1696  case 'tstamp':
1697  return $resource->‪getModificationTime() . 't';
1698  case 'crdate':
1699  return $resource->‪getCreationTime() . 'c';
1700  default:
1701  return '';
1702  }
1703  }
1704 
1705  protected function ‪getFieldLabel(string $field): string
1706  {
1707  $lang = $this->‪getLanguageService();
1708 
1709  if ($specialLabel = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $field)) {
1710  return $specialLabel;
1711  }
1712  if ($customLabel = $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_' . $field)) {
1713  return $customLabel;
1714  }
1715 
1716  $concreteTableName = $this->‪getConcreteTableName($field);
1717  $label = BackendUtility::getItemLabel($concreteTableName, $field);
1718 
1719  // In case global TSconfig exists we have to check if the label is overridden there
1720  $tsConfig = BackendUtility::getPagesTSconfig(0);
1721  $label = $lang->translateLabel(
1722  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label.'] ?? [],
1723  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label'] ?? $label
1724  );
1725 
1726  return $label;
1727  }
1728 
1734  protected function ‪getFileReferenceCount(File $file): int
1735  {
1736  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
1737  return (int)$queryBuilder
1738  ->count('*')
1739  ->from('sys_refindex')
1740  ->where(
1741  $queryBuilder->expr()->eq(
1742  'ref_table',
1743  $queryBuilder->createNamedParameter('sys_file')
1744  ),
1745  $queryBuilder->expr()->eq(
1746  'ref_uid',
1747  $queryBuilder->createNamedParameter($file->getUid(), ‪Connection::PARAM_INT)
1748  ),
1749  $queryBuilder->expr()->neq(
1750  'tablename',
1751  $queryBuilder->createNamedParameter('sys_file_metadata')
1752  )
1753  )
1754  ->executeQuery()
1755  ->fetchOne();
1756  }
1757 
1758  protected function ‪getUserPermissions(): ‪UserPermissions
1759  {
1760  return new ‪UserPermissions($this->‪getBackendUser()->check('tables_modify', 'sys_file_metadata'));
1761  }
1762 
1763  protected function ‪getLanguageService(): ‪LanguageService
1764  {
1765  return ‪$GLOBALS['LANG'];
1766  }
1767 
1768  protected function ‪getBackendUser(): ‪BackendUserAuthentication
1769  {
1770  return ‪$GLOBALS['BE_USER'];
1771  }
1772 }
‪TYPO3\CMS\Filelist\FileList\$addElement_tdCssClass
‪array $addElement_tdCssClass
Definition: FileList.php:128
‪TYPO3\CMS\Filelist\Dto\UserPermissions
Definition: UserPermissions.php:24
‪TYPO3\CMS\Filelist\FileList\setMode
‪setMode(Mode $mode)
Definition: FileList.php:246
‪TYPO3\CMS\Core\View\ViewInterface\render
‪render(string $templateFileName='')
‪TYPO3\CMS\Core\Resource\Folder\getModificationTime
‪getModificationTime()
Definition: Folder.php:561
‪TYPO3\CMS\Filelist\FileList\renderControl
‪renderControl(ResourceView $resourceView)
Definition: FileList.php:853
‪TYPO3\CMS\Filelist\Matcher\ResourceFolderTypeMatcher
Definition: ResourceFolderTypeMatcher.php:27
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:55
‪TYPO3\CMS\Filelist\Pagination\ResourceCollectionPaginator
Definition: ResourceCollectionPaginator.php:27
‪TYPO3\CMS\Filelist\FileList\createControlTranslation
‪createControlTranslation(ResourceView $resourceView)
Definition: FileList.php:1174
‪TYPO3\CMS\Filelist\FileList\$onlineMediaHelperRegistry
‪OnlineMediaHelperRegistry $onlineMediaHelperRegistry
Definition: FileList.php:159
‪TYPO3\CMS\Filelist\FileList\getBackendUser
‪getBackendUser()
Definition: FileList.php:1766
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Filelist\FileList\createEditContentUriForResource
‪createEditContentUriForResource(ResourceInterface $resource)
Definition: FileList.php:1563
‪TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry
Definition: OnlineMediaHelperRegistry.php:27
‪TYPO3\CMS\Filelist\Matcher\ResourceFileExtensionMatcher
Definition: ResourceFileExtensionMatcher.php:26
‪TYPO3\CMS\Core\Resource\Folder\getCreationTime
‪getCreationTime()
Definition: Folder.php:569
‪TYPO3\CMS\Core\Utility\PathUtility\isAbsolutePath
‪static isAbsolutePath(string $path)
Definition: PathUtility.php:287
‪TYPO3\CMS\Filelist\Type\BACKWARD
‪@ BACKWARD
Definition: NavigationDirection.php:26
‪TYPO3\CMS\Core\View\ViewInterface
Definition: ViewInterface.php:24
‪TYPO3\CMS\Filelist\FileList\setColumnsToRender
‪setColumnsToRender(array $additionalFields=[])
Definition: FileList.php:252
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:23
‪TYPO3\CMS\Filelist\FileList\$translateTools
‪TranslationConfigurationProvider $translateTools
Definition: FileList.php:158
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Filelist\FileList\createControlCopy
‪createControlCopy(ResourceView $resourceView)
Definition: FileList.php:1271
‪TYPO3\CMS\Backend\Template\Components\Buttons\GenericButton
Definition: GenericButton.php:34
‪TYPO3\CMS\Filelist\FileList\getFolderInfo
‪getFolderInfo()
Definition: FileList.php:411
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDownButton
Definition: DropDownButton.php:48
‪TYPO3\CMS\Filelist\FileList\$searchDemand
‪FileSearchDemand $searchDemand
Definition: FileList.php:152
‪TYPO3\CMS\Filelist\FileList\createControlUpload
‪createControlUpload(ResourceView $resourceView)
Definition: FileList.php:1095
‪TYPO3\CMS\Core\Resource\FolderInterface\ROLE_DEFAULT
‪const ROLE_DEFAULT
Definition: FolderInterface.php:28
‪TYPO3\CMS\Filelist\Dto\ResourceView\isMissing
‪isMissing()
Definition: ResourceView.php:207
‪TYPO3\CMS\Filelist\Dto\ResourceView\getType
‪getType()
Definition: ResourceView.php:73
‪TYPO3\CMS\Filelist\FileList\renderType
‪renderType(ResourceView $resourceView)
Definition: FileList.php:685
‪TYPO3\CMS\Filelist\FileList\$resourceSelectableMatcher
‪Matcher $resourceSelectableMatcher
Definition: FileList.php:148
‪TYPO3\CMS\Filelist\FileList\$request
‪ServerRequestInterface $request
Definition: FileList.php:154
‪TYPO3\CMS\Filelist\FileList\$maxTitleLength
‪int $maxTitleLength
Definition: FileList.php:116
‪TYPO3\CMS\Core\Resource\File\isIndexed
‪isIndexed()
Definition: File.php:139
‪TYPO3\CMS\Filelist\FileList\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: FileList.php:153
‪TYPO3\CMS\Filelist\Dto\ResourceView\getPublicUrl
‪getPublicUrl()
Definition: ResourceView.php:107
‪TYPO3\CMS\Filelist\FileList\renderTiles
‪renderTiles(ResourceCollectionPaginator $paginator, array $resourceViews, ViewInterface $view)
Definition: FileList.php:260
‪TYPO3\CMS\Filelist\Dto\ResourceView\getUpdatedAt
‪getUpdatedAt()
Definition: ResourceView.php:180
‪TYPO3\CMS\Filelist\FileList\$resourceFactory
‪ResourceFactory $resourceFactory
Definition: FileList.php:156
‪TYPO3\CMS\Core\Resource\Folder\getFileCount
‪int getFileCount(array $filterMethods=[], $recursive=false)
Definition: Folder.php:242
‪TYPO3\CMS\Filelist\FileList\renderSize
‪renderSize(ResourceView $resourceView)
Definition: FileList.php:731
‪TYPO3\CMS\Filelist\FileList\createControlUpdateOnlineMedia
‪createControlUpdateOnlineMedia(ResourceView $resourceView)
Definition: FileList.php:1346
‪TYPO3\CMS\Filelist\FileList\getConcreteTableName
‪getConcreteTableName(string $fieldName)
Definition: FileList.php:1448
‪TYPO3\CMS\Filelist\Matcher\Matcher
Definition: Matcher.php:24
‪TYPO3\CMS\Filelist\FileList\renderListTableForwardBackwardNavigation
‪renderListTableForwardBackwardNavigation(ResourceCollectionPaginator $paginator, NavigationDirection $direction)
Definition: FileList.php:547
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪getExtension()
Definition: AbstractFile.php:243
‪TYPO3\CMS\Filelist\FileList\$viewMode
‪ViewMode $viewMode
Definition: FileList.php:76
‪TYPO3\CMS\Core\Authentication\JsConfirmation
Definition: JsConfirmation.php:28
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:35
‪TYPO3\CMS\Filelist\Type\NavigationDirection
‪NavigationDirection
Definition: NavigationDirection.php:24
‪TYPO3\CMS\Filelist\FileList\$clipObj
‪Clipboard $clipObj
Definition: FileList.php:141
‪TYPO3\CMS\Filelist\FileList\$thumbs
‪bool $thumbs
Definition: FileList.php:111
‪TYPO3\CMS\Core\Pagination\AbstractPaginator\getNumberOfPages
‪getNumberOfPages()
Definition: AbstractPaginator.php:68
‪TYPO3\CMS\Filelist\FileList\renderModificationTime
‪renderModificationTime(ResourceView $resourceView)
Definition: FileList.php:715
‪TYPO3\CMS\Filelist\Dto\ResourceView\getCheckboxConfig
‪getCheckboxConfig()
Definition: ResourceView.php:192
‪TYPO3\CMS\Filelist\FileList\renderReferenceCount
‪renderReferenceCount(ResourceView $resourceView)
Definition: FileList.php:829
‪TYPO3\CMS\Backend\Routing\Route
Definition: Route.php:24
‪TYPO3\CMS\Filelist\FileList\renderList
‪renderList(ResourceCollectionPaginator $paginator, array $resourceViews, ViewInterface $view)
Definition: FileList.php:277
‪TYPO3\CMS\Filelist\FileList\getUserPermissions
‪getUserPermissions()
Definition: FileList.php:1756
‪TYPO3\CMS\Filelist\Type\fieldArray
‪@ fieldArray
Definition: Mode.php:28
‪TYPO3\CMS\Core\View\ViewInterface\assign
‪assign(string $key, mixed $value)
‪TYPO3\CMS\Filelist\Event\ProcessFileListActionsEvent
Definition: ProcessFileListActionsEvent.php:27
‪TYPO3\CMS\Filelist\FileList\createModuleUriForResource
‪createModuleUriForResource(ResourceInterface $resource)
Definition: FileList.php:1579
‪TYPO3\CMS\Core\Pagination\SimplePagination
Definition: SimplePagination.php:21
‪TYPO3\CMS\Filelist\FileList\$sortRev
‪bool $sortRev
Definition: FileList.php:106
‪TYPO3\CMS\Filelist
‪TYPO3\CMS\Filelist\FileList\createControlDownload
‪createControlDownload(ResourceView $resourceView)
Definition: FileList.php:1073
‪TYPO3\CMS\Filelist\FileList\getSortingValueForFolder
‪getSortingValueForFolder(Folder $resource, string $sortField)
Definition: FileList.php:1679
‪TYPO3\CMS\Filelist\FileList\$resourceSelectedMatcher
‪Matcher $resourceSelectedMatcher
Definition: FileList.php:150
‪TYPO3\CMS\Filelist\Dto\ResourceView\canDelete
‪canDelete()
Definition: ResourceView.php:251
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:30
‪TYPO3\CMS\Filelist\FileList\$totalbytes
‪int $totalbytes
Definition: FileList.php:91
‪TYPO3\CMS\Core\Resource\File\getProperty
‪getProperty(string $key)
Definition: File.php:62
‪TYPO3\CMS\Filelist\FileList\$folderObject
‪Folder $folderObject
Definition: FileList.php:137
‪TYPO3\CMS\Backend\ElementBrowser\Event\IsFileSelectableEvent
Definition: IsFileSelectableEvent.php:26
‪TYPO3\CMS\Filelist\FileList\getFileReferenceCount
‪getFileReferenceCount(File $file)
Definition: FileList.php:1732
‪TYPO3\CMS\Filelist\FileList\$mode
‪Mode $mode
Definition: FileList.php:75
‪TYPO3\CMS\Filelist\FileList\renderPath
‪renderPath(ResourceView $resourceView)
Definition: FileList.php:820
‪TYPO3\CMS\Filelist\FileList\$resourceDownloadMatcher
‪Matcher $resourceDownloadMatcher
Definition: FileList.php:144
‪TYPO3\CMS\Core\Pagination\AbstractPaginator\withCurrentPageNumber
‪withCurrentPageNumber(int $currentPageNumber)
Definition: AbstractPaginator.php:55
‪TYPO3\CMS\Filelist\FileList\$translationRecords
‪$translationRecords
Definition: FileList.php:586
‪TYPO3\CMS\Filelist\FileList\render
‪render(?FileSearchDemand $searchDemand, ViewInterface $view)
Definition: FileList.php:287
‪TYPO3\CMS\Filelist\FileList
Definition: FileList.php:74
‪TYPO3\CMS\Filelist\FileList\getSortingValueForFile
‪getSortingValueForFile(File $resource, string $sortField)
Definition: FileList.php:1658
‪TYPO3\CMS\Filelist\FileList\renderThumbnail
‪renderThumbnail(ResourceView $resourceView)
Definition: FileList.php:648
‪TYPO3\CMS\Filelist\Dto\ResourceView
Definition: ResourceView.php:33
‪TYPO3\CMS\Filelist\FileList\createControlInfo
‪createControlInfo(ResourceView $resourceView)
Definition: FileList.php:1111
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand
Definition: FileSearchDemand.php:26
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Filelist\FileList\createControlReplace
‪createControlReplace(ResourceView $resourceView)
Definition: FileList.php:1045
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:124
‪TYPO3\CMS\Filelist\FileList\renderControlBrowse
‪renderControlBrowse(ResourceView $resourceView)
Definition: FileList.php:957
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Filelist\FileList\addElement
‪string addElement(array $data, array $attributes=[], bool $isTableHeader=false)
Definition: FileList.php:380
‪TYPO3\CMS\Filelist\Dto\ResourceView\canRename
‪canRename()
Definition: ResourceView.php:269
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Filelist\FileList\createControlSelect
‪createControlSelect(ResourceView $resourceView)
Definition: FileList.php:978
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪getStorage()
Definition: Folder.php:139
‪TYPO3\CMS\Core\Resource\Folder\checkActionPermission
‪bool checkActionPermission($action)
Definition: Folder.php:442
‪TYPO3\CMS\Filelist\Dto\ResourceView\getName
‪getName()
Definition: ResourceView.php:85
‪TYPO3\CMS\Filelist\FileList\$fieldArray
‪array $fieldArray
Definition: FileList.php:121
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Resource\Folder\getName
‪getName()
Definition: Folder.php:89
‪TYPO3\CMS\Filelist\FileList\renderListTableHeader
‪renderListTableHeader()
Definition: FileList.php:424
‪TYPO3\CMS\Core\Resource\FolderInterface\ROLE_PROCESSING
‪const ROLE_PROCESSING
Definition: FolderInterface.php:30
‪TYPO3\CMS\Filelist\Type\Mode
‪Mode
Definition: Mode.php:24
‪TYPO3\CMS\Core\Resource\Folder\getRole
‪string getRole()
Definition: Folder.php:539
‪TYPO3\CMS\Filelist\Dto\ResourceView\getPreview
‪getPreview()
Definition: ResourceView.php:116
‪TYPO3\CMS\Filelist\FileList\$uriBuilder
‪UriBuilder $uriBuilder
Definition: FileList.php:157
‪TYPO3\CMS\Filelist\Dto\ResourceView\getUid
‪getUid()
Definition: ResourceView.php:49
‪TYPO3\CMS\Filelist\Dto\ResourceView\getIdentifier
‪getIdentifier()
Definition: ResourceView.php:58
‪TYPO3\CMS\Filelist\FileList\start
‪start(Folder $folderObject, int $currentPage, string $sort, bool $sortRev, Mode $mode=Mode::MANAGE)
Definition: FileList.php:233
‪TYPO3\CMS\Filelist\Dto\ResourceView\getMetaDataUid
‪getMetaDataUid()
Definition: ResourceView.php:63
‪TYPO3\CMS\Filelist\Dto\ResourceView\getCreatedAt
‪getCreatedAt()
Definition: ResourceView.php:168
‪TYPO3\CMS\Filelist\FileList\createControlEditContent
‪createControlEditContent(ResourceView $resourceView)
Definition: FileList.php:1000
‪TYPO3\CMS\Filelist\FileList\createControlRename
‪createControlRename(ResourceView $resourceView)
Definition: FileList.php:1059
‪TYPO3\CMS\Filelist\FileList\createControlView
‪createControlView(ResourceView $resourceView)
Definition: FileList.php:1029
‪TYPO3\CMS\Filelist\FileList\getPaginationLinkForDirection
‪getPaginationLinkForDirection(ResourceCollectionPaginator $paginator, NavigationDirection $direction)
Definition: FileList.php:1453
‪TYPO3\CMS\Core\Resource\File\checkActionPermission
‪bool checkActionPermission($action)
Definition: File.php:208
‪TYPO3\CMS\Filelist\FileList\createEditDataUriForResource
‪createEditDataUriForResource(ResourceInterface $resource)
Definition: FileList.php:1547
‪TYPO3\CMS\Core\Resource\AbstractFile\getCreationTime
‪getCreationTime()
Definition: AbstractFile.php:219
‪TYPO3\CMS\Core\Authentication\JsConfirmation\DELETE
‪const DELETE
Definition: JsConfirmation.php:31
‪TYPO3\CMS\Filelist\FileList\$translations
‪foreach($translationRecords as $record) return $translations
Definition: FileList.php:602
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47
‪TYPO3\CMS\Filelist\Dto\ResourceView\canRead
‪canRead()
Definition: ResourceView.php:233
‪TYPO3\CMS\Core\Resource\AbstractFile\getUid
‪return MathUtility::canBeInterpretedAsInteger($size) ?(int) $size int getUid()
Definition: AbstractFile.php:195
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Filelist\FileList\setResourceSelectedMatcher
‪setResourceSelectedMatcher(?Matcher $matcher)
Definition: FileList.php:218
‪TYPO3\CMS\Webhooks\Message\$url
‪identifier readonly UriInterface $url
Definition: LoginErrorOccurredMessage.php:36
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:39
‪TYPO3\CMS\Filelist\FileList\renderField
‪renderField(ResourceView $resourceView, string $field)
Definition: FileList.php:766
‪TYPO3\CMS\Filelist\FileList\createReplaceUriForResource
‪createReplaceUriForResource(ResourceInterface $resource)
Definition: FileList.php:1597
‪TYPO3\CMS\Filelist\FileList\$currentPage
‪int $currentPage
Definition: FileList.php:86
‪TYPO3\CMS\Filelist\FileList\createModuleUri
‪createModuleUri(array $params=[])
Definition: FileList.php:1502
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Filelist\FileList\getPaginationLinkForPage
‪getPaginationLinkForPage(ResourceCollectionPaginator $paginator, ?int $targetPage=null)
Definition: FileList.php:1469
‪TYPO3\CMS\Filelist\FileList\renderListTableBody
‪renderListTableBody(array $resourceViews)
Definition: FileList.php:478
‪TYPO3\CMS\Filelist\FileList\$itemsPerPage
‪int $itemsPerPage
Definition: FileList.php:81
‪TYPO3\CMS\Filelist\FileList\renderPermission
‪renderPermission(ResourceView $resourceView)
Definition: FileList.php:755
‪TYPO3\CMS\Core\Resource\FolderInterface
Definition: FolderInterface.php:24
‪TYPO3\CMS\Filelist\FileList\renderIcon
‪renderIcon(ResourceView $resourceView)
Definition: FileList.php:612
‪TYPO3\CMS\Filelist\Type\TILES
‪@ TILES
Definition: ViewMode.php:26
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Filelist\FileList\getFieldLabel
‪getFieldLabel(string $field)
Definition: FileList.php:1703
‪TYPO3\CMS\Filelist\Dto\ResourceView\canEditMetadata
‪canEditMetadata()
Definition: ResourceView.php:225
‪TYPO3\CMS\Core\Resource\ResourceInterface
Definition: ResourceInterface.php:21
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Filelist\FileList\renderSelector
‪renderSelector(ResourceView $resourceView)
Definition: FileList.php:794
‪TYPO3\CMS\Filelist\FileList\getLanguageService
‪getLanguageService()
Definition: FileList.php:1761
‪TYPO3\CMS\Filelist\Dto\ResourceView\canCopy
‪canCopy()
Definition: ResourceView.php:260
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Filelist\FileList\setResourceDownloadMatcher
‪setResourceDownloadMatcher(?Matcher $matcher)
Definition: FileList.php:200
‪TYPO3\CMS\Filelist\Dto\ResourceView\canMove
‪canMove()
Definition: ResourceView.php:278
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Filelist\FileList\sortResources
‪ResourceInterface[] sortResources(array $resources, string $sortField)
Definition: FileList.php:1615
‪TYPO3\CMS\Filelist\FileList\renderCheckboxActions
‪string renderCheckboxActions()
Definition: FileList.php:1382
‪TYPO3\CMS\Filelist\Dto\ResourceView\canWrite
‪canWrite()
Definition: ResourceView.php:242
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\getSearchTerm
‪getSearchTerm()
Definition: FileSearchDemand.php:75
‪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\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Filelist\Type\ViewMode
‪ViewMode
Definition: ViewMode.php:24
‪TYPO3\CMS\Filelist\FileList\$resourceDisplayMatcher
‪Matcher $resourceDisplayMatcher
Definition: FileList.php:146
‪TYPO3\CMS\Core\Resource\AbstractFile\getModificationTime
‪getModificationTime()
Definition: AbstractFile.php:232
‪TYPO3\CMS\Filelist\FileList\getSortingValue
‪getSortingValue(ResourceInterface $resource, string $sortField)
Definition: FileList.php:1646
‪TYPO3\CMS\Filelist\FileList\__construct
‪__construct(ServerRequestInterface $request)
Definition: FileList.php:161
‪TYPO3\CMS\Filelist\FileList\$sort
‪string $sort
Definition: FileList.php:101
‪TYPO3\CMS\Filelist\Dto\ResourceCollection
Definition: ResourceCollection.php:28
‪TYPO3\CMS\Filelist\Dto\ResourceView\getPath
‪getPath()
Definition: ResourceView.php:94
‪TYPO3\CMS\Filelist\FileList\renderCreationTime
‪renderCreationTime(ResourceView $resourceView)
Definition: FileList.php:699
‪TYPO3\CMS\Filelist\FileList\$totalItems
‪int $totalItems
Definition: FileList.php:96
‪TYPO3\CMS\Filelist\FileList\renderListTableFieldHeader
‪renderListTableFieldHeader(string $field)
Definition: FileList.php:444
‪TYPO3\CMS\Filelist\FileList\setResourceDisplayMatcher
‪setResourceDisplayMatcher(?Matcher $matcher)
Definition: FileList.php:206
‪TYPO3\CMS\Filelist\FileList\$translations
‪$translations
Definition: FileList.php:601
‪TYPO3\CMS\Filelist\FileList\createControlDelete
‪createControlDelete(ResourceView $resourceView)
Definition: FileList.php:1128
‪TYPO3\CMS\Filelist\FileList\renderName
‪renderName(ResourceView $resourceView)
Definition: FileList.php:622
‪TYPO3\CMS\Filelist\FileList\createControlCut
‪createControlCut(ResourceView $resourceView)
Definition: FileList.php:1289
‪TYPO3\CMS\Filelist\FileList\isEditMetadataAllowed
‪isEditMetadataAllowed(File $file)
Definition: FileList.php:1370
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownItem
Definition: DropDownItem.php:34
‪TYPO3\CMS\Filelist\FileList\renderControlManage
‪renderControlManage(ResourceView $resourceView)
Definition: FileList.php:864
‪TYPO3\CMS\Filelist\FileList\createControlEditMetaData
‪createControlEditMetaData(ResourceView $resourceView)
Definition: FileList.php:1015
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Filelist\Dto\ResourceView\getIconSmall
‪getIconSmall()
Definition: ResourceView.php:144
‪TYPO3\CMS\Backend\Template\Components\Buttons\ButtonInterface
Definition: ButtonInterface.php:22
‪TYPO3\CMS\Filelist\FileList\setResourceSelectableMatcher
‪setResourceSelectableMatcher(?Matcher $matcher)
Definition: FileList.php:212
‪TYPO3\CMS\Filelist\FileList\$iconFactory
‪IconFactory $iconFactory
Definition: FileList.php:155
‪TYPO3\CMS\Filelist\FileList\createControlPaste
‪createControlPaste(ResourceView $resourceView)
Definition: FileList.php:1308
‪TYPO3\CMS\Core\Resource\File\hasProperty
‪hasProperty($key)
Definition: File.php:76