languageService = $this->languageServiceFactory->createFromUserPreferences($this->getBackendUser()); } public function canHandleLink(array $linkParts): bool { if (!$linkParts['url']) { return false; } if (isset($linkParts['url'][$this->type->value]) && $linkParts['url'][$this->type->value] instanceof ($this->type->getResourceType())) { $this->linkParts = $linkParts; return true; } return false; } public function formatCurrentUrl(): string { $resource = $this->linkParts['url'][$this->type->value]; if (!$resource->checkActionPermission('read')) { return ''; } if ($resource->getStorage()->isFallbackStorage()) { return ''; } return $this->linkParts['url'][$this->type->value]->getName(); } public function createView(BackendViewFactory $backendViewFactory, ServerRequestInterface $request): ViewInterface { return $backendViewFactory->create($request, ['typo3/cms-filelist']); } public function setView(ViewInterface $view): self { $this->view = $view; return $this; } public function getView(): ViewInterface { return $this->view; } public function getLinkAttributes(): array { return ['target', 'title', 'class', 'params', 'rel', 'download']; } public function initialize(AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration) { $this->linkBrowser = $linkBrowser; } public function initializeVariables(ServerRequestInterface $request): void { $this->pageRenderer->loadJavaScriptModule('@typo3/backend/tree/file-storage-browser.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/filelist/file-list-actions.js'); $this->currentPage = (int)($request->getParsedBody()['currentPage'] ?? $request->getQueryParams()['currentPage'] ?? 1); $this->sortField = ($request->getParsedBody()['sortField'] ?? $request->getQueryParams()['sortField'] ?? 'name'); $this->sortDirection = SortDirection::tryFrom($request->getParsedBody()['sortDirection'] ?? $request->getQueryParams()['sortDirection'] ?? '') ?? SortDirection::ASCENDING; $this->viewMode = ViewMode::tryFrom($request->getParsedBody()['viewMode'] ?? $request->getQueryParams()['viewMode'] ?? ''); if ($this->viewMode !== null) { $this->getBackendUser()->pushModuleData( $this->moduleStorageIdentifier, array_merge($this->getBackendUser()->getModuleData($this->moduleStorageIdentifier) ?? [], ['viewMode' => $this->viewMode->value]) ); } else { $this->viewMode = ViewMode::tryFrom($this->getBackendUser()->getModuleData($this->moduleStorageIdentifier)['viewMode'] ?? '') ?? ViewMode::tryFrom($this->getBackendUser()->getTSConfig()['options.']['defaultResourcesViewMode'] ?? '') ?? ViewMode::TILES; } $displayThumbs = $request->getParsedBody()['displayThumbs'] ?? $request->getQueryParams()['displayThumbs'] ?? null; if ($displayThumbs !== null) { $this->displayThumbs = (bool)$displayThumbs; $this->getBackendUser()->pushModuleData( $this->moduleStorageIdentifier, array_merge($this->getBackendUser()->getModuleData($this->moduleStorageIdentifier) ?? [], ['displayThumbs' => $this->displayThumbs]) ); } else { $this->displayThumbs = (bool)($this->getBackendUser()->getModuleData($this->moduleStorageIdentifier)['displayThumbs'] ?? true); } // Selected Folder folder $this->expandFolder = $request->getParsedBody()['expandFolder'] ?? $request->getQueryParams()['expandFolder'] ?? null; if ($this->expandFolder === null) { if (!empty($this->linkParts)) { $resource = $this->linkParts['url'][$this->type->value]; if ($resource instanceof File) { $resource = $resource->getParentFolder(); } if ($resource instanceof Folder) { $this->expandFolder = $resource->getCombinedIdentifier(); if ($this->type === LinkType::FOLDER) { // Select the parent folder of selected folder as entry point. $this->expandFolder = $resource->getParentFolder()->getCombinedIdentifier(); } } } else { // Look up in the user's session which folder was opened the last time $moduleSessionData = $this->getBackendUser()->getModuleData('browse_links.php', 'ses'); $this->expandFolder = $moduleSessionData['expandFolder'] ?? null; } } if ($this->expandFolder) { try { $selectedFolder = $this->resourceFactory->getFolderObjectFromCombinedIdentifier($this->expandFolder); if ($selectedFolder->checkActionPermission('read') && !$selectedFolder->getStorage()->isFallbackStorage()) { $this->selectedFolder = $selectedFolder; } } catch (FolderDoesNotExistException|InsufficientFolderAccessPermissionsException) { // Outdated module session data: Last used folder has been removed meanwhile, or // access to last used folder has been removed. Do not set a preselected folder. } } $this->filelist = GeneralUtility::makeInstance(FileList::class, $request); $this->filelist->viewMode = $this->viewMode; $this->filelist->thumbs = ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] ?? false) && $this->displayThumbs; } public function modifyLinkAttributes(array $fieldDefinitions): array { return $fieldDefinitions; } public function isUpdateSupported(): bool { $resource = $this->linkParts['url'][$this->type->value]; if (!$resource->checkActionPermission('read')) { return false; } if ($resource->getStorage()->isFallbackStorage()) { return false; } return true; } /** * @return string[] Array of body-tag attributes */ public function getBodyTagAttributes(): array { $resource = $this->linkParts['url'][$this->type->value] ?? null; if (!$resource instanceof ($this->type->getResourceType())) { return []; } if (!$resource->checkActionPermission('read')) { return []; } if ($resource->getStorage()->isFallbackStorage()) { return []; } return [ 'data-linkbrowser-current-link' => GeneralUtility::makeInstance(LinkService::class)->asString([ 'type' => $this->type->getLinkServiceType(), $this->type->value => $resource, ]), ]; } protected function createUri(ServerRequestInterface $request, array $parameters = []): string { return (string)$this->uriBuilder->buildUriFromRequest($request, $this->getUrlParameters($parameters)); } protected function getSortingModeButtons(ServerRequestInterface $request): ButtonInterface { $sortingButton = $this->componentFactory->createDropDownButton() ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.sorting')) ->setIcon($this->iconFactory->getIcon($this->sortDirection->getIconIdentifier())); $sortingModeButtons = []; $sortableFields = $this->filelist->getSortableFields(); if (count($sortableFields) > 1) { foreach ($sortableFields as $field) { $label = $this->filelist->getFieldLabel($field); $sortingModeButtons[] = $this->componentFactory->createDropDownRadio() ->setActive($this->sortField === $field) ->setHref($this->createUri($request, [ 'sortField' => $field, 'sortDirection' => SortDirection::ASCENDING->value, 'currentPage' => 1, ])) ->setLabel($label); } $sortingModeButtons[] = $this->componentFactory->createDropDownDivider(); } $defaultSortingDirectionParams = ['sortField' => $this->sortField, 'currentPage' => 1]; $sortingModeButtons[] = $this->componentFactory->createDropDownRadio() ->setActive($this->sortDirection === SortDirection::ASCENDING) ->setHref($this->createUri($request, array_merge($defaultSortingDirectionParams, ['sortDirection' => SortDirection::ASCENDING->value]))) ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.sorting.asc')); $sortingModeButtons[] = $this->componentFactory->createDropDownRadio() ->setActive($this->sortDirection === SortDirection::DESCENDING) ->setHref($this->createUri($request, array_merge($defaultSortingDirectionParams, ['sortDirection' => SortDirection::DESCENDING->value]))) ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.sorting.desc')); foreach ($sortingModeButtons as $sortingModeButton) { $sortingButton->addItem($sortingModeButton); } return $sortingButton; } protected function getViewModeButton(ServerRequestInterface $request): ButtonInterface { $viewModeItems = []; $viewModeItems[] = $this->componentFactory->createDropDownRadio() ->setActive($this->viewMode === ViewMode::TILES) ->setHref($this->createUri($request, ['viewMode' => ViewMode::TILES->value])) ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.tiles')) ->setIcon($this->iconFactory->getIcon('actions-viewmode-tiles')); $viewModeItems[] = $this->componentFactory->createDropDownRadio() ->setActive($this->viewMode === ViewMode::LIST) ->setHref($this->createUri($request, ['viewMode' => ViewMode::LIST->value])) ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.list')) ->setIcon($this->iconFactory->getIcon('actions-viewmode-list')); if (!($this->getBackendUser()->getTSConfig()['options.']['noThumbsInEB'] ?? false)) { $viewModeItems[] = $this->componentFactory->createDropDownDivider(); $viewModeItems[] = $this->componentFactory->createDropDownToggle() ->setActive($this->displayThumbs) ->setHref($this->createUri($request, ['displayThumbs' => $this->displayThumbs ? 0 : 1])) ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.showThumbnails')) ->setIcon($this->iconFactory->getIcon('actions-image')); } if ( ($this->getBackendUser()->getTSConfig()['options.']['file_list.']['displayColumnSelector'] ?? true) && $this->viewMode === ViewMode::LIST && ($request->getQueryParams()['act'] ?? '') === 'file' ) { $this->pageRenderer->loadJavaScriptModule('@typo3/backend/column-selector-button.js'); $viewModeItems[] = $this->componentFactory->createDropDownDivider(); $viewModeItems[] = $this->componentFactory->createDropDownItem() ->setTag('typo3-backend-column-selector-button') ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view.selectColumns')) ->setAttributes([ 'data-url' => (string)$this->uriBuilder->buildUriFromRoute( 'ajax_show_columns_selector', ['table' => '_FILE'] ), 'data-target' => (string)$this->filelist->createModuleUri(), 'data-title' => sprintf( $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:showColumnsSelection'), $this->tcaSchemaFactory->get('sys_file')->getTitle($this->getLanguageService()->sL(...)), ), 'data-button-ok' => $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:updateColumnView'), 'data-button-close' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.cancel'), 'data-error-message' => $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_column_selector.xlf:updateColumnView.error'), ]) ->setIcon($this->iconFactory->getIcon('actions-options')); } $viewModeButton = $this->componentFactory->createDropDownButton() ->setLabel($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.view')) ->setIcon($this->iconFactory->getIcon('actions-cog')); foreach ($viewModeItems as $viewModeItem) { $viewModeButton->addItem($viewModeItem); } return $viewModeButton; } public function getUrlParameters(array $values): array { $values = array_replace_recursive([ 'expandFolder' => $values['identifier'] ?? $this->expandFolder, ], $values); return array_merge($this->linkBrowser->getUrlParameters($values), $values); } protected function getLanguageService(): LanguageService { return $this->languageService; } protected function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } }