TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
FileBrowser.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Recordlist\Browser;
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 
31 
36 {
45  protected $expandFolder;
46 
50  protected $selectedFolder;
51 
57  protected $elements = [];
58 
62  protected $searchWord;
63 
67  protected $fileRepository;
68 
72  protected function initialize()
73  {
74  parent::initialize();
75  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/BrowseFiles');
76  $this->fileRepository = GeneralUtility::makeInstance(FileRepository::class);
77  }
78 
82  protected function initVariables()
83  {
84  parent::initVariables();
85  $this->expandFolder = GeneralUtility::_GP('expandFolder');
86  $this->searchWord = (string)GeneralUtility::_GP('searchWord');
87  }
88 
95  public function processSessionData($data)
96  {
97  if ($this->expandFolder !== null) {
98  $data['expandFolder'] = $this->expandFolder;
99  $store = true;
100  } else {
101  $this->expandFolder = $data['expandFolder'];
102  $store = false;
103  }
104  return [$data, $store];
105  }
106 
110  public function render()
111  {
112  $backendUser = $this->getBackendUser();
113 
114  // The key number 3 of the bparams contains the "allowed" string. Disallowed is not passed to
115  // the element browser at all but only filtered out in DataHandler afterwards
116  $allowedFileExtensions = GeneralUtility::trimExplode(',', explode('|', $this->bparams)[3], true);
117  if (!empty($allowedFileExtensions) && $allowedFileExtensions[0] !== 'sys_file' && $allowedFileExtensions[0] !== '*') {
118  // Create new filter object
119  $filterObject = GeneralUtility::makeInstance(FileExtensionFilter::class);
120  $filterObject->setAllowedFileExtensions($allowedFileExtensions);
121  // Set file extension filters on all storages
122  $storages = $backendUser->getFileStorages();
124  foreach ($storages as $storage) {
125  $storage->addFileAndFolderNameFilter([$filterObject, 'filterFileList']);
126  }
127  }
128  if ($this->expandFolder) {
129  $fileOrFolderObject = null;
130 
131  // Try to fetch the folder the user had open the last time he browsed files
132  // Fallback to the default folder in case the last used folder is not existing
133  try {
134  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
135  } catch (Exception $accessException) {
136  // We're just catching the exception here, nothing to be done if folder does not exist or is not accessible.
137  } catch (\InvalidArgumentException $driverMissingExecption) {
138  // We're just catching the exception here, nothing to be done if the driver does not exist anymore.
139  }
140 
141  if ($fileOrFolderObject instanceof Folder) {
142  // It's a folder
143  $this->selectedFolder = $fileOrFolderObject;
144  } elseif ($fileOrFolderObject instanceof FileInterface) {
145  // It's a file
146  $this->selectedFolder = $fileOrFolderObject->getParentFolder();
147  }
148  }
149  // Or get the user's default upload folder
150  if (!$this->selectedFolder) {
151  try {
152  $this->selectedFolder = $backendUser->getDefaultUploadFolder();
153  } catch (\Exception $e) {
154  // The configured default user folder does not exist
155  }
156  }
157  // Build the file upload and folder creation form
158  $uploadForm = '';
159  $createFolder = '';
160  if ($this->selectedFolder) {
161  $folderUtilityRenderer = GeneralUtility::makeInstance(FolderUtilityRenderer::class, $this);
162  $uploadForm = $folderUtilityRenderer->uploadForm($this->selectedFolder, $allowedFileExtensions);
163  $createFolder = $folderUtilityRenderer->createFolder($this->selectedFolder);
164  }
165 
166  // Getting flag for showing/not showing thumbnails:
167  $noThumbs = $backendUser->getTSConfigVal('options.noThumbsInEB');
168  $_MOD_SETTINGS = [];
169  if (!$noThumbs) {
170  // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
171  $_MOD_MENU = ['displayThumbs' => ''];
172  $_MCONF['name'] = 'file_list';
173  $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
174  }
175  $noThumbs = $noThumbs ?: !$_MOD_SETTINGS['displayThumbs'];
176  // Create folder tree:
178  $folderTree = GeneralUtility::makeInstance(ElementBrowserFolderTreeView::class);
179  $folderTree->setLinkParameterProvider($this);
180  $tree = $folderTree->getBrowsableTree();
181  if ($this->selectedFolder) {
182  $files = $this->renderFilesInFolder($this->selectedFolder, $allowedFileExtensions, $noThumbs);
183  } else {
184  $files = '';
185  }
186 
187  $this->initDocumentTemplate();
188  // Starting content:
189  $content = $this->doc->startPage(htmlspecialchars($this->getLanguageService()->getLL('fileSelector')));
190  $content .= $this->doc->getFlashMessages();
191 
192  // Insert the upload form on top, if so configured
193  if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
194  $content .= $uploadForm;
195  }
196  // Putting the parts together, side by side:
197  $content .= '
198 
199  <!--
200  Wrapper table for folder tree / filelist:
201  -->
202  <div class="element-browser-section element-browser-filetree">
203  <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
204  <tr>
205  <td class="c-wCell" valign="top"><h3>' . htmlspecialchars($this->getLanguageService()->getLL('folderTree')) . ':</h3>' . $tree . '</td>
206  <td class="c-wCell" valign="top">' . $files . '</td>
207  </tr>
208  </table>
209  </div>
210  ';
211  // Adding create folder + upload forms if applicable:
212  if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
213  $content .= $uploadForm;
214  }
215  $content .= $createFolder;
216  // Add some space
217  $content .= '<br /><br />';
218  // Ending page, returning content:
219  $content .= $this->doc->endPage();
220  return $this->doc->insertStylesAndJS($content);
221  }
222 
231  public function renderFilesInFolder(Folder $folder, array $extensionList = [], $noThumbs = false)
232  {
233  if (!$folder->checkActionPermission('read')) {
234  return '';
235  }
236  $lang = $this->getLanguageService();
237  $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
238 
239  if ($this->searchWord !== '') {
240  $files = $this->fileRepository->searchByName($folder, $this->searchWord);
241  } else {
242  $extensionList = !empty($extensionList) && $extensionList[0] === '*' ? [] : $extensionList;
243  $files = $this->getFilesInFolder($folder, $extensionList);
244  }
245  $filesCount = count($files);
246 
247  $lines = [];
248 
249  // Create the header of current folder:
250  $folderIcon = $this->iconFactory->getIconForResource($folder, Icon::SIZE_SMALL);
251 
252  $lines[] = '
253  <tr>
254  <th class="col-title" nowrap="nowrap">' . $folderIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen)) . '</th>
255  <th class="col-control" nowrap="nowrap"></th>
256  <th class="col-clipboard" nowrap="nowrap">
257  <a href="#" class="btn btn-default" id="t3js-importSelection" title="' . htmlspecialchars($lang->getLL('importSelection')) . '">' . $this->iconFactory->getIcon('actions-document-import-t3d', Icon::SIZE_SMALL) . '</a>
258  <a href="#" class="btn btn-default" id="t3js-toggleSelection" title="' . htmlspecialchars($lang->getLL('toggleSelection')) . '">' . $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL) . '</a>
259  </th>
260  <th nowrap="nowrap">&nbsp;</th>
261  </tr>';
262 
263  if ($filesCount === 0) {
264  $lines[] = '
265  <tr>
266  <td colspan="4">No files found.</td>
267  </tr>';
268  }
269 
270  foreach ($files as $fileObject) {
271  $fileExtension = $fileObject->getExtension();
272  // Thumbnail/size generation:
273  $imgInfo = [];
274  if (!$noThumbs && GeneralUtility::inList(strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] . ',' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['mediafile_ext']), strtolower($fileExtension))) {
275  $processedFile = $fileObject->process(
277  ['width' => 64, 'height' => 64]
278  );
279  $imageUrl = $processedFile->getPublicUrl(true);
280  $imgInfo = [
281  $fileObject->getProperty('width'),
282  $fileObject->getProperty('height')
283  ];
284  $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels';
285  $clickIcon = '<img src="' . $imageUrl . '"'
286  . ' width="' . $processedFile->getProperty('width') . '"'
287  . ' height="' . $processedFile->getProperty('height') . '"'
288  . ' hspace="5" vspace="5" border="1" />';
289  } else {
290  $clickIcon = '';
291  $pDim = '';
292  }
293  // Create file icon:
294  $size = ' (' . GeneralUtility::formatSize($fileObject->getSize(), $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:byteSizeUnits')) . ($pDim ? ', ' . $pDim : '') . ')';
295  $icon = '<span title="' . htmlspecialchars($fileObject->getName() . $size) . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL) . '</span>';
296  // Create links for adding the file:
297  $filesIndex = count($this->elements);
298  $this->elements['file_' . $filesIndex] = [
299  'type' => 'file',
300  'table' => 'sys_file',
301  'uid' => $fileObject->getUid(),
302  'fileName' => $fileObject->getName(),
303  'filePath' => $fileObject->getUid(),
304  'fileExt' => $fileExtension,
305  'fileIcon' => $icon
306  ];
307  if ($this->fileIsSelectableInFileList($fileObject, $imgInfo)) {
308  $ATag = '<a href="#" class="btn btn-default" title="' . htmlspecialchars($fileObject->getName()) . '" data-file-index="' . htmlspecialchars($filesIndex) . '" data-close="0">';
309  $ATag .= '<span title="' . htmlspecialchars($lang->getLL('addToList')) . '">' . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . '</span>';
310  $ATag_alt = '<a href="#" title="' . htmlspecialchars($fileObject->getName()) . '" data-file-index="' . htmlspecialchars($filesIndex) . '" data-close="1">';
311  $ATag_e = '</a>';
312  $bulkCheckBox = '<label class="btn btn-default btn-checkbox"><input type="checkbox" class="typo3-bulk-item" name="file_' . $filesIndex . '" value="0" /><span class="t3-icon fa"></span></label>';
313  } else {
314  $ATag = '';
315  $ATag_alt = '';
316  $ATag_e = '';
317  $bulkCheckBox = '';
318  }
319  // Create link to showing details about the file in a window:
320  $Ahref = BackendUtility::getModuleUrl('show_item', [
321  'type' => 'file',
322  'table' => '_FILE',
323  'uid' => $fileObject->getCombinedIdentifier(),
324  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
325  ]);
326 
327  // Combine the stuff:
328  $filenameAndIcon = $ATag_alt . $icon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(), $titleLen)) . $ATag_e;
329  // Show element:
330  $lines[] = '
331  <tr class="file_list_normal">
332  <td class="col-title" nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
333  <td class="col-control">
334  <div class="btn-group">' . $ATag . $ATag_e . '
335  <a href="' . htmlspecialchars($Ahref) . '" class="btn btn-default" title="' . htmlspecialchars($lang->getLL('info')) . '">' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL) . '</a>
336  </td>
337  <td class="col-clipboard" valign="top">' . $bulkCheckBox . '</td>
338  <td nowrap="nowrap">&nbsp;' . $pDim . '</td>
339  </tr>';
340  if ($pDim) {
341  $lines[] = '
342  <tr>
343  <td class="filelistThumbnail" colspan="4">' . $ATag_alt . $clickIcon . $ATag_e . '</td>
344  </tr>';
345  }
346  }
347 
348  $out = '<h3>' . htmlspecialchars($lang->getLL('files')) . ' ' . $filesCount . ':</h3>';
349  $out .= GeneralUtility::makeInstance(FolderUtilityRenderer::class, $this)->getFileSearchField($this->searchWord);
350  $out .= '<div id="filelist">';
351  $out .= $this->getBulkSelector($filesCount);
352 
353  // Wrap all the rows in table tags:
354  $out .= '
355 
356  <!--
357  Filelisting
358  -->
359  <table class="table table-striped table-hover" id="typo3-filelist">
360  ' . implode('', $lines) . '
361  </table>';
362  // Return accumulated content for filelisting:
363  $out .= '</div>';
364  return $out;
365  }
366 
374  protected function getFilesInFolder(Folder $folder, array $extensionList)
375  {
376  if (!empty($extensionList)) {
378  $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
379  $filter->setAllowedFileExtensions($extensionList);
380  $folder->setFileAndFolderNameFilters([[$filter, 'filterFileList']]);
381  }
382  return $folder->getFiles();
383  }
384 
391  protected function getBulkSelector($filesCount)
392  {
393  if (!$filesCount) {
394  return '';
395  }
396 
397  $lang = $this->getLanguageService();
398  $out = '';
399 
400  // Getting flag for showing/not showing thumbnails:
401  $noThumbsInEB = $this->getBackendUser()->getTSConfigVal('options.noThumbsInEB');
402  if (!$noThumbsInEB && $this->selectedFolder) {
403  // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
404  $_MOD_MENU = ['displayThumbs' => ''];
405  $_MCONF['name'] = 'file_list';
406  $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
407  $addParams = GeneralUtility::implodeArrayForUrl('', $this->getUrlParameters(['identifier' => $this->selectedFolder->getCombinedIdentifier()]));
408  $thumbNailCheck = '<div class="checkbox" style="padding:5px 0 15px 0"><label for="checkDisplayThumbs">'
410  '',
411  'SET[displayThumbs]',
412  $_MOD_SETTINGS['displayThumbs'],
413  $this->thisScript,
414  $addParams,
415  'id="checkDisplayThumbs"'
416  )
417  . htmlspecialchars($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_file_list.xlf:displayThumbs')) . '</label></div>';
418  $out .= $thumbNailCheck;
419  } else {
420  $out .= '<div style="padding-top: 15px;"></div>';
421  }
422  return $out;
423  }
424 
434  protected function fileIsSelectableInFileList(FileInterface $file, array $imgInfo)
435  {
436  return true;
437  }
438 
442  protected function getBodyTagAttributes()
443  {
444  return [
445  'data-mode' => 'file',
446  'data-elements' => json_encode($this->elements)
447  ];
448  }
449 
454  public function getUrlParameters(array $values)
455  {
456  return [
457  'mode' => 'file',
458  'expandFolder' => isset($values['identifier']) ? $values['identifier'] : $this->expandFolder,
459  'bparams' => $this->bparams
460  ];
461  }
462 
467  public function isCurrentlySelectedItem(array $values)
468  {
469  return false;
470  }
471 
477  public function getScriptUrl()
478  {
479  return $this->thisScript;
480  }
481 }
getFiles($start=0, $numberOfItems=0, $filterMode=self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive=false, $sort= '', $sortRev=false)
renderFilesInFolder(Folder $folder, array $extensionList=[], $noThumbs=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static implodeArrayForUrl($name, array $theArray, $str= '', $skipBlank=false, $rawurlencodeParamName=false)
static formatSize($sizeInBytes, $labels= '', $base=0)
static getModuleData($MOD_MENU, $CHANGED_SETTINGS, $modName, $type= '', $dontValidateList= '', $setDefaultList= '')
static getFuncCheck($mainParams, $elementName, $currentValue, $script= '', $addParams= '', $tagParams= '')
fileIsSelectableInFileList(FileInterface $file, array $imgInfo)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)