2 namespace TYPO3\CMS\Recordlist\LinkHandler
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use Psr\Http\Message\ServerRequestInterface
;
18 use TYPO3\CMS\Backend\Tree\View\ElementBrowserFolderTreeView
;
19 use TYPO3\CMS\Core\Imaging\Icon
;
20 use TYPO3\CMS\Core\LinkHandling\LinkService
;
21 use TYPO3\CMS\Core\Page\PageRenderer
;
22 use TYPO3\CMS\Core\
Resource\File
;
23 use TYPO3\CMS\Core\
Resource\FileInterface
;
24 use TYPO3\CMS\Core\
Resource\Filter\FileExtensionFilter
;
25 use TYPO3\CMS\Core\
Resource\Folder
;
26 use TYPO3\CMS\Core\
Resource\ResourceFactory
;
27 use TYPO3\CMS\Core\
Resource\ResourceInterface
;
28 use TYPO3\CMS\Core\Utility\GeneralUtility
;
29 use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface
;
30 use TYPO3\CMS\Recordlist\View\FolderUtilityRenderer
;
33 * Link handler for files
35 class FileLinkHandler
extends AbstractLinkHandler
implements LinkHandlerInterface
, LinkParameterProviderInterface
38 * Parts of the current link
42 protected $linkParts = [];
47 protected $expectedClass = File
::class;
52 protected $mode = 'file';
57 protected $expandFolder;
60 * Checks if this is the handler for the given link
62 * The handler may store this information locally for later usage.
64 * @param array $linkParts Link parts as returned from TypoLinkCodecService
68 public function canHandleLink(array $linkParts)
70 if (!$linkParts['url']) {
73 if (isset($linkParts['url'][$this->mode
]) && $linkParts['url'][$this->mode
] instanceof $this->expectedClass
) {
74 $this->linkParts
= $linkParts;
81 * Format the current link for HTML output
85 public function formatCurrentUrl()
87 return $this->linkParts
['url'][$this->mode
]->getName();
91 * Render the link handler
93 * @param ServerRequestInterface $request
97 public function render(ServerRequestInterface
$request)
99 GeneralUtility
::makeInstance(PageRenderer
::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/FileLinkHandler');
101 /** @var ElementBrowserFolderTreeView $folderTree */
102 $folderTree = GeneralUtility
::makeInstance(ElementBrowserFolderTreeView
::class);
103 $folderTree->setLinkParameterProvider($this);
104 $this->view
->assign('tree', $folderTree->getBrowsableTree());
106 $this->expandFolder
= isset($request->getQueryParams()['expandFolder']) ?
$request->getQueryParams()['expandFolder'] : null;
107 if (!empty($this->linkParts
) && !isset($this->expandFolder
)) {
108 $this->expandFolder
= $this->linkParts
['url'][$this->mode
];
109 if ($this->expandFolder
instanceof File
) {
110 $this->expandFolder
= $this->expandFolder
->getParentFolder();
112 if ($this->expandFolder
instanceof Folder
) {
113 $this->expandFolder
= $this->expandFolder
->getCombinedIdentifier();
117 // Create upload/create folder forms, if a path is given
118 $selectedFolder = $this->getSelectedFolder($this->expandFolder
);
120 // Build the file upload and folder creation form
121 if ($selectedFolder) {
122 $folderUtilityRenderer = GeneralUtility
::makeInstance(FolderUtilityRenderer
::class, $this);
123 $uploadForm = $this->mode
=== 'file' ?
$folderUtilityRenderer->uploadForm($selectedFolder, []) : '';
124 $createFolder = $folderUtilityRenderer->createFolder($selectedFolder);
126 // Insert the upload form on top, if so configured
127 $positionOfUploadFieldsOnTop = $this->getBackendUser()->getTSConfigVal('options.uploadFieldsInTopOfEB');
128 $this->view
->assign('positionOfUploadFields', $positionOfUploadFieldsOnTop ?
'top' : 'bottom');
129 $this->view
->assign('uploadFileForm', $uploadForm);
130 $this->view
->assign('createFolderForm', $createFolder);
132 // Render the file or folderlist
133 if ($selectedFolder->checkActionPermission('read')) {
134 $this->view
->assign('selectedFolder', $selectedFolder);
135 $parameters = $this->linkBrowser
->getUrlParameters();
136 $allowedExtensions = isset($parameters['allowedExtensions']) ?
$parameters['allowedExtensions'] : '';
137 $this->expandFolder($selectedFolder, $allowedExtensions);
141 return $this->view
->render(ucfirst($this->mode
));
145 * For RTE: This displays all files from folder. No thumbnails shown
147 * @param Folder $folder The folder path to expand
148 * @param string $extensionList List of file extensions to show
149 * @return string HTML output
151 public function expandFolder(Folder
$folder, $extensionList = '')
153 // Create header element; The folder from which files are listed.
154 $folderIcon = $this->iconFactory
->getIconForResource($folder, Icon
::SIZE_SMALL
)->render();
155 $this->view
->assign('selectedFolderIcon', $folderIcon);
156 $this->view
->assign('selectedFolderTitle', GeneralUtility
::fixed_lgd_cs($folder->getIdentifier(), (int)$this->getBackendUser()->uc
['titleLen']));
157 if ($this->mode
=== 'file') {
158 $this->view
->assign('currentIdentifier', !empty($this->linkParts
) ?
$this->linkParts
['url']['file']->getUid() : '');
160 $this->view
->assign('currentIdentifier', !empty($this->linkParts
) ?
$this->linkParts
['url']['folder']->getCombinedIdentifier() : '');
163 // Get files from the folder:
164 $fileObjects = $this->getFolderContent($folder, $extensionList);
165 $itemsInSelectedFolder = [];
166 if (!empty($fileObjects)) {
167 foreach ($fileObjects as $fileOrFolderObject) {
168 $itemsInSelectedFolder[] = $this->renderItem($fileOrFolderObject);
171 $this->view
->assign('itemsInSelectedFolder', $itemsInSelectedFolder);
175 * @param Folder $folder
176 * @param string $extensionList
178 * @return FileInterface[]|Folder[]
180 protected function getFolderContent(Folder
$folder, $extensionList)
182 if ($extensionList !== '') {
183 /** @var FileExtensionFilter $filter */
184 $filter = GeneralUtility
::makeInstance(FileExtensionFilter
::class);
185 $filter->setAllowedFileExtensions($extensionList);
186 $folder->setFileAndFolderNameFilters([[$filter, 'filterFileList']]);
188 return $folder->getFiles();
192 * Renders a single item displayed in the current folder
194 * @param ResourceInterface $fileOrFolderObject
197 * @throws \InvalidArgumentException
199 protected function renderItem(ResourceInterface
$fileOrFolderObject)
201 if (!$fileOrFolderObject instanceof File
) {
202 throw new \
InvalidArgumentException('Expected File object, got "' . get_class($fileOrFolderObject) . '" object.', 1443651368);
204 // Get size and icon:
205 $size = GeneralUtility
::formatSize(
206 $fileOrFolderObject->getSize(),
207 $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')
211 'icon' => $this->iconFactory
->getIconForResource($fileOrFolderObject, Icon
::SIZE_SMALL
)->render(),
212 'uid' => $fileOrFolderObject->getUid(),
214 'name' => $fileOrFolderObject->getName(),
215 'url' => GeneralUtility
::makeInstance(LinkService
::class)->asString(['type' => LinkService
::TYPE_FILE
, 'file' => $fileOrFolderObject]),
216 'title' => GeneralUtility
::fixed_lgd_cs($fileOrFolderObject->getName(), (int)$this->getBackendUser()->uc
['titleLen'])
221 * @return string[] Array of body-tag attributes
223 public function getBodyTagAttributes()
226 'data-current-link' => GeneralUtility
::makeInstance(LinkService
::class)->asString(['type' => LinkService
::TYPE_FILE
, 'file' => $this->linkParts
['url']['file']])
231 * @param array $values Array of values to include into the parameters or which might influence the parameters
233 * @return string[] Array of parameters which have to be added to URLs
235 public function getUrlParameters(array $values)
238 'expandFolder' => $values['identifier'] ??
$this->expandFolder
240 return array_merge($this->linkBrowser
->getUrlParameters($values), $parameters);
244 * @param array $values Values to be checked
246 * @return bool Returns TRUE if the given values match the currently selected item
248 public function isCurrentlySelectedItem(array $values)
254 * Returns the URL of the current script
258 public function getScriptUrl()
260 return $this->linkBrowser
->getScriptUrl();
264 * Returns the currently selected folder, or th default upload folder
266 * @param string $folderIdentifier
267 * @return mixed the folder object or false if nothing was found
269 protected function getSelectedFolder($folderIdentifier = '')
271 $selectedFolder = false;
272 if ($folderIdentifier) {
274 $fileOrFolderObject = ResourceFactory
::getInstance()->retrieveFileOrFolderObject($folderIdentifier);
275 if ($fileOrFolderObject instanceof Folder
) {
277 $selectedFolder = $fileOrFolderObject;
278 } elseif ($fileOrFolderObject instanceof FileInterface
) {
281 $selectedFolder = $fileOrFolderObject->getParentFolder();
282 } catch (\Exception
$e) {
283 // Accessing the parent folder failed for some reason. e.g. permissions
286 } catch (\Exception
$e) {
287 // No path is selected
291 // If no folder is selected, get the user's default upload folder
292 if (!$selectedFolder) {
294 $selectedFolder = $this->getBackendUser()->getDefaultUploadFolder();
295 } catch (\Exception
$e) {
296 // The configured default user folder does not exist
299 return $selectedFolder;