2 namespace TYPO3\CMS\Backend\ClickMenu
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Backend\Utility\BackendUtility
;
18 use TYPO3\CMS\Backend\Utility\IconUtility
;
19 use TYPO3\CMS\Core\
Resource\ResourceFactory
;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility
;
21 use TYPO3\CMS\Core\Utility\GeneralUtility
;
24 * Class for generating the click menu
26 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
31 // Internal, static: GPvar:
32 // Defines if the click menu is first level or second. Second means the click menu is triggered from another menu.
35 // Clipboard array (submitted by eg. pressing the paste button)
39 // Backpath for scripts/images.
40 public $backPath = '';
42 // BackPath place holder: We need different backPath set whether the clickmenu is written back to a frame which is not in typo3/ dir or if the clickmenu is shown in the top frame (no backpath)
43 public $PH_backPath = '###BACK_PATH###';
45 // If set, the calling document should be in the listframe of a frameset.
46 public $listFrame = 0;
48 // If set, the menu is about database records, not files. (set if part 2 [1] of the item-var is NOT blank)
51 // If TRUE, the "content" frame is always used for reference (when condensed mode is enabled)
52 public $alwaysContentFrame = 0;
54 // Stores the parts of the input $item string, splitted by "|":
55 // [0] = table/file, [1] = uid/blank, [2] = flag: If set, listFrame,
56 // If "2" then "content frame" is forced [3] = ("+" prefix = disable
57 // all by default, enable these. Default is to disable) Items key list
58 public $iParts = array();
60 // Contains list of keywords of items to disable in the menu
61 public $disabledItems = array();
63 // If TRUE, Show icons on the left.
64 public $leftIcons = 0;
66 // 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.
67 public $extClassArray = array();
69 // Enable/disable ajax behavior
73 // Counter for elements in the menu. Used to number the name / id of the mouse-over icon.
76 // Set, when edit icon is drawn.
77 public $editPageIconSet = 0;
79 // Set to TRUE, if editing of the element is OK.
82 public $rec = array();
85 * Initialize click menu
87 * @return string The clickmenu HTML content
89 public function init() {
91 $this->cmLevel
= (int)GeneralUtility
::_GP('cmLevel');
92 $this->CB
= GeneralUtility
::_GP('CB');
93 if (GeneralUtility
::_GP('ajax')) {
95 // XML has to be parsed, no parse errors allowed
96 @ini_set
('display_errors', 0);
98 // Deal with Drag&Drop context menus
99 if ((string)GeneralUtility
::_GP('dragDrop') !== '') {
100 return $this->printDragDropClickMenu(GeneralUtility
::_GP('dragDrop'), GeneralUtility
::_GP('srcId'), GeneralUtility
::_GP('dstId'));
102 // Can be set differently as well
103 $this->iParts
[0] = GeneralUtility
::_GP('table');
104 $this->iParts
[1] = GeneralUtility
::_GP('uid');
105 $this->iParts
[2] = GeneralUtility
::_GP('listFr');
106 $this->iParts
[3] = GeneralUtility
::_GP('enDisItems');
108 if ($this->iParts
[2]) {
109 $this->listFrame
= 1;
111 if ($this->iParts
[2] == 2) {
112 $this->alwaysContentFrame
= 1;
114 if (isset($this->iParts
[1]) && $this->iParts
[1] !== '') {
117 $TSkey = ($this->isDBmenu ?
'page' : 'folder') . ($this->listFrame ?
'List' : 'Tree');
118 $this->disabledItems
= GeneralUtility
::trimExplode(',', $GLOBALS['BE_USER']->getTSConfigVal('options.contextMenu.' . $TSkey . '.disableItems'), TRUE);
119 $this->leftIcons
= $GLOBALS['BE_USER']->getTSConfigVal('options.contextMenu.options.leftIcons');
120 // &cmLevel flag detected (2nd level menu)
121 if (!$this->cmLevel
) {
122 // Make 1st level clickmenu:
123 if ($this->isDBmenu
) {
124 $CMcontent = $this->printDBClickMenu($this->iParts
[0], $this->iParts
[1]);
126 $CMcontent = $this->printFileClickMenu($this->iParts
[0]);
129 // Make 2nd level clickmenu (only for DBmenus)
130 if ($this->isDBmenu
) {
131 $CMcontent = $this->printNewDBLevel($this->iParts
[0], $this->iParts
[1]);
134 // Return clickmenu content:
138 /***************************************
142 ***************************************/
144 * Make 1st level clickmenu:
146 * @param string $table Table name
147 * @param int $uid UID for the current record.
148 * @return string HTML content
150 public function printDBClickMenu($table, $uid) {
153 $this->rec
= BackendUtility
::getRecordWSOL($table, $uid);
154 $menuItems = array();
158 if ($table === 'pages' && $uid === 0) {
162 if ($table === 'pages' && in_array($uid, $GLOBALS['BE_USER']->returnWebmounts())) {
165 // Used to hide cut,copy icons for l10n-records
166 $l10nOverlay = FALSE;
167 // Should only be performed for overlay-records within the same table
168 if (BackendUtility
::isTableLocalizable($table) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
169 $l10nOverlay = (int)$this->rec
[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0;
171 // If record found (or root), go ahead and fill the $menuItems array which will contain data for the elements to render.
172 if (is_array($this->rec
) ||
$root) {
174 $lCP = $GLOBALS['BE_USER']->calcPerms(BackendUtility
::getRecord('pages', $table == 'pages' ?
$this->rec
['uid'] : $this->rec
['pid']));
176 if (!in_array('view', $this->disabledItems
)) {
177 if ($table === 'pages') {
178 $menuItems['view'] = $this->DB_view($uid);
180 if ($table === 'tt_content') {
181 $ws_rec = BackendUtility
::getRecordWSOL($table, $this->rec
['uid']);
182 $menuItems['view'] = $this->DB_view($ws_rec['pid']);
186 if (!$root && ($GLOBALS['BE_USER']->isPSet($lCP, $table, 'edit') ||
$GLOBALS['BE_USER']->isPSet($lCP, $table, 'editcontent'))) {
187 if (!in_array('edit', $this->disabledItems
)) {
188 $menuItems['edit'] = $this->DB_edit($table, $uid);
193 if (!in_array('new', $this->disabledItems
) && $GLOBALS['BE_USER']->isPSet($lCP, $table, 'new')) {
194 $menuItems['new'] = $this->DB_new($table, $uid);
197 if (!in_array('info', $this->disabledItems
) && !$root) {
198 $menuItems['info'] = $this->DB_info($table, $uid);
200 $menuItems['spacer1'] = 'spacer';
202 if (!in_array('copy', $this->disabledItems
) && !$root && !$DBmount && !$l10nOverlay) {
203 $menuItems['copy'] = $this->DB_copycut($table, $uid, 'copy');
206 if (!in_array('cut', $this->disabledItems
) && !$root && !$DBmount && !$l10nOverlay) {
207 $menuItems['cut'] = $this->DB_copycut($table, $uid, 'cut');
210 $elFromAllTables = count($this->clipObj
->elFromTable(''));
211 if (!in_array('paste', $this->disabledItems
) && $elFromAllTables) {
212 $selItem = $this->clipObj
->getSelectedRecord();
214 GeneralUtility
::fixed_lgd_cs($selItem['_RECORD_TITLE'], $GLOBALS['BE_USER']->uc
['titleLen']),
215 $root ?
$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility
::fixed_lgd_cs(BackendUtility
::getRecordTitle($table, $this->rec
), $GLOBALS['BE_USER']->uc
['titleLen']),
216 $this->clipObj
->currentMode()
218 if ($table === 'pages' && $lCP & 8) {
219 if ($elFromAllTables) {
220 $menuItems['pasteinto'] = $this->DB_paste('', $uid, 'into', $elInfo);
223 $elFromTable = count($this->clipObj
->elFromTable($table));
224 if (!$root && !$DBmount && $elFromTable && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
225 $menuItems['pasteafter'] = $this->DB_paste($table, -$uid, 'after', $elInfo);
228 $subname = \TYPO3\CMS\Core\Utility\GeneralUtility
::_GP('subname');
229 $localItems = array();
230 if (!$this->cmLevel
&& !in_array('moreoptions', $this->disabledItems
, TRUE)) {
231 // Creating menu items here:
233 $localItems[] = 'spacer';
234 $localItems['moreoptions'] = $this->linkItem(
235 $this->label('more'),
236 $this->excludeIcon(''),
237 'top.loadTopMenu(\'' . \TYPO3\CMS\Core\Utility\GeneralUtility
::linkThisScript() . '&cmLevel=1&subname=moreoptions\');return false;',
241 $menuItemHideUnhideAllowed = FALSE;
243 // Check if column for disabled is defined
244 if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
245 $hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
247 $hiddenField !== '' && !empty($GLOBALS['TCA'][$table]['columns'][$hiddenField]['exclude'])
248 && $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $hiddenField)
250 $menuItemHideUnhideAllowed = TRUE;
253 if ($menuItemHideUnhideAllowed && !in_array('hide', $this->disabledItems
, TRUE)) {
254 $localItems['hide'] = $this->DB_hideUnhide($table, $this->rec
, $hiddenField);
256 $anyEnableColumnsFieldAllowed = FALSE;
257 // Check if columns are defined
258 if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
259 $columnsToCheck = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
260 if ($table === 'pages' && !empty($columnsToCheck)) {
261 $columnsToCheck[] = 'extendToSubpages';
263 foreach ($columnsToCheck as $currentColumn) {
265 !empty($GLOBALS['TCA'][$table]['columns'][$currentColumn]['exclude'])
266 && $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $currentColumn)
268 $anyEnableColumnsFieldAllowed = TRUE;
272 if ($anyEnableColumnsFieldAllowed && !in_array('edit_access', $this->disabledItems
, TRUE)) {
273 $localItems['edit_access'] = $this->DB_editAccess($table, $uid);
275 if ($table === 'pages' && $this->editPageIconSet
&& !in_array('edit_pageproperties', $this->disabledItems
, TRUE)) {
276 $localItems['edit_pageproperties'] = $this->DB_editPageProperties($uid);
279 // Find delete element among the input menu items and insert the local items just before that:
281 $deleteFound = FALSE;
282 foreach ($menuItems as $key => $value) {
284 if ($key === 'delete') {
290 // .. subtract two... (delete item + its spacer element...)
292 // and insert the items just before the delete element.
293 array_splice($menuItems, $c, 0, $localItems);
295 $menuItems = array_merge($menuItems, $localItems);
300 $elInfo = array(GeneralUtility
::fixed_lgd_cs(BackendUtility
::getRecordTitle($table, $this->rec
), $GLOBALS['BE_USER']->uc
['titleLen']));
301 if (!in_array('delete', $this->disabledItems
) && !$root && !$DBmount && $GLOBALS['BE_USER']->isPSet($lCP, $table, 'delete')) {
302 $menuItems['spacer2'] = 'spacer';
303 $menuItems['delete'] = $this->DB_delete($table, $uid, $elInfo);
305 if (!in_array('history', $this->disabledItems
)) {
306 $menuItems['history'] = $this->DB_history($table, $uid, $elInfo);
309 // Adding external elements to the menuItems array
310 $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
311 // Processing by external functions?
312 $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
313 if (!is_array($this->rec
)) {
314 $this->rec
= array();
316 // Return the printed elements:
317 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));
321 * Make 2nd level clickmenu (only for DBmenus)
323 * @param string $table Table name
324 * @param int $uid UID for the current record.
325 * @return string HTML content
327 public function printNewDBLevel($table, $uid) {
329 // Setting internal record to the table/uid :
330 $this->rec
= BackendUtility
::getRecordWSOL($table, $uid);
331 $menuItems = array();
334 if ($table === 'pages' && $uid === 0) {
337 // If record was found, check permissions and get menu items.
338 if (is_array($this->rec
) ||
$root) {
339 $lCP = $GLOBALS['BE_USER']->calcPerms(BackendUtility
::getRecord('pages', $table === 'pages' ?
$this->rec
['uid'] : $this->rec
['pid']));
341 if (!$root && ($GLOBALS['BE_USER']->isPSet($lCP, $table, 'edit') ||
$GLOBALS['BE_USER']->isPSet($lCP, $table, 'editcontent'))) {
344 $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
347 $subname = GeneralUtility
::_GP('subname');
348 if ($subname === 'moreoptions') {
349 // If the page can be edited, then show this:
351 if (($table === 'pages' ||
$table === 'tt_content') && !in_array('move_wizard', $this->disabledItems
, TRUE)) {
352 $localItems['move_wizard'] = $this->DB_moveWizard($table, $uid, $this->rec
);
354 if (($table === 'pages' ||
$table === 'tt_content') && !in_array('new_wizard', $this->disabledItems
, TRUE)) {
355 $localItems['new_wizard'] = $this->DB_newWizard($table, $uid, $this->rec
);
357 if ($table === 'pages' && !in_array('perms', $this->disabledItems
, TRUE) && $GLOBALS['BE_USER']->check('modules', 'web_perm')) {
358 $localItems['perms'] = $this->DB_perms($table, $uid, $this->rec
);
360 if (!in_array('db_list', $this->disabledItems
, TRUE) && $GLOBALS['BE_USER']->check('modules', 'web_list')) {
361 $localItems['db_list'] = $this->DB_db_list($table, $uid, $this->rec
);
364 // Temporary mount point item:
365 if ($table === 'pages') {
366 $localItems['temp_mount_point'] = $this->DB_tempMountPoint($uid);
368 // Merge the locally created items into the current menu items passed to this function.
369 $menuItems = array_merge($menuItems, $localItems);
372 // Return the printed elements:
373 if (!is_array($menuItems)) {
374 $menuItems = array();
376 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));
380 * Processing the $menuItems array (for extension classes) (DATABASE RECORDS)
382 * @param array $menuItems Array for manipulation.
383 * @return array Processed $menuItems array
385 public function externalProcessingOfDBMenuItems($menuItems) {
390 * Processing the $menuItems array by external classes (typ. adding items)
392 * @param array $menuItems Array for manipulation.
393 * @param string $table Table name
394 * @param int $uid UID for the current record.
395 * @return array Processed $menuItems array
397 public function processingByExtClassArray($menuItems, $table, $uid) {
398 if (is_array($this->extClassArray
)) {
399 foreach ($this->extClassArray
as $conf) {
400 $obj = GeneralUtility
::makeInstance($conf['name']);
401 $menuItems = $obj->main($this, $menuItems, $table, $uid);
408 * Returning JavaScript for the onClick event linking to the input URL.
410 * @param string $url The URL relative to TYPO3_mainDir
411 * @param string $retUrl The return_url-parameter
412 * @param bool $hideCM If set, the "hideCM()" will be called
413 * @param string $overrideLoc If set, gives alternative location to load in (for example top frame or somewhere else)
414 * @return string JavaScript for an onClick event.
416 public function urlRefForCM($url, $retUrl = '', $hideCM = 1, $overrideLoc = '') {
417 $loc = 'top.content.list_frame';
418 $editOnClick = ($overrideLoc ?
'var docRef=' . $overrideLoc : 'var docRef=(top.content.list_frame)?top.content.list_frame:' . $loc) . '; docRef.location.href=top.TS.PATH_typo3+\'' . $url . '\'' . ($retUrl ?
'+\'&' . $retUrl . '=\'+top.rawurlencode(' . $this->frameLocation('docRef.document') . '.pathname+' . $this->frameLocation('docRef.document') . '.search)' : '') . ';' . ($hideCM ?
'return hideCM();' : '');
423 * Adding CM element for Clipboard "copy" and "cut"
425 * @param string $table Table name
426 * @param int $uid UID for the current record.
427 * @param string $type Type: "copy" or "cut
428 * @return array Item array, element in $menuItems
431 public function DB_copycut($table, $uid, $type) {
432 if ($this->clipObj
->current
== 'normal') {
433 $isSel = $this->clipObj
->isSelected($table, $uid);
436 if ($this->listFrame
) {
437 $addParam['reloadListFrame'] = $this->alwaysContentFrame ?
2 : 1;
439 return $this->linkItem($this->label($type), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-edit-' . $type . ($isSel === $type ?
'-release' : ''))), 'top.loadTopMenu(\'' . $this->clipObj
->selUrlDB($table, $uid, ($type == 'copy' ?
1 : 0), ($isSel == $type), $addParam) . '\');return false;');
443 * Adding CM element for Clipboard "paste into"/"paste after"
444 * NOTICE: $table and $uid should follow the special syntax for paste, see clipboard-class :: pasteUrl();
446 * @param string $table Table name
447 * @param int $uid UID for the current record. NOTICE: Special syntax!
448 * @param string $type Type: "into" or "after
449 * @param array $elInfo Contains instructions about whether to copy or cut an element.
450 * @return array Item array, element in $menuItems
451 * @see \TYPO3\CMS\Backend\Clipboard\Clipboard::pasteUrl()
454 public function DB_paste($table, $uid, $type, $elInfo) {
456 $loc = 'top.content.list_frame';
457 if ($GLOBALS['BE_USER']->jsConfirmation(2)) {
458 $conf = $loc . ' && confirm(' . GeneralUtility
::quoteJSvalue(sprintf($GLOBALS['LANG']->sL(('LLL:EXT:lang/locallang_core.xlf:mess.' . ($elInfo[2] == 'copy' ?
'copy' : 'move') . '_' . $type)), $elInfo[0], $elInfo[1])) . ')';
462 $editOnClick = 'if(' . $conf . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'' . $this->clipObj
->pasteUrl($table, $uid, 0) . '&redirect=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search); hideCM();}';
463 return $this->linkItem($this->label('paste' . $type), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-paste-' . $type)), $editOnClick . 'return false;');
467 * Adding CM element for Info
469 * @param string $table Table name
470 * @param int $uid UID for the current record.
471 * @return array Item array, element in $menuItems
474 public function DB_info($table, $uid) {
475 return $this->linkItem($this->label('info'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-info')), 'top.launchView(\'' . $table . '\', \'' . $uid . '\'); return hideCM();');
479 * Adding CM element for History
481 * @param string $table Table name
482 * @param int $uid UID for the current record.
483 * @return array Item array, element in $menuItems
486 public function DB_history($table, $uid) {
487 $url = BackendUtility
::getModuleUrl('record_history', array('element' => $table . ':' . $uid));
488 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_history')), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-history-open')), $this->urlRefForCM($url, 'returnUrl'), 0);
492 * Adding CM element for Permission setting
494 * @param string $table Table name
495 * @param int $uid UID for the current record.
496 * @param array $rec The "pages" record with "perms_*" fields inside.
497 * @return array Item array, element in $menuItems
500 public function DB_perms($table, $uid, $rec) {
501 if (!ExtensionManagementUtility
::isLoaded('perm')) {
504 $url = ExtensionManagementUtility
::extRelPath('perm') . 'mod1/index.php?id=' . $uid . ($rec['perms_userid'] == $GLOBALS['BE_USER']->user
['uid'] ||
$GLOBALS['BE_USER']->isAdmin() ?
'&return_id=' . $uid . '&edit=1' : '');
505 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_perms')), $this->excludeIcon(IconUtility
::getSpriteIcon('status-status-locked')), $this->urlRefForCM($url), 0);
509 * Adding CM element for DBlist
511 * @param string $table Table name
512 * @param int $uid UID for the current record.
513 * @param array $rec Record of the element (needs "pid" field if not pages-record)
514 * @return array Item array, element in $menuItems
517 public function DB_db_list($table, $uid, $rec) {
518 $urlParams = array();
519 $urlParams['id'] = $table == 'pages' ?
$uid : $rec['pid'];
520 $urlParams['table'] = $table == 'pages' ?
'' : $table;
521 $url = BackendUtility
::getModuleUrl('web_list', $urlParams, '', TRUE);
522 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_db_list')), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-system-list-open')), 'top.nextLoadModuleUrl=\'' . $url . '\';top.goToModule(\'web_list\', 1);', 0);
526 * Adding CM element for Moving wizard
528 * @param string $table Table name
529 * @param int $uid UID for the current record.
530 * @param array $rec Record. Needed for tt-content elements which will have the sys_language_uid sent
531 * @return array Item array, element in $menuItems
534 public function DB_moveWizard($table, $uid, $rec) {
535 // Hardcoded field for tt_content elements.
536 $url = 'move_el.php?table=' . $table . '&uid=' . $uid . ($table == 'tt_content' ?
'&sys_language_uid=' . (int)$rec['sys_language_uid'] : '');
537 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_moveWizard' . ($table == 'pages' ?
'_page' : ''))), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-' . ($table === 'pages' ?
'page' : 'document') . '-move')), $this->urlRefForCM($url, 'returnUrl'), 0);
541 * Adding CM element for Create new wizard (either db_new.php or sysext/cms/layout/db_new_content_el.php or custom wizard)
543 * @param string $table Table name
544 * @param int $uid UID for the current record.
545 * @param array $rec Record.
546 * @return array Item array, element in $menuItems
549 public function DB_newWizard($table, $uid, $rec) {
550 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
551 $tmpTSc = BackendUtility
::getModTSconfig($this->pageinfo
['uid'], 'mod.web_list');
552 $tmpTSc = $tmpTSc['properties']['newContentWiz.']['overrideWithExtension'];
553 $newContentWizScriptPath = ExtensionManagementUtility
::isLoaded($tmpTSc) ? ExtensionManagementUtility
::extRelPath($tmpTSc) . 'mod1/db_new_content_el.php' : 'sysext/cms/layout/db_new_content_el.php';
554 $url = $table == 'pages' ?
'db_new.php?id=' . $uid . '&pagesOnly=1' : $newContentWizScriptPath . '?id=' . $rec['pid'] . '&sys_language_uid=' . (int)$rec['sys_language_uid'];
555 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_newWizard')), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-' . ($table === 'pages' ?
'page' : 'document') . '-new')), $this->urlRefForCM($url, 'returnUrl'), 0);
559 * Adding CM element for Editing of the access related fields of a table (disable, starttime, endtime, fe_groups)
561 * @param string $table Table name
562 * @param int $uid UID for the current record.
563 * @return array Item array, element in $menuItems
566 public function DB_editAccess($table, $uid) {
567 $addParam = '&columnsOnly=' . rawurlencode((implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table == 'pages' ?
',extendToSubpages' : '')));
568 $url = 'alt_doc.php?edit[' . $table . '][' . $uid . ']=edit' . $addParam;
569 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_editAccess')), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-edit-access')), $this->urlRefForCM($url, 'returnUrl'), 1);
573 * Adding CM element for edit page properties
575 * @param int $uid page uid to edit (PID)
576 * @return array Item array, element in $menuItems
579 public function DB_editPageProperties($uid) {
580 $url = 'alt_doc.php?edit[pages][' . $uid . ']=edit';
581 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_editPageProperties')), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-page-open')), $this->urlRefForCM($url, 'returnUrl'), 1);
585 * Adding CM element for regular editing of the element!
587 * @param string $table Table name
588 * @param int $uid UID for the current record.
589 * @return array Item array, element in $menuItems
592 public function DB_edit($table, $uid) {
593 // If another module was specified, replace the default Page module with the new one
594 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
595 $pageModule = BackendUtility
::isModuleSetInTBE_MODULES($newPageModule) ?
$newPageModule : 'web_layout';
597 $loc = 'top.content.list_frame';
599 $theIcon = 'actions-document-open';
600 if ($this->iParts
[0] == 'pages' && $this->iParts
[1] && $GLOBALS['BE_USER']->check('modules', $pageModule)) {
601 $theIcon = 'actions-page-open';
602 $this->editPageIconSet
= 1;
603 if ($GLOBALS['BE_USER']->uc
['classicPageEditMode']) {
604 $addParam = '&editRegularContentFromId=' . (int)$this->iParts
[1];
606 $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'alt_doc.php?returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'&edit[' . $table . '][' . $uid . ']=edit' . $addParam . '\';}';
610 $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'alt_doc.php?returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'&edit[' . $table . '][' . $uid . ']=edit' . $addParam . '\';}';
612 return $this->linkItem($this->label('edit'), $this->excludeIcon(IconUtility
::getSpriteIcon($theIcon)), $editOnClick . 'return hideCM();');
616 * Adding CM element for regular Create new element
618 * @param string $table Table name
619 * @param int $uid UID for the current record.
620 * @return array Item array, element in $menuItems
623 public function DB_new($table, $uid) {
625 $loc = 'top.content.list_frame';
626 $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'' . ($this->listFrame ?
'alt_doc.php?returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'&edit[' . $table . '][-' . $uid . ']=new\'' : 'db_new.php?id=' . (int)$uid . '\'') . ';}';
627 return $this->linkItem($this->label('new'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-' . ($table === 'pages' ?
'page' : 'document') . '-new')), $editOnClick . 'return hideCM();');
631 * Adding CM element for Delete
633 * @param string $table Table name
634 * @param int $uid UID for the current record.
635 * @param array $elInfo Label for including in the confirmation message, EXT:lang/locallang_core.xlf:mess.delete
636 * @return array Item array, element in $menuItems
639 public function DB_delete($table, $uid, $elInfo) {
641 $loc = 'top.content.list_frame';
642 if ($GLOBALS['BE_USER']->jsConfirmation(4)) {
643 $conf = 'confirm(' . GeneralUtility
::quoteJSvalue((sprintf($GLOBALS['LANG']->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, (' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord'))))) . ')';
647 $editOnClick = 'if(' . $loc . ' && ' . $conf . ' ){' . $loc . '.location.href=top.TS.PATH_typo3+\'tce_db.php?redirect=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'' . '&cmd[' . $table . '][' . $uid . '][delete]=1&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility
::getUrlToken('tceAction') . '\';}hideCM();top.nav.refresh.defer(500, top.nav);';
648 return $this->linkItem($this->label('delete'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-edit-delete')), $editOnClick . 'return false;');
652 * Adding CM element for View Page
654 * @param int $id Page uid (PID)
655 * @param string $anchor Anchor, if any
656 * @return array Item array, element in $menuItems
659 public function DB_view($id, $anchor = '') {
660 return $this->linkItem($this->label('view'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-view')), BackendUtility
::viewOnClick($id, $this->PH_backPath
, BackendUtility
::BEgetRootLine($id), $anchor) . 'return hideCM();');
664 * Adding element for setting temporary mount point.
666 * @param int $page_id Page uid (PID)
667 * @return array Item array, element in $menuItems
670 public function DB_tempMountPoint($page_id) {
671 return $this->linkItem($this->label('tempMountPoint'), $this->excludeIcon(IconUtility
::getSpriteIcon('apps-pagetree-page-mountpoint')), 'if (top.content.nav_frame) {
672 var node = top.TYPO3.Backend.NavigationContainer.PageTree.getSelected();
680 id: ' . (int)$page_id . '
685 node.ownerTree.commandProvider.mountAsTreeRoot(useNode, node.ownerTree);
692 * Adding CM element for hide/unhide of the input record
694 * @param string $table Table name
695 * @param array $rec Record array
696 * @param string $hideField Name of the hide field
697 * @return array Item array, element in $menuItems
700 public function DB_hideUnhide($table, $rec, $hideField) {
701 return $this->DB_changeFlag($table, $rec, $hideField, $this->label(($rec[$hideField] ?
'un' : '') . 'hide'), 'hide');
705 * Adding CM element for a flag field of the input record
707 * @param string $table Table name
708 * @param array $rec Record array
709 * @param string $flagField Name of the flag field
710 * @param string $title Menu item Title
711 * @param string $name Name of the item used for icons and labels
712 * @param string $iconRelPath Icon path relative to typo3/ folder
713 * @return array Item array, element in $menuItems
715 public function DB_changeFlag($table, $rec, $flagField, $title, $name, $iconRelPath = 'gfx/') {
716 $uid = $rec['_ORIG_uid'] ?
: $rec['uid'];
718 $loc = 'top.content.list_frame';
719 $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'tce_db.php?redirect=\'' . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'' . '&data[' . $table . '][' . $uid . '][' . $flagField . ']=' . ($rec[$flagField] ?
0 : 1) . '&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility
::getUrlToken('tceAction') . '\';}hideCM();top.nav.refresh.defer(500, top.nav);';
720 return $this->linkItem($title, $this->excludeIcon(IconUtility
::getSpriteIcon('actions-edit-' . ($rec[$flagField] ?
'un' : '') . 'hide')), $editOnClick . 'return false;', 1);
723 /***************************************
727 ***************************************/
729 * Make 1st level clickmenu:
731 * @param string $combinedIdentifier The combined identifier
732 * @return string HTML content
733 * @see \TYPO3\CMS\Core\Resource\ResourceFactory::retrieveFileOrFolderObject()
735 public function printFileClickMenu($combinedIdentifier) {
736 $menuItems = array();
737 $combinedIdentifier = rawurldecode($combinedIdentifier);
738 $fileObject = ResourceFactory
::getInstance()
739 ->retrieveFileOrFolderObject($combinedIdentifier);
742 $isStorageRoot = FALSE;
744 $userMayViewStorage = FALSE;
745 $userMayEditStorage = FALSE;
746 $identifier = $fileObject->getCombinedIdentifier();
747 if ($fileObject instanceof \TYPO3\CMS\Core\
Resource\Folder
) {
748 $icon = IconUtility
::getSpriteIconForResource($fileObject, array(
749 'class' => 'absmiddle',
750 'title' => htmlspecialchars($fileObject->getName())
753 if ($fileObject->getIdentifier() === $fileObject->getStorage()->getRootLevelFolder()->getIdentifier()) {
754 $isStorageRoot = TRUE;
755 if ($GLOBALS['BE_USER']->check('tables_select', 'sys_file_storage')) {
756 $userMayViewStorage = TRUE;
758 if ($GLOBALS['BE_USER']->check('tables_modify', 'sys_file_storage')) {
759 $userMayEditStorage = TRUE;
762 if (!$fileObject->getStorage()->isOnline()) {
766 $icon = IconUtility
::getSpriteIconForResource($fileObject, array(
767 'class' => 'absmiddle',
768 'title' => htmlspecialchars($fileObject->getName() . ' (' . GeneralUtility
::formatSize($fileObject->getSize()) . ')')
772 if (!in_array('hide', $this->disabledItems
) && $isStorageRoot && $userMayEditStorage) {
773 $record = BackendUtility
::getRecord('sys_file_storage', $fileObject->getStorage()->getUid());
774 $menuItems['hide'] = $this->DB_changeFlag(
778 $this->label($record['is_online'] ?
'offline' : 'online'),
783 if (!in_array('edit', $this->disabledItems
) && $fileObject->checkActionPermission('write')) {
784 if (!$folder && !$isStorageRoot && $fileObject->isIndexed()) {
785 $metaData = $fileObject->_getMetaData();
786 $menuItems['edit2'] = $this->DB_edit('sys_file_metadata', $metaData['uid']);
788 if (!$folder && GeneralUtility
::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $fileObject->getExtension()) && $fileObject->checkActionPermission('write')) {
789 $menuItems['edit'] = $this->FILE_launch($identifier, 'file_edit', 'editcontent', 'edit_file.gif');
790 } elseif ($isStorageRoot && $userMayEditStorage) {
791 $menuItems['edit'] = $this->DB_edit('sys_file_storage', $fileObject->getStorage()->getUid());
795 if (!in_array('rename', $this->disabledItems
) && !$isStorageRoot && $fileObject->checkActionPermission('rename')) {
796 $menuItems['rename'] = $this->FILE_launch($identifier, 'file_rename', 'rename', 'rename.gif');
799 if (!in_array('upload', $this->disabledItems
) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
800 $menuItems['upload'] = $this->FILE_upload($identifier);
803 if (!in_array('new', $this->disabledItems
) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
804 $menuItems['new'] = $this->FILE_launch($identifier, 'file_newfolder', 'new', 'new_file.gif');
807 if (!in_array('info', $this->disabledItems
) && $fileObject->checkActionPermission('read')) {
808 if ($isStorageRoot && $userMayViewStorage) {
809 $menuItems['info'] = $this->DB_info('sys_file_storage', $fileObject->getStorage()->getUid());
810 } elseif (!$folder) {
811 $menuItems['info'] = $this->fileInfo($identifier);
814 $menuItems[] = 'spacer';
816 if (!in_array('copy', $this->disabledItems
) && !$isStorageRoot && $fileObject->checkActionPermission('read')) {
817 $menuItems['copy'] = $this->FILE_copycut($identifier, 'copy');
820 if (!in_array('cut', $this->disabledItems
) && !$isStorageRoot && $fileObject->checkActionPermission('move')) {
821 $menuItems['cut'] = $this->FILE_copycut($identifier, 'cut');
824 $elFromAllTables = count($this->clipObj
->elFromTable('_FILE'));
825 if (!in_array('paste', $this->disabledItems
) && $elFromAllTables && $folder && $fileObject->checkActionPermission('write')) {
826 $elArr = $this->clipObj
->elFromTable('_FILE');
827 $selItem = reset($elArr);
830 basename($identifier),
831 $this->clipObj
->currentMode()
833 $menuItems['pasteinto'] = $this->FILE_paste($identifier, $selItem, $elInfo);
835 $menuItems[] = 'spacer';
837 if (!in_array('delete', $this->disabledItems
) && $fileObject->checkActionPermission('delete')) {
838 if ($isStorageRoot && $userMayEditStorage) {
839 $elInfo = array(GeneralUtility
::fixed_lgd_cs($fileObject->getStorage()->getName(), $GLOBALS['BE_USER']->uc
['titleLen']));
840 $menuItems['delete'] = $this->DB_delete('sys_file_storage', $fileObject->getStorage()->getUid(), $elInfo);
841 } elseif (!$isStorageRoot) {
842 $menuItems['delete'] = $this->FILE_delete($identifier);
846 // Adding external elements to the menuItems array
847 $menuItems = $this->processingByExtClassArray($menuItems, $identifier, 0);
848 // Processing by external functions?
849 $menuItems = $this->externalProcessingOfFileMenuItems($menuItems);
850 // Return the printed elements:
851 return $this->printItems($menuItems, $icon . $fileObject->getName());
855 * Processing the $menuItems array (for extension classes) (FILES)
857 * @param array $menuItems Array for manipulation.
858 * @return array Processed $menuItems array
860 public function externalProcessingOfFileMenuItems($menuItems) {
865 * Multi-function for adding an entry to the $menuItems array
867 * @param string $path Path to the file/directory (target)
868 * @param string $moduleName Script (deprecated) or module name (e.g. file_edit) to pass &target= to
869 * @param string $type "type" is the code which fetches the correct label for the element from "cm.
870 * @param string $image icon image-filename from "gfx/" (12x12 icon)
871 * @param bool $noReturnUrl If set, the return URL parameter will not be set in the link
872 * @return array Item array, element in $menuItems
875 public function FILE_launch($path, $moduleName, $type, $image, $noReturnUrl = FALSE) {
876 $loc = 'top.content.list_frame';
878 if (strpos($moduleName, '.php') !== FALSE) {
879 GeneralUtility
::deprecationLog(
880 'Using a php file directly in ClickMenu is deprecated since TYPO3 CMS 6.3.'
881 . ' Register the class as module and use BackendUtility::getModuleUrl() to get the right link.'
882 . ' For examples how to do this see ext_tables.php of EXT:backend.'
884 $scriptUrl = $moduleName;
886 $scriptUrl = BackendUtility
::getModuleUrl($moduleName);
889 $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=top.TS.PATH_typo3+' . GeneralUtility
::quoteJSvalue($scriptUrl . '&target=' . rawurlencode($path)) . ($noReturnUrl ?
'' : '+\'&returnUrl=\'+top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation($loc . '.document') . '.search)') . ';}';
890 return $this->linkItem($this->label($type), $this->excludeIcon('<img' . IconUtility
::skinImg($this->PH_backPath
, ('gfx/' . $image), 'width="12" height="12"') . ' alt="" />'), $editOnClick . 'top.nav.refresh();return hideCM();');
894 * function for adding an upload entry to the $menuItems array
896 * @param string $path Path to the file/directory (target)
897 * @return array Item array, element in $menuItems
900 public function FILE_upload($path) {
901 $script = 'file_upload';
903 $image = 'upload.gif';
904 return $this->FILE_launch($path, $script, $type, $image, TRUE);
908 * Returns element for copy or cut of files.
910 * @param string $path Path to the file/directory (target)
911 * @param string $type Type: "copy" or "cut
912 * @return array Item array, element in $menuItems
915 public function FILE_copycut($path, $type) {
916 // Pseudo table name for use in the clipboard.
918 $uid = GeneralUtility
::shortmd5($path);
919 if ($this->clipObj
->current
== 'normal') {
920 $isSel = $this->clipObj
->isSelected($table, $uid);
923 if ($this->listFrame
) {
924 $addParam['reloadListFrame'] = $this->alwaysContentFrame ?
2 : 1;
926 return $this->linkItem($this->label($type), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-edit-' . $type . ($isSel === $type ?
'-release' : ''))), 'top.loadTopMenu(\'' . $this->clipObj
->selUrlFile($path, ($type == 'copy' ?
1 : 0), ($isSel == $type), $addParam) . '\');return false;');
930 * Creates element for deleting of target
932 * @param string $path Path to the file/directory (target)
933 * @return array Item array, element in $menuItems
936 public function FILE_delete($path) {
938 $loc = 'top.content.list_frame';
939 if ($GLOBALS['BE_USER']->jsConfirmation(4)) {
940 $conf = 'confirm(' . GeneralUtility
::quoteJSvalue((sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:mess.delete'), basename($path)) . BackendUtility
::referenceCount('_FILE', $path, ' (There are %s reference(s) to this file!)'))) . ')';
944 $editOnClick = 'if(' . $loc . ' && ' . $conf . ' ){' . $loc . '.location.href=top.TS.PATH_typo3+\'tce_file.php?redirect=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+\'' . '&file[delete][0][data]=' . rawurlencode($path) . '&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility
::getUrlToken('tceAction') . '\';}hideCM();';
945 return $this->linkItem($this->label('delete'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-edit-delete')), $editOnClick . 'return false;');
949 * Creates element for pasting files.
951 * @param string $path Path to the file/directory (target)
952 * @param string $target target - NOT USED.
953 * @param array $elInfo Various values for the labels.
954 * @return array Item array, element in $menuItems
957 public function FILE_paste($path, $target, $elInfo) {
959 $loc = 'top.content.list_frame';
960 if ($GLOBALS['BE_USER']->jsConfirmation(2)) {
961 $conf = $loc . ' && confirm(' . GeneralUtility
::quoteJSvalue(sprintf($GLOBALS['LANG']->sL(('LLL:EXT:lang/locallang_core.xlf:mess.' . ($elInfo[2] == 'copy' ?
'copy' : 'move') . '_into')), $elInfo[0], $elInfo[1])) . ')';
965 $editOnClick = 'if(' . $conf . '){' . $loc . '.location.href=top.TS.PATH_typo3+\'' . $this->clipObj
->pasteUrl('_FILE', $path, 0) . '&redirect=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search); }hideCM();top.nav.refresh();';
966 return $this->linkItem($this->label('pasteinto'), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-paste-into')), $editOnClick . 'return false;');
970 * Adding ClickMenu element for file info
972 * @param string $identifier The combined identifier of the file.
973 * @return array Item array, element in $menuItems
975 protected function fileInfo($identifier) {
976 return $this->DB_info('_FILE', $identifier);
979 /***************************************
983 ***************************************/
985 * Make 1st level clickmenu:
987 * @param string $table The absolute path
988 * @param int $srcId UID for the current record.
989 * @param int $dstId Destination ID
990 * @return string HTML content
992 public function printDragDropClickMenu($table, $srcId, $dstId) {
993 $menuItems = array();
994 // If the drag and drop menu should apply to PAGES use this set of menu items
995 if ($table == 'pages') {
997 $menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into');
999 $menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after');
1001 $menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into');
1003 $menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after');
1005 // If the drag and drop menu should apply to FOLDERS use this set of menu items
1006 if ($table == 'folders') {
1008 $menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move');
1010 $menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy');
1012 // Adding external elements to the menuItems array
1013 $menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId);
1014 // to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar
1015 // Processing by external functions?
1016 $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
1017 // Return the printed elements:
1018 return $this->printItems($menuItems, IconUtility
::getSpriteIconForRecord($table, $this->rec
, array('title' => BackendUtility
::getRecordTitle($table, $this->rec
, TRUE))));
1022 * Processing the $menuItems array (for extension classes) (DRAG'N DROP)
1024 * @param array $menuItems Array for manipulation.
1025 * @return array Processed $menuItems array
1027 public function externalProcessingOfDragDropMenuItems($menuItems) {
1032 * Adding CM element for Copying/Moving a Page Into/After from a drag & drop action
1034 * @param int $srcUid source UID code for the record to modify
1035 * @param int $dstUid destination UID code for the record to modify
1036 * @param string $action Action code: either "move" or "copy
1037 * @param string $into Parameter code: either "into" or "after
1038 * @return array Item array, element in $menuItems
1041 public function dragDrop_copymovepage($srcUid, $dstUid, $action, $into) {
1042 $negativeSign = $into == 'into' ?
'' : '-';
1044 $loc = 'top.content.list_frame';
1045 $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=top.TS.PATH_typo3+"tce_db.php?redirect="+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+"' . '&cmd[pages][' . $srcUid . '][' . $action . ']=' . $negativeSign . $dstUid . '&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility
::getUrlToken('tceAction') . '";}hideCM();top.nav.refresh();';
1046 return $this->linkItem($this->label($action . 'Page_' . $into), $this->excludeIcon(IconUtility
::getSpriteIcon('actions-document-paste-' . $into)), $editOnClick . 'return false;', 0);
1050 * Adding CM element for Copying/Moving a Folder Into from a drag & drop action
1052 * @param string $srcPath source path for the record to modify
1053 * @param string $dstPath destination path for the records to modify
1054 * @param string $action Action code: either "move" or "copy
1055 * @return array Item array, element in $menuItems
1058 public function dragDrop_copymovefolder($srcPath, $dstPath, $action) {
1060 $loc = 'top.content.list_frame';
1061 $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=top.TS.PATH_typo3+"tce_file.php?redirect="+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+"' . '&file[' . $action . '][0][data]=' . $srcPath . '&file[' . $action . '][0][target]=' . $dstPath . '&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode() . BackendUtility
::getUrlToken('tceAction') . '";}hideCM();top.nav.refresh();';
1062 return $this->linkItem($this->label($action . 'Folder_into'), $this->excludeIcon(IconUtility
::getSpriteIcon('apps-pagetree-drag-move-into')), $editOnClick . 'return false;', 0);
1065 /***************************************
1069 **************************************/
1071 * Prints the items from input $menuItems array - as JS section for writing to the div-layers.
1073 * @param array $menuItems Array
1074 * @param string $item HTML code for the element which was clicked - shown in the end of the horizontal menu in topframe after the close-button.
1075 * @return string HTML code
1077 public function printItems($menuItems, $item) {
1079 // Enable/Disable items:
1080 $menuItems = $this->enableDisableItems($menuItems);
1081 // Clean up spacers:
1082 $menuItems = $this->cleanUpSpacers($menuItems);
1084 $out .= $this->printLayerJScode($menuItems);
1085 // Return the content
1090 * Create the JavaScript section
1092 * @param array $menuItems The $menuItems array to print
1093 * @return string The JavaScript section which will print the content of the CM to the div-layer in the target frame.
1095 public function printLayerJScode($menuItems) {
1097 // Clipboard must not be submitted - then it's probably a copy/cut situation.
1098 if ($this->isCMlayers()) {
1099 $frameName = '.' . ($this->listFrame ?
'list_frame' : 'nav_frame');
1100 if ($this->alwaysContentFrame
) {
1103 // Create the table displayed in the clickmenu layer:
1105 <table border="0" cellpadding="0" cellspacing="0" class="typo3-CSM">
1106 ' . implode('', $this->menuItemsForClickMenu($menuItems)) . '
1108 // Wrap the inner table in another table to create outer border:
1109 $CMtable = $this->wrapColorTableCM($CMtable);
1110 // Set back path place holder to real back path
1111 $CMtable = str_replace($this->PH_backPath
, $this->backPath
, $CMtable);
1113 $innerXML = '<data><clickmenu><htmltable><![CDATA[' . $CMtable . ']]></htmltable><cmlevel>' . $this->cmLevel
. '</cmlevel></clickmenu></data>';
1116 // Create JavaScript section:
1117 $script = $GLOBALS['TBE_TEMPLATE']->wrapScriptTags('
1119 if (top.content && top.content' . $frameName . ' && top.content' . $frameName . '.Clickmenu) {
1120 top.content' . $frameName . '.Clickmenu.populateData(unescape("' . GeneralUtility
::rawurlencodeJS($CMtable) . '"),' . $this->cmLevel
. ');
1130 * Wrapping the input string in a table with background color 4 and a black border style.
1131 * For the pop-up menu
1133 * @param string $str HTML content to wrap in table.
1136 public function wrapColorTableCM($str) {
1137 return '<div class="typo3-CSM-wrapperCM">
1143 * Traverses the menuItems and generates an output array for implosion in the topframe horizontal menu
1145 * @param array $menuItems Array
1146 * @return array Array of menu items for top frame.
1148 public function menuItemsForTopFrame($menuItems) {
1150 foreach ($menuItems as $i) {
1151 // IF the topbar is the ONLY means of the click menu, then items normally disabled from
1152 // the top menu will appear anyways IF they are disabled with a "1" (2+ will still disallow
1153 // them in the topbar)
1154 if ($i[4] == 1 && !$GLOBALS['SOBE']->doc
->isCMlayers()) {
1157 if (is_array($i) && !$i[4]) {
1165 * Traverses the menuItems and generates an output array for implosion in the CM div-layers table.
1167 * @param array $menuItems Array
1168 * @return array array for implosion in the CM div-layers table.
1170 public function menuItemsForClickMenu($menuItems) {
1172 foreach ($menuItems as $cc => $i) {
1173 // MAKE horizontal spacer
1174 if (is_string($i) && $i == 'spacer') {
1176 <tr class="bgColor2">
1177 <td colspan="2"><img src="clear.gif" width="1" height="1" alt="" /></td>
1180 // Just make normal element:
1182 $onClick = preg_replace('/return[[:space:]]+hideCM\\(\\)[[:space:]]*;/i', '', $onClick);
1183 $onClick = preg_replace('/return[[:space:]]+false[[:space:]]*;/i', '', $onClick);
1184 $onClick = preg_replace('/hideCM\\(\\);/i', '', $onClick);
1186 $onClick .= 'Clickmenu.hideAll();';
1188 $CSM = ' oncontextmenu="this.click();return false;"';
1190 <tr class="typo3-CSM-itemRow" onclick="' . htmlspecialchars($onClick) . '"' . $CSM . '>
1191 ' . (!$this->leftIcons ?
'<td class="typo3-CSM-item">' . $i[1] . '</td><td align="center">' . $i[2] . '</td>' : '<td align="center">' . $i[2] . '</td><td class="typo3-CSM-item">' . $i[1] . '</td>') . '
1199 * Adds or inserts a menu item
1200 * Can be used to set the position of new menu entries within the list of existing menu entries. Has this syntax: [cmd]:[menu entry key],[cmd].... cmd can be "after", "before" or "top" (or blank/"bottom" which is default). If "after"/"before" then menu items will be inserted after/before the existing entry with [menu entry key] if found. "after-spacer" and "before-spacer" do the same, but inserts before or after an item and a spacer. If not found, the bottom of list. If "top" the items are inserted in the top of the list.
1202 * @param array $menuItems Menu items array
1203 * @param array $newMenuItems Menu items array to insert
1204 * @param string $position Position command string. Has this syntax: [cmd]:[menu entry key],[cmd].... cmd can be "after", "before" or "top" (or blank/"bottom" which is default). If "after"/"before" then menu items will be inserted after/before the existing entry with [menu entry key] if found. "after-spacer" and "before-spacer" do the same, but inserts before or after an item and a spacer. If not found, the bottom of list. If "top" the items are inserted in the top of the list.
1205 * @return array Menu items array, processed.
1207 public function addMenuItems($menuItems, $newMenuItems, $position = '') {
1208 if (is_array($newMenuItems)) {
1210 $posArr = GeneralUtility
::trimExplode(',', $position, TRUE);
1211 foreach ($posArr as $pos) {
1212 list($place, $menuEntry) = GeneralUtility
::trimExplode(':', $pos, TRUE);
1213 list($place, $placeExtra) = GeneralUtility
::trimExplode('-', $place, TRUE);
1215 $pointer = count($menuItems);
1218 switch (strtolower($place)) {
1226 if ((string)key($menuItems) === $menuEntry) {
1231 if (!next($menuItems)) {
1239 if ($place == 'before') {
1241 if ($placeExtra == 'spacer' and prev($menuItems) == 'spacer') {
1244 } elseif ($place == 'after') {
1245 if ($placeExtra == 'spacer' and next($menuItems) == 'spacer') {
1252 if (strtolower($place) == 'top') {
1255 $pointer = count($menuItems);
1265 $pointer = max(0, $pointer);
1266 $menuItemsBefore = array_slice($menuItems, 0, $pointer ?
: 0);
1267 $menuItemsAfter = array_slice($menuItems, $pointer);
1268 $menuItems = $menuItemsBefore +
$newMenuItems +
$menuItemsAfter;
1274 * Creating an array with various elements for the clickmenu entry
1276 * @param string $str The label, htmlspecialchar'ed already
1277 * @param string $icon <img>-tag for the icon
1278 * @param string $onClick JavaScript onclick event for label/icon
1279 * @param bool $onlyCM ==1 and the element will NOT appear in clickmenus in the topframe (unless clickmenu is totally unavailable)! ==2 and the item will NEVER appear in top frame. (This is mostly for "less important" options since the top frame is not capable of holding so many elements horizontally)
1280 * @param bool $dontHide If set, the clickmenu layer will not hide itself onclick - used for secondary menus to appear...
1281 * @return array $menuItem entry with 6 numerical entries: [0] is the HTML for display of the element with link and icon an mouseover etc., [1]-[5] is simply the input params passed through!
1283 public function linkItem($str, $icon, $onClick, $onlyCM = 0, $dontHide = 0) {
1286 $onClick = str_replace('top.loadTopMenu', 'showClickmenu_raw', $onClick);
1289 IconUtility
::getSpriteIcon('empty-empty', array(
1290 'class' => 'c-roimg',
1291 'id' => ('roimg_' . $this->elCount
)
1292 )) . '<a href="#" onclick="' . htmlspecialchars($onClick) . '" onmouseover="mo(' . $this->elCount
. ');" onmouseout="mout(' . $this->elCount
. ');">' . $str . $icon . '</a>',
1302 * Returns the input string IF not a user setting has disabled display of icons.
1304 * @param string $iconCode The icon-image tag
1305 * @return string The icon-image tag prefixed with space char IF the icon should be printed at all due to user settings
1307 public function excludeIcon($iconCode) {
1308 return $GLOBALS['BE_USER']->uc
['noMenuMode'] && $GLOBALS['BE_USER']->uc
['noMenuMode'] !== 'icons' ?
'' : ' ' . $iconCode;
1312 * Enabling / Disabling items based on list provided from GET var ($this->iParts[3])
1314 * @param array $menuItems Menu items array
1315 * @return array Menu items array, processed.
1317 public function enableDisableItems($menuItems) {
1318 if ($this->iParts
[3]) {
1319 // Detect "only" mode: (only showing listed items)
1320 if ($this->iParts
[3][0] === '+') {
1321 $this->iParts
[3] = substr($this->iParts
[3], 1);
1327 // Transfer ONLY elements which are mentioned (or are spacers)
1329 $newMenuArray = array();
1330 foreach ($menuItems as $key => $value) {
1331 if (GeneralUtility
::inList($this->iParts
[3], $key) ||
is_string($value) && $value == 'spacer') {
1332 $newMenuArray[$key] = $value;
1335 $menuItems = $newMenuArray;
1337 // Traverse all elements except those listed (just unsetting them):
1338 $elements = GeneralUtility
::trimExplode(',', $this->iParts
[3], TRUE);
1339 foreach ($elements as $value) {
1340 unset($menuItems[$value]);
1344 // Return processed menu items:
1349 * Clean up spacers; Will remove any spacers in the start/end of menu items array plus any duplicates.
1351 * @param array $menuItems Menu items array
1352 * @return array Menu items array, processed.
1354 public function cleanUpSpacers($menuItems) {
1356 $prevItemWasSpacer = FALSE;
1357 foreach ($menuItems as $key => $value) {
1358 if (is_string($value) && $value == 'spacer') {
1359 if ($prevItemWasSpacer) {
1360 unset($menuItems[$key]);
1362 $prevItemWasSpacer = TRUE;
1364 $prevItemWasSpacer = FALSE;
1369 $key = key($menuItems);
1370 $value = current($menuItems);
1371 if (is_string($value) && $value == 'spacer') {
1372 unset($menuItems[$key]);
1376 $key = key($menuItems);
1377 $value = current($menuItems);
1378 if (is_string($value) && $value == 'spacer') {
1379 unset($menuItems[$key]);
1381 // Return processed menu items:
1386 * Get label from locallang_core.xlf:cm.*
1388 * @param string $label The "cm."-suffix to get.
1391 public function label($label) {
1392 return $GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:cm.' . $label, TRUE));
1396 * Returns TRUE if there should be writing to the div-layers (commands sent to clipboard MUST NOT write to div-layers)
1400 public function isCMlayers() {
1405 * Appends ".location" to input string
1407 * @param string $str Input string, probably a JavaScript document reference
1410 public function frameLocation($str) {
1411 return $str . '.location';