TYPO3 CMS  TYPO3_7-6
FileLinkHandler.php
Go to the documentation of this file.
1 <?php
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 
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 
91  return true;
92  }
93  } catch (FileDoesNotExistException $e) {
94  }
95  }
96  return false;
97  }
98 
104  public function formatCurrentUrl()
105  {
106  return $this->linkParts['name'];
107  }
108 
116  public function render(ServerRequestInterface $request)
117  {
118  GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/FileLinkHandler');
119 
120  $this->expandFolder = isset($request->getQueryParams()['expandFolder']) ? $request->getQueryParams()['expandFolder'] : null;
121  if (!empty($this->linkParts) && !isset($this->expandFolder)) {
122  $this->expandFolder = $this->linkParts['url'];
123  }
124 
126  $folderTree = GeneralUtility::makeInstance(ElementBrowserFolderTreeView::class);
127  $folderTree->setLinkParameterProvider($this);
128  $tree = $folderTree->getBrowsableTree();
129 
130  // Create upload/create folder forms, if a path is given
131  $selectedFolder = false;
132  if ($this->expandFolder) {
133  $fileOrFolderObject = null;
134  try {
135  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
136  } catch (\Exception $e) {
137  // No path is selected
138  }
139 
140  if ($fileOrFolderObject instanceof Folder) {
141  // It's a folder
142  $selectedFolder = $fileOrFolderObject;
143  } elseif ($fileOrFolderObject instanceof FileInterface) {
144  // It's a file
145  try {
146  $selectedFolder = $fileOrFolderObject->getParentFolder();
147  } catch (\Exception $e) {
148  // Accessing the parent folder failed for some reason. e.g. permissions
149  }
150  }
151  }
152 
153  $backendUser = $this->getBackendUser();
154  // If no folder is selected, get the user's default upload folder
155  if (!$selectedFolder) {
156  try {
157  $selectedFolder = $backendUser->getDefaultUploadFolder();
158  } catch (\Exception $e) {
159  // The configured default user folder does not exist
160  }
161  }
162  // Build the file upload and folder creation form
163  $uploadForm = '';
164  $createFolder = '';
165  $content = '';
166  if ($selectedFolder) {
167  $folderUtilityRenderer = GeneralUtility::makeInstance(FolderUtilityRenderer::class, $this);
168  $uploadForm = $this->mode === 'file' ? $folderUtilityRenderer->uploadForm($selectedFolder, []) : '';
169  $createFolder = $folderUtilityRenderer->createFolder($selectedFolder);
170  }
171  // Insert the upload form on top, if so configured
172  if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
173  $content .= $uploadForm;
174  }
175 
176  // Render the filelist if there is a folder selected
177  $files = '';
178  if ($selectedFolder) {
179  $parameters = $this->linkBrowser->getUrlParameters();
180  $allowedExtensions = isset($parameters['allowedExtensions']) ? $parameters['allowedExtensions'] : '';
181  $files = $this->expandFolder($selectedFolder, $allowedExtensions);
182  }
183  // Create folder tree:
184  $content .= '
185  <!--
186  Wrapper table for folder tree / file/folder list:
187  -->
188  <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
189  <tr>
190  <td class="c-wCell" valign="top"><h3>' . $this->getLanguageService()->getLL('folderTree') . ':</h3>' . $tree . '</td>
191  <td class="c-wCell" valign="top">' . $files . '</td>
192  </tr>
193  </table>
194  ';
195  // Adding create folder + upload form if applicable
196  if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
197  $content .= $uploadForm;
198  }
199  $content .= '<br />' . $createFolder . '<br />';
200  return $content;
201  }
202 
210  public function expandFolder(Folder $folder, $extensionList = '')
211  {
212  if (!$folder->checkActionPermission('read')) {
213  return '';
214  }
215  $out = '<h3>' . htmlspecialchars($this->getTitle()) . ':</h3>';
216 
217  // Create header element; The folder from which files are listed.
218  $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
219  $folderIcon = $this->iconFactory->getIconForResource($folder, Icon::SIZE_SMALL);
220  $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen));
221 
222  $currentIdentifier = !empty($this->linkParts) ? $this->linkParts['url'] : '';
223  $selected = $currentIdentifier === $folder->getCombinedIdentifier() ? $this->additionalFolderClass : '';
224  $out .= '
225  <span class="' . $selected . '" title="' . htmlspecialchars($folder->getIdentifier()) . '">
226  ' . $folderIcon . '
227  </span>
228  ';
229  // Get files from the folder:
230  $folderContent = $this->getFolderContent($folder, $extensionList);
231  if (!empty($folderContent)) {
232  $out .= '<ul class="list-tree">';
233  foreach ($folderContent as $fileOrFolderObject) {
234  list($fileIdentifier, $icon) = $this->renderItem($fileOrFolderObject);
235  $selected = (int)$currentIdentifier === $fileIdentifier ? ' class="active"' : '';
236  $out .=
237  '<li' . $selected . '>
238  <span class="list-tree-group">
239  <a href="#" class="t3js-fileLink list-tree-group" title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" data-file="file:' . htmlspecialchars($fileIdentifier) . '">
240  <span class="list-tree-icon">' . $icon . '</span>
241  <span class="list-tree-title">' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) . '</span>
242  </a>
243  </span>
244  </li>';
245  }
246  $out .= '</ul>';
247  }
248  return $out;
249  }
250 
254  protected function getTitle()
255  {
256  return $this->getLanguageService()->getLL('files');
257  }
258 
265  protected function getFolderContent(Folder $folder, $extensionList)
266  {
267  if ($extensionList !== '') {
269  $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
270  $filter->setAllowedFileExtensions($extensionList);
271  $folder->setFileAndFolderNameFilters([[$filter, 'filterFileList']]);
272  }
273  return $folder->getFiles();
274  }
275 
284  protected function renderItem(ResourceInterface $fileOrFolderObject)
285  {
286  if (!$fileOrFolderObject instanceof File) {
287  throw new \InvalidArgumentException('Expected File object, got "' . get_class($fileOrFolderObject) . '" object.', 1443651368);
288  }
289  $fileIdentifier = $fileOrFolderObject->getUid();
290  // Get size and icon:
291  $size = ' (' . GeneralUtility::formatSize($fileOrFolderObject->getSize()) . 'bytes)';
292  $icon = '<span title="' . htmlspecialchars($fileOrFolderObject->getName() . $size) . '">'
293  . $this->iconFactory->getIconForResource($fileOrFolderObject, Icon::SIZE_SMALL)
294  . '</span>';
295  return [$fileIdentifier, $icon];
296  }
297 
301  public function getBodyTagAttributes()
302  {
303  return [
304  'data-current-link' => empty($this->linkParts) ? '' : 'file:' . $this->linkParts['url']
305  ];
306  }
307 
313  public function getUrlParameters(array $values)
314  {
315  $parameters = [
316  'expandFolder' => isset($values['identifier']) ? $values['identifier'] : (string)$this->expandFolder
317  ];
318  return array_merge($this->linkBrowser->getUrlParameters($values), $parameters);
319  }
320 
326  public function isCurrentlySelectedItem(array $values)
327  {
328  return false;
329  }
330 
336  public function getScriptUrl()
337  {
338  return $this->linkBrowser->getScriptUrl();
339  }
340 }
setFileAndFolderNameFilters(array $filters)
Definition: Folder.php:496
getFiles($start=0, $numberOfItems=0, $filterMode=self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive=false, $sort='', $sortRev=false)
Definition: Folder.php:218
static fixed_lgd_cs($string, $chars, $appendString='...')
static formatSize($sizeInBytes, $labels='', $base=0)
static beginsWith($haystack, $needle)