TYPO3 CMS  TYPO3_8-7
FileProvider.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
24 
29 {
33  protected $record;
34 
38  protected $itemsConfiguration = [
39  'edit' => [
40  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.edit',
41  'iconIdentifier' => 'actions-page-open',
42  'callbackAction' => 'editFile'
43  ],
44  'rename' => [
45  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.rename',
46  'iconIdentifier' => 'actions-edit-rename',
47  'callbackAction' => 'renameFile'
48  ],
49  'upload' => [
50  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.upload',
51  'iconIdentifier' => 'actions-edit-upload',
52  'callbackAction' => 'uploadFile'
53  ],
54  'new' => [
55  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.new',
56  'iconIdentifier' => 'actions-document-new',
57  'callbackAction' => 'createFile'
58  ],
59  'info' => [
60  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.info',
61  'iconIdentifier' => 'actions-document-info',
62  'callbackAction' => 'openInfoPopUp'
63  ],
64  'divider' => [
65  'type' => 'divider'
66  ],
67  'copy' => [
68  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.copy',
69  'iconIdentifier' => 'actions-edit-copy',
70  'callbackAction' => 'copyFile'
71  ],
72  'copyRelease' => [
73  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.copy',
74  'iconIdentifier' => 'actions-edit-copy-release',
75  'callbackAction' => 'copyReleaseFile'
76  ],
77  'cut' => [
78  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.cut',
79  'iconIdentifier' => 'actions-edit-cut',
80  'callbackAction' => 'cutFile'
81  ],
82  'cutRelease' => [
83  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.cutrelease',
84  'iconIdentifier' => 'actions-edit-cut-release',
85  'callbackAction' => 'cutReleaseFile'
86  ],
87  'pasteInto' => [
88  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.pasteinto',
89  'iconIdentifier' => 'actions-document-paste-into',
90  'callbackAction' => 'pasteFileInto'
91  ],
92  'divider2' => [
93  'type' => 'divider'
94  ],
95  'delete' => [
96  'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.delete',
97  'iconIdentifier' => 'actions-edit-delete',
98  'callbackAction' => 'deleteFile'
99  ],
100  ];
101 
105  public function canHandle(): bool
106  {
107  return $this->table === 'sys_file';
108  }
109 
113  protected function initialize()
114  {
115  parent::initialize();
116  $fileObject = ResourceFactory::getInstance()
117  ->retrieveFileOrFolderObject($this->identifier);
118  $this->record = $fileObject;
119  }
120 
128  protected function canRender(string $itemName, string $type): bool
129  {
130  if (in_array($type, ['divider', 'submenu'], true)) {
131  return true;
132  }
133  if (in_array($itemName, $this->disabledItems, true)) {
134  return false;
135  }
136  $canRender = false;
137  switch ($itemName) {
138  //just for files
139  case 'edit':
140  $canRender = $this->canBeEdited();
141  break;
142  case 'info':
143  $canRender = $this->canShowInfo();
144  break;
145 
146  //just for folders
147  case 'upload':
148  case 'new':
149  $canRender = $this->canCreateNew();
150  break;
151  case 'pasteInto':
152  $canRender = $this->canBePastedInto();
153  break;
154 
155  //for both files and folders
156  case 'rename':
157  $canRender = $this->canBeRenamed();
158  break;
159  case 'copy':
160  $canRender = $this->canBeCopied();
161  break;
162  case 'copyRelease':
163  $canRender = $this->isRecordInClipboard('copy');
164  break;
165  case 'cut':
166  $canRender = $this->canBeCut();
167  break;
168  case 'cutRelease':
169  $canRender = $this->isRecordInClipboard('cut');
170  break;
171  case 'delete':
172  $canRender = $this->canBeDeleted();
173  break;
174  }
175  return $canRender;
176  }
177 
181  protected function canBeEdited(): bool
182  {
183  return $this->isFile()
184  && $this->record->checkActionPermission('write')
185  && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $this->record->getExtension());
186  }
187 
191  protected function canBeRenamed(): bool
192  {
193  return $this->record->checkActionPermission('rename');
194  }
195 
199  protected function canBeDeleted(): bool
200  {
201  return $this->record->checkActionPermission('delete');
202  }
203 
207  protected function canShowInfo(): bool
208  {
209  return $this->isFile();
210  }
211 
215  protected function canCreateNew(): bool
216  {
217  return $this->isFolder() && $this->record->checkActionPermission('write');
218  }
219 
223  protected function canBeCopied(): bool
224  {
225  return $this->record->checkActionPermission('read') && !$this->isRecordInClipboard('copy');
226  }
227 
231  protected function canBeCut(): bool
232  {
233  return $this->record->checkActionPermission('move') && !$this->isRecordInClipboard('cut');
234  }
235 
239  protected function canBePastedInto(): bool
240  {
241  $elArr = $this->clipboard->elFromTable('_FILE');
242  if (empty($elArr)) {
243  return false;
244  }
245  $selItem = reset($elArr);
246  $fileOrFolderInClipBoard = ResourceFactory::getInstance()->retrieveFileOrFolderObject($selItem);
247 
248  return $this->isFolder()
249  && $this->record->checkActionPermission('write')
250  && (
251  !$fileOrFolderInClipBoard instanceof Folder
252  || !$fileOrFolderInClipBoard->getStorage()->isWithinFolder($fileOrFolderInClipBoard, $this->record)
253  )
254  && $this->isFoldersAreInTheSameRoot($fileOrFolderInClipBoard);
255  }
256 
264  protected function isFoldersAreInTheSameRoot($fileOrFolderInClipBoard): bool
265  {
266  return (!$fileOrFolderInClipBoard instanceof Folder)
267  || (
268  $this->record->getStorage()->getRootLevelFolder()->getCombinedIdentifier()
269  == $fileOrFolderInClipBoard->getStorage()->getRootLevelFolder()->getCombinedIdentifier()
270  );
271  }
272 
279  protected function isRecordInClipboard(string $mode = ''): bool
280  {
281  $isSelected = '';
282  // Pseudo table name for use in the clipboard.
283  $table = '_FILE';
284  $uid = GeneralUtility::shortMD5($this->record->getCombinedIdentifier());
285  if ($this->clipboard->current === 'normal') {
286  $isSelected = $this->clipboard->isSelected($table, $uid);
287  }
288  return $mode === '' ? !empty($isSelected) : $isSelected === $mode;
289  }
290 
294  protected function isStorageRoot(): bool
295  {
296  return $this->record->getIdentifier() === $this->record->getStorage()->getRootLevelFolder()->getIdentifier();
297  }
298 
302  protected function isFile(): bool
303  {
304  return $this->record instanceof File;
305  }
306 
310  protected function isFolder(): bool
311  {
312  return $this->record instanceof Folder;
313  }
314 
319  protected function getAdditionalAttributes(string $itemName): array
320  {
321  $attributes = [
322  'data-callback-module' => 'TYPO3/CMS/Filelist/ContextMenuActions'
323  ];
324  if ($itemName === 'delete' && $this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
325  $recordTitle = GeneralUtility::fixed_lgd_cs($this->record->getName(), $this->backendUser->uc['titleLen']);
326 
327  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:delete');
328  $confirmMessage = sprintf(
329  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.delete'),
330  $recordTitle
331  );
332  if ($this->isFolder()) {
333  $confirmMessage .= BackendUtility::referenceCount(
334  '_FILE',
335  $this->record->getIdentifier(),
336  ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.referencesToFolder')
337  );
338  } else {
339  $confirmMessage .= BackendUtility::referenceCount(
340  'sys_file',
341  $this->record->getUid(),
342  ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.referencesToFile')
343  );
344  }
345  $attributes += [
346  'data-title' => htmlspecialchars($title),
347  'data-message' => htmlspecialchars($confirmMessage)
348  ];
349  }
350  if ($itemName === 'pasteInto' && $this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
351  $elArr = $this->clipboard->elFromTable('_FILE');
352  $selItem = reset($elArr);
353  $fileOrFolderInClipBoard = ResourceFactory::getInstance()->retrieveFileOrFolderObject($selItem);
354 
355  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:clip_paste');
356 
357  $confirmMessage = sprintf(
358  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.'
359  . ($this->clipboard->currentMode() === 'copy' ? 'copy' : 'move') . '_into'),
360  $fileOrFolderInClipBoard->getName(),
361  $this->record->getName()
362  );
363  $attributes += [
364  'data-title' => htmlspecialchars($title),
365  'data-message' => htmlspecialchars($confirmMessage)
366  ];
367  }
368  return $attributes;
369  }
370 
374  protected function getIdentifier(): string
375  {
376  return $this->record->getCombinedIdentifier();
377  }
378 }
static referenceCount($table, $ref, $msg='', $count=null)
static fixed_lgd_cs($string, $chars, $appendString='...')
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']