ClickMenu.php 58.9 KB
Newer Older
1
2
3
<?php
namespace TYPO3\CMS\Backend\ClickMenu;

4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
8
9
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
10
 *
11
12
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
15
 * The TYPO3 project - inspiring people to share!
 */
16

17
use TYPO3\CMS\Backend\Clipboard\Clipboard;
18
use TYPO3\CMS\Backend\Utility\BackendUtility;
Nicole Cordes's avatar
Nicole Cordes committed
19
use TYPO3\CMS\Backend\Utility\IconUtility;
20
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
21
22
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
23
use TYPO3\CMS\Core\Resource\Folder;
Nicole Cordes's avatar
Nicole Cordes committed
24
use TYPO3\CMS\Core\Resource\ResourceFactory;
25
26
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
Nicole Cordes's avatar
Nicole Cordes committed
27
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
28
use TYPO3\CMS\Core\Utility\GeneralUtility;
29
use TYPO3\CMS\Lang\LanguageService;
30
31
32
33
34
35
36

/**
 * Class for generating the click menu
 * @internal
 */
class ClickMenu {

37
38
39
40
41
42
	/**
	 * Defines if the click menu is first level or second.
	 * Second means the click menu is triggered from another menu.
	 *
	 * @var int
	 */
43
44
	public $cmLevel = 0;

45
46
47
48
49
	/**
	 * Clipboard array (submitted by eg. pressing the paste button)
	 *
	 * @var bool
	 */
50
51
	public $CB;

52
53
54
55
56
57
	/**
	 * If set, the calling document should be in the listframe of a frameset.
	 *
	 * @var bool
	 */
	public $listFrame = FALSE;
58

59
60
61
62
63
64
	/**
	 * If set, the menu is about database records, not files. (set if part 2 [1] of the item-var is NOT blank)
	 *
	 * @var bool
	 */
	public $isDBmenu = FALSE;
65

66
67
68
69
70
71
	/**
	 * If TRUE, the "content" frame is always used for reference (when condensed mode is enabled)
	 *
	 * @var bool
	 */
	public $alwaysContentFrame = FALSE;
72

73
74
75
76
77
78
79
80
	/**
	 * Stores the parts of the input $item string, splitted by "|":
	 * [0] = table/file, [1] = uid/blank, [2] = flag: If set, listFrame,
	 * If "2" then "content frame" is forced  [3] = ("+" prefix = disable
	 * all by default, enable these. Default is to disable) Items key list
	 *
	 * @var array
	 */
81
82
	public $iParts = array();

83
84
85
86
87
	/**
	 * Contains list of keywords of items to disable in the menu
	 *
	 * @var array
	 */
88
89
	public $disabledItems = array();

90
91
92
93
94
95
	/**
	 * If TRUE, Show icons on the left.
	 *
	 * @var bool
	 */
	public $leftIcons = FALSE;
96

97
98
99
100
101
102
	/**
	 * Array of classes to be used for user processing of the menu content.
	 * This is for the API of adding items to the menu from outside.
	 *
	 * @var array
	 */
103
104
	public $extClassArray = array();

105
106
107
108
109
110
	/**
	 * Set, when edit icon is drawn.
	 *
	 * @var bool
	 */
	public $editPageIconSet = FALSE;
111

112
113
114
115
116
117
	/**
	 * Set to TRUE, if editing of the element is OK.
	 *
	 * @var bool
	 */
	public $editOK = FALSE;
118

119
120
121
122
123
	/**
	 * The current record
	 *
	 * @var array
	 */
124
125
	public $rec = array();

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
	/**
	 * Clipboard set from the outside
	 * Declared as public for now, should become protected
	 * soon-ish
	 * @var Clipboard;
	 */
	public $clipObj;

	/**
	 * The current page record
	 * @var array
	 */
	protected $pageinfo;

	/**
	 * Language Service property. Used to access localized labels
	 *
	 * @var LanguageService
	 */
	protected $languageService;

	/**
	 * @var BackendUserAuthentication
	 */
	protected $backendUser;

152
153
154
155
156
	/**
	 * @var IconFactory
	 */
	protected $iconFactory;

157
158
159
160
161
	/**
	 * @param LanguageService $languageService Language Service to inject
	 * @param BackendUserAuthentication $backendUser
	 */
	public function __construct(LanguageService $languageService = NULL, BackendUserAuthentication $backendUser = NULL) {
162
163
		$this->languageService = $languageService ?: $GLOBALS['LANG'];
		$this->backendUser = $backendUser ?: $GLOBALS['BE_USER'];
164
		$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
165
	}
166

167
168
169
170
171
172
	/**
	 * Initialize click menu
	 *
	 * @return string The clickmenu HTML content
	 */
	public function init() {
173
		$CMcontent = '';
174
		// Setting GPvars:
175
		$this->cmLevel = (int)GeneralUtility::_GP('cmLevel');
176
		$this->CB = GeneralUtility::_GP('CB');
177

178
		// Deal with Drag&Drop context menus
179
180
		if ((string)GeneralUtility::_GP('dragDrop') !== '') {
			return $this->printDragDropClickMenu(GeneralUtility::_GP('dragDrop'), GeneralUtility::_GP('srcId'), GeneralUtility::_GP('dstId'));
181
182
183
184
185
186
187
188
		}
		// Can be set differently as well
		$this->iParts[0] = GeneralUtility::_GP('table');
		$this->iParts[1] = GeneralUtility::_GP('uid');
		$this->iParts[2] = GeneralUtility::_GP('listFr');
		$this->iParts[3] = GeneralUtility::_GP('enDisItems');
		// Setting flags:
		if ($this->iParts[2]) {
189
			$this->listFrame = TRUE;
190
		}
191
		if ($this->iParts[2] == 2) {
192
			$this->alwaysContentFrame = TRUE;
193
		}
194
		if (isset($this->iParts[1]) && $this->iParts[1] !== '') {
195
			$this->isDBmenu = TRUE;
196
197
		}
		$TSkey = ($this->isDBmenu ? 'page' : 'folder') . ($this->listFrame ? 'List' : 'Tree');
198
199
		$this->disabledItems = GeneralUtility::trimExplode(',', $this->backendUser->getTSConfigVal('options.contextMenu.' . $TSkey . '.disableItems'), TRUE);
		$this->leftIcons = (bool)$this->backendUser->getTSConfigVal('options.contextMenu.options.leftIcons');
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
		// &cmLevel flag detected (2nd level menu)
		if (!$this->cmLevel) {
			// Make 1st level clickmenu:
			if ($this->isDBmenu) {
				$CMcontent = $this->printDBClickMenu($this->iParts[0], $this->iParts[1]);
			} else {
				$CMcontent = $this->printFileClickMenu($this->iParts[0]);
			}
		} else {
			// Make 2nd level clickmenu (only for DBmenus)
			if ($this->isDBmenu) {
				$CMcontent = $this->printNewDBLevel($this->iParts[0], $this->iParts[1]);
			}
		}
		// Return clickmenu content:
		return $CMcontent;
	}

