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\Backend\Clipboard; |
17
|
|
|
|
18
|
|
|
use TYPO3\CMS\Backend\Routing\UriBuilder; |
19
|
|
|
use TYPO3\CMS\Backend\Utility\BackendUtility; |
20
|
|
|
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; |
21
|
|
|
use TYPO3\CMS\Core\Database\ConnectionPool; |
22
|
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; |
23
|
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; |
24
|
|
|
use TYPO3\CMS\Core\Imaging\Icon; |
25
|
|
|
use TYPO3\CMS\Core\Imaging\IconFactory; |
26
|
|
|
use TYPO3\CMS\Core\Localization\LanguageService; |
27
|
|
|
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException; |
28
|
|
|
use TYPO3\CMS\Core\Resource\File; |
29
|
|
|
use TYPO3\CMS\Core\Resource\Folder; |
30
|
|
|
use TYPO3\CMS\Core\Resource\ProcessedFile; |
31
|
|
|
use TYPO3\CMS\Core\Resource\ResourceFactory; |
32
|
|
|
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; |
33
|
|
|
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; |
34
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
35
|
|
|
use TYPO3\CMS\Core\Utility\MathUtility; |
36
|
|
|
use TYPO3\CMS\Core\Utility\PathUtility; |
37
|
|
|
use TYPO3\CMS\Fluid\View\StandaloneView; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* TYPO3 clipboard for records and files |
41
|
|
|
* |
42
|
|
|
* @internal This class is a specific Backend implementation and is not considered part of the Public TYPO3 API. |
43
|
|
|
*/ |
44
|
|
|
class Clipboard |
45
|
|
|
{ |
46
|
|
|
/** |
47
|
|
|
* @var int |
48
|
|
|
*/ |
49
|
|
|
public $numberTabs = 3; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Clipboard data kept here |
53
|
|
|
* |
54
|
|
|
* Keys: |
55
|
|
|
* 'normal' |
56
|
|
|
* 'tab_[x]' where x is >=1 and denotes the pad-number |
57
|
|
|
* 'mode' : 'copy' means copy-mode, default = moving ('cut') |
58
|
|
|
* 'el' : Array of elements: |
59
|
|
|
* DB: keys = '[tablename]|[uid]' eg. 'tt_content:123' |
60
|
|
|
* DB: values = 1 (basically insignificant) |
61
|
|
|
* FILE: keys = '_FILE|[shortmd5 of path]' eg. '_FILE|9ebc7e5c74' |
62
|
|
|
* FILE: values = The full filepath, eg. '/www/htdocs/typo3/32/dummy/fileadmin/sem1_3_examples/alternative_index.php' |
63
|
|
|
* or 'C:/www/htdocs/typo3/32/dummy/fileadmin/sem1_3_examples/alternative_index.php' |
64
|
|
|
* |
65
|
|
|
* 'current' pointer to current tab (among the above...) |
66
|
|
|
* |
67
|
|
|
* The virtual tablename '_FILE' will always indicate files/folders. When checking for elements from eg. 'all tables' |
68
|
|
|
* (by using an empty string) '_FILE' entries are excluded (so in effect only DB elements are counted) |
69
|
|
|
* |
70
|
|
|
* @var array |
71
|
|
|
*/ |
72
|
|
|
public $clipData = []; |
73
|
|
|
|
74
|
|
|
public bool $changed = false; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @var string |
78
|
|
|
*/ |
79
|
|
|
public $current = ''; |
80
|
|
|
|
81
|
|
|
public bool $lockToNormal = false; |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* If set, clipboard is displaying files. |
85
|
|
|
*/ |
86
|
|
|
public bool $fileMode = false; |
87
|
|
|
|
88
|
|
|
protected IconFactory $iconFactory; |
89
|
|
|
protected UriBuilder $uriBuilder; |
90
|
|
|
protected ResourceFactory $resourceFactory; |
91
|
|
|
|
92
|
|
|
public function __construct(IconFactory $iconFactory, UriBuilder $uriBuilder, ResourceFactory $resourceFactory) |
93
|
|
|
{ |
94
|
|
|
$this->iconFactory = $iconFactory; |
95
|
|
|
$this->uriBuilder = $uriBuilder; |
96
|
|
|
$this->resourceFactory = $resourceFactory; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/***************************************** |
100
|
|
|
* |
101
|
|
|
* Initialize |
102
|
|
|
* |
103
|
|
|
****************************************/ |
104
|
|
|
/** |
105
|
|
|
* Initialize the clipboard from the be_user session |
106
|
|
|
*/ |
107
|
|
|
public function initializeClipboard() |
108
|
|
|
{ |
109
|
|
|
$userTsConfig = $this->getBackendUser()->getTSConfig(); |
110
|
|
|
// Get data |
111
|
|
|
$clipData = $this->getBackendUser()->getModuleData('clipboard', !empty($userTsConfig['options.']['saveClipboard']) ? '' : 'ses') ?: []; |
112
|
|
|
$clipData += ['normal' => []]; |
113
|
|
|
$this->numberTabs = MathUtility::forceIntegerInRange((int)($userTsConfig['options.']['clipboardNumberPads'] ?? 3), 0, 20); |
114
|
|
|
// Resets/reinstates the clipboard pads |
115
|
|
|
$this->clipData['normal'] = is_array($clipData['normal']) ? $clipData['normal']: []; |
116
|
|
|
for ($a = 1; $a <= $this->numberTabs; $a++) { |
117
|
|
|
$index = 'tab_' . $a; |
118
|
|
|
$this->clipData[$index] = is_iterable($clipData[$index] ?? null) ? $clipData[$index] : []; |
119
|
|
|
} |
120
|
|
|
// Setting the current pad pointer ($this->current)) |
121
|
|
|
$current = $clipData['current'] ?? ''; |
122
|
|
|
$this->current = isset($this->clipData[$current]) ? $current : 'normal'; |
123
|
|
|
$this->clipData['current'] = $this->current; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Call this method after initialization if you want to lock the clipboard to operate on the normal pad only. |
128
|
|
|
* Trying to switch pad through ->setCmd will not work. |
129
|
|
|
* This is used by the clickmenu since it only allows operation on single elements at a time (that is the "normal" pad) |
130
|
|
|
*/ |
131
|
|
|
public function lockToNormal() |
132
|
|
|
{ |
133
|
|
|
$this->lockToNormal = true; |
134
|
|
|
$this->current = 'normal'; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* The array $cmd may hold various keys which notes some action to take. |
139
|
|
|
* Normally perform only one action at a time. |
140
|
|
|
* In scripts like db_list.php / filelist/mod1/index.php the GET-var CB is used to control the clipboard. |
141
|
|
|
* |
142
|
|
|
* Selecting / Deselecting elements |
143
|
|
|
* Array $cmd['el'] has keys = element-ident, value = element value (see description of clipData array in header) |
144
|
|
|
* Selecting elements for 'copy' should be done by simultaneously setting setCopyMode. |
145
|
|
|
* |
146
|
|
|
* @param array $cmd Array of actions, see function description |
147
|
|
|
*/ |
148
|
|
|
public function setCmd($cmd) |
149
|
|
|
{ |
150
|
|
|
$cmd['el'] ??= []; |
151
|
|
|
$cmd['el'] = is_iterable($cmd['el']) ? $cmd['el'] : []; |
152
|
|
|
foreach ($cmd['el'] as $k => $v) { |
153
|
|
|
if ($this->current === 'normal') { |
154
|
|
|
unset($this->clipData['normal']); |
155
|
|
|
} |
156
|
|
|
if ($v) { |
157
|
|
|
$this->clipData[$this->current]['el'][$k] = $v; |
158
|
|
|
} else { |
159
|
|
|
$this->removeElement($k); |
160
|
|
|
} |
161
|
|
|
$this->changed = true; |
162
|
|
|
} |
163
|
|
|
// Change clipboard pad (if not locked to normal) |
164
|
|
|
if ($cmd['setP'] ?? false) { |
165
|
|
|
$this->setCurrentPad($cmd['setP']); |
166
|
|
|
} |
167
|
|
|
// Remove element (value = item ident: DB; '[tablename]|[uid]' FILE: '_FILE|[shortmd5 hash of path]' |
168
|
|
|
if ($cmd['remove'] ?? false) { |
169
|
|
|
$this->removeElement($cmd['remove']); |
170
|
|
|
$this->changed = true; |
171
|
|
|
} |
172
|
|
|
// Remove all on current pad (value = pad-ident) |
173
|
|
|
if ($cmd['removeAll'] ?? false) { |
174
|
|
|
$this->clipData[$cmd['removeAll']] = []; |
175
|
|
|
$this->changed = true; |
176
|
|
|
} |
177
|
|
|
// Set copy mode of the tab |
178
|
|
|
if (isset($cmd['setCopyMode'])) { |
179
|
|
|
$this->clipData[$this->current]['mode'] = $cmd['setCopyMode'] ? 'copy' : ''; |
180
|
|
|
$this->changed = true; |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Setting the current pad on clipboard |
186
|
|
|
* |
187
|
|
|
* @param string $padIdentifier Key in the array $this->clipData |
188
|
|
|
*/ |
189
|
|
|
public function setCurrentPad($padIdentifier) |
190
|
|
|
{ |
191
|
|
|
// Change clipboard pad (if not locked to normal) |
192
|
|
|
if (!$this->lockToNormal && $this->current != $padIdentifier) { |
193
|
|
|
if (isset($this->clipData[$padIdentifier])) { |
194
|
|
|
$this->clipData['current'] = ($this->current = $padIdentifier); |
195
|
|
|
} |
196
|
|
|
if ($this->current !== 'normal' || !$this->isElements()) { |
197
|
|
|
$this->clipData[$this->current]['mode'] = ''; |
198
|
|
|
} |
199
|
|
|
// Setting mode to default (move) if no items on it or if not 'normal' |
200
|
|
|
$this->changed = true; |
201
|
|
|
} |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Call this after initialization and setCmd in order to save the clipboard to the user session. |
206
|
|
|
* The function will check if the internal flag ->changed has been set and if so, save the clipboard. Else not. |
207
|
|
|
*/ |
208
|
|
|
public function endClipboard() |
209
|
|
|
{ |
210
|
|
|
if ($this->changed) { |
211
|
|
|
$this->saveClipboard(); |
212
|
|
|
} |
213
|
|
|
$this->changed = false; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Cleans up an incoming element array $CBarr (Array selecting/deselecting elements) |
218
|
|
|
* |
219
|
|
|
* @param array $CBarr Element array from outside ("key" => "selected/deselected") |
220
|
|
|
* @param string $table The 'table which is allowed'. Must be set. |
221
|
|
|
* @param bool|int $removeDeselected Can be set in order to remove entries which are marked for deselection. |
222
|
|
|
* @return array Processed input $CBarr |
223
|
|
|
*/ |
224
|
|
|
public function cleanUpCBC($CBarr, $table, $removeDeselected = 0) |
225
|
|
|
{ |
226
|
|
|
if (is_array($CBarr)) { |
|
|
|
|
227
|
|
|
foreach ($CBarr as $k => $v) { |
228
|
|
|
$p = explode('|', $k); |
229
|
|
|
if ((string)$p[0] != (string)$table || $removeDeselected && !$v) { |
230
|
|
|
unset($CBarr[$k]); |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
} |
234
|
|
|
return $CBarr; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/***************************************** |
238
|
|
|
* |
239
|
|
|
* Clipboard HTML renderings |
240
|
|
|
* |
241
|
|
|
****************************************/ |
242
|
|
|
/** |
243
|
|
|
* Prints the clipboard |
244
|
|
|
* |
245
|
|
|
* @return string HTML output |
246
|
|
|
* @throws \BadFunctionCallException |
247
|
|
|
*/ |
248
|
|
|
public function printClipboard() |
249
|
|
|
{ |
250
|
|
|
$elementCount = count($this->elFromTable($this->fileMode ? '_FILE' : '')); |
251
|
|
|
$view = $this->getStandaloneView(); |
252
|
|
|
|
253
|
|
|
// CopyMode Selector menu |
254
|
|
|
$view->assign('actionCopyModeUrl', GeneralUtility::linkThisScript()); |
255
|
|
|
$view->assign('currentMode', $this->currentMode()); |
256
|
|
|
$view->assign('elementCount', $elementCount); |
257
|
|
|
|
258
|
|
|
if ($elementCount) { |
259
|
|
|
$view->assign('removeAllUrl', GeneralUtility::linkThisScript(['CB' => ['removeAll' => $this->current]])); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
// Print header and content for the NORMAL tab: |
263
|
|
|
$view->assign('current', $this->current); |
264
|
|
|
$tabArray = []; |
265
|
|
|
$tabArray['normal'] = [ |
266
|
|
|
'id' => 'normal', |
267
|
|
|
'number' => 0, |
268
|
|
|
'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'normal']]), |
269
|
|
|
'description' => 'labels.normal-description', |
270
|
|
|
'label' => 'labels.normal', |
271
|
|
|
'padding' => $this->padTitle('normal') |
272
|
|
|
]; |
273
|
|
|
if ($this->current === 'normal') { |
274
|
|
|
$tabArray['normal']['content'] = $this->getContentFromTab('normal'); |
275
|
|
|
} |
276
|
|
|
// Print header and content for the NUMERIC tabs: |
277
|
|
|
for ($a = 1; $a <= $this->numberTabs; $a++) { |
278
|
|
|
$tabArray['tab_' . $a] = [ |
279
|
|
|
'id' => 'tab_' . $a, |
280
|
|
|
'number' => $a, |
281
|
|
|
'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'tab_' . $a]]), |
282
|
|
|
'description' => 'labels.cliptabs-description', |
283
|
|
|
'label' => 'labels.cliptabs-name', |
284
|
|
|
'padding' => $this->padTitle('tab_' . $a) |
285
|
|
|
]; |
286
|
|
|
if ($this->current === 'tab_' . $a) { |
287
|
|
|
$tabArray['tab_' . $a]['content'] = $this->getContentFromTab('tab_' . $a); |
288
|
|
|
} |
289
|
|
|
} |
290
|
|
|
$view->assign('clipboardHeader', BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('buttons.clipboard'))); |
291
|
|
|
$view->assign('tabArray', $tabArray); |
292
|
|
|
return $view->render(); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Print the content on a pad. Called from ->printClipboard() |
297
|
|
|
* |
298
|
|
|
* @internal |
299
|
|
|
* @param string $pad Pad reference |
300
|
|
|
* @return array Array with table rows for the clipboard. |
301
|
|
|
*/ |
302
|
|
|
public function getContentFromTab($pad) |
303
|
|
|
{ |
304
|
|
|
$lines = []; |
305
|
|
|
if (is_array($this->clipData[$pad]['el'] ?? false)) { |
306
|
|
|
foreach ($this->clipData[$pad]['el'] as $k => $v) { |
307
|
|
|
if ($v) { |
308
|
|
|
[$table, $uid] = explode('|', $k); |
309
|
|
|
// Rendering files/directories on the clipboard |
310
|
|
|
if ($table === '_FILE') { |
311
|
|
|
$fileObject = $this->resourceFactory->retrieveFileOrFolderObject($v); |
312
|
|
|
if ($fileObject) { |
313
|
|
|
$thumb = []; |
314
|
|
|
$folder = $fileObject instanceof Folder; |
315
|
|
|
$size = $folder ? '' : '(' . GeneralUtility::formatSize((int)$fileObject->getSize()) . 'bytes)'; |
316
|
|
|
/** @var File $fileObject */ |
317
|
|
|
if (!$folder && $fileObject->isImage()) { |
318
|
|
|
$processedFile = $fileObject->process( |
319
|
|
|
ProcessedFile::CONTEXT_IMAGEPREVIEW, |
320
|
|
|
[ |
321
|
|
|
'width' => 64, |
322
|
|
|
'height' => 64, |
323
|
|
|
] |
324
|
|
|
); |
325
|
|
|
|
326
|
|
|
$thumb = '<img src="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($processedFile->getPublicUrl() ?? '')) . '" ' . |
327
|
|
|
'width="' . htmlspecialchars($processedFile->getProperty('width')) . '" ' . |
|
|
|
|
328
|
|
|
'height="' . htmlspecialchars($processedFile->getProperty('height')) . '" ' . |
329
|
|
|
'title="' . htmlspecialchars($processedFile->getName()) . '" alt="" />'; |
330
|
|
|
} |
331
|
|
|
$lines[] = [ |
332
|
|
|
'icon' => '<span title="' . htmlspecialchars($fileObject->getName() . ' ' . $size) . '">' . $this->iconFactory->getIconForResource( |
333
|
|
|
$fileObject, |
334
|
|
|
Icon::SIZE_SMALL |
335
|
|
|
)->render() . '</span>', |
336
|
|
|
'title' => $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs( |
337
|
|
|
$fileObject->getName(), |
338
|
|
|
$this->getBackendUser()->uc['titleLen'] |
339
|
|
|
)), $fileObject->getName()), |
340
|
|
|
'thumb' => $thumb, |
341
|
|
|
'infoDataDispatch' => [ |
342
|
|
|
'action' => 'TYPO3.InfoWindow.showItem', |
343
|
|
|
'args' => GeneralUtility::jsonEncodeForHtmlAttribute([$table, $v], false), |
344
|
|
|
], |
345
|
|
|
'removeLink' => $this->removeUrl('_FILE', GeneralUtility::shortMD5($v)) |
346
|
|
|
]; |
347
|
|
|
} else { |
348
|
|
|
// If the file did not exist (or is illegal) then it is removed from the clipboard immediately: |
349
|
|
|
unset($this->clipData[$pad]['el'][$k]); |
350
|
|
|
$this->changed = true; |
351
|
|
|
} |
352
|
|
|
} else { |
353
|
|
|
// Rendering records: |
354
|
|
|
$rec = BackendUtility::getRecordWSOL($table, (int)$uid); |
355
|
|
|
if (is_array($rec)) { |
356
|
|
|
$lines[] = [ |
357
|
|
|
'icon' => $this->linkItemText($this->iconFactory->getIconForRecord( |
358
|
|
|
$table, |
359
|
|
|
$rec, |
360
|
|
|
Icon::SIZE_SMALL |
361
|
|
|
)->render(), $rec, $table), |
362
|
|
|
'title' => $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle( |
363
|
|
|
$table, |
364
|
|
|
$rec |
365
|
|
|
), $this->getBackendUser()->uc['titleLen'])), $rec, $table), |
366
|
|
|
'infoDataDispatch' => [ |
367
|
|
|
'action' => 'TYPO3.InfoWindow.showItem', |
368
|
|
|
'args' => GeneralUtility::jsonEncodeForHtmlAttribute([$table, (int)$uid], false), |
369
|
|
|
], |
370
|
|
|
'removeLink' => $this->removeUrl($table, $uid) |
371
|
|
|
]; |
372
|
|
|
|
373
|
|
|
$localizationData = $this->getLocalizations($table, $rec); |
374
|
|
|
if (!empty($localizationData)) { |
375
|
|
|
$lines = array_merge($lines, $localizationData); |
376
|
|
|
} |
377
|
|
|
} else { |
378
|
|
|
unset($this->clipData[$pad]['el'][$k]); |
379
|
|
|
$this->changed = true; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
} |
385
|
|
|
$this->endClipboard(); |
386
|
|
|
return $lines; |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
/** |
390
|
|
|
* Returns true if the clipboard contains elements |
391
|
|
|
* |
392
|
|
|
* @return bool |
393
|
|
|
*/ |
394
|
|
|
public function hasElements() |
395
|
|
|
{ |
396
|
|
|
foreach ($this->clipData as $data) { |
397
|
|
|
if (isset($data['el']) && is_array($data['el']) && !empty($data['el'])) { |
398
|
|
|
return true; |
399
|
|
|
} |
400
|
|
|
} |
401
|
|
|
return false; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Gets all localizations of the current record. |
406
|
|
|
* |
407
|
|
|
* @param string $table The table |
408
|
|
|
* @param array $parentRec The current record |
409
|
|
|
* @return array HTML table rows |
410
|
|
|
*/ |
411
|
|
|
public function getLocalizations($table, $parentRec) |
412
|
|
|
{ |
413
|
|
|
$lines = []; |
414
|
|
|
$tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; |
415
|
|
|
$workspaceId = (int)$this->getBackendUser()->workspace; |
416
|
|
|
|
417
|
|
|
if (BackendUtility::isTableLocalizable($table)) { |
418
|
|
|
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); |
419
|
|
|
$queryBuilder->getRestrictions() |
420
|
|
|
->removeAll() |
421
|
|
|
->add(GeneralUtility::makeInstance(DeletedRestriction::class)); |
422
|
|
|
|
423
|
|
|
$queryBuilder |
424
|
|
|
->select('*') |
425
|
|
|
->from($table) |
426
|
|
|
->where( |
427
|
|
|
$queryBuilder->expr()->eq( |
428
|
|
|
$tcaCtrl['transOrigPointerField'], |
429
|
|
|
$queryBuilder->createNamedParameter($parentRec['uid'], \PDO::PARAM_INT) |
430
|
|
|
), |
431
|
|
|
$queryBuilder->expr()->neq( |
432
|
|
|
$tcaCtrl['languageField'], |
433
|
|
|
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) |
434
|
|
|
), |
435
|
|
|
$queryBuilder->expr()->gt( |
436
|
|
|
'pid', |
437
|
|
|
$queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT) |
438
|
|
|
) |
439
|
|
|
) |
440
|
|
|
->orderBy($tcaCtrl['languageField']); |
441
|
|
|
|
442
|
|
|
if (BackendUtility::isTableWorkspaceEnabled($table)) { |
443
|
|
|
$queryBuilder->getRestrictions()->add( |
444
|
|
|
GeneralUtility::makeInstance(WorkspaceRestriction::class, $workspaceId) |
445
|
|
|
); |
446
|
|
|
} |
447
|
|
|
$rows = $queryBuilder->execute()->fetchAll(); |
448
|
|
|
if (is_array($rows)) { |
449
|
|
|
foreach ($rows as $rec) { |
450
|
|
|
$lines[] = [ |
451
|
|
|
'icon' => $this->iconFactory->getIconForRecord($table, $rec, Icon::SIZE_SMALL)->render(), |
452
|
|
|
'title' => htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $rec), $this->getBackendUser()->uc['titleLen'])) |
453
|
|
|
]; |
454
|
|
|
} |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
return $lines; |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Warps title with number of elements if any. |
462
|
|
|
* |
463
|
|
|
* @param string $pad Pad reference |
464
|
|
|
* @return string padding |
465
|
|
|
*/ |
466
|
|
|
public function padTitle($pad) |
467
|
|
|
{ |
468
|
|
|
$el = count($this->elFromTable($this->fileMode ? '_FILE' : '', $pad)); |
469
|
|
|
if ($el) { |
470
|
|
|
return ' (' . ($pad === 'normal' ? (($this->clipData['normal']['mode'] ?? '') === 'copy' ? $this->clLabel('cm.copy') : $this->clLabel('cm.cut')) : htmlspecialchars((string)$el)) . ')'; |
471
|
|
|
} |
472
|
|
|
return ''; |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* Wraps the title of the items listed in link-tags. The items will link to the page/folder where they originate from |
477
|
|
|
* |
478
|
|
|
* @param string $str Title of element - must be htmlspecialchar'ed on beforehand. |
479
|
|
|
* @param mixed $rec If array, a record is expected. If string, its a path |
480
|
|
|
* @param string $table Table name |
481
|
|
|
* @return string |
482
|
|
|
*/ |
483
|
|
|
public function linkItemText($str, $rec, $table = '') |
484
|
|
|
{ |
485
|
|
|
if (is_array($rec) && $table) { |
486
|
|
|
if ($this->fileMode) { |
487
|
|
|
$str = '<span class="text-muted">' . $str . '</span>'; |
488
|
|
|
} else { |
489
|
|
|
$str = '<a href="' . htmlspecialchars((string)$this->uriBuilder->buildUriFromRoute('web_list', ['id' => $rec['pid']])) . '">' . $str . '</a>'; |
490
|
|
|
} |
491
|
|
|
} elseif (file_exists($rec)) { |
492
|
|
|
if (!$this->fileMode) { |
493
|
|
|
$str = '<span class="text-muted">' . $str . '</span>'; |
494
|
|
|
} elseif (ExtensionManagementUtility::isLoaded('filelist')) { |
495
|
|
|
$str = '<a href="' . htmlspecialchars((string)$this->uriBuilder->buildUriFromRoute('file_list', ['id' => PathUtility::dirname($rec)])) . '">' . $str . '</a>'; |
496
|
|
|
} |
497
|
|
|
} |
498
|
|
|
return $str; |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* Returns the select-url for database elements |
503
|
|
|
* |
504
|
|
|
* @param string $table Table name |
505
|
|
|
* @param int $uid Uid of record |
506
|
|
|
* @param bool|int $copy If set, copymode will be enabled |
507
|
|
|
* @param bool|int $deselect If set, the link will deselect, otherwise select. |
508
|
|
|
* @param array $baseArray The base array of GET vars to be sent in addition. Notice that current GET vars WILL automatically be included. |
509
|
|
|
* @return string URL linking to the current script but with the CB array set to select the element with table/uid |
510
|
|
|
*/ |
511
|
|
|
public function selUrlDB($table, $uid, $copy = 0, $deselect = 0, $baseArray = []) |
512
|
|
|
{ |
513
|
|
|
$CB = ['el' => [rawurlencode($table . '|' . $uid) => $deselect ? 0 : 1]]; |
514
|
|
|
if ($copy) { |
515
|
|
|
$CB['setCopyMode'] = 1; |
516
|
|
|
} |
517
|
|
|
$baseArray['CB'] = $CB; |
518
|
|
|
return GeneralUtility::linkThisScript($baseArray); |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
/** |
522
|
|
|
* Returns the select-url for files |
523
|
|
|
* |
524
|
|
|
* @param string $path Filepath |
525
|
|
|
* @param bool $copy If set, copymode will be enabled |
526
|
|
|
* @param bool $deselect If set, the link will deselect, otherwise select. |
527
|
|
|
* @return string URL linking to the current script but with the CB array set to select the path |
528
|
|
|
*/ |
529
|
|
|
public function selUrlFile($path, $copy = false, $deselect = false) |
530
|
|
|
{ |
531
|
|
|
$CB = [ |
532
|
|
|
'el' => [ |
533
|
|
|
rawurlencode('_FILE|' . GeneralUtility::shortMD5($path)) => $deselect ? '' : $path |
534
|
|
|
] |
535
|
|
|
]; |
536
|
|
|
if ($copy) { |
537
|
|
|
$CB['setCopyMode'] = 1; |
538
|
|
|
} |
539
|
|
|
return GeneralUtility::linkThisScript(['CB' => $CB]); |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
/** |
543
|
|
|
* pasteUrl of the element (database and file) |
544
|
|
|
* For the meaning of $table and $uid, please read from ->makePasteCmdArray!!! |
545
|
|
|
* The URL will point to tce_file or tce_db depending in $table |
546
|
|
|
* |
547
|
|
|
* @param string $table Tablename (_FILE for files) |
548
|
|
|
* @param mixed $uid "destination": can be positive or negative indicating how the paste is done (paste into / paste after) |
549
|
|
|
* @param bool $setRedirect If set, then the redirect URL will point back to the current script, but with CB reset. |
550
|
|
|
* @param array|null $update Additional key/value pairs which should get set in the moved/copied record (via DataHandler) |
551
|
|
|
* @return string |
552
|
|
|
*/ |
553
|
|
|
public function pasteUrl($table, $uid, $setRedirect = true, array $update = null) |
554
|
|
|
{ |
555
|
|
|
$urlParameters = [ |
556
|
|
|
'CB[paste]' => $table . '|' . $uid, |
557
|
|
|
'CB[pad]' => $this->current |
558
|
|
|
]; |
559
|
|
|
if ($setRedirect) { |
560
|
|
|
$urlParameters['redirect'] = GeneralUtility::linkThisScript(['CB' => '']); |
561
|
|
|
} |
562
|
|
|
if (is_array($update)) { |
563
|
|
|
$urlParameters['CB[update]'] = $update; |
564
|
|
|
} |
565
|
|
|
return (string)$this->uriBuilder->buildUriFromRoute($table === '_FILE' ? 'tce_file' : 'tce_db', $urlParameters); |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
/** |
569
|
|
|
* Returns the remove-url (file and db) |
570
|
|
|
* for file $table='_FILE' and $uid = shortmd5 hash of path |
571
|
|
|
* |
572
|
|
|
* @param string $table Tablename |
573
|
|
|
* @param string $uid Uid integer/shortmd5 hash |
574
|
|
|
* @return string URL |
575
|
|
|
*/ |
576
|
|
|
public function removeUrl($table, $uid) |
577
|
|
|
{ |
578
|
|
|
return GeneralUtility::linkThisScript(['CB' => ['remove' => $table . '|' . $uid]]); |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
/** |
582
|
|
|
* Returns confirm JavaScript message |
583
|
|
|
* |
584
|
|
|
* @param string $table Table name |
585
|
|
|
* @param mixed $rec For records its an array, for files its a string (path) |
586
|
|
|
* @param string $type Type-code |
587
|
|
|
* @param array $clElements Array of selected elements |
588
|
|
|
* @param string $columnLabel Name of the content column |
589
|
|
|
* @return string the text for a confirm message |
590
|
|
|
*/ |
591
|
|
|
public function confirmMsgText($table, $rec, $type, $clElements, $columnLabel = '') |
592
|
|
|
{ |
593
|
|
|
if ($this->getBackendUser()->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) { |
594
|
|
|
$labelKey = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.' . ($this->currentMode() === 'copy' ? 'copy' : 'move') . ($this->current === 'normal' ? '' : 'cb') . '_' . $type; |
595
|
|
|
$msg = $this->getLanguageService()->sL($labelKey . ($columnLabel ? '_colPos' : '')); |
596
|
|
|
if ($table === '_FILE') { |
597
|
|
|
$thisRecTitle = PathUtility::basename($rec); |
598
|
|
|
if ($this->current === 'normal') { |
599
|
|
|
$selItem = reset($clElements); |
600
|
|
|
$selRecTitle = PathUtility::basename($selItem); |
601
|
|
|
} else { |
602
|
|
|
$selRecTitle = count($clElements); |
603
|
|
|
} |
604
|
|
|
} else { |
605
|
|
|
$thisRecTitle = $table === 'pages' && !is_array($rec) ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : BackendUtility::getRecordTitle($table, $rec); |
606
|
|
|
if ($this->current === 'normal') { |
607
|
|
|
$selItem = $this->getSelectedRecord(); |
608
|
|
|
$selRecTitle = $selItem['_RECORD_TITLE']; |
609
|
|
|
} else { |
610
|
|
|
$selRecTitle = count($clElements); |
611
|
|
|
} |
612
|
|
|
} |
613
|
|
|
// @TODO |
614
|
|
|
// This can get removed as soon as the "_colPos" label is translated |
615
|
|
|
// into all available locallang languages. |
616
|
|
|
if (!$msg && $columnLabel) { |
617
|
|
|
$thisRecTitle .= ' | ' . $columnLabel; |
618
|
|
|
$msg = $this->getLanguageService()->sL($labelKey); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
// Message |
622
|
|
|
$conf = sprintf( |
623
|
|
|
$msg, |
624
|
|
|
GeneralUtility::fixed_lgd_cs($selRecTitle, 30), |
625
|
|
|
GeneralUtility::fixed_lgd_cs($thisRecTitle, 30), |
626
|
|
|
GeneralUtility::fixed_lgd_cs($columnLabel, 30) |
627
|
|
|
); |
628
|
|
|
} else { |
629
|
|
|
$conf = ''; |
630
|
|
|
} |
631
|
|
|
return $conf; |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
/** |
635
|
|
|
* Clipboard label - getting from "EXT:core/Resources/Private/Language/locallang_core.xlf:" |
636
|
|
|
* |
637
|
|
|
* @param string $key Label Key |
638
|
|
|
* @return string |
639
|
|
|
*/ |
640
|
|
|
public function clLabel($key) |
641
|
|
|
{ |
642
|
|
|
return htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:' . $key)); |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
/***************************************** |
646
|
|
|
* |
647
|
|
|
* Helper functions |
648
|
|
|
* |
649
|
|
|
****************************************/ |
650
|
|
|
/** |
651
|
|
|
* Removes element on clipboard |
652
|
|
|
* |
653
|
|
|
* @param string $el Key of element in ->clipData array |
654
|
|
|
*/ |
655
|
|
|
public function removeElement($el) |
656
|
|
|
{ |
657
|
|
|
unset($this->clipData[$this->current]['el'][$el]); |
658
|
|
|
$this->changed = true; |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
/** |
662
|
|
|
* Saves the clipboard, no questions asked. |
663
|
|
|
* Use ->endClipboard normally (as it checks if changes has been done so saving is necessary) |
664
|
|
|
* |
665
|
|
|
* @internal |
666
|
|
|
*/ |
667
|
|
|
public function saveClipboard() |
668
|
|
|
{ |
669
|
|
|
$this->getBackendUser()->pushModuleData('clipboard', $this->clipData); |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
/** |
673
|
|
|
* Returns the current mode, 'copy' or 'cut' |
674
|
|
|
* |
675
|
|
|
* @return string "copy" or "cut |
676
|
|
|
*/ |
677
|
|
|
public function currentMode() |
678
|
|
|
{ |
679
|
|
|
return ($this->clipData[$this->current]['mode'] ?? '') === 'copy' ? 'copy' : 'cut'; |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
/** |
683
|
|
|
* This traverses the elements on the current clipboard pane |
684
|
|
|
* and unsets elements which does not exist anymore or are disabled. |
685
|
|
|
*/ |
686
|
|
|
public function cleanCurrent() |
687
|
|
|
{ |
688
|
|
|
if (is_array($this->clipData[$this->current]['el'] ?? false)) { |
689
|
|
|
foreach ($this->clipData[$this->current]['el'] as $k => $v) { |
690
|
|
|
[$table, $uid] = explode('|', $k); |
691
|
|
|
if ($table !== '_FILE') { |
692
|
|
|
if (!$v || !is_array(BackendUtility::getRecord($table, (int)$uid, 'uid'))) { |
693
|
|
|
unset($this->clipData[$this->current]['el'][$k]); |
694
|
|
|
$this->changed = true; |
695
|
|
|
} |
696
|
|
|
} else { |
697
|
|
|
if (!$v) { |
698
|
|
|
unset($this->clipData[$this->current]['el'][$k]); |
699
|
|
|
$this->changed = true; |
700
|
|
|
} else { |
701
|
|
|
try { |
702
|
|
|
$this->resourceFactory->retrieveFileOrFolderObject($v); |
703
|
|
|
} catch (ResourceDoesNotExistException $e) { |
704
|
|
|
// The file has been deleted in the meantime, so just remove it silently |
705
|
|
|
unset($this->clipData[$this->current]['el'][$k]); |
706
|
|
|
} |
707
|
|
|
} |
708
|
|
|
} |
709
|
|
|
} |
710
|
|
|
} |
711
|
|
|
} |
712
|
|
|
|
713
|
|
|
/** |
714
|
|
|
* Counts the number of elements from the table $matchTable. If $matchTable is blank, all tables (except '_FILE' of course) is counted. |
715
|
|
|
* |
716
|
|
|
* @param string $matchTable Table to match/count for. |
717
|
|
|
* @param string $pad Can optionally be used to set another pad than the current. |
718
|
|
|
* @return array Array with keys from the CB. |
719
|
|
|
*/ |
720
|
|
|
public function elFromTable($matchTable = '', $pad = '') |
721
|
|
|
{ |
722
|
|
|
$pad = $pad ?: $this->current; |
723
|
|
|
$list = []; |
724
|
|
|
if (is_array($this->clipData[$pad]['el'] ?? false)) { |
725
|
|
|
foreach ($this->clipData[$pad]['el'] as $k => $v) { |
726
|
|
|
if ($v) { |
727
|
|
|
[$table, $uid] = explode('|', $k); |
728
|
|
|
if ($table !== '_FILE') { |
729
|
|
|
if ((!$matchTable || (string)$table == (string)$matchTable) && $GLOBALS['TCA'][$table]) { |
730
|
|
|
$list[$k] = $pad === 'normal' ? $v : $uid; |
731
|
|
|
} |
732
|
|
|
} else { |
733
|
|
|
if ((string)$table == (string)$matchTable) { |
734
|
|
|
$list[$k] = $v; |
735
|
|
|
} |
736
|
|
|
} |
737
|
|
|
} |
738
|
|
|
} |
739
|
|
|
} |
740
|
|
|
return $list; |
741
|
|
|
} |
742
|
|
|
|
743
|
|
|
/** |
744
|
|
|
* Verifies if the item $table/$uid is on the current pad. |
745
|
|
|
* If the pad is "normal" and the element exists, the mode value is returned. Thus you'll know if the item was copied or cut. |
746
|
|
|
* |
747
|
|
|
* @param string $table Table name, (_FILE for files...) |
748
|
|
|
* @param int $uid Element uid (path for files) |
749
|
|
|
* @return string |
750
|
|
|
*/ |
751
|
|
|
public function isSelected($table, $uid) |
752
|
|
|
{ |
753
|
|
|
$k = $table . '|' . $uid; |
754
|
|
|
return !empty($this->clipData[$this->current]['el'][$k]) ? ($this->current === 'normal' ? $this->currentMode() : 1) : ''; |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* Returns the first element on the current clipboard |
759
|
|
|
* Makes sense only for DB records - not files! |
760
|
|
|
* |
761
|
|
|
* @return array Element record with extra field _RECORD_TITLE set to the title of the record |
762
|
|
|
*/ |
763
|
|
|
public function getSelectedRecord() |
764
|
|
|
{ |
765
|
|
|
$elArr = $this->elFromTable(''); |
766
|
|
|
reset($elArr); |
767
|
|
|
[$table, $uid] = explode('|', (string)key($elArr)); |
768
|
|
|
if ($this->isSelected($table, (int)$uid)) { |
769
|
|
|
$selRec = BackendUtility::getRecordWSOL($table, (int)$uid); |
770
|
|
|
$selRec['_RECORD_TITLE'] = BackendUtility::getRecordTitle($table, $selRec); |
771
|
|
|
return $selRec; |
772
|
|
|
} |
773
|
|
|
return []; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
/** |
777
|
|
|
* Reports if the current pad has elements (does not check file/DB type OR if file/DBrecord exists or not. Only counting array) |
778
|
|
|
* |
779
|
|
|
* @return bool TRUE if elements exist. |
780
|
|
|
*/ |
781
|
|
|
public function isElements() |
782
|
|
|
{ |
783
|
|
|
return is_array($this->clipData[$this->current]['el'] ?? null) && !empty($this->clipData[$this->current]['el']); |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
/** |
787
|
|
|
* Applies the proper paste configuration in the $cmd array send to SimpleDataHandlerController (tce_db route) |
788
|
|
|
* $ref is the target, see description below. |
789
|
|
|
* The current pad is pasted |
790
|
|
|
* |
791
|
|
|
* $ref: [tablename]:[paste-uid]. |
792
|
|
|
* Tablename is the name of the table from which elements *on the current clipboard* is pasted with the 'pid' paste-uid. |
793
|
|
|
* No tablename means that all items on the clipboard (non-files) are pasted. This requires paste-uid to be positive though. |
794
|
|
|
* so 'tt_content:-3' means 'paste tt_content elements on the clipboard to AFTER tt_content:3 record |
795
|
|
|
* 'tt_content:30' means 'paste tt_content elements on the clipboard into page with id 30 |
796
|
|
|
* ':30' means 'paste ALL database elements on the clipboard into page with id 30 |
797
|
|
|
* ':-30' not valid. |
798
|
|
|
* |
799
|
|
|
* @param string $ref [tablename]:[paste-uid], see description |
800
|
|
|
* @param array $CMD Command-array |
801
|
|
|
* @param array|null $update If additional values should get set in the copied/moved record this will be an array containing key=>value pairs |
802
|
|
|
* @return array Modified Command-array |
803
|
|
|
*/ |
804
|
|
|
public function makePasteCmdArray($ref, $CMD, array $update = null) |
805
|
|
|
{ |
806
|
|
|
[$pTable, $pUid] = explode('|', $ref); |
807
|
|
|
$pUid = (int)$pUid; |
808
|
|
|
// pUid must be set and if pTable is not set (that means paste ALL elements) |
809
|
|
|
// the uid MUST be positive/zero (pointing to page id) |
810
|
|
|
if ($pTable || $pUid >= 0) { |
811
|
|
|
$elements = $this->elFromTable($pTable); |
812
|
|
|
// So the order is preserved. |
813
|
|
|
$elements = array_reverse($elements); |
814
|
|
|
$mode = $this->currentMode() === 'copy' ? 'copy' : 'move'; |
815
|
|
|
// Traverse elements and make CMD array |
816
|
|
|
foreach ($elements as $tP => $value) { |
817
|
|
|
[$table, $uid] = explode('|', $tP); |
818
|
|
|
if (!is_array($CMD[$table])) { |
819
|
|
|
$CMD[$table] = []; |
820
|
|
|
} |
821
|
|
|
if (is_array($update)) { |
822
|
|
|
$CMD[$table][$uid][$mode] = [ |
823
|
|
|
'action' => 'paste', |
824
|
|
|
'target' => $pUid, |
825
|
|
|
'update' => $update, |
826
|
|
|
]; |
827
|
|
|
} else { |
828
|
|
|
$CMD[$table][$uid][$mode] = $pUid; |
829
|
|
|
} |
830
|
|
|
if ($mode === 'move') { |
831
|
|
|
$this->removeElement($tP); |
832
|
|
|
} |
833
|
|
|
} |
834
|
|
|
$this->endClipboard(); |
835
|
|
|
} |
836
|
|
|
return $CMD; |
837
|
|
|
} |
838
|
|
|
|
839
|
|
|
/** |
840
|
|
|
* Delete record entries in CMD array |
841
|
|
|
* |
842
|
|
|
* @param array $CMD Command-array |
843
|
|
|
* @return array Modified Command-array |
844
|
|
|
*/ |
845
|
|
|
public function makeDeleteCmdArray($CMD) |
846
|
|
|
{ |
847
|
|
|
// all records |
848
|
|
|
$elements = $this->elFromTable(''); |
849
|
|
|
foreach ($elements as $tP => $value) { |
850
|
|
|
[$table, $uid] = explode('|', $tP); |
851
|
|
|
if (!is_array($CMD[$table])) { |
852
|
|
|
$CMD[$table] = []; |
853
|
|
|
} |
854
|
|
|
$CMD[$table][$uid]['delete'] = 1; |
855
|
|
|
$this->removeElement($tP); |
856
|
|
|
} |
857
|
|
|
$this->endClipboard(); |
858
|
|
|
return $CMD; |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
/***************************************** |
862
|
|
|
* |
863
|
|
|
* FOR USE IN tce_file.php: |
864
|
|
|
* |
865
|
|
|
****************************************/ |
866
|
|
|
/** |
867
|
|
|
* Applies the proper paste configuration in the $file array send to tce_file.php. |
868
|
|
|
* The current pad is pasted |
869
|
|
|
* |
870
|
|
|
* @param string $ref Reference to element (splitted by "|") |
871
|
|
|
* @param array $FILE Command-array |
872
|
|
|
* @return array Modified Command-array |
873
|
|
|
*/ |
874
|
|
|
public function makePasteCmdArray_file($ref, $FILE) |
875
|
|
|
{ |
876
|
|
|
$pUid = explode('|', $ref)[1]; |
877
|
|
|
$elements = $this->elFromTable('_FILE'); |
878
|
|
|
$mode = $this->currentMode() === 'copy' ? 'copy' : 'move'; |
879
|
|
|
// Traverse elements and make CMD array |
880
|
|
|
foreach ($elements as $tP => $path) { |
881
|
|
|
$FILE[$mode][] = ['data' => $path, 'target' => $pUid]; |
882
|
|
|
if ($mode === 'move') { |
883
|
|
|
$this->removeElement($tP); |
884
|
|
|
} |
885
|
|
|
} |
886
|
|
|
$this->endClipboard(); |
887
|
|
|
return $FILE; |
888
|
|
|
} |
889
|
|
|
|
890
|
|
|
/** |
891
|
|
|
* Delete files in CMD array |
892
|
|
|
* |
893
|
|
|
* @param array $FILE Command-array |
894
|
|
|
* @return array Modified Command-array |
895
|
|
|
*/ |
896
|
|
|
public function makeDeleteCmdArray_file($FILE) |
897
|
|
|
{ |
898
|
|
|
$elements = $this->elFromTable('_FILE'); |
899
|
|
|
// Traverse elements and make CMD array |
900
|
|
|
foreach ($elements as $tP => $path) { |
901
|
|
|
$FILE['delete'][] = ['data' => $path]; |
902
|
|
|
$this->removeElement($tP); |
903
|
|
|
} |
904
|
|
|
$this->endClipboard(); |
905
|
|
|
return $FILE; |
906
|
|
|
} |
907
|
|
|
|
908
|
|
|
/** |
909
|
|
|
* Returns LanguageService |
910
|
|
|
* |
911
|
|
|
* @return LanguageService |
912
|
|
|
*/ |
913
|
|
|
protected function getLanguageService() |
914
|
|
|
{ |
915
|
|
|
return $GLOBALS['LANG']; |
916
|
|
|
} |
917
|
|
|
|
918
|
|
|
/** |
919
|
|
|
* Returns the current BE user. |
920
|
|
|
* |
921
|
|
|
* @return BackendUserAuthentication |
922
|
|
|
*/ |
923
|
|
|
protected function getBackendUser() |
924
|
|
|
{ |
925
|
|
|
return $GLOBALS['BE_USER']; |
926
|
|
|
} |
927
|
|
|
|
928
|
|
|
/** |
929
|
|
|
* returns a new standalone view, shorthand function |
930
|
|
|
*/ |
931
|
|
|
protected function getStandaloneView(): StandaloneView |
932
|
|
|
{ |
933
|
|
|
$view = GeneralUtility::makeInstance(StandaloneView::class); |
934
|
|
|
$view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]); |
935
|
|
|
$view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]); |
936
|
|
|
$view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]); |
937
|
|
|
|
938
|
|
|
$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/Clipboard/Main.html')); |
939
|
|
|
|
940
|
|
|
$view->getRequest()->setControllerExtensionName('Backend'); |
941
|
|
|
return $view; |
942
|
|
|
} |
943
|
|
|
} |
944
|
|
|
|