TYPO3  7.6
FileLinkHandler.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Recordlist\LinkHandler;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
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.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
21 use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
32 
37 {
43  protected $linkParts = [];
44 
48  protected $expectedClass = File::class;
49 
53  protected $mode = 'file';
54 
58  protected $expandFolder;
59 
63  protected $additionalFolderClass = '';
64 
74  public function canHandleLink(array $linkParts)
75  {
76  if (!$linkParts['url']) {
77  return false;
78  }
79  $url = rawurldecode($linkParts['url']);
80 
81  if (StringUtility::beginsWith($url, 'file:') && !StringUtility::beginsWith($url, 'file://')) {
82  $rel = substr($url, 5);
83  try {
84  // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
85  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
86  if (is_a($fileOrFolderObject, $this->expectedClass)) {
87  $this->linkParts = $linkParts;
88  $this->linkParts['url'] = $rel;
89  $this->linkParts['name'] = $fileOrFolderObject->getName();
90  return true;
91  }
92  } catch (FileDoesNotExistException $e) {
93  }
94  }
95  return false;
96  }
97 
103  public function formatCurrentUrl()
104  {
105  return $this->linkParts['name'];
106  }
107 
115  public function render(ServerRequestInterface $request)
116  {
117  GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/FileLinkHandler');
118 
119  $this->expandFolder = isset($request->getQueryParams()['expandFolder']) ? $request->getQueryParams()['expandFolder'] : null;
120  if (!empty($this->linkParts) && !isset($this->expandFolder)) {
121  $this->expandFolder = $this->linkParts['url'];
122  }
123 
125  $folderTree = GeneralUtility::makeInstance(ElementBrowserFolderTreeView::class);
126  $folderTree->setLinkParameterProvider($this);
127  $tree = $folderTree->getBrowsableTree();
128 
129  // Create upload/create folder forms, if a path is given
130  $selectedFolder = false;
131  if ($this->expandFolder) {
132  $fileOrFolderObject = null;
133  try {
134  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
135  } catch (\Exception $e) {
136  // No path is selected
137  }
138 
139  if ($fileOrFolderObject instanceof Folder) {
140  // It's a folder
141  $selectedFolder = $fileOrFolderObject;
142  } elseif ($fileOrFolderObject instanceof FileInterface) {
143  // It's a file
144  try {
145  $selectedFolder = $fileOrFolderObject->getParentFolder();
146  } catch (\Exception $e) {
147  // Accessing the parent folder failed for some reason. e.g. permissions
148  }
149  }
150  }
151 
152  $backendUser = $this->getBackendUser();
153  // If no folder is selected, get the user's default upload folder
154  if (!$selectedFolder) {
155  try {
156  $selectedFolder = $backendUser->getDefaultUploadFolder();
157  } catch (\Exception $e) {
158  // The configured default user folder does not exist
159  }
160  }
161  // Build the file upload and folder creation form
162  $uploadForm = '';
163  $createFolder = '';
164  $content = '';
165  if ($selectedFolder) {
166  $folderUtilityRenderer = GeneralUtility::makeInstance(FolderUtilityRenderer::class, $this);
167  $uploadForm = $this->mode === 'file' ? $folderUtilityRenderer->uploadForm($selectedFolder, []) : '';
168  $createFolder = $folderUtilityRenderer->createFolder($selectedFolder);
169  }
170  // Insert the upload form on top, if so configured
171  if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
172  $content .= $uploadForm;
173  }
174 
175  // Render the filelist if there is a folder selected
176  $files = '';
177  if ($selectedFolder) {
178  $parameters = $this->linkBrowser->getUrlParameters();
179  $allowedExtensions = isset($parameters['allowedExtensions']) ? $parameters['allowedExtensions'] : '';
180  $files = $this->expandFolder($selectedFolder, $allowedExtensions);
181  }
182  // Create folder tree:
183  $content .= '
184  <!--
185  Wrapper table for folder tree / file/folder list:
186  -->
187  <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
188  <tr>
189  <td class="c-wCell" valign="top"><h3>' . $this->getLanguageService()->getLL('folderTree') . ':</h3>' . $tree . '</td>
190  <td class="c-wCell" valign="top">' . $files . '</td>
191  </tr>
192  </table>
193  ';
194  // Adding create folder + upload form if applicable
195  if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
196  $content .= $uploadForm;
197  }
198  $content .= '<br />' . $createFolder . '<br />';
199  return $content;
200  }
201 
209  public function expandFolder(Folder $folder, $extensionList = '')
210  {
211  if (!$folder->checkActionPermission('read')) {
212  return '';
213  }
214  $out = '<h3>' . htmlspecialchars($this->getTitle()) . ':</h3>';
215 
216  // Create header element; The folder from which files are listed.
217  $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
218  $folderIcon = $this->iconFactory->getIconForResource($folder, Icon::SIZE_SMALL);
219  $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen));
220 
221  $currentIdentifier = !empty($this->linkParts) ? $this->linkParts['url'] : '';
222  $selected = $currentIdentifier === $folder->getCombinedIdentifier() ? $this->additionalFolderClass : '';
223  $out .= '
224  <span class="' . $selected . '" title="' . htmlspecialchars($folder->getIdentifier()) . '">
225  ' . $folderIcon . '
226  </span>
227  ';
228  // Get files from the folder:
229  $folderContent = $this->getFolderContent($folder, $extensionList);
230  if (!empty($folderContent)) {
231  $out .= '<ul class="list-tree list-tree-root">';
232  foreach ($folderContent as $fileOrFolderObject) {
233  list($fileIdentifier, $icon) = $this->renderItem($fileOrFolderObject);
234  $selected = $currentIdentifier === $fileIdentifier ? ' class="active"' : '';
235  $out .=
236  '<li' . $selected . '>
237  <a href="#" class="t3js-fileLink" title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" data-file="file:' . htmlspecialchars($fileIdentifier) . '">
238  ' . $icon . '
239  ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) . '
240  </a>
241  </li>';
242  }
243  $out .= '</ul>';
244  }
245  return $out;
246  }
247 
251  protected function getTitle()
252  {
253  return $this->getLanguageService()->getLL('files');
254  }
255 
262  protected function getFolderContent(Folder $folder, $extensionList)
263  {
264  if ($extensionList !== '') {
266  $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
267  $filter->setAllowedFileExtensions($extensionList);
268  $folder->setFileAndFolderNameFilters(array(array($filter, 'filterFileList')));
269  }
270  return $folder->getFiles();
271  }
272 
281  protected function renderItem(ResourceInterface $fileOrFolderObject)
282  {
283  if (!$fileOrFolderObject instanceof File) {
284  throw new \InvalidArgumentException('Expected File object, got "' . get_class($fileOrFolderObject) . '" object.', 1443651368);
285  }
286  $fileIdentifier = $fileOrFolderObject->getUid();
287  // Get size and icon:
288  $size = ' (' . GeneralUtility::formatSize($fileOrFolderObject->getSize()) . 'bytes)';
289  $icon = '<span title="' . htmlspecialchars($fileOrFolderObject->getName() . $size) . '">'
290  . $this->iconFactory->getIconForResource($fileOrFolderObject, Icon::SIZE_SMALL)
291  . '</span>';
292  return [$fileIdentifier, $icon];
293  }
294 
298  public function getBodyTagAttributes()
299  {
300  return [
301  'data-current-link' => empty($this->linkParts) ? '' : 'file:' . $this->linkParts['url']
302  ];
303  }
304 
310  public function getUrlParameters(array $values)
311  {
312  $parameters = [
313  'expandFolder' => isset($values['identifier']) ? $values['identifier'] : (string)$this->expandFolder
314  ];
315  return array_merge($this->linkBrowser->getUrlParameters($values), $parameters);
316  }
317 
323  public function isCurrentlySelectedItem(array $values)
324  {
325  return false;
326  }
327 
333  public function getScriptUrl()
334  {
335  return $this->linkBrowser->getScriptUrl();
336  }
337 }