‪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  $timestamp = ($resourceView->resource instanceof File) ? $resourceView->getCreatedAt() : null;
704  return $timestamp ? BackendUtility::datetime($timestamp) : '';
705  }
706 
710  protected function ‪renderModificationTime(ResourceView $resourceView): string
711  {
712  $timestamp = ($resourceView->resource instanceof File) ? $resourceView->getUpdatedAt() : null;
713  return $timestamp ? BackendUtility::datetime($timestamp) : '';
714  }
715 
719  protected function ‪renderSize(ResourceView $resourceView): string
720  {
721  if ($resourceView->resource instanceof File) {
722  return GeneralUtility::formatSize((int)$resourceView->resource->getSize(), htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')));
723  }
724 
725  if ($resourceView->resource instanceof Folder) {
726  try {
727  $numFiles = $resourceView->resource->getFileCount();
728  } catch (InsufficientFolderAccessPermissionsException $e) {
729  $numFiles = 0;
730  }
731  if ($numFiles === 1) {
732  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:file'));
733  }
734  return $numFiles . ' ' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:files'));
735  }
736 
737  return '';
738  }
739 
743  protected function ‪renderPermission(ResourceView $resourceView): string
744  {
745  return '<strong class="text-danger">'
746  . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:read'))
747  . ($resourceView->canWrite() ? htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:write')) : '')
748  . '</strong>';
749  }
750 
754  protected function ‪renderField(ResourceView $resourceView, string $field): string
755  {
756  if ($resourceView->resource instanceof File && $resourceView->resource->hasProperty($field)) {
757  if ($field === 'storage') {
758  // Fetch storage name of the current file
759  $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid((int)$resourceView->resource->getProperty($field));
760  if ($storage !== null) {
761  return htmlspecialchars($storage->getName());
762  }
763  } else {
764  return htmlspecialchars(
765  (string)BackendUtility::getProcessedValueExtra(
766  $this->‪getConcreteTableName($field),
767  $field,
768  $resourceView->resource->getProperty($field),
769  $this->maxTitleLength,
770  $resourceView->resource->getMetaData()->offsetGet('uid')
771  )
772  );
773  }
774  }
775 
776  return '';
777  }
778 
782  protected function ‪renderSelector(ResourceView $resourceView): string
783  {
784  $checkboxConfig = $resourceView->getCheckboxConfig();
785  if ($checkboxConfig === null) {
786  return '';
787  }
788  if (!$resourceView->isSelectable) {
789  return '';
790  }
791 
792  $attributes = [
793  'class' => 'form-check-input ' . $checkboxConfig['class'],
794  'type' => 'checkbox',
795  'name' => $checkboxConfig['name'],
796  'value' => $checkboxConfig['value'],
797  'checked' => $checkboxConfig['checked'],
798  ];
799 
800  return '<span class="form-check form-check-type-toggle">'
801  . '<input ' . GeneralUtility::implodeAttributes($attributes, true) . ' />'
802  . '</span>';
803  }
804 
808  protected function ‪renderPath(ResourceView $resourceView): string
809  {
810  return htmlspecialchars($resourceView->getPath());
811  }
812 
817  protected function ‪renderReferenceCount(ResourceView $resourceView): string
818  {
819  if (!$resourceView->resource instanceof File) {
820  return '-';
821  }
822 
823  $referenceCount = $this->‪getFileReferenceCount($resourceView->resource);
824  if (!$referenceCount) {
825  return '-';
826  }
827 
828  $attributes = [
829  'type' => 'button',
830  'class' => 'btn btn-sm btn-link',
831  'data-filelist-action' => 'show',
832  'title' => $this->‪getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:show_references') . ' (' . $referenceCount . ')',
833  ];
834 
835  return '<button ' . GeneralUtility::implodeAttributes($attributes, true) . '>' . $referenceCount . '</button>';
836  }
837 
841  protected function ‪renderControl(ResourceView $resourceView): string
842  {
843  return match ($this->mode) {
844  Mode::MANAGE => $this->‪renderControlManage($resourceView),
845  Mode::BROWSE => $this->‪renderControlBrowse($resourceView),
846  };
847  }
848 
852  protected function ‪renderControlManage(ResourceView $resourceView): string
853  {
854  if (!$resourceView->resource instanceof File && !$resourceView->resource instanceof Folder) {
855  return '';
856  }
857 
858  // primary actions
859  $primaryActions = ['view', 'metadata', 'translations', 'delete'];
860  $userTsConfig = $this->‪getBackendUser()->getTSConfig();
861  if ($userTsConfig['options.']['file_list.']['primaryActions'] ?? false) {
862  $primaryActions = ‪GeneralUtility::trimExplode(',', $userTsConfig['options.']['file_list.']['primaryActions']);
863  // Always add "translations" as this action has an own dropdown container and therefore cannot be a secondary action
864  if (!in_array('translations', $primaryActions, true)) {
865  $primaryActions[] = 'translations';
866  }
867  }
868 
869  $actions = [
870  'edit' => $this->‪createControlEditContent($resourceView),
871  'metadata' => $this->‪createControlEditMetaData($resourceView),
872  'translations' => $this->‪createControlTranslation($resourceView),
873  'view' => $this->‪createControlView($resourceView),
874  'replace' => $this->‪createControlReplace($resourceView),
875  'rename' => $this->‪createControlRename($resourceView),
876  'download' => $this->‪createControlDownload($resourceView),
877  'upload' => $this->‪createControlUpload($resourceView),
878  'info' => $this->‪createControlInfo($resourceView),
879  'delete' => $this->‪createControlDelete($resourceView),
880  'copy' => $this->‪createControlCopy($resourceView),
881  'cut' => $this->‪createControlCut($resourceView),
882  'paste' => $this->‪createControlPaste($resourceView),
883  'updateOnlineMedia' => $this->‪createControlUpdateOnlineMedia($resourceView),
884  ];
885 
886  $event = new ProcessFileListActionsEvent($resourceView->resource, $actions);
887  $event = $this->eventDispatcher->dispatch($event);
888  $actions = $event->getActionItems();
889 
890  // Remove empty actions
891  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
892 
893  // Compile items into a dropdown
894  $cellOutput = '';
895  ‪$output = '';
896  foreach ($actions as $key => $action) {
897  if (in_array($key, $primaryActions, true)) {
898  ‪$output .= $action;
899  continue;
900  }
901  // This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12.
902  $action = str_replace('btn btn-sm btn-default', 'dropdown-item dropdown-item-spaced', $action);
903  $title = [];
904  preg_match('/title="([^"]*)"/', $action, $title);
905  if (empty($title)) {
906  preg_match('/aria-label="([^"]*)"/', $action, $title);
907  }
908  if (!empty($title[1])) {
909  $action = str_replace(
910  [
911  '</a>',
912  '</button>',
913  ],
914  [
915  ' ' . $title[1] . '</a>',
916  ' ' . $title[1] . '</button>',
917  ],
918  $action
919  );
920  // In case we added the title as tag content, we can remove the attribute,
921  // since this is duplicated and would trigger a tooltip with the same content.
922  if (!empty($title[0])) {
923  $action = str_replace($title[0], '', $action);
924  }
925  $cellOutput .= '<li>' . $action . '</li>';
926  }
927  }
928 
929  if ($cellOutput !== '') {
930  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.more');
931  ‪$output .= '<div class="btn-group dropdown" title="' . htmlspecialchars($title) . '" >'
932  . '<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">'
933  . $this->iconFactory->getIcon('actions-menu-alternative', IconSize::SMALL)->render()
934  . '</a>'
935  . '<ul id="actions_' . $resourceView->resource->getHashedIdentifier() . '" class="dropdown-menu">' . $cellOutput . '</ul>'
936  . '</div>';
937  }
938 
939  return '<div class="btn-group">' . ‪$output . '</div>';
940  }
941 
945  protected function ‪renderControlBrowse(ResourceView $resourceView): string
946  {
947  $fileOrFolderObject = $resourceView->resource;
948  if (!$fileOrFolderObject instanceof File && !$fileOrFolderObject instanceof Folder) {
949  return '';
950  }
951 
952  $actions = [
953  'select' => $this->‪createControlSelect($resourceView),
954  'info' => $this->‪createControlInfo($resourceView),
955  ];
956 
957  // Remove empty actions
958  $actions = array_filter($actions, static fn($action) => $action !== null && trim($action) !== '');
959  if (empty($actions)) {
960  return '';
961  }
962 
963  return '<div class="btn-group">' . implode(' ', $actions) . '</div>';
964  }
965 
966  protected function ‪createControlSelect(‪ResourceView $resourceView): ?‪ButtonInterface
967  {
968  if (!$resourceView->isSelectable) {
969  return null;
970  }
971 
972  $title = sprintf(
973  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.selectFile'),
974  $resourceView->‪getName(),
975  );
976  $button = GeneralUtility::makeInstance(GenericButton::class);
977  $button->setTitle($title);
978  $button->setAttributes([
979  'type' => 'button',
980  'data-filelist-action' => 'select',
981  'aria-label' => $title,
982  ]);
983  $button->setIcon($this->iconFactory->getIcon('actions-plus', IconSize::SMALL));
984 
985  return $button;
986  }
987 
988  protected function ‪createControlEditContent(‪ResourceView $resourceView): ?‪ButtonInterface
989  {
990  if (!($resourceView->resource instanceof ‪File && $resourceView->resource->isTextFile())
991  || !$resourceView->‪canWrite()) {
992  return null;
993  }
994 
995  $button = GeneralUtility::makeInstance(LinkButton::class);
996  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent'));
997  $button->setHref($resourceView->editContentUri);
998  $button->setIcon($this->iconFactory->getIcon('actions-page-open', IconSize::SMALL));
999 
1000  return $button;
1001  }
1002 
1003  protected function ‪createControlEditMetaData(‪ResourceView $resourceView): ?‪ButtonInterface
1004  {
1005  if (!$resourceView->‪getMetaDataUid() || !$this->getBackendUser()->checkLanguageAccess(0)) {
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.editMetadata'));
1011  $button->setHref($resourceView->editDataUri);
1012  $button->setIcon($this->iconFactory->getIcon('actions-open', IconSize::SMALL));
1013 
1014  return $button;
1015  }
1016 
1017  protected function ‪createControlView(‪ResourceView $resourceView): ?‪ButtonInterface
1018  {
1019  if (!$resourceView->‪getPublicUrl()) {
1020  return null;
1021  }
1022 
1023  $button = GeneralUtility::makeInstance(GenericButton::class);
1024  $button->setTag('a');
1025  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.view'));
1026  $button->setHref($resourceView->‪getPublicUrl());
1027  $button->setAttributes(['target' => '_blank']);
1028  $button->setIcon($this->iconFactory->getIcon('actions-document-view', IconSize::SMALL));
1029 
1030  return $button;
1031  }
1032 
1033  protected function ‪createControlReplace(‪ResourceView $resourceView): ?‪ButtonInterface
1034  {
1035  if (!$resourceView->replaceUri) {
1036  return null;
1037  }
1038 
1039  $button = GeneralUtility::makeInstance(LinkButton::class);
1040  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace'));
1041  $button->setHref($resourceView->replaceUri);
1042  $button->setIcon($this->iconFactory->getIcon('actions-edit-replace', IconSize::SMALL));
1043 
1044  return $button;
1045  }
1046 
1047  protected function ‪createControlRename(‪ResourceView $resourceView): ?‪ButtonInterface
1048  {
1049  if (!$resourceView->‪canRename()) {
1050  return null;
1051  }
1052 
1053  $button = GeneralUtility::makeInstance(GenericButton::class);
1054  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename'));
1055  $button->setAttributes(['type' => 'button', 'data-filelist-action' => 'rename']);
1056  $button->setIcon($this->iconFactory->getIcon('actions-edit-rename', IconSize::SMALL));
1057 
1058  return $button;
1059  }
1060 
1061  protected function ‪createControlDownload(‪ResourceView $resourceView): ?‪ButtonInterface
1062  {
1063  if (!$resourceView->‪canRead() || !(bool)($this->getBackendUser()->getTSConfig()['options.']['file_list.']['fileDownload.']['enabled'] ?? true)) {
1064  return null;
1065  }
1066 
1067  if (!$resourceView->isDownloadable) {
1068  return null;
1069  }
1070 
1071  $button = GeneralUtility::makeInstance(GenericButton::class);
1072  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:download'));
1073  $button->setAttributes([
1074  'type' => 'button',
1075  'data-filelist-action' => 'download',
1076  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_download'),
1077  ]);
1078  $button->setIcon($this->iconFactory->getIcon('actions-download', IconSize::SMALL));
1079 
1080  return $button;
1081  }
1082 
1083  protected function ‪createControlUpload(‪ResourceView $resourceView): ?‪ButtonInterface
1084  {
1085  if (!$resourceView->resource->getStorage()->checkUserActionPermission('add', 'File')
1086  || !$resourceView->resource instanceof ‪Folder
1087  || !$resourceView->‪canWrite()) {
1088  return null;
1089  }
1090 
1091  $button = GeneralUtility::makeInstance(LinkButton::class);
1092  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload'));
1093  $button->setHref($this->uriBuilder->buildUriFromRoute('file_upload', ['target' => $resourceView->‪getIdentifier(), 'returnUrl' => $this->createModuleUri()]));
1094  $button->setIcon($this->iconFactory->getIcon('actions-edit-upload', IconSize::SMALL));
1095 
1096  return $button;
1097  }
1098 
1099  protected function ‪createControlInfo(‪ResourceView $resourceView): ?‪ButtonInterface
1100  {
1101  if (!$resourceView->‪canRead()) {
1102  return null;
1103  }
1104 
1105  $button = GeneralUtility::makeInstance(GenericButton::class);
1106  $button->setLabel($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info'));
1107  $button->setAttributes([
1108  'type' => 'button',
1109  'data-filelist-action' => 'show',
1110  ]);
1111  $button->setIcon($this->iconFactory->getIcon('actions-document-info', IconSize::SMALL));
1112 
1113  return $button;
1114  }
1115 
1116  protected function ‪createControlDelete(‪ResourceView $resourceView): ?‪ButtonInterface
1117  {
1118  if (!$resourceView->‪canDelete()) {
1119  return null;
1120  }
1121 
1122  $recordInfo = $resourceView->‪getName();
1123 
1124  if ($resourceView->resource instanceof Folder) {
1125  ‪$identifier = $resourceView->‪getIdentifier();
1126  $referenceCountText = BackendUtility::referenceCount('_FILE', ‪$identifier, LF . $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToFolder'));
1127  $deleteType = 'delete_folder';
1128  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1129  $recordInfo .= ' [' . ‪$identifier . ']';
1130  }
1131  } else {
1132  $referenceCountText = BackendUtility::referenceCount('sys_file', (string)$resourceView->‪getUid(), LF . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToFile'));
1133  $deleteType = 'delete_file';
1134  if ($this->‪getBackendUser()->shallDisplayDebugInformation()) {
1135  $recordInfo .= ' [sys_file:' . $resourceView->‪getUid() . ']';
1136  }
1137  }
1138 
1139  $title = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete');
1140  $button = GeneralUtility::makeInstance(GenericButton::class);
1141  $button->setLabel($title);
1142  $button->setIcon($this->iconFactory->getIcon('actions-edit-delete', IconSize::SMALL));
1143  $button->setAttributes([
1144  'type' => 'button',
1145  'data-title' => $title,
1146  'data-bs-content' => sprintf($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete'), trim($recordInfo)) . $referenceCountText,
1147  'data-filelist-action' => 'delete',
1148  'data-filelist-delete' => 'true',
1149  'data-filelist-delete-identifier' => $resourceView->‪getIdentifier(),
1150  'data-filelist-delete-url' => $this->uriBuilder->buildUriFromRoute('tce_file'),
1151  'data-filelist-delete-type' => $deleteType,
1152  'data-filelist-delete-check' => $this->getBackendUser()->jsConfirmation(‪JsConfirmation::DELETE) ? '1' : '0',
1153  ]);
1154 
1155  return $button;
1156  }
1157 
1164  protected function ‪createControlTranslation(ResourceView $resourceView): ?ButtonInterface
1165  {
1166  if (!$resourceView->resource instanceof File) {
1167  return null;
1168  }
1169 
1170  $backendUser = $this->‪getBackendUser();
1171 
1172  // Fetch all system languages except "default (0)" and "all languages (-1)"
1173  $systemLanguages = array_filter(
1174  $this->translateTools->getSystemLanguages(),
1175  static fn(array $languageRecord): bool => $languageRecord['uid'] > 0 && $backendUser->checkLanguageAccess($languageRecord['uid'])
1176  );
1177 
1178  if ($systemLanguages === []
1179  || !(‪$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? false)
1180  || !$resourceView->resource->isIndexed()
1181  || !$resourceView->resource->checkActionPermission('editMeta')
1182  || !$backendUser->check('tables_modify', 'sys_file_metadata')
1183  ) {
1184  // Early return in case no system languages exists or metadata
1185  // of this file can not be created / edited by the current user.
1186  return null;
1187  }
1188 
1189  $dropdownItems = [];
1190  $metaDataRecord = $resourceView->resource->getMetaData()->get();
1191  $existingTranslations = $this->getTranslationsForMetaData($metaDataRecord);
1192 
1193  foreach ($systemLanguages as $languageId => $language) {
1194  if (!isset($existingTranslations[$languageId]) && !($metaDataRecord['uid'] ?? false)) {
1195  // Skip if neither a translation nor the metadata uid exists
1196  continue;
1197  }
1198 
1199  if (isset($existingTranslations[$languageId])) {
1200  // Set options for edit action of an existing translation
1201  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:editMetadataForLanguage'), $language['title']);
1202  $actionType = 'edit';
1203  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1204  'record_edit',
1205  [
1206  'edit' => [
1207  'sys_file_metadata' => [
1208  $existingTranslations[$languageId]['uid'] => 'edit',
1209  ],
1210  ],
1211  'returnUrl' => $this->createModuleUri(),
1212  ]
1213  );
1214  } else {
1215  // Set options for "create new" action of a new translation
1216  $title = sprintf($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:createMetadataForLanguage'), $language['title']);
1217  $actionType = 'new';
1218  $metaDataRecordId = (int)($metaDataRecord['uid'] ?? 0);
1219  ‪$url = (string)$this->uriBuilder->buildUriFromRoute(
1220  'tce_db',
1221  [
1222  'cmd' => [
1223  'sys_file_metadata' => [
1224  $metaDataRecordId => [
1225  'localize' => $languageId,
1226  ],
1227  ],
1228  ],
1229  'redirect' => (string)$this->uriBuilder->buildUriFromRoute(
1230  'record_edit',
1231  [
1232  'justLocalized' => 'sys_file_metadata:' . $metaDataRecordId . ':' . $languageId,
1233  'returnUrl' => $this->‪createModuleUri(),
1234  ]
1235  ),
1236  ]
1237  );
1238  }
1239 
1240  $dropdownItem = GeneralUtility::makeInstance(DropDownItem::class);
1241  $dropdownItem->setLabel($title);
1242  $dropdownItem->setHref(‪$url);
1243  $dropdownItem->setIcon($this->iconFactory->getIcon($language['flagIcon'], IconSize::SMALL, 'overlay-' . $actionType));
1244  $dropdownItems[] = $dropdownItem;
1245  }
1246 
1247  if (empty($dropdownItems)) {
1248  return null;
1249  }
1250 
1251  $dropdownButton = GeneralUtility::makeInstance(DropDownButton::class);
1252  $dropdownButton->setLabel($this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:translations'));
1253  $dropdownButton->setIcon($this->iconFactory->getIcon('actions-translate', IconSize::SMALL));
1254  foreach ($dropdownItems as $dropdownItem) {
1255  $dropdownButton->addItem($dropdownItem);
1256  }
1257 
1258  return $dropdownButton;
1259  }
1260 
1261  protected function ‪createControlCopy(‪ResourceView $resourceView): ?‪ButtonInterface
1262  {
1263  if (!$resourceView->‪canRead() || !$resourceView->‪canCopy()) {
1264  return null;
1265  }
1266 
1267  if ($this->clipObj->current === 'normal') {
1268  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1269  $button = GeneralUtility::makeInstance(LinkButton::class);
1270  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'copy' ? 'copyrelease' : 'copy')));
1271  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), true, $isSelected === 'copy'));
1272  $button->setIcon($this->iconFactory->getIcon($isSelected === 'copy' ? 'actions-edit-copy-release' : 'actions-edit-copy', IconSize::SMALL));
1273  return $button;
1274  }
1275 
1276  return null;
1277  }
1278 
1279  protected function ‪createControlCut(‪ResourceView $resourceView): ?‪ButtonInterface
1280  {
1281  if (!$resourceView->‪canRead() || !$resourceView->‪canMove()) {
1282  return null;
1283  }
1284 
1285  if ($this->clipObj->current === 'normal') {
1286  $isSelected = $this->clipObj->isSelected('_FILE', md5($resourceView->‪getIdentifier()));
1287  $button = GeneralUtility::makeInstance(LinkButton::class);
1288  $button->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.' . ($isSelected === 'cut' ? 'cutrelease' : 'cut')));
1289  $button->setHref($this->clipObj->selUrlFile($resourceView->‪getIdentifier(), false, $isSelected === 'cut'));
1290  $button->setIcon($this->iconFactory->getIcon($isSelected === 'cut' ? 'actions-edit-cut-release' : 'actions-edit-cut', IconSize::SMALL));
1291 
1292  return $button;
1293  }
1294 
1295  return null;
1296  }
1297 
1298  protected function ‪createControlPaste(‪ResourceView $resourceView): ?‪ButtonInterface
1299  {
1300  $permission = ($this->clipObj->clipData[$this->clipObj->current]['mode'] ?? '') === 'copy' ? 'copy' : 'move';
1301  $addPasteButton = $this->folderObject->checkActionPermission($permission);
1302  $elementFromTable = $this->clipObj->elFromTable('_FILE');
1303  if ($elementFromTable === []
1304  || !$addPasteButton
1305  || !$resourceView->‪canRead()
1306  || !$resourceView->‪canWrite()
1307  || !$resourceView->resource instanceof ‪Folder) {
1308  return null;
1309  }
1310 
1311  $elementsToConfirm = [];
1312  foreach ($elementFromTable as $key => $element) {
1313  $clipBoardElement = $this->resourceFactory->retrieveFileOrFolderObject($element);
1314  if ($clipBoardElement instanceof Folder
1315  && $clipBoardElement->getStorage()->isWithinFolder($clipBoardElement, $resourceView->resource)
1316  ) {
1317  // In case folder is already present in the target folder, return actions without paste button
1318  return null;
1319  }
1320  $elementsToConfirm[$key] = $clipBoardElement->getName();
1321  }
1322 
1323  $pasteTitle = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:clip_pasteInto');
1324  $button = GeneralUtility::makeInstance(LinkButton::class);
1325  $button->setTitle($pasteTitle);
1326  $button->setHref($this->clipObj->pasteUrl('_FILE', $resourceView->‪getIdentifier()));
1327  $button->setDataAttributes([
1328  'title' => $pasteTitle,
1329  'bs-content' => $this->clipObj->confirmMsgText('_FILE', $resourceView->‪getName(), 'into', $elementsToConfirm),
1330  ]);
1331  $button->setIcon($this->iconFactory->getIcon('actions-document-paste-into', IconSize::SMALL));
1332 
1333  return $button;
1334  }
1335 
1336  protected function ‪createControlUpdateOnlineMedia(‪ResourceView $resourceView): ?‪ButtonInterface
1337  {
1338  if (!($resourceView->resource instanceof ‪File)
1339  || !$resourceView->‪canEditMetadata()
1340  || !$this->getBackendUser()->checkLanguageAccess(0)
1341  || !$this->onlineMediaHelperRegistry->hasOnlineMediaHelper($resourceView->resource->getExtension())
1342  ) {
1343  return null;
1344  }
1345 
1346  $title = $this->‪getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:reloadMetadata');
1347  $button = GeneralUtility::makeInstance(GenericButton::class);
1348  $button->setLabel($title);
1349  $button->setIcon($this->iconFactory->getIcon('actions-refresh', IconSize::SMALL));
1350  $button->setAttributes([
1351  'type' => 'button',
1352  'data-title' => $title,
1353  'data-filelist-action' => 'updateOnlineMedia',
1354  'data-filelist-action-url' => $this->uriBuilder->buildUriFromRoute('file_update_online_media'),
1355  ]);
1356 
1357  return $button;
1358  }
1359 
1360  protected function ‪isEditMetadataAllowed(‪File $file): bool
1361  {
1362  return $file->‪isIndexed()
1363  && $file->‪checkActionPermission('editMeta')
1364  && $this->‪getUserPermissions()->editMetaData;
1365  }
1366 
1372  protected function ‪renderCheckboxActions(): string
1373  {
1374  // Early return in case there are no items
1375  if (!$this->totalItems) {
1376  return '';
1377  }
1378 
1379  $lang = $this->‪getLanguageService();
1380 
1381  $dropdownItems['checkAll'] = '
1382  <li>
1383  <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')) . '">
1384  <span class="dropdown-item-columns">
1385  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1386  ' . $this->iconFactory->getIcon('actions-selection-elements-all', IconSize::SMALL)->render() . '
1387  </span>
1388  <span class="dropdown-item-column dropdown-item-column-title">
1389  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.checkAll')) . '
1390  </span>
1391  </span>
1392  </button>
1393  </li>';
1394 
1395  $dropdownItems['checkNone'] = '
1396  <li>
1397  <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')) . '">
1398  <span class="dropdown-item-columns">
1399  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1400  ' . $this->iconFactory->getIcon('actions-selection-elements-none', IconSize::SMALL)->render() . '
1401  </span>
1402  <span class="dropdown-item-column dropdown-item-column-title">
1403  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.uncheckAll')) . '
1404  </span>
1405  </span>
1406  </button>
1407  </li>';
1408 
1409  $dropdownItems['toggleSelection'] = '
1410  <li>
1411  <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')) . '">
1412  <span class="dropdown-item-columns">
1413  <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden="true">
1414  ' . $this->iconFactory->getIcon('actions-selection-elements-invert', IconSize::SMALL)->render() . '
1415  </span>
1416  <span class="dropdown-item-column dropdown-item-column-title">
1417  ' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleSelection')) . '
1418  </span>
1419  </span>
1420  </button>
1421  </li>';
1422 
1423  return '
1424  <div class="btn-group dropdown">
1425  <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">
1426  ' . $this->iconFactory->getIcon('actions-selection', IconSize::SMALL) . '
1427  </button>
1428  <ul class="dropdown-menu t3js-multi-record-selection-check-actions">
1429  ' . implode(PHP_EOL, $dropdownItems) . '
1430  </ul>
1431  </div>';
1432  }
1433 
1438  protected function ‪getConcreteTableName(string $fieldName): string
1439  {
1440  return (‪$GLOBALS['TCA']['sys_file']['columns'][$fieldName] ?? false) ? 'sys_file' : 'sys_file_metadata';
1441  }
1442 
1444  {
1445  $currentPagination = new ‪SimplePagination($paginator);
1446  $targetPage = null;
1447  switch ($direction) {
1449  $targetPage = $currentPagination->getPreviousPageNumber();
1450  break;
1451  case NavigationDirection::FORWARD:
1452  $targetPage = $currentPagination->getNextPageNumber();
1453  break;
1454  }
1455 
1456  return $this->‪getPaginationLinkForPage($paginator, $targetPage);
1457  }
1458 
1459  protected function ‪getPaginationLinkForPage(‪ResourceCollectionPaginator $paginator, ?int $targetPage = null): ?‪PaginationLink
1460  {
1461  if ($targetPage === null) {
1462  return null;
1463  }
1464  if ($targetPage > $paginator->‪getNumberOfPages()) {
1465  return null;
1466  }
1467  if ($targetPage < 1) {
1468  return null;
1469  }
1470 
1471  $targetPaginator = $paginator->‪withCurrentPageNumber($targetPage);
1472  $targetPagination = new SimplePagination($targetPaginator);
1473 
1474  $uri = new Uri($this->request->getAttribute('normalizedParams')->getRequestUri());
1475  parse_str($uri->getQuery(), $queryParameters);
1476  unset($queryParameters['contentOnly']);
1477  $queryParameters = array_merge($queryParameters, ['currentPage' => $targetPage]);
1478  if ($this->searchDemand) {
1479  $queryParameters['searchTerm'] = $this->searchDemand->getSearchTerm() ?? '';
1480  }
1481  $uri = $uri->withQuery(‪HttpUtility::buildQueryString($queryParameters, '&'));
1482 
1483  return new PaginationLink(
1484  $targetPagination->getStartRecordNumber() . '-' . $targetPagination->getEndRecordNumber(),
1485  (string)$uri,
1486  );
1487  }
1488 
1492  public function ‪createModuleUri(array $params = []): ?string
1493  {
1495  $queryParams = ‪$request->getQueryParams();
1496  $parsedBody = ‪$request->getParsedBody();
1497 
1498  $route = ‪$request->getAttribute('route');
1499  if (!$route instanceof Route) {
1500  return null;
1501  }
1502 
1503  $baseParams = [
1504  'currentPage' => ‪$this->currentPage,
1505  'id' => $this->folderObject->getCombinedIdentifier(),
1506  'searchTerm' => $this->searchDemand ? $this->searchDemand->getSearchTerm() : '',
1507  ];
1508 
1509  // Keep ElementBrowser Settings
1510  if (‪$mode = $parsedBody['mode'] ?? $queryParams['mode'] ?? null) {
1511  $baseParams['mode'] = ‪$mode;
1512  }
1513  if ($bparams = $parsedBody['bparams'] ?? $queryParams['bparams'] ?? null) {
1514  $baseParams['bparams'] = $bparams;
1515  }
1516 
1517  // Keep LinkHandler Settings
1518  if ($act = ($parsedBody['act'] ?? $queryParams['act'] ?? null)) {
1519  $baseParams['act'] = $act;
1520  }
1521  if ($linkHandlerParams = ($parsedBody['P'] ?? $queryParams['P'] ?? null)) {
1522  $baseParams['P'] = $linkHandlerParams;
1523  }
1524 
1525  $params = array_replace_recursive($baseParams, $params);
1526 
1527  // Expanded folder is used in the element browser.
1528  // We always map it to the id here.
1529  $params['expandFolder'] = $params['id'];
1530  $params = array_filter($params, static function ($value) {
1531  return (is_array($value) && $value !== []) || (trim((string)$value) !== '');
1532  });
1533 
1534  return (string)$this->uriBuilder->buildUriFromRequest(‪$request, $params);
1535  }
1536 
1537  protected function ‪createEditDataUriForResource(‪ResourceInterface $resource): ?string
1538  {
1539  if ($resource instanceof ‪File
1540  && $this->‪isEditMetadataAllowed($resource)
1541  && ($metaDataUid = $resource->getMetaData()->offsetGet('uid'))
1542  ) {
1543  $parameter = [
1544  'edit' => ['sys_file_metadata' => [$metaDataUid => 'edit']],
1545  'returnUrl' => $this->‪createModuleUri(),
1546  ];
1547  return (string)$this->uriBuilder->buildUriFromRoute('record_edit', $parameter);
1548  }
1549 
1550  return null;
1551  }
1552 
1553  protected function ‪createEditContentUriForResource(‪ResourceInterface $resource): ?string
1554  {
1555  if ($resource instanceof ‪File
1556  && $resource->checkActionPermission('write')
1557  && $resource->isTextFile()
1558  ) {
1559  $parameter = [
1560  'target' => $resource->getCombinedIdentifier(),
1561  'returnUrl' => $this->‪createModuleUri(),
1562  ];
1563  return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $parameter);
1564  }
1565 
1566  return null;
1567  }
1568 
1569  protected function ‪createModuleUriForResource(‪ResourceInterface $resource): ?string
1570  {
1571  if ($resource instanceof ‪Folder) {
1572  $parameter = [
1573  'id' => $resource->getCombinedIdentifier(),
1574  'searchTerm' => '',
1575  'currentPage' => 1,
1576  ];
1577  return (string)$this->‪createModuleUri($parameter);
1578  }
1579 
1580  if ($resource instanceof File) {
1581  return $this->‪createEditDataUriForResource($resource);
1582  }
1583 
1584  return null;
1585  }
1586 
1587  protected function ‪createReplaceUriForResource(‪ResourceInterface $resource): ?string
1588  {
1589  if ($resource instanceof ‪File
1590  && $resource->checkActionPermission('replace')
1591  ) {
1592  $parameter = [
1593  'target' => $resource->getCombinedIdentifier(),
1594  'uid' => $resource->getUid(),
1595  'returnUrl' => $this->‪createModuleUri(),
1596  ];
1597  return (string)$this->uriBuilder->buildUriFromRoute('file_replace', $parameter);
1598  }
1599  return null;
1600  }
1601 
1605  protected function ‪sortResources(array $resources, string $sortField): array
1606  {
1607  $collator = new \Collator((string)($this->‪getLanguageService()->getLocale() ?? 'en'));
1608  if ($sortField === 'size') {
1609  $collator->setAttribute(\Collator::NUMERIC_COLLATION, \Collator::ON);
1610  }
1611  uksort($resources, function (int $index1, int $index2) use ($sortField, $resources, $collator) {
1612  $resource1 = $resources[$index1];
1613  $resource2 = $resources[$index2];
1614 
1615  // Folders are always prioritized above files
1616  if ($resource1 instanceof File && $resource2 instanceof Folder) {
1617  return 1;
1618  }
1619  if ($resource1 instanceof Folder && $resource2 instanceof File) {
1620  return -1;
1621  }
1622 
1623  return (int)$collator->compare(
1624  $this->getSortingValue($resource1, $sortField) . $index1,
1625  $this->getSortingValue($resource2, $sortField) . $index2
1626  );
1627  });
1628 
1629  if ($this->sortRev) {
1630  $resources = array_reverse($resources);
1631  }
1632 
1633  return $resources;
1634  }
1635 
1636  protected function ‪getSortingValue(‪ResourceInterface $resource, string $sortField): string
1637  {
1638  if ($resource instanceof ‪File) {
1639  return $this->‪getSortingValueForFile($resource, $sortField);
1640  }
1641  if ($resource instanceof Folder) {
1642  return $this->‪getSortingValueForFolder($resource, $sortField);
1643  }
1644 
1645  return '';
1646  }
1647 
1648  protected function ‪getSortingValueForFile(‪File $resource, string $sortField): string
1649  {
1650  switch ($sortField) {
1651  case 'fileext':
1652  return $resource->‪getExtension();
1653  case 'size':
1654  return $resource->getSize() . 's';
1655  case 'rw':
1656  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1657  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1658  case '_REF_':
1659  return $this->‪getFileReferenceCount($resource) . 'ref';
1660  case 'tstamp':
1661  return $resource->‪getModificationTime() . 't';
1662  case 'crdate':
1663  return $resource->‪getCreationTime() . 'c';
1664  default:
1665  return $resource->‪hasProperty($sortField) ? (string)$resource->‪getProperty($sortField) : '';
1666  }
1667  }
1668 
1669  protected function ‪getSortingValueForFolder(‪Folder $resource, string $sortField): string
1670  {
1671  switch ($sortField) {
1672  case 'size':
1673  try {
1674  $fileCount = $resource->‪getFileCount();
1676  $fileCount = 0;
1677  }
1678  return '0' . $fileCount . 's';
1679  case 'rw':
1680  return ($resource->‪checkActionPermission('read') ? 'R' : '')
1681  . ($resource->‪checkActionPermission('write') ? 'W' : '');
1682  case 'name':
1683  return $resource->‪getName();
1684  default:
1685  return '';
1686  }
1687  }
1688 
1689  protected function ‪getFieldLabel(string $field): string
1690  {
1691  $lang = $this->‪getLanguageService();
1692 
1693  if ($specialLabel = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.' . $field)) {
1694  return $specialLabel;
1695  }
1696  if ($customLabel = $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:c_' . $field)) {
1697  return $customLabel;
1698  }
1699 
1700  $concreteTableName = $this->‪getConcreteTableName($field);
1701  $label = BackendUtility::getItemLabel($concreteTableName, $field);
1702 
1703  // In case global TSconfig exists we have to check if the label is overridden there
1704  $tsConfig = BackendUtility::getPagesTSconfig(0);
1705  $label = $lang->translateLabel(
1706  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label.'] ?? [],
1707  $tsConfig['TCEFORM.'][$concreteTableName . '.'][$field . '.']['label'] ?? $label
1708  );
1709 
1710  return $label;
1711  }
1712 
1718  protected function ‪getFileReferenceCount(File $file): int
1719  {
1720  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
1721  return (int)$queryBuilder
1722  ->count('*')
1723  ->from('sys_refindex')
1724  ->where(
1725  $queryBuilder->expr()->eq(
1726  'ref_table',
1727  $queryBuilder->createNamedParameter('sys_file')
1728  ),
1729  $queryBuilder->expr()->eq(
1730  'ref_uid',
1731  $queryBuilder->createNamedParameter($file->getUid(), ‪Connection::PARAM_INT)
1732  ),
1733  $queryBuilder->expr()->neq(
1734  'tablename',
1735  $queryBuilder->createNamedParameter('sys_file_metadata')
1736  )
1737  )
1738  ->executeQuery()
1739  ->fetchOne();
1740  }
1741 
1742  protected function ‪getUserPermissions(): ‪UserPermissions
1743  {
1744  return new ‪UserPermissions($this->‪getBackendUser()->check('tables_modify', 'sys_file_metadata'));
1745  }
1746 
1747  protected function ‪getLanguageService(): ‪LanguageService
1748  {
1749  return ‪$GLOBALS['LANG'];
1750  }
1751 
1752  protected function ‪getBackendUser(): ‪BackendUserAuthentication
1753  {
1754  return ‪$GLOBALS['BE_USER'];
1755  }
1756 }
‪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\Filelist\FileList\renderControl
‪renderControl(ResourceView $resourceView)
Definition: FileList.php:839
‪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:1162
‪TYPO3\CMS\Filelist\FileList\$onlineMediaHelperRegistry
‪OnlineMediaHelperRegistry $onlineMediaHelperRegistry
Definition: FileList.php:159
‪TYPO3\CMS\Filelist\FileList\getBackendUser
‪getBackendUser()
Definition: FileList.php:1750
‪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:1551
‪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: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:1259
‪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:1081
‪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:717
‪TYPO3\CMS\Filelist\FileList\createControlUpdateOnlineMedia
‪createControlUpdateOnlineMedia(ResourceView $resourceView)
Definition: FileList.php:1334
‪TYPO3\CMS\Filelist\FileList\getConcreteTableName
‪getConcreteTableName(string $fieldName)
Definition: FileList.php:1436
‪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:34
‪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:708
‪TYPO3\CMS\Filelist\Dto\ResourceView\getCheckboxConfig
‪getCheckboxConfig()
Definition: ResourceView.php:192
‪TYPO3\CMS\Filelist\FileList\renderReferenceCount
‪renderReferenceCount(ResourceView $resourceView)
Definition: FileList.php:815
‪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:1740
‪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:1567
‪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:1059
‪TYPO3\CMS\Filelist\FileList\getSortingValueForFolder
‪getSortingValueForFolder(Folder $resource, string $sortField)
Definition: FileList.php:1667
‪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:1716
‪TYPO3\CMS\Filelist\FileList\$mode
‪Mode $mode
Definition: FileList.php:75
‪TYPO3\CMS\Filelist\FileList\renderPath
‪renderPath(ResourceView $resourceView)
Definition: FileList.php:806
‪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:1646
‪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:1097
‪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:1031
‪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:943
‪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:964
‪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:986
‪TYPO3\CMS\Filelist\FileList\createControlRename
‪createControlRename(ResourceView $resourceView)
Definition: FileList.php:1045
‪TYPO3\CMS\Filelist\FileList\createControlView
‪createControlView(ResourceView $resourceView)
Definition: FileList.php:1015
‪TYPO3\CMS\Filelist\FileList\getPaginationLinkForDirection
‪getPaginationLinkForDirection(ResourceCollectionPaginator $paginator, NavigationDirection $direction)
Definition: FileList.php:1441
‪TYPO3\CMS\Core\Resource\File\checkActionPermission
‪bool checkActionPermission($action)
Definition: File.php:208
‪TYPO3\CMS\Filelist\FileList\createEditDataUriForResource
‪createEditDataUriForResource(ResourceInterface $resource)
Definition: FileList.php:1535
‪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
‪$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: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:752
‪TYPO3\CMS\Filelist\FileList\createReplaceUriForResource
‪createReplaceUriForResource(ResourceInterface $resource)
Definition: FileList.php:1585
‪TYPO3\CMS\Filelist\FileList\$currentPage
‪int $currentPage
Definition: FileList.php:86
‪TYPO3\CMS\Filelist\FileList\createModuleUri
‪createModuleUri(array $params=[])
Definition: FileList.php:1490
‪$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:1457
‪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:741
‪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:1687
‪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:780
‪TYPO3\CMS\Filelist\FileList\getLanguageService
‪getLanguageService()
Definition: FileList.php:1745
‪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:1603
‪TYPO3\CMS\Filelist\FileList\renderCheckboxActions
‪string renderCheckboxActions()
Definition: FileList.php:1370
‪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:1634
‪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:1114
‪TYPO3\CMS\Filelist\FileList\renderName
‪renderName(ResourceView $resourceView)
Definition: FileList.php:622
‪TYPO3\CMS\Filelist\FileList\createControlCut
‪createControlCut(ResourceView $resourceView)
Definition: FileList.php:1277
‪TYPO3\CMS\Filelist\FileList\isEditMetadataAllowed
‪isEditMetadataAllowed(File $file)
Definition: FileList.php:1358
‪TYPO3\CMS\Backend\Template\Components\Buttons\DropDown\DropDownItem
Definition: DropDownItem.php:34
‪TYPO3\CMS\Filelist\FileList\renderControlManage
‪renderControlManage(ResourceView $resourceView)
Definition: FileList.php:850
‪TYPO3\CMS\Filelist\FileList\createControlEditMetaData
‪createControlEditMetaData(ResourceView $resourceView)
Definition: FileList.php:1001
‪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:1296
‪TYPO3\CMS\Core\Resource\File\hasProperty
‪hasProperty($key)
Definition: File.php:76