‪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;
31 use TYPO3\CMS\Backend\Utility\BackendUtility;
38 use TYPO3\CMS\Core\Imaging\IconSize;
68 
75 {
76  public ‪Mode ‪$mode = Mode::MANAGE;
78 
82  public int ‪$itemsPerPage = 40;
83 
87  public int ‪$currentPage = 1;
88 
92  public int ‪$totalbytes = 0;
93 
97  public int ‪$totalItems = 0;
98 
102  public string ‪$sort = '';
103 
107  public bool ‪$sortRev = true;
108 
112  public bool ‪$thumbs = false;
113 
117  public int ‪$maxTitleLength = 30;
118 
122  public array ‪$fieldArray = [];
123 
129  public array ‪$addElement_tdCssClass = [
130  '_CONTROL_' => 'col-control',
131  '_SELECTOR_' => 'col-checkbox',
132  'icon' => 'col-icon',
133  'name' => 'col-title col-responsive',
134  ];
135 
139  protected ‪$folderObject;
140 
144  public ‪$clipObj;
145 
146  // Evaluates if a resource can be downloaded
148  // Evaluates if a resource can be displayed
150  // Evaluates if a resource can be selected
152  // Evaluates if a resource is currently selected
154 
156  protected EventDispatcherInterface ‪$eventDispatcher;
157  protected ServerRequestInterface ‪$request;
163 
164  public function ‪__construct(ServerRequestInterface ‪$request)
165  {
166  $this->request = ‪$request;
167 
168  // Setting the maximum length of the filenames to the user's settings or minimum 30 (= $this->maxTitleLength)
169  $this->maxTitleLength = max($this->maxTitleLength, (int)($this->‪getBackendUser()->uc['titleLen'] ?? 1));
170  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
171  $this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
172  $this->translateTools = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
173  $this->itemsPerPage = ‪MathUtility::forceIntegerInRange(
174  $this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['filesPerPage'] ?? $this->itemsPerPage,
175  1
176  );
177  // Create clipboard object and initialize that
178  $this->clipObj = GeneralUtility::makeInstance(Clipboard::class);
179  $this->clipObj->initializeClipboard(‪$request);
180  $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
181  $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
182  $this->onlineMediaHelperRegistry = GeneralUtility::makeInstance(OnlineMediaHelperRegistry::class);
183 
184  // Initialize Resource Download
185  $this->resourceDownloadMatcher = GeneralUtility::makeInstance(Matcher::class);
186  $this->resourceDownloadMatcher->addMatcher(GeneralUtility::makeInstance(ResourceFolderTypeMatcher::class));
187 
188  // Create filter for file extensions
189  $fileExtensionMatcher = GeneralUtility::makeInstance(ResourceFileExtensionMatcher::class);
190  $fileDownloadConfiguration = (array)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.'] ?? []);
191  if ($fileDownloadConfiguration !== []) {
192  $allowedExtensions = ‪GeneralUtility::trimExplode(',', (string)($fileDownloadConfiguration['allowedFileExtensions'] ?? ''), true);
193  $disallowedExtensions = ‪GeneralUtility::trimExplode(',', (string)($fileDownloadConfiguration['disallowedFileExtensions'] ?? ''), true);
194  $fileExtensionMatcher = GeneralUtility::makeInstance(ResourceFileExtensionMatcher::class);
195  $fileExtensionMatcher->setExtensions($allowedExtensions);
196  $fileExtensionMatcher->setIgnoredExtensions($disallowedExtensions);
197  } else {
198  $fileExtensionMatcher->addExtension('*');
199  }
200  $this->resourceDownloadMatcher->addMatcher($fileExtensionMatcher);
201  }
202 
203  public function ‪setResourceDownloadMatcher(?‪Matcher $matcher): self
204  {
205  $this->resourceDownloadMatcher = $matcher;
206  return $this;
207  }
208 
209  public function ‪setResourceDisplayMatcher(?‪Matcher $matcher): self
210  {
211  $this->resourceDisplayMatcher = $matcher;
212  return $this;
213  }
214 
215  public function ‪setResourceSelectableMatcher(?‪Matcher $matcher): self
216  {
217  $this->resourceSelectableMatcher = $matcher;
218  return $this;
219  }
220 
221  public function ‪setResourceSelectedMatcher(?‪Matcher $matcher): self
222  {
223  $this->resourceSelectedMatcher = $matcher;
224  return $this;
225  }
226 
236  public function ‪start(Folder ‪$folderObject, int ‪$currentPage, string ‪$sort, bool ‪$sortRev, ‪Mode ‪$mode = Mode::MANAGE)
237  {
238  $this->folderObject = ‪$folderObject;
239  $this->currentPage = ‪MathUtility::forceIntegerInRange(‪$currentPage, 1, 100000);
240  $this->sort = ‪$sort;
241  $this->sortRev = ‪$sortRev;
242  $this->totalbytes = 0;
243  $this->resourceDownloadMatcher = null;
244  $this->resourceDisplayMatcher = null;
245  $this->resourceSelectableMatcher = null;
246  $this->‪setMode($mode);
247  }
248 
249  public function ‪setMode(‪Mode ‪$mode)
250  {
251  $this->mode = ‪$mode;
252  $this->‪fieldArray = $mode->fieldArray();
253  }
254 
255  public function ‪setColumnsToRender(array $additionalFields = []): void
256  {
257  $this->‪fieldArray = array_unique(array_merge($this->‪fieldArray, $additionalFields));
258  }
259 
263  protected function ‪renderTiles(ResourceCollectionPaginator $paginator, array $resourceViews, ViewInterface $view): string
264  {
265  $view->assign('displayThumbs', $this->thumbs);
266  $view->assign('displayCheckbox', $this->resourceSelectableMatcher ? true : false);
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  foreach ($this->‪fieldArray as $field) {
501  switch ($field) {
502  case 'icon':
503  $data[$field] = $this->‪renderIcon($resourceView);
504  break;
505  case 'name':
506  $data[$field] = $this->‪renderName($resourceView)
507  . $this->‪renderThumbnail($resourceView);
508  break;
509  case 'size':
510  $data[$field] = $this->‪renderSize($resourceView);
511  break;
512  case 'rw':
513  $data[$field] = $this->‪renderPermission($resourceView);
514  break;
515  case 'record_type':
516  $data[$field] = $this->‪renderType($resourceView);
517  break;
518  case 'crdate':
519  $data[$field] = $this->‪renderCreationTime($resourceView);
520  break;
521  case 'tstamp':
522  $data[$field] = $this->‪renderModificationTime($resourceView);
523  break;
524  case '_SELECTOR_':
525  $data[$field] = $this->‪renderSelector($resourceView);
526  break;
527  case '_PATH_':
528  $data[$field] = $this->‪renderPath($resourceView);
529  break;
530  case '_REF_':
531  $data[$field] = $this->‪renderReferenceCount($resourceView);
532  break;
533  case '_CONTROL_':
534  $data[$field] = $this->‪renderControl($resourceView);
535  break;
536  default:
537  $data[$field] = $this->‪renderField($resourceView, $field);
538  }
539  }
540  ‪$output .= $this->‪addElement($data, $attributes);
541  }
542 
543  return ‪$output;
544  }
545 
548  ‪NavigationDirection $direction
549  ): string {
550  if (!$link = $this->‪getPaginationLinkForDirection($paginator, $direction)) {
551  return '';
552  }
553 
554  $iconIdentifier = match ($direction) {
555  ‪NavigationDirection::BACKWARD => 'actions-move-up',
556  NavigationDirection::FORWARD => 'actions-move-down',
557  };
558 
559  $markup = [];
560  $markup[] = '<tr>';
561  $markup[] = ' <td colspan="' . count($this->‪fieldArray) . '">';
562  $markup[] = ' <a href="' . htmlspecialchars($link->uri) . '">';
563  $markup[] = ' ' . $this->iconFactory->getIcon($iconIdentifier, IconSize::SMALL)->render();
564  $markup[] = ' <i>[' . $link->label . ']</i>';
565  $markup[] = ' </a>';
566  $markup[] = ' </td>';
567  $markup[] = '</tr>';
568 
569  return implode(PHP_EOL, $markup);
570  }
571 
578  protected function getTranslationsForMetaData($metaDataRecord)
579  {
580  $languageField = ‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? '';
581  $languageParentField = ‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['transOrigPointerField'] ?? '';
582 
583  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_metadata');
584  $queryBuilder->getRestrictions()->removeAll();
585  ‪$translationRecords = $queryBuilder->select('*')
586  ->from('sys_file_metadata')
587  ->where(
588  $queryBuilder->expr()->eq(
589  $languageParentField,
590  $queryBuilder->createNamedParameter($metaDataRecord['uid'] ?? 0, ‪Connection::PARAM_INT)
591  ),
592  $queryBuilder->expr()->gt(
593  $languageField,
594  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
595  )
596  )
597  ->executeQuery()
598  ->fetchAllAssociative();
599 
600  ‪$translations = [];
601  foreach (‪$translationRecords as ‪$record) {
602  $languageId = ‪$record[$languageField];
603  ‪$translations[$languageId] = ‪$record;
604  }
605  return ‪$translations;
606  }
607 
611  protected function ‪renderIcon(ResourceView $resourceView): string
612  {
613  return $this->mode === Mode::BROWSE
614  ? $resourceView->getIconSmall()->render()
615  : BackendUtility::wrapClickMenuOnIcon($resourceView->getIconSmall()->render(), 'sys_file', $resourceView->getIdentifier());
616  }
617 
621  protected function ‪renderName(ResourceView $resourceView): string
622  {
623  $resourceName = htmlspecialchars($resourceView->getName());
624  if ($resourceView->resource instanceof Folder
625  && $resourceView->resource->getRole() !== ‪FolderInterface::ROLE_DEFAULT) {
626  $resourceName = '<strong>' . $resourceName . '</strong>';
627  }
628 
629  $attributes = [];
630  $attributes['title'] = $resourceView->getName();
631  $attributes['type'] = 'button';
632  $attributes['class'] = 'btn btn-link p-0';
633  $attributes['data-filelist-action'] = 'primary';
634 
635  ‪$output = '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>' . $resourceName . '</button>';
636  if ($resourceView->isMissing()) {
637  $label = htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.file_missing'));
638  ‪$output = '<span class="badge badge-danger">' . $label . '</span> ' . ‪$output;
639  }
640 
641  return ‪$output;
642  }
643 
647  protected function ‪renderThumbnail(ResourceView $resourceView): string
648  {
649  if ($this->thumbs === false
650  || $resourceView->getPreview() === null
651  || !($resourceView->getPreview()->isImage() || $resourceView->getPreview()->isMediaFile())
652  ) {
653  return '';
654  }
655 
656  $processedFile = $resourceView->getPreview()->process(
658  [
659  'width' => (int)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['thumbnail.']['width'] ?? 64),
660  'height' => (int)($this->‪getBackendUser()->getTSConfig()['options.']['file_list.']['thumbnail.']['height'] ?? 64),
661  ]
662  );
663 
664  if (($thumbnailUrl = ($processedFile->getPublicUrl() ?? '')) === '') {
665  // Prevent rendering of a "img" tag with an empty "src" attribute
666  return '';
667  }
668 
669  if (‪PathUtility::isAbsolutePath($thumbnailUrl)) {
670  $thumbnailUrl .= '?' . filemtime($processedFile->getForLocalProcessing(false));
671  }
672 
673  return '<br><img src="' . htmlspecialchars($thumbnailUrl) . '" ' .
674  'width="' . htmlspecialchars($processedFile->getProperty('width')) . '" ' .
675  'height="' . htmlspecialchars($processedFile->getProperty('height')) . '" ' .
676  'title="' . htmlspecialchars($resourceView->getName()) . '" ' .
677  'loading="lazy" ' .
678  'alt="" />';
679  }
680 
684  protected function ‪renderType(ResourceView $resourceView): string
685  {
686  $type = $resourceView->getType();
687  $content = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:' . $type);
688  if ($resourceView->resource instanceof File && $resourceView->resource->getExtension() !== '') {
689  $content .= ' (' . strtoupper($resourceView->resource->getExtension()) . ')';
690  }
691 
692  return htmlspecialchars($content);
693  }
694 
698  protected function ‪renderCreationTime(ResourceView $resourceView): string
699  {
700  $timestamp = ($resourceView->resource instanceof File) ? $resourceView->getCreatedAt() : null;
701  return $timestamp ? BackendUtility::datetime($timestamp) : '';
702  }
703 
707  protected function ‪renderModificationTime(ResourceView $resourceView): string
708  {
709  $timestamp = ($resourceView->resource instanceof File) ? $resourceView->getUpdatedAt() : null;
710  return $timestamp ? BackendUtility::datetime($timestamp) : '';
711  }
712 
716  protected function ‪renderSize(ResourceView $resourceView): string
717  {
718  if ($resourceView->resource instanceof File) {
719  return GeneralUtility::formatSize((int)$resourceView->resource->getSize(), htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')));
720  }
721 
722  if ($resourceView->resource instanceof Folder) {
723  try {
724  $numFiles = $resourceView->resource->getFileCount();
725  } catch (InsufficientFolderAccessPermissionsException $e) {
726  $numFiles = 0;
727  }
728  if ($numFiles === 1) {
729  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:file'));
730  }
731  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:files'));
732  }
733 
734  return '';
735  }
736 
740  protected function ‪renderPermission(ResourceView $resourceView): string
741  {
742  return '<strong class="text-danger">'
743  . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read'))
744  . ($resourceView->canWrite() ? htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write')) : '')
745  . '</strong>';
746  }
747 
751  protected function ‪renderField(ResourceView $resourceView, string $field): string
752  {
753  if ($resourceView->resource instanceof File && $resourceView->resource->hasProperty($field)) {
754  if ($field === 'storage') {
755  // Fetch storage name of the current file
756  $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$resourceView->resource->getProperty($field));
757  if ($storage !== null) {
758  return htmlspecialchars($storage->getName());
759  }
760  } else {
761  return htmlspecialchars(
762  (string)BackendUtility::getProcessedValueExtra(
763  $this->‪getConcreteTableName($field),
764  $field,
765  $resourceView->resource->getProperty($field),
766  $this->maxTitleLength,
767  $resourceView->resource->getMetaData()->offsetGet('uid')
768  )
769  );
770  }
771  }
772 
773  return '';
774  }
775 
779  protected function ‪renderSelector(ResourceView $resourceView): string
780  {
781  $checkboxConfig = $resourceView->getCheckboxConfig();
782  if ($checkboxConfig === null) {
783  return '';
784  }
785  if (!$resourceView->isSelectable) {
786  return '';
787  }
788 
789  $attributes = [
790  'class' => 'form-check-input ' . $checkboxConfig['class'],
791  'type' => 'checkbox',
792  'name' => $checkboxConfig['name'],
793  'value' => $checkboxConfig['value'],
794  'checked' => $checkboxConfig['checked'],
795  ];
796 
797  return '<span class="form-check form-check-type-toggle">'
798  . '<input ' . GeneralUtility::implodeAttributes($attributes, true) . ' />'
799  . '</span>';
800  }
801 
805  protected function ‪renderPath(ResourceView $resourceView): string
806  {
807  return htmlspecialchars($resourceView->getPath());
808  }
809 
814  protected function ‪renderReferenceCount(ResourceView $resourceView): string
815  {
816  if (!$resourceView->resource instanceof File) {
817  return '-';
818  }
819 
820  $referenceCount = $this->‪getFileReferenceCount($resourceView->resource);
821  if (!$referenceCount) {
822  return '-';
823  }
824 
825  $attributes = [
826  'type' => 'button',
827  'class' => 'btn btn-sm btn-link',
828  'data-filelist-action' => 'show',
829  'title' => $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references') . ' (' . $referenceCount . ')',
830  ];
831 
832  return '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>' . $referenceCount . '</button>';
833  }
834 
838  protected function ‪renderControl(ResourceView $resourceView): string
839  {
840  if ($this->mode === Mode::MANAGE) {
841  return $this->‪renderControlManage($resourceView);
842  }
843  if ($this->mode === Mode::BROWSE) {
844  return $this->‪renderControlBrowse($resourceView);
845  }
846 
847  return '';
848  }
849 
853  protected function ‪renderControlManage(ResourceView $resourceView): string
854  {
855  if (!$resourceView->resource instanceof File && !$resourceView->resource instanceof Folder) {
856  return '';
857  }
858 
859  // primary actions
860  $primaryActions = ['view', 'metadata', 'translations', 'delete'];
861  $userTsConfig = $this->‪getBackendUser()->getTSConfig();
862  if ($userTsConfig['options.']['file_list.']['primaryActions'] ?? false) {
863  $primaryActions = ‪GeneralUtility::trimExplode(',', $userTsConfig['options.']['file_list.']['primaryActions']);
864  // Always add "translations" as this action has an own dropdown container and therefore cannot be a secondary action
865  if (!in_array('translations', $primaryActions, true)) {
866  $primaryActions[] = 'translations';
867  }
868  }
869 
870  $actions = [
871  'edit' => $this->‪createControlEditContent($resourceView),
872  'metadata' => $this->‪createControlEditMetaData($resourceView),
873  'translations' => $this->‪createControlTranslation($resourceView),
874  'view' => $this->‪createControlView($resourceView),
875  'replace' => $this->‪createControlReplace($resourceView),
876  'rename' => $this->‪createControlRename($resourceView),
877  'download' => $this->‪createControlDownload($resourceView),
878  'upload' => $this->‪createControlUpload($resourceView),
879  'info' => $this->‪createControlInfo($resourceView),
880  'delete' => $this->‪createControlDelete($resourceView),
881  'copy' => $this->‪createControlCopy($resourceView),
882  'cut' => $this->‪createControlCut($resourceView),
883  'paste' => $this->‪createControlPaste($resourceView),
884  'updateOnlineMedia' => $this->‪createControlUpdateOnlineMedia($resourceView),
885  ];
886 
887  $event = new ProcessFileListActionsEvent($resourceView->resource, $actions);
888  $event = $this->eventDispatcher->dispatch($event);
889  $actions = $event->getActionItems();
890 
891  // Remove empty actions
892  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
893 
894  // Compile items into a dropdown
895  $cellOutput = '';
896  ‪$output = '';
897  foreach ($actions as $key => $action) {
898  if (in_array($key, $primaryActions, true)) {
899  ‪$output .= $action;
900  continue;
901  }
902  // This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12.
903  $action = str_replace('btn btn-sm btn-default', 'dropdown-item dropdown-item-spaced', $action);
904  $title = [];
905  preg_match('/title="([^"]*)"/', $action, $title);
906  if (empty($title)) {
907  preg_match('/aria-label="([^"]*)"/', $action, $title);
908  }
909  if (!empty($title[1])) {
910  $action = str_replace(
911  [
912  '</a>',
913  '</button>',
914  ],
915  [
916  ' ' . $title[1] . '</a>',
917  ' ' . $title[1] . '</button>',
918  ],
919  $action
920  );
921  // In case we added the title as tag content, we can remove the attribute,
922  // since this is duplicated and would trigger a tooltip with the same content.
923  if (!empty($title[0])) {
924  $action = str_replace($title[0], '', $action);
925  }
926  $cellOutput .= '<li>' . $action . '</li>';
927  }
928  }
929 
930  if ($cellOutput !== '') {
931  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.more');
932  ‪$output .= '<div class="btn-group dropdown" title="' . htmlspecialchars($title) . '" >'
933  . '<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">'
934  . $this->iconFactory->getIcon('actions-menu-alternative', IconSize::SMALL)->render()
935  . '</a>'
936  . '<ul id="actions_' . $resourceView->resource->getHashedIdentifier() . '" class="dropdown-menu">' . $cellOutput . '</ul>'
937  . '</div>';
938  }
939 
940  return '<div class="btn-group">' . ‪$output . '</div>';
941  }
942 
946  protected function ‪renderControlBrowse(ResourceView $resourceView): string
947  {
948  $fileOrFolderObject = $resourceView->resource;
949  if (!$fileOrFolderObject instanceof File && !$fileOrFolderObject instanceof Folder) {
950  return '';
951  }
952 
953  $actions = [
954  'select' => $this->‪createControlSelect($resourceView),
955  'info' => $this->‪createControlInfo($resourceView),
956  ];
957 
958  // Remove empty actions
959  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
960  if (empty($actions)) {
961  return '';
962  }
963 
964  return '<div class="btn-group">' . implode(' ', $actions) . '</div>';
965  }
966 
967  protected function ‪createControlSelect(‪ResourceView $resourceView): ?‪ButtonInterface
968  {
969  if (!$resourceView->isSelectable) {
970  return null;
971  }
972 
973  $button = GeneralUtility::makeInstance(InputButton::class);
974  $button->setTitle($resourceView->‪getName());
975  $button->setIcon($this->iconFactory->getIcon('actions-plus', IconSize::SMALL));
976  $button->setDataAttributes(['filelist-action' => 'select']);
977 
978  return $button;
979  }
980 
981  protected function ‪createControlEditContent(‪ResourceView $resourceView): ?‪ButtonInterface
982  {
983  if (!($resourceView->resource instanceof ‪File && $resourceView->resource->isTextFile())
984  || !$resourceView->‪canWrite()) {
985  return null;
986  }
987 
988  $button = GeneralUtility::makeInstance(LinkButton::class);
989  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent'));
990  $button->setHref($resourceView->editContentUri);
991  $button->setIcon($this->iconFactory->getIcon('actions-page-open', IconSize::SMALL));
992 
993  return $button;
994  }
995 
996  protected function ‪createControlEditMetaData(‪ResourceView $resourceView): ?‪ButtonInterface
997  {
998  if (!$resourceView->‪getMetaDataUid()) {
999  return null;
1000  }
1001 
1002  $button = GeneralUtility::makeInstance(LinkButton::class);
1003  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editMetadata'));
1004  $button->setHref($resourceView->editDataUri);
1005  $button->setIcon($this->iconFactory->getIcon('actions-open', IconSize::SMALL));
1006 
1007  return $button;
1008  }
1009 
1010  protected function ‪createControlView(‪ResourceView $resourceView): ?‪ButtonInterface
1011  {
1012  if (!$resourceView->‪getPublicUrl()) {
1013  return null;
1014  }
1015 
1016  $button = GeneralUtility::makeInstance(GenericButton::class);
1017  $button->setTag('a');
1018  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.view'));
1019  $button->setHref($resourceView->‪getPublicUrl());
1020  $button->setAttributes(['target' => '_blank']);
1021  $button->setIcon($this->iconFactory->getIcon('actions-document-view', IconSize::SMALL));
1022 
1023  return $button;
1024  }
1025 
1026  protected function ‪createControlReplace(‪ResourceView $resourceView): ?‪ButtonInterface
1027  {
1028  if (!$resourceView->replaceUri) {
1029  return null;
1030  }
1031 
1032  $button = GeneralUtility::makeInstance(LinkButton::class);
1033  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace'));
1034  $button->setHref($resourceView->replaceUri);
1035  $button->setIcon($this->iconFactory->getIcon('actions-edit-replace', IconSize::SMALL));
1036 
1037  return $button;
1038  }
1039 
1040  protected function ‪createControlRename(‪ResourceView $resourceView): ?‪ButtonInterface
1041  {
1042  if (!$resourceView->‪canRename()) {
1043  return null;
1044  }
1045 
1046  $button = GeneralUtility::makeInstance(GenericButton::class);
1047  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename'));
1048  $button->setAttributes(['type' => 'button', 'data-filelist-action' => 'rename']);
1049  $button->setIcon($this->iconFactory->getIcon('actions-edit-rename', IconSize::SMALL));
1050 
1051  return $button;
1052  }
1053 
1054  protected function ‪createControlDownload(‪ResourceView $resourceView): ?‪ButtonInterface
1055  {
1056  if (!$resourceView->‪canRead() || !(bool)($this->getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.']['enabled'] ?? true)) {
1057  return null;
1058  }
1059 
1060  if (!$resourceView->isDownloadable) {
1061  return null;
1062  }
1063 
1064  $button = GeneralUtility::makeInstance(GenericButton::class);
1065  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:download'));
1066  $button->setAttributes([
1067  'type' => 'button',
1068  'data-filelist-action' => 'download',
1069  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_download'),
1070  ]);
1071  $button->setIcon($this->iconFactory->getIcon('actions-download', IconSize::SMALL));
1072 
1073  return $button;
1074  }
1075 
1076  protected function ‪createControlUpload(‪ResourceView $resourceView): ?‪ButtonInterface
1077  {
1078  if (!$resourceView->resource->getStorage()->checkUserActionPermission('add', 'File')
1079  || !$resourceView->resource instanceof ‪Folder
1080  || !$resourceView->‪canWrite()) {
1081  return null;
1082  }
1083 
1084  $button = GeneralUtility::makeInstance(LinkButton::class);
1085  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'));
1086  $button->setHref($this->uriBuilder->buildUriFromRoute('file_upload', ['target' => $resourceView->‪getIdentifier(), 'returnUrl' => $this->createModuleUri()]));
1087  $button->setIcon($this->iconFactory->getIcon('actions-edit-upload', IconSize::SMALL));
1088 
1089  return $button;
1090  }
1091 
1092  protected function ‪createControlInfo(‪ResourceView $resourceView): ?‪ButtonInterface
1093  {
1094  if (!$resourceView->‪canRead()) {
1095  return null;
1096  }
1097 
1098  $button = GeneralUtility::makeInstance(GenericButton::class);
1099  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info'));
1100  $button->setAttributes([
1101  'type' => 'button',
1102  'data-filelist-action' => 'show',
1103  ]);
1104  $button->setIcon($this->iconFactory->getIcon('actions-document-info', IconSize::SMALL));
1105 
1106  return $button;
1107  }
1108 
1109  protected function ‪createControlDelete(‪ResourceView $resourceView): ?‪ButtonInterface
1110  {
1111  if (!$resourceView->‪canDelete()) {
1112  return null;
1113  }
1114 
1115  $recordInfo = $resourceView->‪getName();
1116 
1117  if ($resourceView->resource instanceof Folder) {
1118  ‪$identifier = $resourceView->‪getIdentifier();
1119  $referenceCountText = BackendUtility::referenceCount('_FILE', ‪$identifier, LF . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToFolder'));
1120  $deleteType = 'delete_folder';
1121  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1122  $recordInfo .= ' [' . ‪$identifier . ']';
1123  }
1124  } else {
1125  $referenceCountText = BackendUtility::referenceCount('sys_file', (string)$resourceView->‪getUid(), LF . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToFile'));
1126  $deleteType = 'delete_file';
1127  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1128  $recordInfo .= ' [sys_file:' . $resourceView->‪getUid() . ']';
1129  }
1130  }
1131 
1132  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete');
1133  $button = GeneralUtility::makeInstance(GenericButton::class);
1134  $button->setLabel($title);
1135  $button->setIcon($this->iconFactory->getIcon('actions-edit-delete', IconSize::SMALL));
1136  $button->setAttributes([
1137  'type' => 'button',
1138  'data-title' => $title,
1139  'data-bs-content' => sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete'), trim($recordInfo)) . $referenceCountText,
1140  'data-filelist-action' => 'delete',
1141  'data-filelist-delete' => 'true',
1142  'data-filelist-delete-identifier' => $resourceView->‪getIdentifier(),
1143  'data-filelist-delete-url' => $this->uriBuilder->buildUriFromRoute('tce_file'),
1144  'data-filelist-delete-type' => $deleteType,
1145  'data-filelist-delete-check' => $this->getBackendUser()->jsConfirmation(‪JsConfirmation::DELETE) ? '1' : '0',
1146  ]);
1147 
1148  return $button;
1149  }
1150 
1157  protected function ‪createControlTranslation(ResourceView $resourceView): ?ButtonInterface
1158  {
1159  if (!$resourceView->resource instanceof File) {
1160  return null;
1161  }
1162 
1163  $backendUser = $this->‪getBackendUser();
1164 
1165  // Fetch all system languages except "default (0)" and "all languages (-1)"
1166  $systemLanguages = array_filter(
1167  $this->translateTools->getSystemLanguages(),
1168  static fn(array $languageRecord): bool => $languageRecord['uid'] > 0 && $backendUser->checkLanguageAccess($languageRecord['uid'])
1169  );
1170 
1171  if ($systemLanguages === []
1172  || !(‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? false)
1173  || !$resourceView->resource->isIndexed()
1174  || !$resourceView->resource->checkActionPermission('editMeta')
1175  || !$backendUser->check('tables_modify', 'sys_file_metadata')
1176  ) {
1177  // Early return in case no system languages exists or metadata
1178  // of this file can not be created / edited by the current user.
1179  return null;
1180  }
1181 
1182  $dropdownItems = [];
1183  $metaDataRecord = $resourceView->resource->getMetaData()->get();
1184  $existingTranslations = $this->getTranslationsForMetaData($metaDataRecord);
1185 
1186  foreach ($systemLanguages as $languageId => $language) {
1187  if (!isset($existingTranslations[$languageId]) && !($metaDataRecord['uid'] ?? false)) {
1188  // Skip if neither a translation nor the metadata uid exists
1189  continue;
1190  }
1191 
1192  if (isset($existingTranslations[$languageId])) {
1193  // Set options for edit action of an existing translation
1194  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:editMetadataForLanguage'), $language['title']);
1195  $actionType = 'edit';
1196  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1197  'record_edit',
1198  [
1199  'edit' => [
1200  'sys_file_metadata' => [
1201  $existingTranslations[$languageId]['uid'] => 'edit',
1202  ],
1203  ],
1204  'returnUrl' => $this->createModuleUri(),
1205  ]
1206  );
1207  } else {
1208  // Set options for "create new" action of a new translation
1209  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:createMetadataForLanguage'), $language['title']);
1210  $actionType = 'new';
1211  $metaDataRecordId = (int)($metaDataRecord['uid'] ?? 0);
1212  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1213  'tce_db',
1214  [
1215  'cmd' => [
1216  'sys_file_metadata' => [
1217  $metaDataRecordId => [
1218  'localize' => $languageId,
1219  ],
1220  ],
1221  ],
1222  'redirect' => (string)$this->uriBuilder->buildUriFromRoute(
1223  'record_edit',
1224  [
1225  'justLocalized' => 'sys_file_metadata:' . $metaDataRecordId . ':' . $languageId,
1226  'returnUrl' => $this->‪createModuleUri(),
1227  ]
1228  ),
1229  ]
1230  );
1231  }
1232 
1233  $dropdownItem = GeneralUtility::makeInstance(DropDownItem::class);
1234  $dropdownItem->setLabel($title);
1235  $dropdownItem->setHref(‪$url);
1236  $dropdownItem->setIcon($this->iconFactory->getIcon($language['flagIcon'], IconSize::SMALL, 'overlay-' . $actionType));
1237  $dropdownItems[] = $dropdownItem;
1238  }
1239 
1240  if (empty($dropdownItems)) {
1241  return null;
1242  }
1243 
1244  $dropdownButton = GeneralUtility::makeInstance(DropDownButton::class);
1245  $dropdownButton->setLabel('Translations');
1246  $dropdownButton->setIcon($this->iconFactory->getIcon('actions-translate', IconSize::SMALL));
1247  foreach ($dropdownItems as $dropdownItem) {
1248  $dropdownButton->addItem($dropdownItem);
1249  }
1250 
1251  return $dropdownButton;
1252  }
1253 
1254  protected function ‪createControlCopy(‪ResourceView $resourceView): ?‪ButtonInterface
1255  {
1256  if (!$resourceView->‪canRead() || !$resourceView->‪canCopy()) {
1257  return null;
1258  }
1259 
1260  if ($this->clipObj->current === 'normal') {
1261  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1262  $button = GeneralUtility::makeInstance(LinkButton::class);
1263  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'copy' ? 'copyrelease' : 'copy')));
1264  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), true, $isSelected === 'copy'));
1265  $button->setIcon($this->iconFactory->getIcon($isSelected === 'copy' ? 'actions-edit-copy-release' : 'actions-edit-copy', IconSize::SMALL));
1266  return $button;
1267  }
1268 
1269  return null;
1270  }
1271 
1272  protected function ‪createControlCut(‪ResourceView $resourceView): ?‪ButtonInterface
1273  {
1274  if (!$resourceView->‪canRead() || !$resourceView->‪canMove()) {
1275  return null;
1276  }
1277 
1278  if ($this->clipObj->current === 'normal') {
1279  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1280  $button = GeneralUtility::makeInstance(LinkButton::class);
1281  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'cut' ? 'cutrelease' : 'cut')));
1282  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), false, $isSelected === 'cut'));
1283  $button->setIcon($this->iconFactory->getIcon($isSelected === 'cut' ? 'actions-edit-cut-release' : 'actions-edit-cut', IconSize::SMALL));
1284 
1285  return $button;
1286  }
1287 
1288  return null;
1289  }
1290 
1291  protected function ‪createControlPaste(‪ResourceView $resourceView): ?‪ButtonInterface
1292  {
1293  $permission = ($this->clipObj->clipData[$this->clipObj->current]['mode'] ?? '') === 'copy' ? 'copy' : 'move';
1294  $addPasteButton = $this->folderObject->checkActionPermission($permission);
1295  $elementFromTable = $this->clipObj->elFromTable('_FILE');
1296  if ($elementFromTable === []
1297  || !$addPasteButton
1298  || !$resourceView->‪canRead()
1299  || !$resourceView->‪canWrite()
1300  || !$resourceView->resource instanceof ‪Folder) {
1301  return null;
1302  }
1303 
1304  $elementsToConfirm = [];
1305  foreach ($elementFromTable as $key => $element) {
1306  $clipBoardElement = $this->resourceFactory->retrieveFileOrFolderObject($element);
1307  if ($clipBoardElement instanceof Folder
1308  && $clipBoardElement->getStorage()->isWithinFolder($clipBoardElement, $resourceView->resource)
1309  ) {
1310  // In case folder is already present in the target folder, return actions without paste button
1311  return null;
1312  }
1313  $elementsToConfirm[$key] = $clipBoardElement->getName();
1314  }
1315 
1316  $pasteTitle = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_pasteInto');
1317  $button = GeneralUtility::makeInstance(LinkButton::class);
1318  $button->setTitle($pasteTitle);
1319  $button->setHref($this->clipObj->pasteUrl('_FILE', $resourceView->‪getIdentifier()));
1320  $button->setDataAttributes([
1321  'title' => $pasteTitle,
1322  'bs-content' => $this->clipObj->confirmMsgText('_FILE', $resourceView->‪getName(), 'into', $elementsToConfirm),
1323  ]);
1324  $button->setIcon($this->iconFactory->getIcon('actions-document-paste-into', IconSize::SMALL));
1325 
1326  return $button;
1327  }
1328 
1329  protected function ‪createControlUpdateOnlineMedia(‪ResourceView $resourceView): ?‪ButtonInterface
1330  {
1331  if (!($resourceView->resource instanceof ‪File)
1332  || !$resourceView->‪canEditMetadata()
1333  || !$this->onlineMediaHelperRegistry->hasOnlineMediaHelper($resourceView->resource->getExtension())
1334  ) {
1335  return null;
1336  }
1337 
1338  $title = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:reloadMetadata');
1339  $button = GeneralUtility::makeInstance(GenericButton::class);
1340  $button->setLabel($title);
1341  $button->setIcon($this->iconFactory->getIcon('actions-refresh', IconSize::SMALL));
1342  $button->setAttributes([
1343  'type' => 'button',
1344  'data-title' => $title,
1345  'data-filelist-action' => 'updateOnlineMedia',
1346  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_update_online_media'),
1347  ]);
1348 
1349  return $button;
1350  }
1351 
1352  protected function ‪isEditMetadataAllowed(‪File $file): bool
1353  {
1354  return $file->‪isIndexed()
1355  && $file->‪checkActionPermission('editMeta')
1356  && $this->‪getUserPermissions()->editMetaData;
1357  }
1358 
1364  protected function ‪renderCheckboxActions(): string
1365  {
1366  // Early return in case there are no items
1367  if (!$this->totalItems) {
1368  return '';
1369  }
1370 
1371  $lang = $this->‪getLanguageService();
1372 
1373  $dropdownItems['checkAll'] = '
1374  <li>
1375  <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')) . '">
1376  <span class="dropdown-item-columns">
1377  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1378  ' . $this->iconFactory->getIcon('actions-selection-elements-all', IconSize::SMALL)->render() . '
1379  </span>
1380  <span class="dropdown-item-column dropdown-item-column-title">
1381  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll')) . '
1382  </span>
1383  </span>
1384  </button>
1385  </li>';
1386 
1387  $dropdownItems['checkNone'] = '
1388  <li>
1389  <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')) . '">
1390  <span class="dropdown-item-columns">
1391  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1392  ' . $this->iconFactory->getIcon('actions-selection-elements-none', IconSize::SMALL)->render() . '
1393  </span>
1394  <span class="dropdown-item-column dropdown-item-column-title">
1395  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll')) . '
1396  </span>
1397  </span>
1398  </button>
1399  </li>';
1400 
1401  $dropdownItems['toggleSelection'] = '
1402  <li>
1403  <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')) . '">
1404  <span class="dropdown-item-columns">
1405  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1406  ' . $this->iconFactory->getIcon('actions-selection-elements-invert', IconSize::SMALL)->render() . '
1407  </span>
1408  <span class="dropdown-item-column dropdown-item-column-title">
1409  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection')) . '
1410  </span>
1411  </span>
1412  </button>
1413  </li>';
1414 
1415  return '
1416  <div class="btn-group dropdown">
1417  <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">
1418  ' . $this->iconFactory->getIcon('actions-selection', IconSize::SMALL) . '
1419  </button>
1420  <ul class="dropdown-menu t3js-multi-record-selection-check-actions">
1421  ' . implode(PHP_EOL, $dropdownItems) . '
1422  </ul>
1423  </div>';
1424  }
1425 
1430  protected function ‪getConcreteTableName(string $fieldName): string
1431  {
1432  return (‪$GLOBALS['TCA']['sys_file']['columns'][$fieldName] ?? false) ? 'sys_file' : 'sys_file_metadata';
1433  }
1434 
1436  {
1437  $currentPagination = new ‪SimplePagination($paginator);
1438  $targetPage = null;
1439  switch ($direction) {
1441  $targetPage = $currentPagination->getPreviousPageNumber();
1442  break;
1443  case NavigationDirection::FORWARD:
1444  $targetPage = $currentPagination->getNextPageNumber();
1445  break;
1446  }
1447 
1448  return $this->‪getPaginationLinkForPage($paginator, $targetPage);
1449  }
1450 
1451  protected function ‪getPaginationLinkForPage(‪ResourceCollectionPaginator $paginator, ?int $targetPage = null): ?‪PaginationLink
1452  {
1453  if ($targetPage === null) {
1454  return null;
1455  }
1456  if ($targetPage > $paginator->‪getNumberOfPages()) {
1457  return null;
1458  }
1459  if ($targetPage < 1) {
1460  return null;
1461  }
1462 
1463  $targetPaginator = $paginator->‪withCurrentPageNumber($targetPage);
1464  $targetPagination = new SimplePagination($targetPaginator);
1465 
1466  $uri = new Uri($this->request->getAttribute('normalizedParams')->getRequestUri());
1467  parse_str($uri->getQuery(), $queryParameters);
1468  unset($queryParameters['contentOnly']);
1469  $queryParameters = array_merge($queryParameters, ['currentPage' => $targetPage]);
1470  if ($this->searchDemand) {
1471  $queryParameters['searchTerm'] = $this->searchDemand->getSearchTerm() ?? '';
1472  }
1473  $uri = $uri->withQuery(‪HttpUtility::buildQueryString($queryParameters, '&'));
1474 
1475  return new PaginationLink(
1476  $targetPagination->getStartRecordNumber() . '-' . $targetPagination->getEndRecordNumber(),
1477  (string)$uri,
1478  );
1479  }
1480 
1484  public function ‪createModuleUri(array $params = []): ?string
1485  {
1487  $queryParams = ‪$request->getQueryParams();
1488  $parsedBody = ‪$request->getParsedBody();
1489 
1490  $route = ‪$request->getAttribute('route');
1491  if (!$route instanceof Route) {
1492  return null;
1493  }
1494 
1495  $baseParams = [
1496  'currentPage' => ‪$this->currentPage,
1497  'id' => $this->folderObject->getCombinedIdentifier(),
1498  'searchTerm' => $this->searchDemand ? $this->searchDemand->getSearchTerm() : '',
1499  ];
1500 
1501  // Keep ElementBrowser Settings
1502  if (‪$mode = $parsedBody['mode'] ?? $queryParams['mode'] ?? null) {
1503  $baseParams['mode'] = ‪$mode;
1504  }
1505  if ($bparams = $parsedBody['bparams'] ?? $queryParams['bparams'] ?? null) {
1506  $baseParams['bparams'] = $bparams;
1507  }
1508 
1509  // Keep LinkHandler Settings
1510  if ($act = ($parsedBody['act'] ?? $queryParams['act'] ?? null)) {
1511  $baseParams['act'] = $act;
1512  }
1513  if ($linkHandlerParams = ($parsedBody['P'] ?? $queryParams['P'] ?? null)) {
1514  $baseParams['P'] = $linkHandlerParams;
1515  }
1516 
1517  $params = array_replace_recursive($baseParams, $params);
1518 
1519  // Expanded folder is used in the element browser.
1520  // We always map it to the id here.
1521  $params['expandFolder'] = $params['id'];
1522  $params = array_filter($params, static function ($value) {
1523  return (is_array($value) && $value !== []) || (trim((string)$value) !== '');
1524  });
1525 
1526  return (string)$this->uriBuilder->buildUriFromRequest(‪$request, $params);
1527  }
1528 
1529  protected function ‪createEditDataUriForResource(‪ResourceInterface $resource): ?string
1530  {
1531  if ($resource instanceof ‪File
1532  && $this->‪isEditMetadataAllowed($resource)
1533  && ($metaDataUid = $resource->getMetaData()->offsetGet('uid'))
1534  ) {
1535  $parameter = [
1536  'edit' => ['sys_file_metadata' => [$metaDataUid => 'edit']],
1537  'returnUrl' => $this->‪createModuleUri(),
1538  ];
1539  return (string)$this->uriBuilder->buildUriFromRoute('record_edit', $parameter);
1540  }
1541 
1542  return null;
1543  }
1544 
1545  protected function ‪createEditContentUriForResource(‪ResourceInterface $resource): ?string
1546  {
1547  if ($resource instanceof ‪File
1548  && $resource->checkActionPermission('write')
1549  && $resource->isTextFile()
1550  ) {
1551  $parameter = [
1552  'target' => $resource->getCombinedIdentifier(),
1553  'returnUrl' => $this->‪createModuleUri(),
1554  ];
1555  return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $parameter);
1556  }
1557 
1558  return null;
1559  }
1560 
1561  protected function ‪createModuleUriForResource(‪ResourceInterface $resource): ?string
1562  {
1563  if ($resource instanceof ‪Folder) {
1564  $parameter = [
1565  'id' => $resource->getCombinedIdentifier(),
1566  'searchTerm' => '',
1567  'currentPage' => 1,
1568  ];
1569  return (string)$this->‪createModuleUri($parameter);
1570  }
1571 
1572  if ($resource instanceof File) {
1573  return $this->‪createEditDataUriForResource($resource);
1574  }
1575 
1576  return null;
1577  }
1578 
1579  protected function ‪createReplaceUriForResource(‪ResourceInterface $resource): ?string
1580  {
1581  if ($resource instanceof ‪File
1582  && $resource->checkActionPermission('replace')
1583  ) {
1584  $parameter = [
1585  'target' => $resource->getCombinedIdentifier(),
1586  'uid' => $resource->getUid(),
1587  'returnUrl' => $this->‪createModuleUri(),
1588  ];
1589  return (string)$this->uriBuilder->buildUriFromRoute('file_replace', $parameter);
1590  }
1591  return null;
1592  }
1593 
1597  protected function ‪sortResources(array $resources, string $sortField): array
1598  {
1599  $collator = new \Collator((string)($this->‪getLanguageService()->getLocale() ?? 'en'));
1600  if ($sortField === 'size') {
1601  $collator->setAttribute(\Collator::NUMERIC_COLLATION, \Collator::ON);
1602  }
1603  uksort($resources, function (int $index1, int $index2) use ($sortField, $resources, $collator) {
1604  $resource1 = $resources[$index1];
1605  $resource2 = $resources[$index2];
1606 
1607  // Folders are always prioritized above files
1608  if ($resource1 instanceof File && $resource2 instanceof Folder) {
1609  return 1;
1610  }
1611  if ($resource1 instanceof Folder && $resource2 instanceof File) {
1612  return -1;
1613  }
1614 
1615  return (int)$collator->compare(
1616  $this->getSortingValue($resource1, $sortField) . $index1,
1617  $this->getSortingValue($resource2, $sortField) . $index2
1618  );
1619  });
1620 
1621  if ($this->sortRev) {
1622  $resources = array_reverse($resources);
1623  }
1624 
1625  return $resources;
1626  }
1627 
1628  protected function ‪getSortingValue(‪ResourceInterface $resource, string $sortField): string
1629  {
1630  if ($resource instanceof ‪File) {
1631  return $this->‪getSortingValueForFile($resource, $sortField);
1632  }
1633  if ($resource instanceof Folder) {
1634  return $this->‪getSortingValueForFolder($resource, $sortField);
1635  }
1636 
1637  return '';
1638  }
1639 
1640  protected function ‪getSortingValueForFile(‪File $resource, string $sortField): string
1641  {
1642  switch ($sortField) {
1643  case 'fileext':
1644  return $resource->‪getExtension();
1645  case 'size':
1646  return $resource->getSize() . 's';
1647  case 'rw':
1648  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1649  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1650  case '_REF_':
1651  return $this->‪getFileReferenceCount($resource) . 'ref';
1652  case 'tstamp':
1653  return $resource->‪getModificationTime() . 't';
1654  case 'crdate':
1655  return $resource->‪getCreationTime() . 'c';
1656  default:
1657  return $resource->‪hasProperty($sortField) ? (string)$resource->‪getProperty($sortField) : '';
1658  }
1659  }
1660 
1661  protected function ‪getSortingValueForFolder(‪Folder $resource, string $sortField): string
1662  {
1663  switch ($sortField) {
1664  case 'size':
1665  try {
1666  $fileCount = $resource->‪getFileCount();
1668  $fileCount = 0;
1669  }
1670  return '0' . $fileCount . 's';
1671  case 'rw':
1672  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1673  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1674  case 'name':
1675  return $resource->‪getName();
1676  default:
1677  return '';
1678  }
1679  }
1680 
1681  protected function ‪getFieldLabel(string $field): string
1682  {
1683  $lang = $this->‪getLanguageService();
1684 
1685  if ($specialLabel = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $field)) {
1686  return $specialLabel;
1687  }
1688  if ($customLabel = $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_' . $field)) {
1689  return $customLabel;
1690  }
1691 
1692  $concreteTableName = $this->‪getConcreteTableName($field);
1693  $label = BackendUtility::getItemLabel($concreteTableName, $field);
1694 
1695  // In case global TSconfig exists we have to check if the label is overridden there
1696  $tsConfig = BackendUtility::getPagesTSconfig(0);
1697  $label = $lang->translateLabel(
1698  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label.'] ?? [],
1699  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label'] ?? $label
1700  );
1701 
1702  return $label;
1703  }
1704 
1710  protected function ‪getFileReferenceCount(File $file): int
1711  {
1712  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
1713  return (int)$queryBuilder
1714  ->count('*')
1715  ->from('sys_refindex')
1716  ->where(
1717  $queryBuilder->expr()->eq(
1718  'ref_table',
1719  $queryBuilder->createNamedParameter('sys_file')
1720  ),
1721  $queryBuilder->expr()->eq(
1722  'ref_uid',
1723  $queryBuilder->createNamedParameter($file->getUid(), ‪Connection::PARAM_INT)
1724  ),
1725  $queryBuilder->expr()->neq(
1726  'tablename',
1727  $queryBuilder->createNamedParameter('sys_file_metadata')
1728  )
1729  )
1730  ->executeQuery()
1731  ->fetchOne();
1732  }
1733 
1734  protected function ‪getUserPermissions(): ‪UserPermissions
1735  {
1736  return new ‪UserPermissions($this->‪getBackendUser()->check('tables_modify', 'sys_file_metadata'));
1737  }
1738 
1739  protected function ‪getLanguageService(): ‪LanguageService
1740  {
1741  return ‪$GLOBALS['LANG'];
1742  }
1743 
1744  protected function ‪getBackendUser(): ‪BackendUserAuthentication
1745  {
1746  return ‪$GLOBALS['BE_USER'];
1747  }
1748 }
‪TYPO3\CMS\Filelist\FileList\$addElement_tdCssClass
‪array $addElement_tdCssClass
Definition: FileList.php:129
‪TYPO3\CMS\Filelist\Dto\UserPermissions
Definition: UserPermissions.php:24
‪TYPO3\CMS\Filelist\FileList\setMode
‪setMode(Mode $mode)
Definition: FileList.php:247
‪TYPO3\CMS\Core\View\ViewInterface\render
‪render(string $templateFileName='')
‪TYPO3\CMS\Filelist\FileList\renderControl
‪renderControl(ResourceView $resourceView)
Definition: FileList.php:836
‪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:1155
‪TYPO3\CMS\Filelist\FileList\$onlineMediaHelperRegistry
‪OnlineMediaHelperRegistry $onlineMediaHelperRegistry
Definition: FileList.php:160
‪TYPO3\CMS\Filelist\FileList\getBackendUser
‪getBackendUser()
Definition: FileList.php:1742
‪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:1543
‪TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry
Definition: OnlineMediaHelperRegistry.php:27
‪TYPO3\CMS\Filelist\Matcher\ResourceFileExtensionMatcher
Definition: ResourceFileExtensionMatcher.php:26
‪TYPO3\CMS\Core\Utility\PathUtility\isAbsolutePath
‪static isAbsolutePath(string $path)
Definition: PathUtility.php:286
‪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:253
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:23
‪TYPO3\CMS\Filelist\FileList\$translateTools
‪TranslationConfigurationProvider $translateTools
Definition: FileList.php:159
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Filelist\FileList\createControlCopy
‪createControlCopy(ResourceView $resourceView)
Definition: FileList.php:1252
‪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:153
‪TYPO3\CMS\Filelist\FileList\createControlUpload
‪createControlUpload(ResourceView $resourceView)
Definition: FileList.php:1074
‪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:682
‪TYPO3\CMS\Filelist\FileList\$resourceSelectableMatcher
‪Matcher $resourceSelectableMatcher
Definition: FileList.php:149
‪TYPO3\CMS\Filelist\FileList\$request
‪ServerRequestInterface $request
Definition: FileList.php:155
‪TYPO3\CMS\Filelist\FileList\$maxTitleLength
‪int $maxTitleLength
Definition: FileList.php:117
‪TYPO3\CMS\Core\Resource\File\isIndexed
‪isIndexed()
Definition: File.php:139
‪TYPO3\CMS\Filelist\FileList\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: FileList.php:154
‪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:261
‪TYPO3\CMS\Filelist\Dto\ResourceView\getUpdatedAt
‪getUpdatedAt()
Definition: ResourceView.php:180
‪TYPO3\CMS\Filelist\FileList\$resourceFactory
‪ResourceFactory $resourceFactory
Definition: FileList.php:157
‪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:714
‪TYPO3\CMS\Filelist\FileList\createControlUpdateOnlineMedia
‪createControlUpdateOnlineMedia(ResourceView $resourceView)
Definition: FileList.php:1327
‪TYPO3\CMS\Filelist\FileList\getConcreteTableName
‪getConcreteTableName(string $fieldName)
Definition: FileList.php:1428
‪TYPO3\CMS\Filelist\Matcher\Matcher
Definition: Matcher.php:24
‪TYPO3\CMS\Filelist\FileList\renderListTableForwardBackwardNavigation
‪renderListTableForwardBackwardNavigation(ResourceCollectionPaginator $paginator, NavigationDirection $direction)
Definition: FileList.php:544
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪getExtension()
Definition: AbstractFile.php:243
‪TYPO3\CMS\Filelist\FileList\$viewMode
‪ViewMode $viewMode
Definition: FileList.php:77
‪TYPO3\CMS\Core\Authentication\JsConfirmation
Definition: JsConfirmation.php:28
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Filelist\Type\NavigationDirection
‪NavigationDirection
Definition: NavigationDirection.php:24
‪TYPO3\CMS\Filelist\FileList\$clipObj
‪Clipboard $clipObj
Definition: FileList.php:142
‪TYPO3\CMS\Filelist\FileList\$thumbs
‪bool $thumbs
Definition: FileList.php:112
‪TYPO3\CMS\Core\Pagination\AbstractPaginator\getNumberOfPages
‪getNumberOfPages()
Definition: AbstractPaginator.php:68
‪TYPO3\CMS\Filelist\FileList\renderModificationTime
‪renderModificationTime(ResourceView $resourceView)
Definition: FileList.php:705
‪TYPO3\CMS\Filelist\Dto\ResourceView\getCheckboxConfig
‪getCheckboxConfig()
Definition: ResourceView.php:192
‪TYPO3\CMS\Filelist\FileList\renderReferenceCount
‪renderReferenceCount(ResourceView $resourceView)
Definition: FileList.php:812
‪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:1732
‪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:1559
‪TYPO3\CMS\Core\Pagination\SimplePagination
Definition: SimplePagination.php:21
‪TYPO3\CMS\Filelist\FileList\$sortRev
‪bool $sortRev
Definition: FileList.php:107
‪TYPO3\CMS\Filelist
‪TYPO3\CMS\Filelist\FileList\createControlDownload
‪createControlDownload(ResourceView $resourceView)
Definition: FileList.php:1052
‪TYPO3\CMS\Filelist\FileList\getSortingValueForFolder
‪getSortingValueForFolder(Folder $resource, string $sortField)
Definition: FileList.php:1659
‪TYPO3\CMS\Filelist\FileList\$resourceSelectedMatcher
‪Matcher $resourceSelectedMatcher
Definition: FileList.php:151
‪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:92
‪TYPO3\CMS\Core\Resource\File\getProperty
‪getProperty(string $key)
Definition: File.php:62
‪TYPO3\CMS\Filelist\FileList\$folderObject
‪Folder $folderObject
Definition: FileList.php:138
‪TYPO3\CMS\Backend\ElementBrowser\Event\IsFileSelectableEvent
Definition: IsFileSelectableEvent.php:26
‪TYPO3\CMS\Filelist\FileList\getFileReferenceCount
‪getFileReferenceCount(File $file)
Definition: FileList.php:1708
‪TYPO3\CMS\Filelist\FileList\$mode
‪Mode $mode
Definition: FileList.php:76
‪TYPO3\CMS\Filelist\FileList\renderPath
‪renderPath(ResourceView $resourceView)
Definition: FileList.php:803
‪TYPO3\CMS\Filelist\FileList\$resourceDownloadMatcher
‪Matcher $resourceDownloadMatcher
Definition: FileList.php:145
‪TYPO3\CMS\Core\Pagination\AbstractPaginator\withCurrentPageNumber
‪withCurrentPageNumber(int $currentPageNumber)
Definition: AbstractPaginator.php:55
‪TYPO3\CMS\Filelist\FileList\$translationRecords
‪$translationRecords
Definition: FileList.php:583
‪TYPO3\CMS\Filelist\FileList\render
‪render(?FileSearchDemand $searchDemand, ViewInterface $view)
Definition: FileList.php:287
‪TYPO3\CMS\Filelist\FileList
Definition: FileList.php:75
‪TYPO3\CMS\Filelist\FileList\getSortingValueForFile
‪getSortingValueForFile(File $resource, string $sortField)
Definition: FileList.php:1638
‪TYPO3\CMS\Filelist\FileList\renderThumbnail
‪renderThumbnail(ResourceView $resourceView)
Definition: FileList.php:645
‪TYPO3\CMS\Filelist\Dto\ResourceView
Definition: ResourceView.php:33
‪TYPO3\CMS\Filelist\FileList\createControlInfo
‪createControlInfo(ResourceView $resourceView)
Definition: FileList.php:1090
‪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:1024
‪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:944
‪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:965
‪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:122
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:61
‪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:158
‪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:234
‪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:979
‪TYPO3\CMS\Filelist\FileList\createControlRename
‪createControlRename(ResourceView $resourceView)
Definition: FileList.php:1038
‪TYPO3\CMS\Filelist\FileList\createControlView
‪createControlView(ResourceView $resourceView)
Definition: FileList.php:1008
‪TYPO3\CMS\Filelist\FileList\getPaginationLinkForDirection
‪getPaginationLinkForDirection(ResourceCollectionPaginator $paginator, NavigationDirection $direction)
Definition: FileList.php:1433
‪TYPO3\CMS\Core\Resource\File\checkActionPermission
‪bool checkActionPermission($action)
Definition: File.php:208
‪TYPO3\CMS\Filelist\FileList\createEditDataUriForResource
‪createEditDataUriForResource(ResourceInterface $resource)
Definition: FileList.php:1527
‪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:599
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47
‪TYPO3\CMS\Filelist\Dto\ResourceView\canRead
‪canRead()
Definition: ResourceView.php:233
‪$output
‪$output
Definition: annotationChecker.php:114
‪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:219
‪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:749
‪TYPO3\CMS\Filelist\FileList\createReplaceUriForResource
‪createReplaceUriForResource(ResourceInterface $resource)
Definition: FileList.php:1577
‪TYPO3\CMS\Filelist\FileList\$currentPage
‪int $currentPage
Definition: FileList.php:87
‪TYPO3\CMS\Filelist\FileList\createModuleUri
‪createModuleUri(array $params=[])
Definition: FileList.php:1482
‪TYPO3\CMS\Backend\Template\Components\Buttons\InputButton
Definition: InputButton.php:40
‪$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:1449
‪TYPO3\CMS\Filelist\FileList\renderListTableBody
‪renderListTableBody(array $resourceViews)
Definition: FileList.php:478
‪TYPO3\CMS\Filelist\FileList\$itemsPerPage
‪int $itemsPerPage
Definition: FileList.php:82
‪TYPO3\CMS\Filelist\FileList\renderPermission
‪renderPermission(ResourceView $resourceView)
Definition: FileList.php:738
‪TYPO3\CMS\Core\Resource\FolderInterface
Definition: FolderInterface.php:24
‪TYPO3\CMS\Filelist\FileList\renderIcon
‪renderIcon(ResourceView $resourceView)
Definition: FileList.php:609
‪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:1679
‪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:777
‪TYPO3\CMS\Filelist\FileList\getLanguageService
‪getLanguageService()
Definition: FileList.php:1737
‪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:201
‪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:1595
‪TYPO3\CMS\Filelist\FileList\renderCheckboxActions
‪string renderCheckboxActions()
Definition: FileList.php:1362
‪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:147
‪TYPO3\CMS\Core\Resource\AbstractFile\getModificationTime
‪getModificationTime()
Definition: AbstractFile.php:232
‪TYPO3\CMS\Filelist\FileList\getSortingValue
‪getSortingValue(ResourceInterface $resource, string $sortField)
Definition: FileList.php:1626
‪TYPO3\CMS\Filelist\FileList\__construct
‪__construct(ServerRequestInterface $request)
Definition: FileList.php:162
‪TYPO3\CMS\Filelist\FileList\$sort
‪string $sort
Definition: FileList.php:102
‪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:696
‪TYPO3\CMS\Filelist\FileList\$totalItems
‪int $totalItems
Definition: FileList.php:97
‪TYPO3\CMS\Filelist\FileList\renderListTableFieldHeader
‪renderListTableFieldHeader(string $field)
Definition: FileList.php:444
‪TYPO3\CMS\Filelist\FileList\setResourceDisplayMatcher
‪setResourceDisplayMatcher(?Matcher $matcher)
Definition: FileList.php:207
‪TYPO3\CMS\Filelist\FileList\$translations
‪$translations
Definition: FileList.php:598
‪TYPO3\CMS\Filelist\FileList\createControlDelete
‪createControlDelete(ResourceView $resourceView)
Definition: FileList.php:1107
‪TYPO3\CMS\Filelist\FileList\renderName
‪renderName(ResourceView $resourceView)
Definition: FileList.php:619
‪TYPO3\CMS\Filelist\FileList\createControlCut
‪createControlCut(ResourceView $resourceView)
Definition: FileList.php:1270
‪TYPO3\CMS\Filelist\FileList\isEditMetadataAllowed
‪isEditMetadataAllowed(File $file)
Definition: FileList.php:1350
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownItem
Definition: DropDownItem.php:34
‪TYPO3\CMS\Filelist\FileList\renderControlManage
‪renderControlManage(ResourceView $resourceView)
Definition: FileList.php:851
‪TYPO3\CMS\Filelist\FileList\createControlEditMetaData
‪createControlEditMetaData(ResourceView $resourceView)
Definition: FileList.php:994
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:817
‪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:213
‪TYPO3\CMS\Filelist\FileList\$iconFactory
‪IconFactory $iconFactory
Definition: FileList.php:156
‪TYPO3\CMS\Filelist\FileList\createControlPaste
‪createControlPaste(ResourceView $resourceView)
Definition: FileList.php:1289
‪TYPO3\CMS\Core\Resource\File\hasProperty
‪hasProperty($key)
Definition: File.php:76