	/***************************************
	 *
	 * DATABASE
	 *
	 ***************************************/
	/**
	 * Make 1st level clickmenu:
	 *
	 * @param string $table Table name
227
	 * @param int $uid UID for the current record.
228
229
230
	 * @return string HTML content
	 */
	public function printDBClickMenu($table, $uid) {
231
		$uid = (int)$uid;
232
		// Get record:
Nicole Cordes's avatar
Nicole Cordes committed
233
		$this->rec = BackendUtility::getRecordWSOL($table, $uid);
234
235
236
237
		$menuItems = array();
		$root = 0;
		$DBmount = FALSE;
		// Rootlevel
238
		if ($table === 'pages' && $uid === 0) {
239
240
241
			$root = 1;
		}
		// DB mount
242
		if ($table === 'pages' && in_array($uid, $this->backendUser->returnWebmounts())) {
243
244
245
246
247
			$DBmount = TRUE;
		}
		// Used to hide cut,copy icons for l10n-records
		$l10nOverlay = FALSE;
		// Should only be performed for overlay-records within the same table
Nicole Cordes's avatar
Nicole Cordes committed
248
		if (BackendUtility::isTableLocalizable($table) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
249
			$l10nOverlay = (int)$this->rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0;
250
251
252
253
		}
		// If record found (or root), go ahead and fill the $menuItems array which will contain data for the elements to render.
		if (is_array($this->rec) || $root) {
			// Get permissions
254
			$lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? $this->rec['uid'] : $this->rec['pid']));
255
256
			// View
			if (!in_array('view', $this->disabledItems)) {
257
				if ($table === 'pages') {
258
259
					$menuItems['view'] = $this->DB_view($uid);
				}
260
				if ($table === 'tt_content') {
Nicole Cordes's avatar
Nicole Cordes committed
261
					$ws_rec = BackendUtility::getRecordWSOL($table, $this->rec['uid']);
262
263
264
265
					$menuItems['view'] = $this->DB_view($ws_rec['pid']);
				}
			}
			// Edit:
266
			if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
267
268
269
				if (!in_array('edit', $this->disabledItems)) {
					$menuItems['edit'] = $this->DB_edit($table, $uid);
				}
270
				$this->editOK = TRUE;
271
272
			}
			// New:
273
			if (!in_array('new', $this->disabledItems) && $this->backendUser->isPSet($lCP, $table, 'new')) {
274
275
276
277
278
279
280
281
				$menuItems['new'] = $this->DB_new($table, $uid);
			}
			// Info:
			if (!in_array('info', $this->disabledItems) && !$root) {
				$menuItems['info'] = $this->DB_info($table, $uid);
			}
			$menuItems['spacer1'] = 'spacer';
			// Copy:
282
			if (!in_array('copy', $this->disabledItems) && !$root && !$DBmount && !$l10nOverlay) {
283
284
285
				$menuItems['copy'] = $this->DB_copycut($table, $uid, 'copy');
			}
			// Cut:
286
			if (!in_array('cut', $this->disabledItems) && !$root && !$DBmount && !$l10nOverlay) {
287
288
289
290
291
292
293
				$menuItems['cut'] = $this->DB_copycut($table, $uid, 'cut');
			}
			// Paste:
			$elFromAllTables = count($this->clipObj->elFromTable(''));
			if (!in_array('paste', $this->disabledItems) && $elFromAllTables) {
				$selItem = $this->clipObj->getSelectedRecord();
				$elInfo = array(
294
295
					GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->backendUser->uc['titleLen']),
					$root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen']),
296
297
					$this->clipObj->currentMode()
				);
298
				if ($table === 'pages' && $lCP & Permission::PAGE_NEW) {
299
300
301
302
303
					if ($elFromAllTables) {
						$menuItems['pasteinto'] = $this->DB_paste('', $uid, 'into', $elInfo);
					}
				}
				$elFromTable = count($this->clipObj->elFromTable($table));
304
				if (!$root && !$DBmount && $elFromTable && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
305
306
307
					$menuItems['pasteafter'] = $this->DB_paste($table, -$uid, 'after', $elInfo);
				}
			}
308
309
310
311
312
313
314
			$localItems = array();
			if (!$this->cmLevel && !in_array('moreoptions', $this->disabledItems, TRUE)) {
				// Creating menu items here:
				if ($this->editOK) {
					$localItems[] = 'spacer';
					$localItems['moreoptions'] = $this->linkItem(
						$this->label('more'),
315
						'',
316
						'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript() . '&cmLevel=1&subname=moreoptions') . ');return false;',
317
318
319
320
321
322
323
324
325
						FALSE,
						TRUE
					);
					$menuItemHideUnhideAllowed = FALSE;
					$hiddenField = '';
					// Check if column for disabled is defined
					if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
						$hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
						if (
326
							$hiddenField !== '' && !empty($GLOBALS['TCA'][$table]['columns'][$hiddenField]['exclude'])
327
							&& $this->backendUser->check('non_exclude_fields', $table . ':' . $hiddenField)
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
						) {
							$menuItemHideUnhideAllowed = TRUE;
						}
					}
					if ($menuItemHideUnhideAllowed && !in_array('hide', $this->disabledItems, TRUE)) {
						$localItems['hide'] = $this->DB_hideUnhide($table, $this->rec, $hiddenField);
					}
					$anyEnableColumnsFieldAllowed = FALSE;
					// Check if columns are defined
					if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
						$columnsToCheck = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
						if ($table === 'pages' && !empty($columnsToCheck)) {
							$columnsToCheck[] = 'extendToSubpages';
						}
						foreach ($columnsToCheck as $currentColumn) {
							if (
								!empty($GLOBALS['TCA'][$table]['columns'][$currentColumn]['exclude'])
345
								&& $this->backendUser->check('non_exclude_fields', $table . ':' . $currentColumn)
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
							) {
								$anyEnableColumnsFieldAllowed = TRUE;
							}
						}
					}
					if ($anyEnableColumnsFieldAllowed && !in_array('edit_access', $this->disabledItems, TRUE)) {
						$localItems['edit_access'] = $this->DB_editAccess($table, $uid);
					}
					if ($table === 'pages' && $this->editPageIconSet && !in_array('edit_pageproperties', $this->disabledItems, TRUE)) {
						$localItems['edit_pageproperties'] = $this->DB_editPageProperties($uid);
					}
				}
				// Find delete element among the input menu items and insert the local items just before that:
				$c = 0;
				$deleteFound = FALSE;
				foreach ($menuItems as $key => $value) {
					$c++;
					if ($key === 'delete') {
						$deleteFound = TRUE;
						break;
					}
				}
				if ($deleteFound) {
					// .. subtract two... (delete item + its spacer element...)
					$c -= 2;
					// and insert the items just before the delete element.
					array_splice($menuItems, $c, 0, $localItems);
				} else {
					$menuItems = array_merge($menuItems, $localItems);
				}
			}

378
			// Delete:
379
380
			$elInfo = array(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen']));
			if (!in_array('delete', $this->disabledItems) && !$root && !$DBmount && $this->backendUser->isPSet($lCP, $table, 'delete')) {
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
				$menuItems['spacer2'] = 'spacer';
				$menuItems['delete'] = $this->DB_delete($table, $uid, $elInfo);
			}
			if (!in_array('history', $this->disabledItems)) {
				$menuItems['history'] = $this->DB_history($table, $uid, $elInfo);
			}
		}
		// Adding external elements to the menuItems array
		$menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
		// Processing by external functions?
		$menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
		if (!is_array($this->rec)) {
			$this->rec = array();
		}
		// Return the printed elements:
Nicole Cordes's avatar
Nicole Cordes committed
396
		return $this->printItems($menuItems, $root ? IconUtility::getSpriteIcon('apps-pagetree-root') . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) : IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => htmlspecialchars(BackendUtility::getRecordIconAltText($this->rec, $table)))) . BackendUtility::getRecordTitle($table, $this->rec, TRUE));
397
398
399
400
401
402
	}

	/**
	 * Make 2nd level clickmenu (only for DBmenus)
	 *
	 * @param string $table Table name
403
	 * @param int $uid UID for the current record.
404
405
406
	 * @return string HTML content
	 */
	public function printNewDBLevel($table, $uid) {
407
		$localItems = [];
408
		$uid = (int)$uid;
409
		// Setting internal record to the table/uid :
Nicole Cordes's avatar
Nicole Cordes committed
410
		$this->rec = BackendUtility::getRecordWSOL($table, $uid);
411
412
413
		$menuItems = array();
		$root = 0;
		// Rootlevel
414
		if ($table === 'pages' && $uid === 0) {
415
416
417
418
			$root = 1;
		}
		// If record was found, check permissions and get menu items.
		if (is_array($this->rec) || $root) {
419
			$lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? $this->rec['uid'] : $this->rec['pid']));
420
			// Edit:
421
			if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
422
				$this->editOK = TRUE;
423
424
425
			}
			$menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
		}
426
427
428
429
430
431
432
433
434
435
436

		$subname = GeneralUtility::_GP('subname');
		if ($subname === 'moreoptions') {
			// If the page can be edited, then show this:
			if ($this->editOK) {
				if (($table === 'pages' || $table === 'tt_content') && !in_array('move_wizard', $this->disabledItems, TRUE)) {
					$localItems['move_wizard'] = $this->DB_moveWizard($table, $uid, $this->rec);
				}
				if (($table === 'pages' || $table === 'tt_content') && !in_array('new_wizard', $this->disabledItems, TRUE)) {
					$localItems['new_wizard'] = $this->DB_newWizard($table, $uid, $this->rec);
				}
437
				if ($table === 'pages' && !in_array('perms', $this->disabledItems, TRUE) && $this->backendUser->check('modules', 'system_BeuserTxPermission')) {
438
439
					$localItems['perms'] = $this->DB_perms($table, $uid, $this->rec);
				}
440
				if (!in_array('db_list', $this->disabledItems, TRUE) && $this->backendUser->check('modules', 'web_list')) {
441
442
443
444
445
446
447
448
449
450
451
					$localItems['db_list'] = $this->DB_db_list($table, $uid, $this->rec);
				}
			}
			// Temporary mount point item:
			if ($table === 'pages') {
				$localItems['temp_mount_point'] = $this->DB_tempMountPoint($uid);
			}
			// Merge the locally created items into the current menu items passed to this function.
			$menuItems = array_merge($menuItems, $localItems);
		}

452
453
454
455
		// Return the printed elements:
		if (!is_array($menuItems)) {
			$menuItems = array();
		}
Nicole Cordes's avatar
Nicole Cordes committed
456
		return $this->printItems($menuItems, $root ? IconUtility::getSpriteIcon('apps-pagetree-root') . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) : IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => htmlspecialchars(BackendUtility::getRecordIconAltText($this->rec, $table)))) . BackendUtility::getRecordTitle($table, $this->rec, TRUE));
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
	}

	/**
	 * Processing the $menuItems array (for extension classes) (DATABASE RECORDS)
	 *
	 * @param array $menuItems Array for manipulation.
	 * @return array Processed $menuItems array
	 */
	public function externalProcessingOfDBMenuItems($menuItems) {
		return $menuItems;
	}

	/**
	 * Processing the $menuItems array by external classes (typ. adding items)
	 *
	 * @param array $menuItems Array for manipulation.
	 * @param string $table Table name
474
	 * @param int $uid UID for the current record.
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
	 * @return array Processed $menuItems array
	 */
	public function processingByExtClassArray($menuItems, $table, $uid) {
		if (is_array($this->extClassArray)) {
			foreach ($this->extClassArray as $conf) {
				$obj = GeneralUtility::makeInstance($conf['name']);
				$menuItems = $obj->main($this, $menuItems, $table, $uid);
			}
		}
		return $menuItems;
	}

	/**
	 * Returning JavaScript for the onClick event linking to the input URL.
	 *
	 * @param string $url The URL relative to TYPO3_mainDir
	 * @param string $retUrl The return_url-parameter
492
	 * @param bool $hideCM If set, the "hideCM()" will be called
493
494
495
	 * @param string $overrideLoc If set, gives alternative location to load in (for example top frame or somewhere else)
	 * @return string JavaScript for an onClick event.
	 */
496
	public function urlRefForCM($url, $retUrl = '', $hideCM = TRUE, $overrideLoc = '') {
497
		$loc = 'top.content.list_frame';
498
		return ($overrideLoc ? 'var docRef=' . $overrideLoc : 'var docRef=(top.content.list_frame)?top.content.list_frame:' . $loc)
499
			. '; docRef.location.href=' . GeneralUtility::quoteJSvalue($url) . ($retUrl ? '+' . GeneralUtility::quoteJSvalue('&' . $retUrl . '=') . '+top.rawurlencode('
500
			. $this->frameLocation('docRef.document') . '.pathname+' . $this->frameLocation('docRef.document') . '.search)' : '')
501
			. ';';
502
503
504
505
506
507
	}

	/**
	 * Adding CM element for Clipboard "copy" and "cut"
	 *
	 * @param string $table Table name
508
	 * @param int $uid UID for the current record.
509
510
511
512
513
	 * @param string $type Type: "copy" or "cut
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_copycut($table, $uid, $type) {
514
		$isSel = '';
515
		if ($this->clipObj->current === 'normal') {
516
517
518
519
520
521
			$isSel = $this->clipObj->isSelected($table, $uid);
		}
		$addParam = array();
		if ($this->listFrame) {
			$addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
		}
522
		return $this->linkItem($this->label($type), IconUtility::getSpriteIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : '')), 'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB($table, $uid, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;');
523
524
525
526
527
528
529
	}

	/**
	 * Adding CM element for Clipboard "paste into"/"paste after"
	 * NOTICE: $table and $uid should follow the special syntax for paste, see clipboard-class :: pasteUrl();
	 *
	 * @param string $table Table name
530
	 * @param int $uid UID for the current record. NOTICE: Special syntax!
531
532
533
	 * @param string $type Type: "into" or "after
	 * @param array $elInfo Contains instructions about whether to copy or cut an element.
	 * @return array Item array, element in $menuItems
Christian Kuhn's avatar
Christian Kuhn committed
534
	 * @see \TYPO3\CMS\Backend\Clipboard\Clipboard::pasteUrl()
535
536
537
538
	 * @internal
	 */
	public function DB_paste($table, $uid, $type, $elInfo) {
		$loc = 'top.content.list_frame';
539
		if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
540
			$conf = $loc . ' && confirm(' . GeneralUtility::quoteJSvalue(sprintf($this->languageService->sL(('LLL:EXT:lang/locallang_core.xlf:mess.' . ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_' . $type)), $elInfo[0], $elInfo[1])) . ')';
541
542
543
		} else {
			$conf = $loc;
		}
544
		$editOnClick = 'if(' . $conf . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl($table, $uid, 0) . '&redirect=') . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search);}';
545
		return $this->linkItem($this->label('paste' . $type), IconUtility::getSpriteIcon('actions-document-paste-' . $type), $editOnClick . 'return false;');
