|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of the TYPO3 CMS project. |
|
5
|
|
|
* |
|
6
|
|
|
* It is free software; you can redistribute it and/or modify it under |
|
7
|
|
|
* the terms of the GNU General Public License, either version 2 |
|
8
|
|
|
* of the License, or any later version. |
|
9
|
|
|
* |
|
10
|
|
|
* For the full copyright and license information, please read the |
|
11
|
|
|
* LICENSE.txt file that was distributed with this source code. |
|
12
|
|
|
* |
|
13
|
|
|
* The TYPO3 project - inspiring people to share! |
|
14
|
|
|
*/ |
|
15
|
|
|
|
|
16
|
|
|
namespace TYPO3\CMS\Filelist\Controller; |
|
17
|
|
|
|
|
18
|
|
|
use Psr\Http\Message\ResponseInterface; |
|
19
|
|
|
use Psr\Log\LoggerAwareInterface; |
|
20
|
|
|
use Psr\Log\LoggerAwareTrait; |
|
21
|
|
|
use TYPO3\CMS\Backend\Clipboard\Clipboard; |
|
22
|
|
|
use TYPO3\CMS\Backend\Routing\UriBuilder; |
|
23
|
|
|
use TYPO3\CMS\Backend\Template\Components\ButtonBar; |
|
24
|
|
|
use TYPO3\CMS\Backend\Utility\BackendUtility; |
|
25
|
|
|
use TYPO3\CMS\Backend\View\BackendTemplateView; |
|
26
|
|
|
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; |
|
27
|
|
|
use TYPO3\CMS\Core\Imaging\Icon; |
|
28
|
|
|
use TYPO3\CMS\Core\Imaging\IconFactory; |
|
29
|
|
|
use TYPO3\CMS\Core\Localization\LanguageService; |
|
30
|
|
|
use TYPO3\CMS\Core\Messaging\FlashMessage; |
|
31
|
|
|
use TYPO3\CMS\Core\Resource\DuplicationBehavior; |
|
32
|
|
|
use TYPO3\CMS\Core\Resource\Exception; |
|
33
|
|
|
use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; |
|
34
|
|
|
use TYPO3\CMS\Core\Resource\FileRepository; |
|
35
|
|
|
use TYPO3\CMS\Core\Resource\Folder; |
|
36
|
|
|
use TYPO3\CMS\Core\Resource\ResourceFactory; |
|
37
|
|
|
use TYPO3\CMS\Core\Resource\ResourceStorage; |
|
38
|
|
|
use TYPO3\CMS\Core\Resource\Search\FileSearchDemand; |
|
39
|
|
|
use TYPO3\CMS\Core\Resource\StorageRepository; |
|
40
|
|
|
use TYPO3\CMS\Core\Resource\Utility\ListUtility; |
|
41
|
|
|
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; |
|
42
|
|
|
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility; |
|
43
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
|
44
|
|
|
use TYPO3\CMS\Core\Utility\MathUtility; |
|
45
|
|
|
use TYPO3\CMS\Extbase\Http\ForwardResponse; |
|
46
|
|
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; |
|
47
|
|
|
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; |
|
48
|
|
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility; |
|
49
|
|
|
use TYPO3\CMS\Filelist\Configuration\ThumbnailConfiguration; |
|
50
|
|
|
use TYPO3\CMS\Filelist\FileFacade; |
|
51
|
|
|
use TYPO3\CMS\Filelist\FileList; |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Script Class for creating the list of files in the File > Filelist module |
|
55
|
|
|
* @internal this is a concrete TYPO3 controller implementation and solely used for EXT:filelist and not part of TYPO3's Core API. |
|
56
|
|
|
*/ |
|
57
|
|
|
class FileListController extends ActionController implements LoggerAwareInterface |
|
58
|
|
|
{ |
|
59
|
|
|
use LoggerAwareTrait; |
|
60
|
|
|
|
|
61
|
|
|
public const UPLOAD_ACTION_REPLACE = 'replace'; |
|
62
|
|
|
public const UPLOAD_ACTION_RENAME = 'rename'; |
|
63
|
|
|
public const UPLOAD_ACTION_SKIP = 'cancel'; |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* @var array |
|
67
|
|
|
*/ |
|
68
|
|
|
protected $MOD_MENU = []; |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* @var array |
|
72
|
|
|
*/ |
|
73
|
|
|
protected $MOD_SETTINGS = []; |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* "id" -> the path to list. |
|
77
|
|
|
* |
|
78
|
|
|
* @var string |
|
79
|
|
|
*/ |
|
80
|
|
|
protected $id; |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* @var Folder|null |
|
84
|
|
|
*/ |
|
85
|
|
|
protected $folderObject; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* @var FlashMessage |
|
89
|
|
|
*/ |
|
90
|
|
|
protected $errorMessage; |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* Pointer to listing |
|
94
|
|
|
* |
|
95
|
|
|
* @var int |
|
96
|
|
|
*/ |
|
97
|
|
|
protected $pointer; |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* Thumbnail mode. |
|
101
|
|
|
* |
|
102
|
|
|
* @var string |
|
103
|
|
|
*/ |
|
104
|
|
|
protected $imagemode; |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* @var string |
|
108
|
|
|
*/ |
|
109
|
|
|
protected $cmd; |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Defines behaviour when uploading files with names that already exist; possible values are |
|
113
|
|
|
* the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration |
|
114
|
|
|
* |
|
115
|
|
|
* @var \TYPO3\CMS\Core\Resource\DuplicationBehavior |
|
116
|
|
|
*/ |
|
117
|
|
|
protected $overwriteExistingFiles; |
|
118
|
|
|
|
|
119
|
|
|
/** |
|
120
|
|
|
* The filelist object |
|
121
|
|
|
* |
|
122
|
|
|
* @var FileList |
|
123
|
|
|
*/ |
|
124
|
|
|
protected $filelist; |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* The name of the module |
|
128
|
|
|
* |
|
129
|
|
|
* @var string |
|
130
|
|
|
*/ |
|
131
|
|
|
protected $moduleName = 'file_list'; |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* @var \TYPO3\CMS\Core\Resource\FileRepository |
|
135
|
|
|
*/ |
|
136
|
|
|
protected $fileRepository; |
|
137
|
|
|
|
|
138
|
|
|
/** |
|
139
|
|
|
* @var BackendTemplateView |
|
140
|
|
|
*/ |
|
141
|
|
|
protected $view; |
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* BackendTemplateView Container |
|
145
|
|
|
* |
|
146
|
|
|
* @var string |
|
147
|
|
|
*/ |
|
148
|
|
|
protected $defaultViewObjectName = BackendTemplateView::class; |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* @param \TYPO3\CMS\Core\Resource\FileRepository $fileRepository |
|
152
|
|
|
*/ |
|
153
|
|
|
public function injectFileRepository(FileRepository $fileRepository) |
|
154
|
|
|
{ |
|
155
|
|
|
$this->fileRepository = $fileRepository; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Initialize variables, file object |
|
160
|
|
|
* Incoming GET vars include id, pointer, table, imagemode |
|
161
|
|
|
* |
|
162
|
|
|
* @throws \RuntimeException |
|
163
|
|
|
*/ |
|
164
|
|
|
public function initializeObject() |
|
165
|
|
|
{ |
|
166
|
|
|
$this->getLanguageService()->includeLLFile('EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf'); |
|
167
|
|
|
$this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_misc.xlf'); |
|
168
|
|
|
|
|
169
|
|
|
// Setting GPvars: |
|
170
|
|
|
$this->id = ($combinedIdentifier = GeneralUtility::_GP('id')); |
|
171
|
|
|
$this->pointer = GeneralUtility::_GP('pointer'); |
|
|
|
|
|
|
172
|
|
|
$this->imagemode = GeneralUtility::_GP('imagemode'); |
|
173
|
|
|
$this->cmd = GeneralUtility::_GP('cmd'); |
|
174
|
|
|
$this->overwriteExistingFiles = DuplicationBehavior::cast(GeneralUtility::_GP('overwriteExistingFiles')); |
|
175
|
|
|
|
|
176
|
|
|
try { |
|
177
|
|
|
if ($combinedIdentifier) { |
|
178
|
|
|
$this->getBackendUser()->evaluateUserSpecificFileFilterSettings(); |
|
179
|
|
|
$storage = GeneralUtility::makeInstance(StorageRepository::class)->findByCombinedIdentifier($combinedIdentifier); |
|
180
|
|
|
$identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1); |
|
181
|
|
|
if (!$storage->hasFolder($identifier)) { |
|
182
|
|
|
$identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier); |
|
183
|
|
|
} |
|
184
|
|
|
$this->folderObject = $storage->getFolder($identifier); |
|
185
|
|
|
// Disallow access to fallback storage 0 |
|
186
|
|
|
if ($storage->getUid() === 0) { |
|
187
|
|
|
throw new InsufficientFolderAccessPermissionsException( |
|
188
|
|
|
'You are not allowed to access files outside your storages', |
|
189
|
|
|
1434539815 |
|
190
|
|
|
); |
|
191
|
|
|
} |
|
192
|
|
|
// Disallow the rendering of the processing folder (e.g. could be called manually) |
|
193
|
|
|
if ($this->folderObject && $storage->isProcessingFolder($this->folderObject)) { |
|
194
|
|
|
$this->folderObject = $storage->getRootLevelFolder(); |
|
195
|
|
|
} |
|
196
|
|
|
} else { |
|
197
|
|
|
// Take the first object of the first storage |
|
198
|
|
|
$fileStorages = $this->getBackendUser()->getFileStorages(); |
|
199
|
|
|
$fileStorage = reset($fileStorages); |
|
200
|
|
|
if ($fileStorage) { |
|
201
|
|
|
$this->folderObject = $fileStorage->getRootLevelFolder(); |
|
202
|
|
|
} else { |
|
203
|
|
|
throw new \RuntimeException('Could not find any folder to be displayed.', 1349276894); |
|
204
|
|
|
} |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
if ($this->folderObject && !$this->folderObject->getStorage()->isWithinFileMountBoundaries($this->folderObject)) { |
|
208
|
|
|
throw new \RuntimeException('Folder not accessible.', 1430409089); |
|
209
|
|
|
} |
|
210
|
|
|
} catch (InsufficientFolderAccessPermissionsException $permissionException) { |
|
211
|
|
|
$this->folderObject = null; |
|
212
|
|
|
$this->errorMessage = GeneralUtility::makeInstance( |
|
213
|
|
|
FlashMessage::class, |
|
214
|
|
|
sprintf( |
|
215
|
|
|
$this->getLanguageService()->getLL('missingFolderPermissionsMessage'), |
|
216
|
|
|
$this->id |
|
217
|
|
|
), |
|
218
|
|
|
$this->getLanguageService()->getLL('missingFolderPermissionsTitle'), |
|
219
|
|
|
FlashMessage::NOTICE |
|
220
|
|
|
); |
|
221
|
|
|
} catch (Exception $fileException) { |
|
222
|
|
|
// Set folder object to null and throw a message later on |
|
223
|
|
|
$this->folderObject = null; |
|
224
|
|
|
// Take the first object of the first storage |
|
225
|
|
|
$fileStorages = $this->getBackendUser()->getFileStorages(); |
|
226
|
|
|
$fileStorage = reset($fileStorages); |
|
227
|
|
|
if ($fileStorage instanceof ResourceStorage) { |
|
228
|
|
|
$this->folderObject = $fileStorage->getRootLevelFolder(); |
|
229
|
|
|
if (!$fileStorage->isWithinFileMountBoundaries($this->folderObject)) { |
|
230
|
|
|
$this->folderObject = null; |
|
231
|
|
|
} |
|
232
|
|
|
} |
|
233
|
|
|
$this->errorMessage = GeneralUtility::makeInstance( |
|
234
|
|
|
FlashMessage::class, |
|
235
|
|
|
sprintf( |
|
236
|
|
|
$this->getLanguageService()->getLL('folderNotFoundMessage'), |
|
237
|
|
|
$this->id |
|
238
|
|
|
), |
|
239
|
|
|
$this->getLanguageService()->getLL('folderNotFoundTitle'), |
|
240
|
|
|
FlashMessage::NOTICE |
|
241
|
|
|
); |
|
242
|
|
|
} catch (\RuntimeException $e) { |
|
243
|
|
|
$this->folderObject = null; |
|
244
|
|
|
$this->errorMessage = GeneralUtility::makeInstance( |
|
245
|
|
|
FlashMessage::class, |
|
246
|
|
|
$e->getMessage() . ' (' . $e->getCode() . ')', |
|
247
|
|
|
$this->getLanguageService()->getLL('folderNotFoundTitle'), |
|
248
|
|
|
FlashMessage::NOTICE |
|
249
|
|
|
); |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
if ($this->folderObject && !$this->folderObject->getStorage()->checkFolderActionPermission( |
|
253
|
|
|
'read', |
|
254
|
|
|
$this->folderObject |
|
255
|
|
|
) |
|
256
|
|
|
) { |
|
257
|
|
|
$this->folderObject = null; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
// Configure the "menu" - which is used internally to save the values of sorting, displayThumbs etc. |
|
261
|
|
|
$this->menuConfig(); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
/** |
|
265
|
|
|
* Setting the menu/session variables |
|
266
|
|
|
*/ |
|
267
|
|
|
protected function menuConfig() |
|
268
|
|
|
{ |
|
269
|
|
|
// MENU-ITEMS: |
|
270
|
|
|
// If array, then it's a selector box menu |
|
271
|
|
|
// If empty string it's just a variable, that will be saved. |
|
272
|
|
|
// Values NOT in this array will not be saved in the settings-array for the module. |
|
273
|
|
|
$this->MOD_MENU = [ |
|
274
|
|
|
'sort' => '', |
|
275
|
|
|
'reverse' => '', |
|
276
|
|
|
'displayThumbs' => '', |
|
277
|
|
|
'clipBoard' => '', |
|
278
|
|
|
]; |
|
279
|
|
|
// CLEANSE SETTINGS |
|
280
|
|
|
$this->MOD_SETTINGS = BackendUtility::getModuleData( |
|
281
|
|
|
$this->MOD_MENU, |
|
282
|
|
|
GeneralUtility::_GP('SET'), |
|
|
|
|
|
|
283
|
|
|
$this->moduleName |
|
284
|
|
|
); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
/** |
|
288
|
|
|
* Initialize the view |
|
289
|
|
|
* |
|
290
|
|
|
* @param ViewInterface $view The view |
|
291
|
|
|
*/ |
|
292
|
|
|
protected function initializeView(ViewInterface $view) |
|
293
|
|
|
{ |
|
294
|
|
|
/** @var BackendTemplateView $view */ |
|
295
|
|
|
parent::initializeView($view); |
|
296
|
|
|
$pageRenderer = $this->view->getModuleTemplate()->getPageRenderer(); |
|
297
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation'); |
|
298
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileList'); |
|
299
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileSearch'); |
|
300
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu'); |
|
301
|
|
|
$this->registerDocHeaderButtons(); |
|
302
|
|
|
if ($this->folderObject instanceof Folder) { |
|
303
|
|
|
$view->assign( |
|
304
|
|
|
'currentFolderHash', |
|
305
|
|
|
'folder' . GeneralUtility::md5int($this->folderObject->getCombinedIdentifier()) |
|
306
|
|
|
); |
|
307
|
|
|
} |
|
308
|
|
|
$view->assign('currentIdentifier', $this->id); |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
|
|
protected function initializeIndexAction() |
|
312
|
|
|
{ |
|
313
|
|
|
// Apply predefined values for hidden checkboxes |
|
314
|
|
|
$backendUser = $this->getBackendUser(); |
|
315
|
|
|
$userTsConfig = $backendUser->getTSConfig(); |
|
316
|
|
|
// Set predefined value for DisplayThumbnails: |
|
317
|
|
|
if (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'activated') { |
|
318
|
|
|
$this->MOD_SETTINGS['displayThumbs'] = true; |
|
319
|
|
|
} elseif (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'deactivated') { |
|
320
|
|
|
$this->MOD_SETTINGS['displayThumbs'] = false; |
|
321
|
|
|
} |
|
322
|
|
|
// Set predefined value for Clipboard: |
|
323
|
|
|
if (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'activated') { |
|
324
|
|
|
$this->MOD_SETTINGS['clipBoard'] = true; |
|
325
|
|
|
} elseif (($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'deactivated') { |
|
326
|
|
|
$this->MOD_SETTINGS['clipBoard'] = false; |
|
327
|
|
|
} |
|
328
|
|
|
if (!isset($this->MOD_SETTINGS['sort'])) { |
|
329
|
|
|
// Set default sorting |
|
330
|
|
|
$this->MOD_SETTINGS['sort'] = 'file'; |
|
331
|
|
|
$this->MOD_SETTINGS['reverse'] = 0; |
|
332
|
|
|
} |
|
333
|
|
|
} |
|
334
|
|
|
|
|
335
|
|
|
protected function indexAction(): ResponseInterface |
|
336
|
|
|
{ |
|
337
|
|
|
$pageRenderer = $this->view->getModuleTemplate()->getPageRenderer(); |
|
338
|
|
|
$pageRenderer->setTitle($this->getLanguageService()->getLL('files')); |
|
339
|
|
|
|
|
340
|
|
|
// There there was access to this file path, continue, make the list |
|
341
|
|
|
if ($this->folderObject) { |
|
342
|
|
|
$this->initClipboard(); |
|
343
|
|
|
$userTsConfig = $this->getBackendUser()->getTSConfig(); |
|
344
|
|
|
$this->filelist = GeneralUtility::makeInstance(FileList::class); |
|
345
|
|
|
$this->filelist->thumbs = ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] ?? false) && ($this->MOD_SETTINGS['displayThumbs'] ?? false); |
|
346
|
|
|
$CB = GeneralUtility::_GET('CB'); |
|
347
|
|
|
if ($this->cmd === 'setCB') { |
|
348
|
|
|
$CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge( |
|
349
|
|
|
GeneralUtility::_POST('CBH'), |
|
|
|
|
|
|
350
|
|
|
(array)GeneralUtility::_POST('CBC') |
|
351
|
|
|
), '_FILE'); |
|
352
|
|
|
} |
|
353
|
|
|
if (!($this->MOD_SETTINGS['clipBoard'] ?? false)) { |
|
354
|
|
|
$CB['setP'] = 'normal'; |
|
355
|
|
|
} |
|
356
|
|
|
$this->filelist->clipObj->setCmd($CB); |
|
357
|
|
|
$this->filelist->clipObj->cleanCurrent(); |
|
358
|
|
|
// Saves |
|
359
|
|
|
$this->filelist->clipObj->endClipboard(); |
|
360
|
|
|
|
|
361
|
|
|
// If the "cmd" was to delete files from the list (clipboard thing), do that: |
|
362
|
|
|
if ($this->cmd === 'delete') { |
|
363
|
|
|
$items = $this->filelist->clipObj->cleanUpCBC(GeneralUtility::_POST('CBC'), '_FILE', 1); |
|
364
|
|
|
if (!empty($items)) { |
|
365
|
|
|
// Make command array: |
|
366
|
|
|
$FILE = []; |
|
367
|
|
|
foreach ($items as $clipboardIdentifier => $combinedIdentifier) { |
|
368
|
|
|
$FILE['delete'][] = ['data' => $combinedIdentifier]; |
|
369
|
|
|
$this->filelist->clipObj->removeElement($clipboardIdentifier); |
|
370
|
|
|
} |
|
371
|
|
|
// Init file processing object for deleting and pass the cmd array. |
|
372
|
|
|
/** @var ExtendedFileUtility $fileProcessor */ |
|
373
|
|
|
$fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class); |
|
374
|
|
|
$fileProcessor->setActionPermissions(); |
|
375
|
|
|
$fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles); |
|
376
|
|
|
$fileProcessor->start($FILE); |
|
377
|
|
|
$fileProcessor->processData(); |
|
378
|
|
|
// Clean & Save clipboard state |
|
379
|
|
|
$this->filelist->clipObj->cleanCurrent(); |
|
380
|
|
|
$this->filelist->clipObj->endClipboard(); |
|
381
|
|
|
} |
|
382
|
|
|
} |
|
383
|
|
|
// Start up filelisting object, include settings. |
|
384
|
|
|
$this->filelist->start( |
|
385
|
|
|
$this->folderObject, |
|
386
|
|
|
MathUtility::forceIntegerInRange($this->pointer, 0, 100000), |
|
387
|
|
|
$this->MOD_SETTINGS['sort'], |
|
388
|
|
|
(bool)($this->MOD_SETTINGS['reverse'] ?? false), |
|
389
|
|
|
(bool)($this->MOD_SETTINGS['clipBoard'] ?? false) |
|
390
|
|
|
); |
|
391
|
|
|
// Generate the list, if accessible |
|
392
|
|
|
if ($this->folderObject->getStorage()->isBrowsable()) { |
|
393
|
|
|
$this->view->assign('listHtml', $this->filelist->getTable()); |
|
394
|
|
|
} else { |
|
395
|
|
|
$this->addFlashMessage( |
|
396
|
|
|
$this->getLanguageService()->getLL('storageNotBrowsableMessage'), |
|
397
|
|
|
$this->getLanguageService()->getLL('storageNotBrowsableTitle'), |
|
398
|
|
|
FlashMessage::INFO |
|
399
|
|
|
); |
|
400
|
|
|
} |
|
401
|
|
|
|
|
402
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ClipboardComponent'); |
|
403
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete'); |
|
404
|
|
|
$pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons'); |
|
405
|
|
|
|
|
406
|
|
|
// Include DragUploader only if we have write access |
|
407
|
|
|
if ($this->folderObject->getStorage()->checkUserActionPermission('add', 'File') |
|
408
|
|
|
&& $this->folderObject->checkActionPermission('write') |
|
409
|
|
|
) { |
|
410
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader'); |
|
411
|
|
|
$pageRenderer->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/locallang_core.xlf', 'file_upload'); |
|
412
|
|
|
$pageRenderer->addInlineLanguageLabelArray([ |
|
413
|
|
|
'permissions.read' => $this->getLanguageService()->getLL('read'), |
|
414
|
|
|
'permissions.write' => $this->getLanguageService()->getLL('write'), |
|
415
|
|
|
]); |
|
416
|
|
|
} |
|
417
|
|
|
|
|
418
|
|
|
// Setting up the buttons |
|
419
|
|
|
$this->registerButtons(); |
|
420
|
|
|
|
|
421
|
|
|
$pageRecord = [ |
|
422
|
|
|
'_additional_info' => $this->filelist->getFolderInfo(), |
|
423
|
|
|
'combined_identifier' => $this->folderObject->getCombinedIdentifier(), |
|
424
|
|
|
]; |
|
425
|
|
|
$this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($pageRecord); |
|
426
|
|
|
|
|
427
|
|
|
$this->view->assign('headline', $this->getModuleHeadline()); |
|
428
|
|
|
|
|
429
|
|
|
$this->view->assign('checkboxes', [ |
|
430
|
|
|
'displayThumbs' => [ |
|
431
|
|
|
'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && ($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'selectable', |
|
432
|
|
|
'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')), |
|
433
|
|
|
'html' => BackendUtility::getFuncCheck( |
|
434
|
|
|
$this->id, |
|
435
|
|
|
'SET[displayThumbs]', |
|
436
|
|
|
$this->MOD_SETTINGS['displayThumbs'] ?? '', |
|
437
|
|
|
'', |
|
438
|
|
|
'', |
|
439
|
|
|
'id="checkDisplayThumbs"' |
|
440
|
|
|
), |
|
441
|
|
|
], |
|
442
|
|
|
'enableClipBoard' => [ |
|
443
|
|
|
'enabled' => ($userTsConfig['options.']['file_list.']['enableClipBoard'] ?? '') === 'selectable', |
|
444
|
|
|
'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')), |
|
445
|
|
|
'html' => BackendUtility::getFuncCheck( |
|
446
|
|
|
$this->id, |
|
447
|
|
|
'SET[clipBoard]', |
|
448
|
|
|
$this->MOD_SETTINGS['clipBoard'] ?? '', |
|
449
|
|
|
'', |
|
450
|
|
|
'', |
|
451
|
|
|
'id="checkClipBoard"' |
|
452
|
|
|
), |
|
453
|
|
|
] |
|
454
|
|
|
]); |
|
455
|
|
|
$this->view->assign('showClipBoard', (bool)($this->MOD_SETTINGS['clipBoard'] ?? false)); |
|
456
|
|
|
$this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard()); |
|
457
|
|
|
$this->view->assign('folderIdentifier', $this->folderObject->getCombinedIdentifier()); |
|
458
|
|
|
$this->view->assign('fileDenyPattern', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] ?? null); |
|
459
|
|
|
$this->view->assign('maxFileSize', GeneralUtility::getMaxUploadFileSize() * 1024); |
|
460
|
|
|
$this->view->assign('defaultAction', $this->getDefaultAction()); |
|
461
|
|
|
$this->buildListOptionCheckboxes(); |
|
462
|
|
|
$this->view->getModuleTemplate()->setTitle( |
|
463
|
|
|
$this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:mlang_tabs_tab'), |
|
464
|
|
|
$this->getModuleHeadline() |
|
465
|
|
|
); |
|
466
|
|
|
} else { |
|
467
|
|
|
return new ForwardResponse('missingFolder'); |
|
468
|
|
|
} |
|
469
|
|
|
|
|
470
|
|
|
return $this->htmlResponse(); |
|
471
|
|
|
} |
|
472
|
|
|
|
|
473
|
|
|
protected function getDefaultAction(): string |
|
474
|
|
|
{ |
|
475
|
|
|
$defaultAction = $this->getBackendUser()->getTSConfig() |
|
476
|
|
|
['options.']['file_list.']['uploader.']['defaultAction'] ?? ''; |
|
477
|
|
|
|
|
478
|
|
|
if ($defaultAction === '') { |
|
479
|
|
|
$defaultAction = self::UPLOAD_ACTION_SKIP; |
|
480
|
|
|
} |
|
481
|
|
|
if (!in_array($defaultAction, [ |
|
482
|
|
|
self::UPLOAD_ACTION_REPLACE, |
|
483
|
|
|
self::UPLOAD_ACTION_RENAME, |
|
484
|
|
|
self::UPLOAD_ACTION_SKIP |
|
485
|
|
|
], true)) { |
|
486
|
|
|
$this->logger->warning('TSConfig: options.file_list.uploader.defaultAction contains an invalid value ("{value}"), fallback to default value: "{default}"', [ |
|
|
|
|
|
|
487
|
|
|
'value' => $defaultAction, |
|
488
|
|
|
'default' => self::UPLOAD_ACTION_SKIP |
|
489
|
|
|
]); |
|
490
|
|
|
$defaultAction = self::UPLOAD_ACTION_SKIP; |
|
491
|
|
|
} |
|
492
|
|
|
return $defaultAction; |
|
493
|
|
|
} |
|
494
|
|
|
|
|
495
|
|
|
protected function missingFolderAction(): ResponseInterface |
|
496
|
|
|
{ |
|
497
|
|
|
if ($this->errorMessage) { |
|
498
|
|
|
$this->errorMessage->setSeverity(FlashMessage::ERROR); |
|
499
|
|
|
$this->getFlashMessageQueue('core.template.flashMessages')->addMessage($this->errorMessage); |
|
500
|
|
|
} |
|
501
|
|
|
|
|
502
|
|
|
return $this->htmlResponse(); |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
/** |
|
506
|
|
|
* Search for files by name and pass them with a facade to fluid |
|
507
|
|
|
* |
|
508
|
|
|
* @param string $searchWord |
|
509
|
|
|
*/ |
|
510
|
|
|
protected function searchAction($searchWord = ''): ResponseInterface |
|
511
|
|
|
{ |
|
512
|
|
|
if (empty($searchWord)) { |
|
513
|
|
|
return new ForwardResponse('index'); |
|
514
|
|
|
} |
|
515
|
|
|
$searchDemand = FileSearchDemand::createForSearchTerm($searchWord)->withRecursive(); |
|
516
|
|
|
$files = $this->folderObject->searchFiles($searchDemand); |
|
|
|
|
|
|
517
|
|
|
|
|
518
|
|
|
$fileFacades = []; |
|
519
|
|
|
if (count($files) === 0) { |
|
520
|
|
|
$this->getFlashMessageQueue('core.template.flashMessages')->addMessage( |
|
521
|
|
|
new FlashMessage( |
|
522
|
|
|
LocalizationUtility::translate('flashmessage.no_results', 'filelist') ?? '', |
|
523
|
|
|
'', |
|
524
|
|
|
FlashMessage::INFO |
|
525
|
|
|
) |
|
526
|
|
|
); |
|
527
|
|
|
} else { |
|
528
|
|
|
foreach ($files as $file) { |
|
529
|
|
|
$fileFacades[] = new FileFacade($file); |
|
530
|
|
|
} |
|
531
|
|
|
} |
|
532
|
|
|
|
|
533
|
|
|
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
|
534
|
|
|
|
|
535
|
|
|
$thumbnailConfiguration = GeneralUtility::makeInstance(ThumbnailConfiguration::class); |
|
536
|
|
|
$this->view->assign('thumbnail', [ |
|
537
|
|
|
'width' => $thumbnailConfiguration->getWidth(), |
|
538
|
|
|
'height' => $thumbnailConfiguration->getHeight(), |
|
539
|
|
|
]); |
|
540
|
|
|
|
|
541
|
|
|
$this->view->assign('searchWord', $searchWord); |
|
542
|
|
|
$this->view->assign('files', $fileFacades); |
|
543
|
|
|
$this->view->assign('deleteUrl', (string)$uriBuilder->buildUriFromRoute('tce_file')); |
|
544
|
|
|
$this->view->assign('settings', [ |
|
545
|
|
|
'jsConfirmationDelete' => $this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE) |
|
546
|
|
|
]); |
|
547
|
|
|
$this->view->assign('moduleSettings', $this->MOD_SETTINGS); |
|
548
|
|
|
|
|
549
|
|
|
$pageRenderer = $this->view->getModuleTemplate()->getPageRenderer(); |
|
550
|
|
|
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete'); |
|
551
|
|
|
$pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons'); |
|
552
|
|
|
|
|
553
|
|
|
$this->initClipboard(); |
|
554
|
|
|
$this->buildListOptionCheckboxes($searchWord); |
|
555
|
|
|
|
|
556
|
|
|
return $this->htmlResponse(); |
|
557
|
|
|
} |
|
558
|
|
|
|
|
559
|
|
|
/** |
|
560
|
|
|
* Get main headline based on active folder or storage for backend module |
|
561
|
|
|
* Folder names are resolved to their special names like done in the tree view. |
|
562
|
|
|
* |
|
563
|
|
|
* @return string |
|
564
|
|
|
*/ |
|
565
|
|
|
protected function getModuleHeadline() |
|
566
|
|
|
{ |
|
567
|
|
|
$name = $this->folderObject->getName(); |
|
568
|
|
|
if ($name === '') { |
|
569
|
|
|
// Show storage name on storage root |
|
570
|
|
|
if ($this->folderObject->getIdentifier() === '/') { |
|
571
|
|
|
$name = $this->folderObject->getStorage()->getName(); |
|
572
|
|
|
} |
|
573
|
|
|
} else { |
|
574
|
|
|
$name = key(ListUtility::resolveSpecialFolderNames( |
|
575
|
|
|
[$name => $this->folderObject] |
|
576
|
|
|
)); |
|
577
|
|
|
} |
|
578
|
|
|
return $name; |
|
579
|
|
|
} |
|
580
|
|
|
|
|
581
|
|
|
/** |
|
582
|
|
|
* Registers the Icons into the docheader |
|
583
|
|
|
* |
|
584
|
|
|
* @throws \InvalidArgumentException |
|
585
|
|
|
*/ |
|
586
|
|
|
protected function registerDocHeaderButtons() |
|
587
|
|
|
{ |
|
588
|
|
|
/** @var ButtonBar $buttonBar */ |
|
589
|
|
|
$buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); |
|
590
|
|
|
|
|
591
|
|
|
// CSH |
|
592
|
|
|
$cshButton = $buttonBar->makeHelpButton() |
|
593
|
|
|
->setModuleName('xMOD_csh_corebe') |
|
594
|
|
|
->setFieldName('filelist_module'); |
|
595
|
|
|
$buttonBar->addButton($cshButton); |
|
596
|
|
|
} |
|
597
|
|
|
|
|
598
|
|
|
/** |
|
599
|
|
|
* Create the panel of buttons for submitting the form or otherwise perform operations. |
|
600
|
|
|
*/ |
|
601
|
|
|
protected function registerButtons() |
|
602
|
|
|
{ |
|
603
|
|
|
/** @var ButtonBar $buttonBar */ |
|
604
|
|
|
$buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); |
|
605
|
|
|
|
|
606
|
|
|
/** @var IconFactory $iconFactory */ |
|
607
|
|
|
$iconFactory = $this->view->getModuleTemplate()->getIconFactory(); |
|
608
|
|
|
|
|
609
|
|
|
$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); |
|
610
|
|
|
|
|
611
|
|
|
$lang = $this->getLanguageService(); |
|
612
|
|
|
|
|
613
|
|
|
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
|
614
|
|
|
|
|
615
|
|
|
// Refresh page |
|
616
|
|
|
$refreshLink = GeneralUtility::linkThisScript( |
|
617
|
|
|
[ |
|
618
|
|
|
'target' => rawurlencode($this->folderObject->getCombinedIdentifier()), |
|
619
|
|
|
'imagemode' => $this->filelist->thumbs |
|
620
|
|
|
] |
|
621
|
|
|
); |
|
622
|
|
|
$refreshButton = $buttonBar->makeLinkButton() |
|
623
|
|
|
->setHref($refreshLink) |
|
624
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload')) |
|
625
|
|
|
->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL)); |
|
626
|
|
|
$buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT); |
|
627
|
|
|
|
|
628
|
|
|
// Level up |
|
629
|
|
|
try { |
|
630
|
|
|
$currentStorage = $this->folderObject->getStorage(); |
|
631
|
|
|
$parentFolder = $this->folderObject->getParentFolder(); |
|
632
|
|
|
if ($parentFolder->getIdentifier() !== $this->folderObject->getIdentifier() |
|
633
|
|
|
&& $currentStorage->isWithinFileMountBoundaries($parentFolder) |
|
634
|
|
|
) { |
|
635
|
|
|
$levelUpButton = $buttonBar->makeLinkButton() |
|
636
|
|
|
->setDataAttributes([ |
|
637
|
|
|
'tree-update-request' => htmlspecialchars('folder' . GeneralUtility::md5int($parentFolder->getCombinedIdentifier())), |
|
638
|
|
|
]) |
|
639
|
|
|
->setHref((string)$uriBuilder->buildUriFromRoute('file_FilelistList', ['id' => $parentFolder->getCombinedIdentifier()])) |
|
640
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.upOneLevel')) |
|
641
|
|
|
->setIcon($iconFactory->getIcon('actions-view-go-up', Icon::SIZE_SMALL)); |
|
642
|
|
|
$buttonBar->addButton($levelUpButton, ButtonBar::BUTTON_POSITION_LEFT, 1); |
|
643
|
|
|
} |
|
644
|
|
|
} catch (\Exception $e) { |
|
|
|
|
|
|
645
|
|
|
} |
|
646
|
|
|
|
|
647
|
|
|
// Shortcut |
|
648
|
|
|
$shortCutButton = $buttonBar->makeShortcutButton() |
|
649
|
|
|
->setRouteIdentifier('file_FilelistList') |
|
650
|
|
|
->setDisplayName($this->getShortcutTitle()) |
|
651
|
|
|
->setArguments(['id' => $this->id]); |
|
652
|
|
|
$buttonBar->addButton($shortCutButton, ButtonBar::BUTTON_POSITION_RIGHT); |
|
653
|
|
|
|
|
654
|
|
|
// Upload button (only if upload to this directory is allowed) |
|
655
|
|
|
if ($this->folderObject && $this->folderObject->getStorage()->checkUserActionPermission( |
|
656
|
|
|
'add', |
|
657
|
|
|
'File' |
|
658
|
|
|
) && $this->folderObject->checkActionPermission('write') |
|
659
|
|
|
) { |
|
660
|
|
|
$uploadButton = $buttonBar->makeLinkButton() |
|
661
|
|
|
->setHref((string)$uriBuilder->buildUriFromRoute( |
|
662
|
|
|
'file_upload', |
|
663
|
|
|
[ |
|
664
|
|
|
'target' => $this->folderObject->getCombinedIdentifier(), |
|
665
|
|
|
'returnUrl' => $this->filelist->listURL(), |
|
666
|
|
|
] |
|
667
|
|
|
)) |
|
668
|
|
|
->setClasses('t3js-drag-uploader-trigger') |
|
669
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.upload')) |
|
670
|
|
|
->setIcon($iconFactory->getIcon('actions-edit-upload', Icon::SIZE_SMALL)); |
|
671
|
|
|
$buttonBar->addButton($uploadButton, ButtonBar::BUTTON_POSITION_LEFT, 1); |
|
672
|
|
|
} |
|
673
|
|
|
|
|
674
|
|
|
// New folder button |
|
675
|
|
|
if ($this->folderObject && $this->folderObject->checkActionPermission('write') |
|
676
|
|
|
&& ($this->folderObject->getStorage()->checkUserActionPermission( |
|
677
|
|
|
'add', |
|
678
|
|
|
'File' |
|
679
|
|
|
) || $this->folderObject->checkActionPermission('add')) |
|
680
|
|
|
) { |
|
681
|
|
|
$newButton = $buttonBar->makeLinkButton() |
|
682
|
|
|
->setHref((string)$uriBuilder->buildUriFromRoute( |
|
683
|
|
|
'file_newfolder', |
|
684
|
|
|
[ |
|
685
|
|
|
'target' => $this->folderObject->getCombinedIdentifier(), |
|
686
|
|
|
'returnUrl' => $this->filelist->listURL(), |
|
687
|
|
|
] |
|
688
|
|
|
)) |
|
689
|
|
|
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.new')) |
|
690
|
|
|
->setIcon($iconFactory->getIcon('actions-add', Icon::SIZE_SMALL)); |
|
691
|
|
|
$buttonBar->addButton($newButton, ButtonBar::BUTTON_POSITION_LEFT, 1); |
|
692
|
|
|
} |
|
693
|
|
|
|
|
694
|
|
|
// Add paste button if clipboard is initialized |
|
695
|
|
|
if ($this->filelist->clipObj instanceof Clipboard && $this->folderObject->checkActionPermission('write')) { |
|
696
|
|
|
$elFromTable = $this->filelist->clipObj->elFromTable('_FILE'); |
|
697
|
|
|
if (!empty($elFromTable)) { |
|
698
|
|
|
$addPasteButton = true; |
|
699
|
|
|
$elToConfirm = []; |
|
700
|
|
|
foreach ($elFromTable as $key => $element) { |
|
701
|
|
|
$clipBoardElement = $resourceFactory->retrieveFileOrFolderObject($element); |
|
702
|
|
|
if ($clipBoardElement instanceof Folder && $clipBoardElement->getStorage()->isWithinFolder( |
|
703
|
|
|
$clipBoardElement, |
|
704
|
|
|
$this->folderObject |
|
|
|
|
|
|
705
|
|
|
) |
|
706
|
|
|
) { |
|
707
|
|
|
$addPasteButton = false; |
|
708
|
|
|
} |
|
709
|
|
|
$elToConfirm[$key] = $clipBoardElement->getName(); |
|
710
|
|
|
} |
|
711
|
|
|
if ($addPasteButton) { |
|
712
|
|
|
$confirmText = $this->filelist->clipObj |
|
713
|
|
|
->confirmMsgText('_FILE', $this->folderObject->getReadablePath(), 'into', $elToConfirm); |
|
714
|
|
|
$pasteButton = $buttonBar->makeLinkButton() |
|
715
|
|
|
->setHref($this->filelist->clipObj |
|
716
|
|
|
->pasteUrl('_FILE', $this->folderObject->getCombinedIdentifier())) |
|
717
|
|
|
->setClasses('t3js-modal-trigger') |
|
718
|
|
|
->setDataAttributes([ |
|
719
|
|
|
'severity' => 'warning', |
|
720
|
|
|
'bs-content' => $confirmText, |
|
721
|
|
|
'title' => $lang->getLL('clip_paste') |
|
722
|
|
|
]) |
|
723
|
|
|
->setTitle($lang->getLL('clip_paste')) |
|
724
|
|
|
->setIcon($iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)); |
|
725
|
|
|
$buttonBar->addButton($pasteButton, ButtonBar::BUTTON_POSITION_LEFT, 2); |
|
726
|
|
|
} |
|
727
|
|
|
} |
|
728
|
|
|
} |
|
729
|
|
|
} |
|
730
|
|
|
|
|
731
|
|
|
/** |
|
732
|
|
|
* Returns an instance of LanguageService |
|
733
|
|
|
* |
|
734
|
|
|
* @return LanguageService |
|
735
|
|
|
*/ |
|
736
|
|
|
protected function getLanguageService(): LanguageService |
|
737
|
|
|
{ |
|
738
|
|
|
return $GLOBALS['LANG']; |
|
739
|
|
|
} |
|
740
|
|
|
|
|
741
|
|
|
/** |
|
742
|
|
|
* Returns the current BE user. |
|
743
|
|
|
* |
|
744
|
|
|
* @return BackendUserAuthentication |
|
745
|
|
|
*/ |
|
746
|
|
|
protected function getBackendUser(): BackendUserAuthentication |
|
747
|
|
|
{ |
|
748
|
|
|
return $GLOBALS['BE_USER']; |
|
749
|
|
|
} |
|
750
|
|
|
|
|
751
|
|
|
/** |
|
752
|
|
|
* build option checkboxes for filelist |
|
753
|
|
|
*/ |
|
754
|
|
|
protected function buildListOptionCheckboxes(string $searchWord = ''): void |
|
755
|
|
|
{ |
|
756
|
|
|
$backendUser = $this->getBackendUser(); |
|
757
|
|
|
$userTsConfig = $backendUser->getTSConfig(); |
|
758
|
|
|
|
|
759
|
|
|
$addParams = ''; |
|
760
|
|
|
if ($searchWord) { |
|
761
|
|
|
$addParams = '&tx_filelist_file_filelistlist%5Baction%5D=search'; |
|
762
|
|
|
$addParams .= '&tx_filelist_file_filelistlist%5Bcontroller%5D=FileList'; |
|
763
|
|
|
$addParams .= '&tx_filelist_file_filelistlist%5BsearchWord%5D=' . htmlspecialchars($searchWord); |
|
764
|
|
|
} |
|
765
|
|
|
$this->view->assign('checkboxes', [ |
|
766
|
|
|
'displayThumbs' => [ |
|
767
|
|
|
'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] === 'selectable', |
|
768
|
|
|
'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')), |
|
769
|
|
|
'html' => BackendUtility::getFuncCheck( |
|
770
|
|
|
$this->id, |
|
771
|
|
|
'SET[displayThumbs]', |
|
772
|
|
|
$this->MOD_SETTINGS['displayThumbs'] ?? '', |
|
773
|
|
|
'', |
|
774
|
|
|
$addParams, |
|
775
|
|
|
'id="checkDisplayThumbs"' |
|
776
|
|
|
), |
|
777
|
|
|
], |
|
778
|
|
|
'enableClipBoard' => [ |
|
779
|
|
|
'enabled' => $userTsConfig['options.']['file_list.']['enableClipBoard'] === 'selectable', |
|
780
|
|
|
'label' => htmlspecialchars($this->getLanguageService()->getLL('clipBoard')), |
|
781
|
|
|
'html' => BackendUtility::getFuncCheck( |
|
782
|
|
|
$this->id, |
|
783
|
|
|
'SET[clipBoard]', |
|
784
|
|
|
$this->MOD_SETTINGS['clipBoard'] ?? '', |
|
785
|
|
|
'', |
|
786
|
|
|
$addParams, |
|
787
|
|
|
'id="checkClipBoard"' |
|
788
|
|
|
), |
|
789
|
|
|
] |
|
790
|
|
|
]); |
|
791
|
|
|
} |
|
792
|
|
|
|
|
793
|
|
|
/** |
|
794
|
|
|
* init and assign clipboard to view |
|
795
|
|
|
*/ |
|
796
|
|
|
protected function initClipboard(): void |
|
797
|
|
|
{ |
|
798
|
|
|
// Create fileListing object |
|
799
|
|
|
$this->filelist = GeneralUtility::makeInstance(FileList::class, $this); |
|
800
|
|
|
$this->filelist->thumbs = ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] ?? false) && ($this->MOD_SETTINGS['displayThumbs'] ?? false); |
|
801
|
|
|
// Create clipboard object and initialize that |
|
802
|
|
|
$this->filelist->clipObj = GeneralUtility::makeInstance(Clipboard::class); |
|
803
|
|
|
$this->filelist->clipObj->fileMode = true; |
|
804
|
|
|
$this->filelist->clipObj->initializeClipboard(); |
|
805
|
|
|
$CB = GeneralUtility::_GET('CB'); |
|
806
|
|
|
if ($this->cmd === 'setCB') { |
|
807
|
|
|
$CB['el'] = $this->filelist->clipObj->cleanUpCBC(array_merge( |
|
808
|
|
|
GeneralUtility::_POST('CBH'), |
|
|
|
|
|
|
809
|
|
|
(array)GeneralUtility::_POST('CBC') |
|
810
|
|
|
), '_FILE'); |
|
811
|
|
|
} |
|
812
|
|
|
if (!($this->MOD_SETTINGS['clipBoard'] ?? false)) { |
|
813
|
|
|
$CB['setP'] = 'normal'; |
|
814
|
|
|
} |
|
815
|
|
|
$this->filelist->clipObj->setCmd($CB); |
|
816
|
|
|
$this->filelist->clipObj->cleanCurrent(); |
|
817
|
|
|
// Saves |
|
818
|
|
|
$this->filelist->clipObj->endClipboard(); |
|
819
|
|
|
|
|
820
|
|
|
$this->view->assign('showClipBoard', (bool)($this->MOD_SETTINGS['clipBoard'] ?? false)); |
|
821
|
|
|
$this->view->assign('clipBoardHtml', $this->filelist->clipObj->printClipboard()); |
|
822
|
|
|
} |
|
823
|
|
|
|
|
824
|
|
|
/** |
|
825
|
|
|
* Returns the shortcut title for the current folder object |
|
826
|
|
|
* |
|
827
|
|
|
* @return string |
|
828
|
|
|
*/ |
|
829
|
|
|
protected function getShortcutTitle(): string |
|
830
|
|
|
{ |
|
831
|
|
|
return sprintf( |
|
832
|
|
|
'%s: %s', |
|
833
|
|
|
$this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:mlang_tabs_tab'), |
|
834
|
|
|
$this->folderObject->getName() ?: $this->folderObject->getIdentifier() |
|
835
|
|
|
); |
|
836
|
|
|
} |
|
837
|
|
|
} |
|
838
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.