546
547
548
549
550
551
	}

	/**
	 * Adding CM element for Info
	 *
	 * @param string $table Table name
552
	 * @param int $uid UID for the current record.
553
554
555
556
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_info($table, $uid) {
557
		return $this->linkItem($this->label('info'), $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL), 'top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($uid) . ');');
558
559
560
561
562
563
	}

	/**
	 * Adding CM element for History
	 *
	 * @param string $table Table name
564
	 * @param int $uid UID for the current record.
565
566
567
568
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_history($table, $uid) {
569
		$url = BackendUtility::getModuleUrl('record_history', array('element' => $table . ':' . $uid));
570
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_history')), $this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL), $this->urlRefForCM($url, 'returnUrl'), 0);
571
572
573
574
575
576
	}

	/**
	 * Adding CM element for Permission setting
	 *
	 * @param string $table Table name
577
	 * @param int $uid UID for the current record.
578
579
580
581
582
	 * @param array $rec The "pages" record with "perms_*" fields inside.
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_perms($table, $uid, $rec) {
583
		if (!ExtensionManagementUtility::isLoaded('beuser')) {
584
585
			return '';
		}
586
587
588
589
590

		$parameters = array(
			'id' => $uid,
		);

591
		if ($rec['perms_userid'] == $this->backendUser->user['uid'] || $this->backendUser->isAdmin()) {
592
593
594
595
			$parameters['return_id'] = $uid;
			$parameters['edit'] = '1';
		}

596
		$url = BackendUtility::getModuleUrl('system_BeuserTxPermission', $parameters);
597
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_perms')), IconUtility::getSpriteIcon('status-status-locked'), $this->urlRefForCM($url), 0);
598
599
600
601
602
603
	}

	/**
	 * Adding CM element for DBlist
	 *
	 * @param string $table Table name
604
	 * @param int $uid UID for the current record.
605
606
607
608
609
610
	 * @param array $rec Record of the element (needs "pid" field if not pages-record)
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_db_list($table, $uid, $rec) {
		$urlParams = array();
611
612
		$urlParams['id'] = $table === 'pages' ? $uid : $rec['pid'];
		$urlParams['table'] = $table === 'pages' ? '' : $table;
Nicole Cordes's avatar
Nicole Cordes committed
613
		$url = BackendUtility::getModuleUrl('web_list', $urlParams, '', TRUE);
614
615
616
617
618
		return $this->linkItem(
			$this->languageService->makeEntities($this->languageService->getLL('CM_db_list')),
			IconUtility::getSpriteIcon('actions-system-list-open'), 'top.nextLoadModuleUrl=' . GeneralUtility::quoteJSvalue($url) . ';top.goToModule(\'web_list\', 1);',
			0
		);
619
620
621
622
623
624
	}

	/**
	 * Adding CM element for Moving wizard
	 *
	 * @param string $table Table name
625
	 * @param int $uid UID for the current record.
626
627
628
629
630
631
	 * @param array $rec Record. Needed for tt-content elements which will have the sys_language_uid sent
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_moveWizard($table, $uid, $rec) {
		// Hardcoded field for tt_content elements.
632
633
		$url = BackendUtility::getModuleUrl('move_element') . '&table=' . $table . '&uid=' . $uid;
		$url .= ($table === 'tt_content' ? '&sys_language_uid=' . (int)$rec['sys_language_uid'] : '');
634
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_moveWizard' . ($table === 'pages' ? '_page' : ''))), IconUtility::getSpriteIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-move'), $this->urlRefForCM($url, 'returnUrl'), 0);
635
636
637
	}

	/**
638
	 * Adding CM element for Create new wizard (either BackendUtility::getModuleUrl('db_new') or BackendUtility::getModuleUrl('new_content_element') or custom wizard)
639
640
	 *
	 * @param string $table Table name
641
	 * @param int $uid UID for the current record.
642
643
644
645
646
647
	 * @param array $rec Record.
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_newWizard($table, $uid, $rec) {
		//  If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
Nicole Cordes's avatar
Nicole Cordes committed
648
		$tmpTSc = BackendUtility::getModTSconfig($this->pageinfo['uid'], 'mod.web_list');
649
		$tmpTSc = $tmpTSc['properties']['newContentWiz.']['overrideWithExtension'];
650
651

		$newContentWizScriptPath = ExtensionManagementUtility::isLoaded($tmpTSc) ? ExtensionManagementUtility::extRelPath($tmpTSc) . 'mod1/db_new_content_el.php?' : BackendUtility::getModuleUrl('new_content_element') . '&';
652
		$url = $table === 'pages' ? BackendUtility::getModuleUrl('db_new', ['id' => $uid, 'pagesOnly' => 1]) : $newContentWizScriptPath . 'id=' . $rec['pid'] . '&sys_language_uid=' . (int)$rec['sys_language_uid'];
653
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_newWizard')), IconUtility::getSpriteIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-new'), $this->urlRefForCM($url, 'returnUrl'), 0);
654
655
656
657
658
659
	}

	/**
	 * Adding CM element for Editing of the access related fields of a table (disable, starttime, endtime, fe_groups)
	 *
	 * @param string $table Table name
660
	 * @param int $uid UID for the current record.
661
662
663
664
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_editAccess($table, $uid) {
665
666
667
668
		$url = BackendUtility::getModuleUrl('record_edit', array(
			'columnsOnly' => rawurlencode((implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table === 'pages' ? ',extendToSubpages' : ''))),
			'edit[' . $table . '][' . $uid . ']' => 'edit'
		));
669
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_editAccess')), $this->iconFactory->getIcon('actions-document-edit-access', Icon::SIZE_SMALL), $this->urlRefForCM($url, 'returnUrl'), 1);
670
671
672
673
674
	}

	/**
	 * Adding CM element for edit page properties
	 *
675
	 * @param int $uid page uid to edit (PID)
676
677
678
679
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_editPageProperties($uid) {
680
681
682
		$url = BackendUtility::getModuleUrl('record_edit', array(
			'edit[pages][' . $uid . ']' => 'edit'
		));
683
		return $this->linkItem($this->languageService->makeEntities($this->languageService->getLL('CM_editPageProperties')), IconUtility::getSpriteIcon('actions-page-open'), $this->urlRefForCM($url, 'returnUrl'), 1);
684
685
686
687
688
689
	}

	/**
	 * Adding CM element for regular editing of the element!
	 *
	 * @param string $table Table name
690
	 * @param int $uid UID for the current record.
691
692
693
694
695
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_edit($table, $uid) {
		// If another module was specified, replace the default Page module with the new one
696
		$newPageModule = trim($this->backendUser->getTSConfigVal('options.overridePageModule'));
Nicole Cordes's avatar
Nicole Cordes committed
697
		$pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
698
699
		$loc = 'top.content.list_frame';
		$theIcon = 'actions-document-open';
700
701
702
703
704

		$link = BackendUtility::getModuleUrl('record_edit', array(
			'edit[' . $table . '][' . $uid . ']' => 'edit'
		));

705
		if ($this->iParts[0] === 'pages' && $this->iParts[1] && $this->backendUser->check('modules', $pageModule)) {
706
			$this->editPageIconSet = TRUE;
707
		}
708
		$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($link . '&returnUrl=') . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search);}';
709
		return $this->linkItem($this->label('edit'), IconUtility::getSpriteIcon($theIcon), $editOnClick . ';');
710
711
712
713
714
715
	}

	/**
	 * Adding CM element for regular Create new element
	 *
	 * @param string $table Table name
716
	 * @param int $uid UID for the current record.
717
718
719
720
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_new($table, $uid) {
721
722
723
		$frame = 'top.content.list_frame';
		$location = $this->frameLocation($frame . '.document');
		$module = $this->listFrame
724
725
			? GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('record_edit', array('edit[' . $table . '][-' . $uid . ']' => 'new')) . '&returnUrl=') . '+top.rawurlencode(' . $location . '.pathname+' . $location . '.search)'
			: GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('db_new', array('id' => (int)$uid)));
726
		$editOnClick = 'if(' . $frame . '){' . $frame . '.location.href=' . $module . ';}';
727
728
		$icon = IconUtility::getSpriteIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-new');
		return $this->linkItem($this->label('new'), $icon, $editOnClick);
729
730
731
732
733
734
	}

	/**
	 * Adding CM element for Delete
	 *
	 * @param string $table Table name
735
	 * @param int $uid UID for the current record.
736
	 * @param array $elInfo Label for including in the confirmation message, EXT:lang/locallang_core.xlf:mess.delete
737
738
739
740
741
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_delete($table, $uid, $elInfo) {
		$loc = 'top.content.list_frame';
742
		if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
743
			$conf = 'confirm(' . GeneralUtility::quoteJSvalue((sprintf($this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.delete'), $elInfo[0]) . BackendUtility::referenceCount($table, $uid, ' (There are %s reference(s) to this record!)') . BackendUtility::translationCount($table, $uid, (' ' . $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord'))))) . ')';
744
745
746
		} else {
			$conf = '1==1';
		}
747
		$editOnClick = 'if(' . $loc . ' && ' . $conf . ' ){' . $loc . '.location.href=' .
748
749
750
751
752
			GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
			$this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
			GeneralUtility::quoteJSvalue(
				'&cmd[' . $table . '][' . $uid . '][delete]=1&prErr=1&vC=' . $this->backendUser->veriCode() . BackendUtility::getUrlToken('tceAction')
			) . ';};';
753
754
755
		if ($table === 'pages') {
			$editOnClick .= 'top.nav.refresh.defer(500, top.nav);';
		}
756
		return $this->linkItem($this->label('delete'), $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL), $editOnClick . 'return false;');
757
758
759
760
761
	}

	/**
	 * Adding CM element for View Page
	 *
762
	 * @param int $id Page uid (PID)
763
764
765
766
767
	 * @param string $anchor Anchor, if any
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_view($id, $anchor = '') {
768
769
		$icon = $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL);
		return $this->linkItem($this->label('view'), $icon, BackendUtility::viewOnClick($id, '', NULL, $anchor) . ';');
770
771
772
773
774
	}

	/**
	 * Adding element for setting temporary mount point.
	 *
775
	 * @param int $page_id Page uid (PID)
776
777
778
779
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_tempMountPoint($page_id) {
780
		return $this->linkItem($this->label('tempMountPoint'), IconUtility::getSpriteIcon('apps-pagetree-page-mountpoint'), 'if (top.content.nav_frame) {
781
782
783
784
785
786
787
788
				var node = top.TYPO3.Backend.NavigationContainer.PageTree.getSelected();
				if (node === null) {
					return false;
				}

				var useNode = {
					attributes: {
						nodeData: {
789
							id: ' . (int)$page_id . '
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
						}
					}
				};

				node.ownerTree.commandProvider.mountAsTreeRoot(useNode, node.ownerTree);
			}
			');
	}

	/**
	 * Adding CM element for hide/unhide of the input record
	 *
	 * @param string $table Table name
	 * @param array $rec Record array
	 * @param string $hideField Name of the hide field
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function DB_hideUnhide($table, $rec, $hideField) {
		return $this->DB_changeFlag($table, $rec, $hideField, $this->label(($rec[$hideField] ? 'un' : '') . 'hide'), 'hide');
	}

	/**
	 * Adding CM element for a flag field of the input record
	 *
	 * @param string $table Table name
	 * @param array $rec Record array
	 * @param string $flagField Name of the flag field
	 * @param string $title Menu item Title
	 * @return array Item array, element in $menuItems
	 */
821
	public function DB_changeFlag($table, $rec, $flagField, $title) {
822
		$uid = $rec['_ORIG_uid'] ?: $rec['uid'];
823
		$loc = 'top.content.list_frame';
824
		$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' .
825
			GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
826
			$this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
827
828
829
			GeneralUtility::quoteJSvalue(
				'&data[' . $table . '][' . $uid . '][' . $flagField . ']=' . ($rec[$flagField] ? 0 : 1) . '&prErr=1&vC=' . $this->backendUser->veriCode() . BackendUtility::getUrlToken('tceAction')
			) . ';};';
830
831
832
		if ($table === 'pages') {
			$editOnClick .= 'top.nav.refresh.defer(500, top.nav);';
		}
833
		return $this->linkItem($title, $this->iconFactory->getIcon('actions-edit-' . ($rec[$flagField] ? 'un' : '') . 'hide', Icon::SIZE_SMALL), $editOnClick . 'return false;', 1);
834
835
836
837
838
839
840
841
842
843
844
845
	}

	/***************************************
	 *
	 * FILE
	 *
	 ***************************************/
	/**
	 * Make 1st level clickmenu:
	 *
	 * @param string $combinedIdentifier The combined identifier
	 * @return string HTML content
846
	 * @see \TYPO3\CMS\Core\Resource\ResourceFactory::retrieveFileOrFolderObject()
847
848
	 */
	public function printFileClickMenu($combinedIdentifier) {
849
850
		$icon = '';
		$identifier = '';
851
852
		$menuItems = array();
		$combinedIdentifier = rawurldecode($combinedIdentifier);
Nicole Cordes's avatar
Nicole Cordes committed
853
		$fileObject = ResourceFactory::getInstance()
854
855
856
				->retrieveFileOrFolderObject($combinedIdentifier);
		if ($fileObject) {
			$folder = FALSE;
857
858
859
860
			$isStorageRoot = FALSE;
			$isOnline = TRUE;
			$userMayViewStorage = FALSE;
			$userMayEditStorage = FALSE;
861
			$identifier = $fileObject->getCombinedIdentifier();
862
			if ($fileObject instanceof Folder) {
863
				$icon = IconUtility::getSpriteIconForResource($fileObject, array(
864
865
866
867
					'class' => 'absmiddle',
					'title' => htmlspecialchars($fileObject->getName())
				));
				$folder = TRUE;
868
869
				if ($fileObject->getIdentifier() === $fileObject->getStorage()->getRootLevelFolder()->getIdentifier()) {
					$isStorageRoot = TRUE;
870
					if ($this->backendUser->check('tables_select', 'sys_file_storage')) {
871
872
						$userMayViewStorage = TRUE;
					}
873
					if ($this->backendUser->check('tables_modify', 'sys_file_storage')) {
874
875
876
877
878
879
						$userMayEditStorage = TRUE;
					}
				}
				if (!$fileObject->getStorage()->isOnline()) {
					$isOnline = FALSE;
				}
880
			} else {
881
				$icon = IconUtility::getSpriteIconForResource($fileObject, array(
882
					'class' => 'absmiddle',
883
					'title' => htmlspecialchars($fileObject->getName() . ' (' . GeneralUtility::formatSize($fileObject->getSize()) . ')')
884
885
				));
			}
886
887
888
889
890
891
892
893
894
895
896
			// Hide
			if (!in_array('hide', $this->disabledItems) && $isStorageRoot && $userMayEditStorage) {
				$record = BackendUtility::getRecord('sys_file_storage', $fileObject->getStorage()->getUid());
				$menuItems['hide'] = $this->DB_changeFlag(
					'sys_file_storage',
					$record,
					'is_online',
					$this->label($record['is_online'] ? 'offline' : 'online'),
					'hide'
				);
			}
897
			// Edit
898
			if (!in_array('edit', $this->disabledItems) && $fileObject->checkActionPermission('write')) {
899
				if (!$folder && !$isStorageRoot && $fileObject->isIndexed() && $this->backendUser->check('tables_modify', 'sys_file_metadata')) {
900
901
902
					$metaData = $fileObject->_getMetaData();
					$menuItems['edit2'] = $this->DB_edit('sys_file_metadata', $metaData['uid']);
				}
903
				if (!$folder && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $fileObject->getExtension()) && $fileObject->checkActionPermission('write')) {
904
					$menuItems['edit'] = $this->FILE_launch($identifier, 'file_edit', 'editcontent', 'actions-page-open');
905
906
907
				} elseif ($isStorageRoot && $userMayEditStorage) {
					$menuItems['edit'] = $this->DB_edit('sys_file_storage', $fileObject->getStorage()->getUid());
				}
908
909
			}
			// Rename
910
			if (!in_array('rename', $this->disabledItems) && !$isStorageRoot && $fileObject->checkActionPermission('rename')) {
911
				$menuItems['rename'] = $this->FILE_launch($identifier, 'file_rename', 'rename', 'actions-edit-rename');
912
913
			}
			// Upload
914
			if (!in_array('upload', $this->disabledItems) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
915
				$menuItems['upload'] = $this->FILE_launch($identifier, 'file_upload', 'upload', 'actions-edit-upload');
916
917
			}
			// New
918
			if (!in_array('new', $this->disabledItems) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
919
				$menuItems['new'] = $this->FILE_launch($identifier, 'file_newfolder', 'new', 'actions-document-new');
920
921
			}
			// Info
922
			if (!in_array('info', $this->disabledItems) && $fileObject->checkActionPermission('read')) {
923
924
925
926
927
				if ($isStorageRoot && $userMayViewStorage) {
					$menuItems['info'] = $this->DB_info('sys_file_storage', $fileObject->getStorage()->getUid());
				} elseif (!$folder) {
					$menuItems['info'] = $this->fileInfo($identifier);
				}
928
929
930
			}
			$menuItems[] = 'spacer';
			// Copy:
931
			if (!in_array('copy', $this->disabledItems) && !$isStorageRoot && $fileObject->checkActionPermission('read')) {
932
933
934
				$menuItems['copy'] = $this->FILE_copycut($identifier, 'copy');
			}
			// Cut:
935
			if (!in_array('cut', $this->disabledItems) && !$isStorageRoot && $fileObject->checkActionPermission('move')) {
936
937
938
939
				$menuItems['cut'] = $this->FILE_copycut($identifier, 'cut');
			}
			// Paste:
			$elFromAllTables = count($this->clipObj->elFromTable('_FILE'));
940
			if (!in_array('paste', $this->disabledItems) && $elFromAllTables && $folder && $fileObject->checkActionPermission('write')) {
941
942
				$elArr = $this->clipObj->elFromTable('_FILE');
				$selItem = reset($elArr);
943
944
				$clickedFileOrFolder = ResourceFactory::getInstance()->retrieveFileOrFolderObject($combinedIdentifier);
				$fileOrFolderInClipBoard = ResourceFactory::getInstance()->retrieveFileOrFolderObject($selItem);
945
				$elInfo = array(
946
					$fileOrFolderInClipBoard->getName(),
947
					$clickedFileOrFolder->getName(),
948
949
					$this->clipObj->currentMode()
				);
950
951
952
				if (!$fileOrFolderInClipBoard instanceof Folder || !$fileOrFolderInClipBoard->getStorage()->isWithinFolder($fileOrFolderInClipBoard, $clickedFileOrFolder)) {
					$menuItems['pasteinto'] = $this->FILE_paste($identifier, $selItem, $elInfo);
				}
953
954
955
			}
			$menuItems[] = 'spacer';
			// Delete:
956
			if (!in_array('delete', $this->disabledItems) && $fileObject->checkActionPermission('delete')) {
957
				if ($isStorageRoot && $userMayEditStorage) {
958
					$elInfo = array(GeneralUtility::fixed_lgd_cs($fileObject->getStorage()->getName(), $this->backendUser->uc['titleLen']));
959
960
961
962
					$menuItems['delete'] = $this->DB_delete('sys_file_storage', $fileObject->getStorage()->getUid(), $elInfo);
				} elseif (!$isStorageRoot) {
					$menuItems['delete'] = $this->FILE_delete($identifier);
				}
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
			}
		}
		// Adding external elements to the menuItems array
		$menuItems = $this->processingByExtClassArray($menuItems, $identifier, 0);
		// Processing by external functions?
		$menuItems = $this->externalProcessingOfFileMenuItems($menuItems);
		// Return the printed elements:
		return $this->printItems($menuItems, $icon . $fileObject->getName());
	}

	/**
	 * Processing the $menuItems array (for extension classes) (FILES)
	 *
	 * @param array $menuItems Array for manipulation.
	 * @return array Processed $menuItems array
	 */
	public function externalProcessingOfFileMenuItems($menuItems) {
		return $menuItems;
	}

	/**
	 * Multi-function for adding an entry to the $menuItems array
	 *
	 * @param string $path Path to the file/directory (target)
987
	 * @param string $moduleName Script (deprecated) or module name (e.g. file_edit) to pass &target= to
988
	 * @param string $type "type" is the code which fetches the correct label for the element from "cm.
989
	 * @param string $iconName
990
	 * @param bool $noReturnUrl If set, the return URL parameter will not be set in the link
991
992
993
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
994
	public function FILE_launch($path, $moduleName, $type, $iconName, $noReturnUrl = FALSE) {
995
		$loc = 'top.content.list_frame';
996
997
998

		if (strpos($moduleName, '.php') !== FALSE) {
			GeneralUtility::deprecationLog(
999
				'Using a php file directly in ClickMenu is deprecated since TYPO3 CMS 7, and will be removed in CMS 8.'
1000
1001
1002
1003
1004
1005
1006
1007
				. ' Register the class as module and use BackendUtility::getModuleUrl() to get the right link.'
				. ' For examples how to do this see ext_tables.php of EXT:backend.'
			);
			$scriptUrl = $moduleName;
		} else {
			$scriptUrl = BackendUtility::getModuleUrl($moduleName);
		}

1008
		$editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($scriptUrl . '&target=' . rawurlencode($path)) . ($noReturnUrl ? '' : '+\'&returnUrl=\'+top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation($loc . '.document') . '.search)') . ';}';
1009
		return $this->linkItem($this->label($type), IconUtility::getSpriteIcon($iconName), $editOnClick . 'top.nav.refresh();');
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
	}

	/**
	 * Returns element for copy or cut of files.
	 *
	 * @param string $path Path to the file/directory (target)
	 * @param string $type Type: "copy" or "cut
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function FILE_copycut($path, $type) {
1021
		$isSel = '';
1022
1023
1024
		// Pseudo table name for use in the clipboard.
		$table = '_FILE';
		$uid = GeneralUtility::shortmd5($path);
1025
		if ($this->clipObj->current === 'normal') {
1026
1027
1028
1029
1030
1031
			$isSel = $this->clipObj->isSelected($table, $uid);
		}
		$addParam = array();
		if ($this->listFrame) {
			$addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
		}
1032
		return $this->linkItem($this->label($type), IconUtility::getSpriteIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : '')), 'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlFile($path, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;');
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
	}

	/**
	 * Creates element for deleting of target
	 *
	 * @param string $path Path to the file/directory (target)
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function FILE_delete($path) {
		$loc = 'top.content.list_frame';
1044
1045
		if ($this->backendUser->jsConfirmation(4)) {
			$conf = 'confirm(' . GeneralUtility::quoteJSvalue((sprintf($this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.delete'), basename($path)) . BackendUtility::referenceCount('_FILE', $path, ' (There are %s reference(s) to this file!)'))) . ')';
1046
1047
1048
		} else {
			$conf = '1==1';
		}
1049
		$editOnClick = 'if(' . $loc . ' && ' . $conf . ' ){' . $loc . '.location.href=' .
1050
1051
1052
1053
1054
			GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_file') . '&redirect=') . '+top.rawurlencode(' .
			$this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
			GeneralUtility::quoteJSvalue(
				'&file[delete][0][data]=' . rawurlencode($path) . '&vC=' . $this->backendUser->veriCode() . BackendUtility::getUrlToken('tceAction')
			) . ';};';
1055
		return $this->linkItem($this->label('delete'), $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL), $editOnClick . 'return false;');
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
	}

	/**
	 * Creates element for pasting files.
	 *
	 * @param string $path Path to the file/directory (target)
	 * @param string $target target - NOT USED.
	 * @param array $elInfo Various values for the labels.
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function FILE_paste($path, $target, $elInfo) {
		$loc = 'top.content.list_frame';
1069
		if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
1070
			$conf = $loc . ' && confirm(' . GeneralUtility::quoteJSvalue(sprintf($this->languageService->sL(('LLL:EXT:lang/locallang_core.xlf:mess.' . ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_into')), $elInfo[0], $elInfo[1])) . ')';
1071
1072
1073
		} else {
			$conf = $loc;
		}
1074
		$editOnClick = 'if(' . $conf . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl('_FILE', $path, 0) . '&redirect=') . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search);  };top.nav.refresh();';
1075
		return $this->linkItem($this->label('pasteinto'), $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL), $editOnClick . 'return false;');
1076
1077
	}

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
	/**
	 * Adding ClickMenu element for file info
	 *
	 * @param string $identifier The combined identifier of the file.
	 * @return array Item array, element in $menuItems
	 */
	protected function fileInfo($identifier) {
		return $this->DB_info('_FILE', $identifier);
	}

1088
1089
1090
1091
1092
1093
1094
1095
1096
	/***************************************
	 *
	 * DRAG AND DROP
	 *
	 ***************************************/
	/**
	 * Make 1st level clickmenu:
	 *
	 * @param string $table The absolute path
1097
1098
	 * @param int $srcId UID for the current record.
	 * @param int $dstId Destination ID
1099
1100
1101
1102
1103
	 * @return string HTML content
	 */
	public function printDragDropClickMenu($table, $srcId, $dstId) {
		$menuItems = array();
		// If the drag and drop menu should apply to PAGES use this set of menu items
1104
		if ($table === 'pages') {
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
			// Move Into:
			$menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into');
			// Move After:
			$menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after');
			// Copy Into:
			$menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into');
			// Copy After:
			$menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after');
		}
		// If the drag and drop menu should apply to FOLDERS use this set of menu items
1115
		if ($table === 'folders') {
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
			// Move Into:
			$menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move');
			// Copy Into:
			$menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy');
		}
		// Adding external elements to the menuItems array
		$menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId);
		// to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar
		// Processing by external functions?
		$menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
		// Return the printed elements:
Nicole Cordes's avatar
Nicole Cordes committed
1127
		return $this->printItems($menuItems, IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => BackendUtility::getRecordTitle($table, $this->rec, TRUE))));
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
	}

	/**
	 * Processing the $menuItems array (for extension classes) (DRAG'N DROP)
	 *
	 * @param array $menuItems Array for manipulation.
	 * @return array Processed $menuItems array
	 */
	public function externalProcessingOfDragDropMenuItems($menuItems) {
		return $menuItems;
	}

	/**
	 * Adding CM element for Copying/Moving a Page Into/After from a drag & drop action
	 *
1143
1144
	 * @param int $srcUid source UID code for the record to modify
	 * @param int $dstUid destination UID code for the record to modify
1145
1146
1147
1148
1149
1150
	 * @param string $action Action code: either "move" or "copy
	 * @param string $into Parameter code: either "into" or "after
	 * @return array Item array, element in $menuItems
	 * @internal
	 */
	public function dragDrop_copymovepage($srcUid, $dstUid, $action, $into) {