47a87da3224119f735aa806472947170875fee18
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / ClickMenu / ClickMenu.php
1 <?php
2 namespace TYPO3\CMS\Backend\ClickMenu;
3
4 use TYPO3\CMS\Core\Utility\GeneralUtility;
5
6 /**
7 * Class for generating the click menu
8 *
9 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
10 * @package TYPO3
11 * @subpackage core
12 * @internal
13 */
14 class ClickMenu {
15
16 // Internal, static: GPvar:
17 // Defines if the click menu is first level or second. Second means the click menu is triggered from another menu.
18 /**
19 * @todo Define visibility
20 */
21 public $cmLevel = 0;
22
23 // Clipboard array (submitted by eg. pressing the paste button)
24 /**
25 * @todo Define visibility
26 */
27 public $CB;
28
29 // Internal, static:
30 // Backpath for scripts/images.
31 /**
32 * @todo Define visibility
33 */
34 public $backPath = '';
35
36 // 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)
37 /**
38 * @todo Define visibility
39 */
40 public $PH_backPath = '###BACK_PATH###';
41
42 // If set, the calling document should be in the listframe of a frameset.
43 /**
44 * @todo Define visibility
45 */
46 public $listFrame = 0;
47
48 // If set, the menu is about database records, not files. (set if part 2 [1] of the item-var is NOT blank)
49 /**
50 * @todo Define visibility
51 */
52 public $isDBmenu = 0;
53
54 // If TRUE, the "content" frame is always used for reference (when condensed mode is enabled)
55 /**
56 * @todo Define visibility
57 */
58 public $alwaysContentFrame = 0;
59
60 // Stores the parts of the input $item string, splitted by "|":
61 // [0] = table/file, [1] = uid/blank, [2] = flag: If set, listFrame,
62 // If "2" then "content frame" is forced [3] = ("+" prefix = disable
63 // all by default, enable these. Default is to disable) Items key list
64 /**
65 * @todo Define visibility
66 */
67 public $iParts = array();
68
69 // Contains list of keywords of items to disable in the menu
70 /**
71 * @todo Define visibility
72 */
73 public $disabledItems = array();
74
75 // If TRUE, the context sensitive menu will not appear in the top frame, only as a layer.
76 /**
77 * @todo Define visibility
78 */
79 public $dontDisplayTopFrameCM = 0;
80
81 // If TRUE, Show icons on the left.
82 /**
83 * @todo Define visibility
84 */
85 public $leftIcons = 0;
86
87 // 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.
88 /**
89 * @todo Define visibility
90 */
91 public $extClassArray = array();
92
93 // Enable/disable ajax behavior
94 /**
95 * @todo Define visibility
96 */
97 public $ajax = 0;
98
99 // Internal, dynamic:
100 // Counter for elements in the menu. Used to number the name / id of the mouse-over icon.
101 /**
102 * @todo Define visibility
103 */
104 public $elCount = 0;
105
106 // Set, when edit icon is drawn.
107 /**
108 * @todo Define visibility
109 */
110 public $editPageIconSet = 0;
111
112 // Set to TRUE, if editing of the element is OK.
113 /**
114 * @todo Define visibility
115 */
116 public $editOK = 0;
117
118 /**
119 * @todo Define visibility
120 */
121 public $rec = array();
122
123 /**
124 * Initialize click menu
125 *
126 * @return string The clickmenu HTML content
127 * @todo Define visibility
128 */
129 public function init() {
130 // Setting GPvars:
131 $this->cmLevel = intval(GeneralUtility::_GP('cmLevel'));
132 $this->CB = GeneralUtility::_GP('CB');
133 if (GeneralUtility::_GP('ajax')) {
134 $this->ajax = 1;
135 // XML has to be parsed, no parse errors allowed
136 @ini_set('display_errors', 0);
137 }
138 // Deal with Drag&Drop context menus
139 if (strcmp(GeneralUtility::_GP('dragDrop'), '')) {
140 $CMcontent = $this->printDragDropClickMenu(GeneralUtility::_GP('dragDrop'), GeneralUtility::_GP('srcId'), GeneralUtility::_GP('dstId'));
141 return $CMcontent;
142 }
143 // Can be set differently as well
144 $this->iParts[0] = GeneralUtility::_GP('table');
145 $this->iParts[1] = GeneralUtility::_GP('uid');
146 $this->iParts[2] = GeneralUtility::_GP('listFr');
147 $this->iParts[3] = GeneralUtility::_GP('enDisItems');
148 // Setting flags:
149 if ($this->iParts[2]) {
150 $this->listFrame = 1;
151 }
152 if ($GLOBALS['BE_USER']->uc['condensedMode'] || $this->iParts[2] == 2) {
153 $this->alwaysContentFrame = 1;
154 }
155 if (strcmp($this->iParts[1], '')) {
156 $this->isDBmenu = 1;
157 }
158 $TSkey = ($this->isDBmenu ? 'page' : 'folder') . ($this->listFrame ? 'List' : 'Tree');
159 $this->disabledItems = GeneralUtility::trimExplode(',', $GLOBALS['BE_USER']->getTSConfigVal(('options.contextMenu.' . $TSkey) . '.disableItems'), 1);
160 $this->leftIcons = $GLOBALS['BE_USER']->getTSConfigVal('options.contextMenu.options.leftIcons');
161 // &cmLevel flag detected (2nd level menu)
162 if (!$this->cmLevel) {
163 // Make 1st level clickmenu:
164 if ($this->isDBmenu) {
165 $CMcontent = $this->printDBClickMenu($this->iParts[0], $this->iParts[1]);
166 } else {
167 $CMcontent = $this->printFileClickMenu($this->iParts[0]);
168 }
169 } else {
170 // Make 2nd level clickmenu (only for DBmenus)
171 if ($this->isDBmenu) {
172 $CMcontent = $this->printNewDBLevel($this->iParts[0], $this->iParts[1]);
173 }
174 }
175 // Return clickmenu content:
176 return $CMcontent;
177 }
178
179 /**
180 * Returns TRUE if the menu should (also?) be displayed in topframe, not just <div>-layers
181 *
182 * @return boolean
183 * @todo Define visibility
184 */
185 public function doDisplayTopFrameCM() {
186 if ($this->ajax) {
187 return FALSE;
188 } else {
189 return !$GLOBALS['SOBE']->doc->isCMlayers() || !$this->dontDisplayTopFrameCM;
190 }
191 }
192
193 /***************************************
194 *
195 * DATABASE
196 *
197 ***************************************/
198 /**
199 * Make 1st level clickmenu:
200 *
201 * @param string $table Table name
202 * @param integer $uid UID for the current record.
203 * @return string HTML content
204 * @todo Define visibility
205 */
206 public function printDBClickMenu($table, $uid) {
207 // Get record:
208 $this->rec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL($table, $uid);
209 $menuItems = array();
210 $root = 0;
211 $DBmount = FALSE;
212 // Rootlevel
213 if ($table == 'pages' && !strcmp($uid, '0')) {
214 $root = 1;
215 }
216 // DB mount
217 if ($table == 'pages' && in_array($uid, $GLOBALS['BE_USER']->returnWebmounts())) {
218 $DBmount = TRUE;
219 }
220 // Used to hide cut,copy icons for l10n-records
221 $l10nOverlay = FALSE;
222 // Should only be performed for overlay-records within the same table
223 if (\TYPO3\CMS\Backend\Utility\BackendUtility::isTableLocalizable($table) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
224 $l10nOverlay = intval($this->rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]) != 0;
225 }
226 // If record found (or root), go ahead and fill the $menuItems array which will contain data for the elements to render.
227 if (is_array($this->rec) || $root) {
228 // Get permissions
229 $lCP = $GLOBALS['BE_USER']->calcPerms(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $table == 'pages' ? $this->rec['uid'] : $this->rec['pid']));
230 // View
231 if (!in_array('view', $this->disabledItems)) {
232 if ($table == 'pages') {
233 $menuItems['view'] = $this->DB_view($uid);
234 }
235 if ($table == $GLOBALS['TYPO3_CONF_VARS']['SYS']['contentTable']) {
236 $ws_rec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL($table, $this->rec['uid']);
237 $menuItems['view'] = $this->DB_view($ws_rec['pid']);
238 }
239 }
240 // Edit:
241 if (!$root && ($GLOBALS['BE_USER']->isPSet($lCP, $table, 'edit') || $GLOBALS['BE_USER']->isPSet($lCP, $table, 'editcontent'))) {
242 if (!in_array('edit', $this->disabledItems)) {
243 $menuItems['edit'] = $this->DB_edit($table, $uid);
244 }
245 $this->editOK = 1;
246 }
247 // New:
248 if (!in_array('new', $this->disabledItems) && $GLOBALS['BE_USER']->isPSet($lCP, $table, 'new')) {
249 $menuItems['new'] = $this->DB_new($table, $uid);
250 }
251 // Info:
252 if (!in_array('info', $this->disabledItems) && !$root) {
253 $menuItems['info'] = $this->DB_info($table, $uid);
254 }
255 $menuItems['spacer1'] = 'spacer';
256 // Copy:
257 if (((!in_array('copy', $this->disabledItems) && !$root) && !$DBmount) && !$l10nOverlay) {
258 $menuItems['copy'] = $this->DB_copycut($table, $uid, 'copy');
259 }
260 // Cut:
261 if (((!in_array('cut', $this->disabledItems) && !$root) && !$DBmount) && !$l10nOverlay) {
262 $menuItems['cut'] = $this->DB_copycut($table, $uid, 'cut');
263 }
264 // Paste:
265 $elFromAllTables = count($this->clipObj->elFromTable(''));
266 if (!in_array('paste', $this->disabledItems) && $elFromAllTables) {
267 $selItem = $this->clipObj->getSelectedRecord();
268 $elInfo = array(
269 GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $GLOBALS['BE_USER']->uc['titleLen']),
270 $root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec), $GLOBALS['BE_USER']->uc['titleLen']),
271 $this->clipObj->currentMode()
272 );
273 if ($table == 'pages' && $lCP & 8) {
274 if ($elFromAllTables) {
275 $menuItems['pasteinto'] = $this->DB_paste('', $uid, 'into', $elInfo);
276 }
277 }
278 $elFromTable = count($this->clipObj->elFromTable($table));
279 if (((!$root && !$DBmount) && $elFromTable) && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
280 $menuItems['pasteafter'] = $this->DB_paste($table, -$uid, 'after', $elInfo);
281 }
282 }
283 // Delete:
284 $elInfo = array(GeneralUtility::fixed_lgd_cs(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec), $GLOBALS['BE_USER']->uc['titleLen']));
285 if (((!in_array('delete', $this->disabledItems) && !$root) && !$DBmount) && $GLOBALS['BE_USER']->isPSet($lCP, $table, 'delete')) {
286 $menuItems['spacer2'] = 'spacer';
287 $menuItems['delete'] = $this->DB_delete($table, $uid, $elInfo);
288 }
289 if (!in_array('history', $this->disabledItems)) {
290 $menuItems['history'] = $this->DB_history($table, $uid, $elInfo);
291 }
292 }
293 // Adding external elements to the menuItems array
294 $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
295 // Processing by external functions?
296 $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
297 if (!is_array($this->rec)) {
298 $this->rec = array();
299 }
300 // Return the printed elements:
301 return $this->printItems($menuItems, $root ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-pagetree-root') . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) : \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => htmlspecialchars(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordIconAltText($this->rec, $table)))) . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec, TRUE));
302 }
303
304 /**
305 * Make 2nd level clickmenu (only for DBmenus)
306 *
307 * @param string $table Table name
308 * @param integer $uid UID for the current record.
309 * @return string HTML content
310 * @todo Define visibility
311 */
312 public function printNewDBLevel($table, $uid) {
313 // Setting internal record to the table/uid :
314 $this->rec = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL($table, $uid);
315 $menuItems = array();
316 $root = 0;
317 // Rootlevel
318 if ($table == 'pages' && !strcmp($uid, '0')) {
319 $root = 1;
320 }
321 // If record was found, check permissions and get menu items.
322 if (is_array($this->rec) || $root) {
323 $lCP = $GLOBALS['BE_USER']->calcPerms(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $table == 'pages' ? $this->rec['uid'] : $this->rec['pid']));
324 // Edit:
325 if (!$root && ($GLOBALS['BE_USER']->isPSet($lCP, $table, 'edit') || $GLOBALS['BE_USER']->isPSet($lCP, $table, 'editcontent'))) {
326 $this->editOK = 1;
327 }
328 $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
329 }
330 // Return the printed elements:
331 if (!is_array($menuItems)) {
332 $menuItems = array();
333 }
334 return $this->printItems($menuItems, $root ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-pagetree-root') . htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) : \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => htmlspecialchars(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordIconAltText($this->rec, $table)))) . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec, TRUE));
335 }
336
337 /**
338 * Processing the $menuItems array (for extension classes) (DATABASE RECORDS)
339 *
340 * @param array $menuItems Array for manipulation.
341 * @return array Processed $menuItems array
342 * @todo Define visibility
343 */
344 public function externalProcessingOfDBMenuItems($menuItems) {
345 return $menuItems;
346 }
347
348 /**
349 * Processing the $menuItems array by external classes (typ. adding items)
350 *
351 * @param array $menuItems Array for manipulation.
352 * @param string $table Table name
353 * @param integer $uid UID for the current record.
354 * @return array Processed $menuItems array
355 * @todo Define visibility
356 */
357 public function processingByExtClassArray($menuItems, $table, $uid) {
358 if (is_array($this->extClassArray)) {
359 foreach ($this->extClassArray as $conf) {
360 $obj = GeneralUtility::makeInstance($conf['name']);
361 $menuItems = $obj->main($this, $menuItems, $table, $uid);
362 }
363 }
364 return $menuItems;
365 }
366
367 /**
368 * Returning JavaScript for the onClick event linking to the input URL.
369 *
370 * @param string $url The URL relative to TYPO3_mainDir
371 * @param string $retUrl The return_url-parameter
372 * @param boolean $hideCM If set, the "hideCM()" will be called
373 * @param string $overrideLoc If set, gives alternative location to load in (for example top frame or somewhere else)
374 * @return string JavaScript for an onClick event.
375 * @todo Define visibility
376 */
377 public function urlRefForCM($url, $retUrl = '', $hideCM = 1, $overrideLoc = '') {
378 $loc = 'top.content.list_frame';
379 $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();' : '');
380 return $editOnClick;
381 }
382
383 /**
384 * Adding CM element for Clipboard "copy" and "cut"
385 *
386 * @param string $table Table name
387 * @param integer $uid UID for the current record.
388 * @param string $type Type: "copy" or "cut
389 * @return array Item array, element in $menuItems
390 * @internal
391 * @todo Define visibility
392 */
393 public function DB_copycut($table, $uid, $type) {
394 if ($this->clipObj->current == 'normal') {
395 $isSel = $this->clipObj->isSelected($table, $uid);
396 }
397 $addParam = array();
398 if ($this->listFrame) {
399 $addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
400 }
401 return $this->linkItem($this->label($type), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-edit-' . $type) . ($isSel === $type ? '-release' : ''))), ('top.loadTopMenu(\'' . $this->clipObj->selUrlDB($table, $uid, ($type == 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . '\');return false;');
402 }
403
404 /**
405 * Adding CM element for Clipboard "paste into"/"paste after"
406 * NOTICE: $table and $uid should follow the special syntax for paste, see clipboard-class :: pasteUrl();
407 *
408 * @param string $table Table name
409 * @param integer $uid UID for the current record. NOTICE: Special syntax!
410 * @param string $type Type: "into" or "after
411 * @param array $elInfo Contains instructions about whether to copy or cut an element.
412 * @return array Item array, element in $menuItems
413 * @see t3lib_clipboard::pasteUrl()
414 * @internal
415 * @todo Define visibility
416 */
417 public function DB_paste($table, $uid, $type, $elInfo) {
418 $editOnClick = '';
419 $loc = 'top.content.list_frame';
420 if ($GLOBALS['BE_USER']->jsConfirmation(2)) {
421 $conf = (($loc . ' && confirm(') . $GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->sL(((('LLL:EXT:lang/locallang_core.php:mess.' . ($elInfo[2] == 'copy' ? 'copy' : 'move')) . '_') . $type)), $elInfo[0], $elInfo[1]))) . ')';
422 } else {
423 $conf = $loc;
424 }
425 $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();}';
426 return $this->linkItem($this->label('paste' . $type), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-paste-' . $type)), $editOnClick . 'return false;');
427 }
428
429 /**
430 * Adding CM element for Info
431 *
432 * @param string $table Table name
433 * @param integer $uid UID for the current record.
434 * @return array Item array, element in $menuItems
435 * @internal
436 * @todo Define visibility
437 */
438 public function DB_info($table, $uid) {
439 return $this->linkItem($this->label('info'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-info')), ((('top.launchView(\'' . $table) . '\', \'') . $uid) . '\'); return hideCM();');
440 }
441
442 /**
443 * Adding CM element for History
444 *
445 * @param string $table Table name
446 * @param integer $uid UID for the current record.
447 * @return array Item array, element in $menuItems
448 * @internal
449 * @todo Define visibility
450 */
451 public function DB_history($table, $uid) {
452 $url = 'show_rechis.php?element=' . rawurlencode((($table . ':') . $uid));
453 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_history')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-history-open')), $this->urlRefForCM($url, 'returnUrl'), 0);
454 }
455
456 /**
457 * Adding CM element for Permission setting
458 *
459 * @param string $table Table name
460 * @param integer $uid UID for the current record.
461 * @param array $rec The "pages" record with "perms_*" fields inside.
462 * @return array Item array, element in $menuItems
463 * @internal
464 * @todo Define visibility
465 */
466 public function DB_perms($table, $uid, $rec) {
467 if (!\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('perm')) {
468 return '';
469 }
470 $url = ((\TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath('perm') . 'mod1/index.php?id=') . $uid) . ($rec['perms_userid'] == $GLOBALS['BE_USER']->user['uid'] || $GLOBALS['BE_USER']->isAdmin() ? ('&return_id=' . $uid) . '&edit=1' : '');
471 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_perms')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-locked')), $this->urlRefForCM($url), 0);
472 }
473
474 /**
475 * Adding CM element for DBlist
476 *
477 * @param string $table Table name
478 * @param integer $uid UID for the current record.
479 * @param array $rec Record of the element (needs "pid" field if not pages-record)
480 * @return array Item array, element in $menuItems
481 * @internal
482 * @todo Define visibility
483 */
484 public function DB_db_list($table, $uid, $rec) {
485 $urlParams = array();
486 $urlParams['id'] = $table == 'pages' ? $uid : $rec['pid'];
487 $urlParams['table'] = $table == 'pages' ? '' : $table;
488 $url = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('web_list', $urlParams, '', TRUE);
489 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_db_list')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-system-list-open')), ('top.nextLoadModuleUrl=\'' . $url) . '\';top.goToModule(\'web_list\', 1);', 0);
490 }
491
492 /**
493 * Adding CM element for Moving wizard
494 *
495 * @param string $table Table name
496 * @param integer $uid UID for the current record.
497 * @param array $rec Record. Needed for tt-content elements which will have the sys_language_uid sent
498 * @return array Item array, element in $menuItems
499 * @internal
500 * @todo Define visibility
501 */
502 public function DB_moveWizard($table, $uid, $rec) {
503 // Hardcoded field for tt_content elements.
504 $url = ((('move_el.php?table=' . $table) . '&uid=') . $uid) . ($table == 'tt_content' ? '&sys_language_uid=' . intval($rec['sys_language_uid']) : '');
505 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_moveWizard' . ($table == 'pages' ? '_page' : ''))), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-' . ($table === 'pages' ? 'page' : 'document')) . '-move')), $this->urlRefForCM($url, 'returnUrl'), 0);
506 }
507
508 /**
509 * Adding CM element for Create new wizard (either db_new.php or sysext/cms/layout/db_new_content_el.php or custom wizard)
510 *
511 * @param string $table Table name
512 * @param integer $uid UID for the current record.
513 * @param array $rec Record.
514 * @return array Item array, element in $menuItems
515 * @internal
516 * @todo Define visibility
517 */
518 public function DB_newWizard($table, $uid, $rec) {
519 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead:
520 $tmpTSc = \TYPO3\CMS\Backend\Utility\BackendUtility::getModTSconfig($this->pageinfo['uid'], 'mod.web_list');
521 $tmpTSc = $tmpTSc['properties']['newContentWiz.']['overrideWithExtension'];
522 $newContentWizScriptPath = \TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($tmpTSc) ? \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($tmpTSc) . 'mod1/db_new_content_el.php' : 'sysext/cms/layout/db_new_content_el.php';
523 $url = $table == 'pages' || !\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('cms') ? ('db_new.php?id=' . $uid) . '&pagesOnly=1' : ((($newContentWizScriptPath . '?id=') . $rec['pid']) . '&sys_language_uid=') . intval($rec['sys_language_uid']);
524 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_newWizard')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-' . ($table === 'pages' ? 'page' : 'document')) . '-new')), $this->urlRefForCM($url, 'returnUrl'), 0);
525 }
526
527 /**
528 * Adding CM element for Editing of the access related fields of a table (disable, starttime, endtime, fe_groups)
529 *
530 * @param string $table Table name
531 * @param integer $uid UID for the current record.
532 * @return array Item array, element in $menuItems
533 * @internal
534 * @todo Define visibility
535 */
536 public function DB_editAccess($table, $uid) {
537 $addParam = '&columnsOnly=' . rawurlencode((implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table == 'pages' ? ',extendToSubpages' : '')));
538 $url = (((('alt_doc.php?edit[' . $table) . '][') . $uid) . ']=edit') . $addParam;
539 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_editAccess')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-edit-access')), $this->urlRefForCM($url, 'returnUrl'), 1);
540 }
541
542 /**
543 * Adding CM element for edit page properties
544 *
545 * @param integer $uid page uid to edit (PID)
546 * @return array Item array, element in $menuItems
547 * @internal
548 * @todo Define visibility
549 */
550 public function DB_editPageProperties($uid) {
551 $url = ('alt_doc.php?edit[pages][' . $uid) . ']=edit';
552 return $this->linkItem($GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->getLL('CM_editPageProperties')), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-page-open')), $this->urlRefForCM($url, 'returnUrl'), 1);
553 }
554
555 /**
556 * Adding CM element for regular editing of the element!
557 *
558 * @param string $table Table name
559 * @param integer $uid UID for the current record.
560 * @return array Item array, element in $menuItems
561 * @internal
562 * @todo Define visibility
563 */
564 public function DB_edit($table, $uid) {
565 // If another module was specified, replace the default Page module with the new one
566 $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule'));
567 $pageModule = \TYPO3\CMS\Backend\Utility\BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
568 $editOnClick = '';
569 $loc = 'top.content.list_frame';
570 $addParam = '';
571 $theIcon = 'actions-document-open';
572 if (($this->iParts[0] == 'pages' && $this->iParts[1]) && $GLOBALS['BE_USER']->check('modules', $pageModule)) {
573 $theIcon = 'actions-page-open';
574 $this->editPageIconSet = 1;
575 if ($GLOBALS['BE_USER']->uc['classicPageEditMode'] || !\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('cms')) {
576 $addParam = '&editRegularContentFromId=' . intval($this->iParts[1]);
577 } else {
578 $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) . '\';}';
579 }
580 }
581 if (!$editOnClick) {
582 $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) . '\';}';
583 }
584 return $this->linkItem($this->label('edit'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon($theIcon)), $editOnClick . 'return hideCM();');
585 }
586
587 /**
588 * Adding CM element for regular Create new element
589 *
590 * @param string $table Table name
591 * @param integer $uid UID for the current record.
592 * @return array Item array, element in $menuItems
593 * @internal
594 * @todo Define visibility
595 */
596 public function DB_new($table, $uid) {
597 $editOnClick = '';
598 $loc = 'top.content.list_frame';
599 $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=' . intval($uid)) . '\'')) . ';}';
600 return $this->linkItem($this->label('new'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-' . ($table === 'pages' ? 'page' : 'document')) . '-new')), $editOnClick . 'return hideCM();');
601 }
602
603 /**
604 * Adding CM element for Delete
605 *
606 * @param string $table Table name
607 * @param integer $uid UID for the current record.
608 * @param array $elInfo Label for including in the confirmation message, EXT:lang/locallang_core.php:mess.delete
609 * @return array Item array, element in $menuItems
610 * @internal
611 * @todo Define visibility
612 */
613 public function DB_delete($table, $uid, $elInfo) {
614 $editOnClick = '';
615 $loc = 'top.content.list_frame';
616 if ($GLOBALS['BE_USER']->jsConfirmation(4)) {
617 $conf = ('confirm(' . $GLOBALS['LANG']->JScharCode(((sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.delete'), $elInfo[0]) . \TYPO3\CMS\Backend\Utility\BackendUtility::referenceCount($table, $uid, ' (There are %s reference(s) to this record!)')) . \TYPO3\CMS\Backend\Utility\BackendUtility::translationCount($table, $uid, (' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.translationsOfRecord')))))) . ')';
618 } else {
619 $conf = '1==1';
620 }
621 $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()) . \TYPO3\CMS\Backend\Utility\BackendUtility::getUrlToken('tceAction')) . '\';}hideCM();top.nav.refresh.defer(500, top.nav);';
622 return $this->linkItem($this->label('delete'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete')), $editOnClick . 'return false;');
623 }
624
625 /**
626 * Adding CM element for View Page
627 *
628 * @param integer $id Page uid (PID)
629 * @param string $anchor Anchor, if any
630 * @return array Item array, element in $menuItems
631 * @internal
632 * @todo Define visibility
633 */
634 public function DB_view($id, $anchor = '') {
635 return $this->linkItem($this->label('view'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-view')), \TYPO3\CMS\Backend\Utility\BackendUtility::viewOnClick($id, $this->PH_backPath, \TYPO3\CMS\Backend\Utility\BackendUtility::BEgetRootLine($id), $anchor) . 'return hideCM();');
636 }
637
638 /**
639 * Adding element for setting temporary mount point.
640 *
641 * @param integer $page_id Page uid (PID)
642 * @return array Item array, element in $menuItems
643 * @internal
644 * @todo Define visibility
645 */
646 public function DB_tempMountPoint($page_id) {
647 return $this->linkItem($this->label('tempMountPoint'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-pagetree-page-mountpoint')), ('if (top.content.nav_frame) {
648 var node = top.TYPO3.Backend.NavigationContainer.PageTree.getSelected();
649 if (node === null) {
650 return false;
651 }
652
653 var useNode = {
654 attributes: {
655 nodeData: {
656 id: ' . intval($page_id)) . '
657 }
658 }
659 };
660
661 node.ownerTree.commandProvider.mountAsTreeRoot(useNode, node.ownerTree);
662 }
663 return hideCM();
664 ');
665 }
666
667 /**
668 * Adding CM element for hide/unhide of the input record
669 *
670 * @param string $table Table name
671 * @param array $rec Record array
672 * @param string $hideField Name of the hide field
673 * @return array Item array, element in $menuItems
674 * @internal
675 * @todo Define visibility
676 */
677 public function DB_hideUnhide($table, $rec, $hideField) {
678 return $this->DB_changeFlag($table, $rec, $hideField, $this->label(($rec[$hideField] ? 'un' : '') . 'hide'), 'hide');
679 }
680
681 /**
682 * Adding CM element for a flag field of the input record
683 *
684 * @param string $table Table name
685 * @param array $rec Record array
686 * @param string $flagField Name of the flag field
687 * @param string $title Menu item Title
688 * @param string $name Name of the item used for icons and labels
689 * @param string $iconRelPath Icon path relative to typo3/ folder
690 * @return array Item array, element in $menuItems
691 * @todo Define visibility
692 */
693 public function DB_changeFlag($table, $rec, $flagField, $title, $name, $iconRelPath = 'gfx/') {
694 $uid = $rec['_ORIG_uid'] ? $rec['_ORIG_uid'] : $rec['uid'];
695 $editOnClick = '';
696 $loc = 'top.content.list_frame';
697 $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()) . \TYPO3\CMS\Backend\Utility\BackendUtility::getUrlToken('tceAction')) . '\';}hideCM();top.nav.refresh.defer(500, top.nav);';
698 return $this->linkItem($title, $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-edit-' . ($rec[$flagField] ? 'un' : '')) . 'hide')), $editOnClick . 'return false;', 1);
699 }
700
701 /***************************************
702 *
703 * FILE
704 *
705 ***************************************/
706 /**
707 * Make 1st level clickmenu:
708 *
709 * @param string $combinedIdentifier The combined identifier
710 * @return string HTML content
711 * @see \TYPO3\CMS\Core\Resource\ResourceFactory::retrieveFileOrFolderObject()
712 * @todo Define visibility
713 */
714 public function printFileClickMenu($combinedIdentifier) {
715 $menuItems = array();
716 $combinedIdentifier = rawurldecode($combinedIdentifier);
717 $fileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()
718 ->retrieveFileOrFolderObject($combinedIdentifier);
719 if ($fileObject) {
720 $folder = FALSE;
721 $identifier = $fileObject->getCombinedIdentifier();
722 if ($fileObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
723 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForFile('folder', array(
724 'class' => 'absmiddle',
725 'title' => htmlspecialchars($fileObject->getName())
726 ));
727 $folder = TRUE;
728 } else {
729 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForFile($fileObject->getExtension(), array(
730 'class' => 'absmiddle',
731 'title' => htmlspecialchars((($fileObject->getName() . ' (') . GeneralUtility::formatSize($fileObject->getSize())) . ')')
732 ));
733 }
734 // Edit
735 if ((!in_array('edit', $this->disabledItems) && !$folder) && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $fileObject->getExtension())) {
736 $menuItems['edit'] = $this->FILE_launch($identifier, 'file_edit.php', 'edit', 'edit_file.gif');
737 }
738 // Rename
739 if (!in_array('rename', $this->disabledItems)) {
740 $menuItems['rename'] = $this->FILE_launch($identifier, 'file_rename.php', 'rename', 'rename.gif');
741 }
742 // Upload
743 if (!in_array('upload', $this->disabledItems) && $folder) {
744 $menuItems['upload'] = $this->FILE_upload($identifier);
745 }
746 // New
747 if (!in_array('new', $this->disabledItems) && $folder) {
748 $menuItems['new'] = $this->FILE_launch($identifier, 'file_newfolder.php', 'new', 'new_file.gif');
749 }
750 // Info
751 if (!in_array('info', $this->disabledItems)) {
752 $menuItems['info'] = $this->DB_info($identifier, '');
753 }
754 $menuItems[] = 'spacer';
755 // Copy:
756 if (!in_array('copy', $this->disabledItems)) {
757 $menuItems['copy'] = $this->FILE_copycut($identifier, 'copy');
758 }
759 // Cut:
760 if (!in_array('cut', $this->disabledItems)) {
761 $menuItems['cut'] = $this->FILE_copycut($identifier, 'cut');
762 }
763 // Paste:
764 $elFromAllTables = count($this->clipObj->elFromTable('_FILE'));
765 if ((!in_array('paste', $this->disabledItems) && $elFromAllTables) && $folder) {
766 $elArr = $this->clipObj->elFromTable('_FILE');
767 $selItem = reset($elArr);
768 $elInfo = array(
769 basename($selItem),
770 basename($path),
771 $this->clipObj->currentMode()
772 );
773 $menuItems['pasteinto'] = $this->FILE_paste($identifier, $selItem, $elInfo);
774 }
775 $menuItems[] = 'spacer';
776 // Delete:
777 if (!in_array('delete', $this->disabledItems)) {
778 $menuItems['delete'] = $this->FILE_delete($identifier);
779 }
780 }
781 // Adding external elements to the menuItems array
782 $menuItems = $this->processingByExtClassArray($menuItems, $identifier, 0);
783 // Processing by external functions?
784 $menuItems = $this->externalProcessingOfFileMenuItems($menuItems);
785 // Return the printed elements:
786 return $this->printItems($menuItems, $icon . $fileObject->getName());
787 }
788
789 /**
790 * Processing the $menuItems array (for extension classes) (FILES)
791 *
792 * @param array $menuItems Array for manipulation.
793 * @return array Processed $menuItems array
794 * @todo Define visibility
795 */
796 public function externalProcessingOfFileMenuItems($menuItems) {
797 return $menuItems;
798 }
799
800 /**
801 * Multi-function for adding an entry to the $menuItems array
802 *
803 * @param string $path Path to the file/directory (target)
804 * @param string $script Script (eg. file_edit.php) to pass &target= to
805 * @param string $type "type" is the code which fetches the correct label for the element from "cm.
806 * @param string $image icon image-filename from "gfx/" (12x12 icon)
807 * @param boolean $noReturnUrl If set, the return URL parameter will not be set in the link
808 * @return array Item array, element in $menuItems
809 * @internal
810 * @todo Define visibility
811 */
812 public function FILE_launch($path, $script, $type, $image, $noReturnUrl = FALSE) {
813 $loc = 'top.content.list_frame';
814 $editOnClick = (((((((('if(' . $loc) . '){') . $loc) . '.location.href=top.TS.PATH_typo3+\'') . $script) . '?target=') . rawurlencode($path)) . ($noReturnUrl ? '\'' : ((('&returnUrl=\'+top.rawurlencode(' . $this->frameLocation(($loc . '.document'))) . '.pathname+') . $this->frameLocation(($loc . '.document'))) . '.search)')) . ';}';
815 return $this->linkItem($this->label($type), $this->excludeIcon(('<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->PH_backPath, ('gfx/' . $image), 'width="12" height="12"')) . ' alt="" />'), $editOnClick . 'top.nav.refresh();return hideCM();');
816 }
817
818 /**
819 * function for adding an upload entry to the $menuItems array
820 *
821 * @param string $path Path to the file/directory (target)
822 * @return array Item array, element in $menuItems
823 * @internal
824 * @todo Define visibility
825 */
826 public function FILE_upload($path) {
827 $script = 'file_upload.php';
828 $type = 'upload';
829 $image = 'upload.gif';
830 if ($GLOBALS['BE_USER']->uc['enableFlashUploader']) {
831 $loc = 'top.content.list_frame';
832 $editOnClick = ((((((((('if (top.TYPO3.FileUploadWindow.isFlashAvailable()) { initFlashUploader("' . rawurlencode($path)) . '"); } else if(') . $loc) . '){') . $loc) . '.location.href=top.TS.PATH_typo3+\'') . $script) . '?target=') . rawurlencode($path)) . '\';}';
833 return $this->linkItem($this->label($type), $this->excludeIcon(('<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->PH_backPath, ('gfx/' . $image), 'width="12" height="12"')) . ' alt="" />'), $editOnClick . 'return hideCM();');
834 } else {
835 return $this->FILE_launch($path, $script, $type, $image, TRUE);
836 }
837 }
838
839 /**
840 * Returns element for copy or cut of files.
841 *
842 * @param string $path Path to the file/directory (target)
843 * @param string $type Type: "copy" or "cut
844 * @return array Item array, element in $menuItems
845 * @internal
846 * @todo Define visibility
847 */
848 public function FILE_copycut($path, $type) {
849 // Pseudo table name for use in the clipboard.
850 $table = '_FILE';
851 $uid = GeneralUtility::shortmd5($path);
852 if ($this->clipObj->current == 'normal') {
853 $isSel = $this->clipObj->isSelected($table, $uid);
854 }
855 $addParam = array();
856 if ($this->listFrame) {
857 $addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
858 }
859 return $this->linkItem($this->label($type), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon(('actions-edit-' . $type) . ($isSel === $type ? '-release' : ''))), ('top.loadTopMenu(\'' . $this->clipObj->selUrlFile($path, ($type == 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . '\');return false;');
860 }
861
862 /**
863 * Creates element for deleting of target
864 *
865 * @param string $path Path to the file/directory (target)
866 * @return array Item array, element in $menuItems
867 * @internal
868 * @todo Define visibility
869 */
870 public function FILE_delete($path) {
871 $editOnClick = '';
872 $loc = 'top.content.list_frame';
873 if ($GLOBALS['BE_USER']->jsConfirmation(4)) {
874 $conf = ('confirm(' . $GLOBALS['LANG']->JScharCode((sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.delete'), basename($path)) . \TYPO3\CMS\Backend\Utility\BackendUtility::referenceCount('_FILE', $path, ' (There are %s reference(s) to this file!)')))) . ')';
875 } else {
876 $conf = '1==1';
877 }
878 $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()) . '\';}hideCM();';
879 return $this->linkItem($this->label('delete'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete')), $editOnClick . 'return false;');
880 }
881
882 /**
883 * Creates element for pasting files.
884 *
885 * @param string $path Path to the file/directory (target)
886 * @param string $target target - NOT USED.
887 * @param array $elInfo Various values for the labels.
888 * @return array Item array, element in $menuItems
889 * @internal
890 * @todo Define visibility
891 */
892 public function FILE_paste($path, $target, $elInfo) {
893 $editOnClick = '';
894 $loc = 'top.content.list_frame';
895 if ($GLOBALS['BE_USER']->jsConfirmation(2)) {
896 $conf = (($loc . ' && confirm(') . $GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->sL((('LLL:EXT:lang/locallang_core.php:mess.' . ($elInfo[2] == 'copy' ? 'copy' : 'move')) . '_into')), $elInfo[0], $elInfo[1]))) . ')';
897 } else {
898 $conf = $loc;
899 }
900 $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();';
901 return $this->linkItem($this->label('pasteinto'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-paste-into')), $editOnClick . 'return false;');
902 }
903
904 /***************************************
905 *
906 * DRAG AND DROP
907 *
908 ***************************************/
909 /**
910 * Make 1st level clickmenu:
911 *
912 * @param string $table The absolute path
913 * @param integer $srcId UID for the current record.
914 * @param integer $dstId Destination ID
915 * @return string HTML content
916 * @todo Define visibility
917 */
918 public function printDragDropClickMenu($table, $srcId, $dstId) {
919 $menuItems = array();
920 // If the drag and drop menu should apply to PAGES use this set of menu items
921 if ($table == 'pages') {
922 // Move Into:
923 $menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into');
924 // Move After:
925 $menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after');
926 // Copy Into:
927 $menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into');
928 // Copy After:
929 $menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after');
930 }
931 // If the drag and drop menu should apply to FOLDERS use this set of menu items
932 if ($table == 'folders') {
933 // Move Into:
934 $menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move');
935 // Copy Into:
936 $menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy');
937 }
938 // Adding external elements to the menuItems array
939 $menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId);
940 // to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar
941 // Processing by external functions?
942 $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
943 // Return the printed elements:
944 return $this->printItems($menuItems, \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $this->rec, array('title' => \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $this->rec, TRUE))));
945 }
946
947 /**
948 * Processing the $menuItems array (for extension classes) (DRAG'N DROP)
949 *
950 * @param array $menuItems Array for manipulation.
951 * @return array Processed $menuItems array
952 * @todo Define visibility
953 */
954 public function externalProcessingOfDragDropMenuItems($menuItems) {
955 return $menuItems;
956 }
957
958 /**
959 * Adding CM element for Copying/Moving a Page Into/After from a drag & drop action
960 *
961 * @param integer $srcUid source UID code for the record to modify
962 * @param integer $dstUid destination UID code for the record to modify
963 * @param string $action Action code: either "move" or "copy
964 * @param string $into Parameter code: either "into" or "after
965 * @return array Item array, element in $menuItems
966 * @internal
967 * @todo Define visibility
968 */
969 public function dragDrop_copymovepage($srcUid, $dstUid, $action, $into) {
970 $negativeSign = $into == 'into' ? '' : '-';
971 $editOnClick = '';
972 $loc = 'top.content.list_frame';
973 $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()) . \TYPO3\CMS\Backend\Utility\BackendUtility::getUrlToken('tceAction')) . '";}hideCM();top.nav.refresh();';
974 return $this->linkItem($this->label(($action . 'Page_') . $into), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-paste-' . $into)), $editOnClick . 'return false;', 0);
975 }
976
977 /**
978 * Adding CM element for Copying/Moving a Folder Into from a drag & drop action
979 *
980 * @param string $srcPath source path for the record to modify
981 * @param string $dstPath destination path for the records to modify
982 * @param string $action Action code: either "move" or "copy
983 * @return array Item array, element in $menuItems
984 * @internal
985 * @todo Define visibility
986 */
987 public function dragDrop_copymovefolder($srcPath, $dstPath, $action) {
988 $editOnClick = '';
989 $loc = 'top.content.list_frame';
990 $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()) . '";}hideCM();top.nav.refresh();';
991 return $this->linkItem($this->label($action . 'Folder_into'), $this->excludeIcon(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-pagetree-drag-move-into')), $editOnClick . 'return false;', 0);
992 }
993
994 /***************************************
995 *
996 * COMMON
997 *
998 **************************************/
999 /**
1000 * Prints the items from input $menuItems array - both as topframe menu AND the JS section for writing to the div-layers.
1001 * Of course the topframe menu will appear only if $this->doDisplayTopFrameCM() returns TRUE
1002 *
1003 * @param array $menuItems Array
1004 * @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.
1005 * @return string HTML code
1006 * @todo Define visibility
1007 */
1008 public function printItems($menuItems, $item) {
1009 $out = '';
1010 // Enable/Disable items:
1011 $menuItems = $this->enableDisableItems($menuItems);
1012 // Clean up spacers:
1013 $menuItems = $this->cleanUpSpacers($menuItems);
1014 // Adding topframe part (horizontal clickmenu)
1015 if ($this->doDisplayTopFrameCM()) {
1016 $out .= ((((('
1017
1018 <!--
1019 Table, which contains the click menu when shown in the top frame of the backend:
1020 -->
1021 <table border="0" cellpadding="0" cellspacing="0" id="typo3-CSM-top">
1022 <tr>
1023
1024 <!-- Items: -->
1025 <td class="c-item">' . implode((('</td>
1026 <td><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->PH_backPath, 'gfx/acm_spacer2.gif', 'width="8" height="12"')) . ' alt="" /></td>
1027 <td class="c-item">'), $this->menuItemsForTopFrame($menuItems))) . '</td>
1028
1029 <!-- Close button: -->
1030 <td class="c-closebutton"><a href="#" onclick="hideCM();return false;">') . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-close', array(
1031 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.close', 1)
1032 ))) . '</a></td>
1033
1034 <!-- The item of the clickmenu: -->
1035 <td class="c-itemicon">') . $item) . '</td>
1036 </tr>
1037 </table>
1038 ';
1039 // Set remaining BACK_PATH to blank (if any)
1040 $out = str_replace($this->PH_backPath, '', $out);
1041 }
1042 // Adding JS part:
1043 $out .= $this->printLayerJScode($menuItems);
1044 // Return the content
1045 return $out;
1046 }
1047
1048 /**
1049 * Create the JavaScript section
1050 *
1051 * @param array $menuItems The $menuItems array to print
1052 * @return string The JavaScript section which will print the content of the CM to the div-layer in the target frame.
1053 * @todo Define visibility
1054 */
1055 public function printLayerJScode($menuItems) {
1056 $script = '';
1057 // Clipboard must not be submitted - then it's probably a copy/cut situation.
1058 if ($this->isCMlayers()) {
1059 $frameName = '.' . ($this->listFrame ? 'list_frame' : 'nav_frame');
1060 if ($this->alwaysContentFrame) {
1061 $frameName = '';
1062 }
1063 // Create the table displayed in the clickmenu layer:
1064 $CMtable = ('
1065 <table border="0" cellpadding="0" cellspacing="0" class="typo3-CSM">
1066 ' . implode('', $this->menuItemsForClickMenu($menuItems))) . '
1067 </table>';
1068 // Wrap the inner table in another table to create outer border:
1069 $CMtable = $this->wrapColorTableCM($CMtable);
1070 // Set back path place holder to real back path
1071 $CMtable = str_replace($this->PH_backPath, $this->backPath, $CMtable);
1072 if ($this->ajax) {
1073 $innerXML = ((('<data><clickmenu><htmltable><![CDATA[' . $CMtable) . ']]></htmltable><cmlevel>') . $this->cmLevel) . '</cmlevel></clickmenu></data>';
1074 return $innerXML;
1075 } else {
1076 // Create JavaScript section:
1077 $script = $GLOBALS['TBE_TEMPLATE']->wrapScriptTags((((((((((('
1078
1079 if (top.content && top.content' . $frameName) . ' && top.content') . $frameName) . '.Clickmenu) {
1080 top.content') . $frameName) . '.Clickmenu.populateData(unescape("') . GeneralUtility::rawurlencodeJS($CMtable)) . '"),') . $this->cmLevel) . ');
1081 }
1082 ') . (!$this->doDisplayTopFrameCM() ? 'hideCM();' : ''));
1083 return $script;
1084 }
1085 }
1086 }
1087
1088 /**
1089 * Wrapping the input string in a table with background color 4 and a black border style.
1090 * For the pop-up menu
1091 *
1092 * @param string $str HTML content to wrap in table.
1093 * @return string
1094 * @todo Define visibility
1095 */
1096 public function wrapColorTableCM($str) {
1097 return ('<div class="typo3-CSM-wrapperCM">
1098 ' . $str) . '
1099 </div>';
1100 }
1101
1102 /**
1103 * Traverses the menuItems and generates an output array for implosion in the topframe horizontal menu
1104 *
1105 * @param array $menuItems Array
1106 * @return array Array of menu items for top frame.
1107 * @todo Define visibility
1108 */
1109 public function menuItemsForTopFrame($menuItems) {
1110 $out = array();
1111 foreach ($menuItems as $i) {
1112 // IF the topbar is the ONLY means of the click menu, then items normally disabled from
1113 // the top menu will appear anyways IF they are disabled with a "1" (2+ will still disallow
1114 // them in the topbar)
1115 if ($i[4] == 1 && !$GLOBALS['SOBE']->doc->isCMlayers()) {
1116 $i[4] = 0;
1117 }
1118 if (is_array($i) && !$i[4]) {
1119 $out[] = $i[0];
1120 }
1121 }
1122 return $out;
1123 }
1124
1125 /**
1126 * Traverses the menuItems and generates an output array for implosion in the CM div-layers table.
1127 *
1128 * @param array $menuItems Array
1129 * @return array array for implosion in the CM div-layers table.
1130 * @todo Define visibility
1131 */
1132 public function menuItemsForClickMenu($menuItems) {
1133 $out = array();
1134 foreach ($menuItems as $cc => $i) {
1135 // MAKE horizontal spacer
1136 if (is_string($i) && $i == 'spacer') {
1137 $out[] = '
1138 <tr class="bgColor2">
1139 <td colspan="2"><img src="clear.gif" width="1" height="1" alt="" /></td>
1140 </tr>';
1141 } else {
1142 // Just make normal element:
1143 $onClick = $i[3];
1144 $onClick = preg_replace('/return[[:space:]]+hideCM\\(\\)[[:space:]]*;/i', '', $onClick);
1145 $onClick = preg_replace('/return[[:space:]]+false[[:space:]]*;/i', '', $onClick);
1146 $onClick = preg_replace('/hideCM\\(\\);/i', '', $onClick);
1147 if (!$i[5]) {
1148 $onClick .= 'Clickmenu.hideAll();';
1149 }
1150 $CSM = (' oncontextmenu="' . htmlspecialchars($onClick)) . ';return false;"';
1151 $out[] = ((((((('
1152 <tr class="typo3-CSM-itemRow" onclick="' . htmlspecialchars($onClick)) . '" onmouseover="this.bgColor=\'') . $GLOBALS['TBE_TEMPLATE']->bgColor5) . '\';" onmouseout="this.bgColor=\'\';"') . $CSM) . '>
1153 ') . (!$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>')) . '
1154 </tr>';
1155 }
1156 }
1157 return $out;
1158 }
1159
1160 /**
1161 * Adds or inserts a menu item
1162 * 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.
1163 *
1164 * @param array $menuItems Menu items array
1165 * @param array $newMenuItems Menu items array to insert
1166 * @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.
1167 * @return array Menu items array, processed.
1168 * @todo Define visibility
1169 */
1170 public function addMenuItems($menuItems, $newMenuItems, $position = '') {
1171 if (is_array($newMenuItems)) {
1172 if ($position) {
1173 $posArr = GeneralUtility::trimExplode(',', $position, 1);
1174 foreach ($posArr as $pos) {
1175 list($place, $menuEntry) = GeneralUtility::trimExplode(':', $pos, 1);
1176 list($place, $placeExtra) = GeneralUtility::trimExplode('-', $place, 1);
1177 // Bottom
1178 $pointer = count($menuItems);
1179 $found = FALSE;
1180 if ($place) {
1181 switch (strtolower($place)) {
1182 case 'after':
1183
1184 case 'before':
1185 if ($menuEntry) {
1186 $p = 1;
1187 reset($menuItems);
1188 while (TRUE) {
1189 if (!strcmp(key($menuItems), $menuEntry)) {
1190 $pointer = $p;
1191 $found = TRUE;
1192 break;
1193 }
1194 if (!next($menuItems)) {
1195 break;
1196 }
1197 $p++;
1198 }
1199 if (!$found) {
1200 break;
1201 }
1202 if ($place == 'before') {
1203 $pointer--;
1204 if ($placeExtra == 'spacer' and prev($menuItems) == 'spacer') {
1205 $pointer--;
1206 }
1207 } elseif ($place == 'after') {
1208 if ($placeExtra == 'spacer' and next($menuItems) == 'spacer') {
1209 $pointer++;
1210 }
1211 }
1212 }
1213 break;
1214 default:
1215 if (strtolower($place) == 'top') {
1216 $pointer = 0;
1217 } else {
1218 $pointer = count($menuItems);
1219 }
1220 $found = TRUE;
1221 break;
1222 }
1223 }
1224 if ($found) {
1225 break;
1226 }
1227 }
1228 }
1229 $pointer = max(0, $pointer);
1230 $menuItemsBefore = array_slice($menuItems, 0, $pointer ? $pointer : 0);
1231 $menuItemsAfter = array_slice($menuItems, $pointer);
1232 $menuItems = ($menuItemsBefore + $newMenuItems) + $menuItemsAfter;
1233 }
1234 return $menuItems;
1235 }
1236
1237 /**
1238 * Creating an array with various elements for the clickmenu entry
1239 *
1240 * @param string $str The label, htmlspecialchar'ed already
1241 * @param string $icon <img>-tag for the icon
1242 * @param string $onClick JavaScript onclick event for label/icon
1243 * @param boolean $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)
1244 * @param boolean $dontHide If set, the clickmenu layer will not hide itself onclick - used for secondary menus to appear...
1245 * @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!
1246 * @todo Define visibility
1247 */
1248 public function linkItem($str, $icon, $onClick, $onlyCM = 0, $dontHide = 0) {
1249 $this->elCount++;
1250 if ($this->ajax) {
1251 $onClick = str_replace('top.loadTopMenu', 'showClickmenu_raw', $onClick);
1252 }
1253 return array(
1254 (((((((((\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('empty-empty', array(
1255 'class' => 'c-roimg',
1256 'id' => ('roimg_' . $this->elCount)
1257 )) . '<a href="#" onclick="') . htmlspecialchars($onClick)) . '" onmouseover="mo(') . $this->elCount) . ');" onmouseout="mout(') . $this->elCount) . ');">') . $str) . $icon) . '</a>',
1258 $str,
1259 $icon,
1260 $onClick,
1261 $onlyCM,
1262 $dontHide
1263 );
1264 }
1265
1266 /**
1267 * Returns the input string IF not a user setting has disabled display of icons.
1268 *
1269 * @param string $iconCode The icon-image tag
1270 * @return string The icon-image tag prefixed with space char IF the icon should be printed at all due to user settings
1271 * @todo Define visibility
1272 */
1273 public function excludeIcon($iconCode) {
1274 return $GLOBALS['BE_USER']->uc['noMenuMode'] && strcmp($GLOBALS['BE_USER']->uc['noMenuMode'], 'icons') ? '' : ' ' . $iconCode;
1275 }
1276
1277 /**
1278 * Enabling / Disabling items based on list provided from GET var ($this->iParts[3])
1279 *
1280 * @param array $menuItems Menu items array
1281 * @return array Menu items array, processed.
1282 * @todo Define visibility
1283 */
1284 public function enableDisableItems($menuItems) {
1285 if ($this->iParts[3]) {
1286 // Detect "only" mode: (only showing listed items)
1287 if (substr($this->iParts[3], 0, 1) == '+') {
1288 $this->iParts[3] = substr($this->iParts[3], 1);
1289 $only = TRUE;
1290 } else {
1291 $only = FALSE;
1292 }
1293 // Do filtering:
1294 // Transfer ONLY elements which are mentioned (or are spacers)
1295 if ($only) {
1296 $newMenuArray = array();
1297 foreach ($menuItems as $key => $value) {
1298 if (GeneralUtility::inList($this->iParts[3], $key) || is_string($value) && $value == 'spacer') {
1299 $newMenuArray[$key] = $value;
1300 }
1301 }
1302 $menuItems = $newMenuArray;
1303 } else {
1304 // Traverse all elements except those listed (just unsetting them):
1305 $elements = GeneralUtility::trimExplode(',', $this->iParts[3], 1);
1306 foreach ($elements as $value) {
1307 unset($menuItems[$value]);
1308 }
1309 }
1310 }
1311 // Return processed menu items:
1312 return $menuItems;
1313 }
1314
1315 /**
1316 * Clean up spacers; Will remove any spacers in the start/end of menu items array plus any duplicates.
1317 *
1318 * @param array $menuItems Menu items array
1319 * @return array Menu items array, processed.
1320 * @todo Define visibility
1321 */
1322 public function cleanUpSpacers($menuItems) {
1323 // Remove doubles:
1324 $prevItemWasSpacer = FALSE;
1325 foreach ($menuItems as $key => $value) {
1326 if (is_string($value) && $value == 'spacer') {
1327 if ($prevItemWasSpacer) {
1328 unset($menuItems[$key]);
1329 }
1330 $prevItemWasSpacer = TRUE;
1331 } else {
1332 $prevItemWasSpacer = FALSE;
1333 }
1334 }
1335 // Remove first:
1336 reset($menuItems);
1337 $key = key($menuItems);
1338 $value = current($menuItems);
1339 if (is_string($value) && $value == 'spacer') {
1340 unset($menuItems[$key]);
1341 }
1342 // Remove last:
1343 end($menuItems);
1344 $key = key($menuItems);
1345 $value = current($menuItems);
1346 if (is_string($value) && $value == 'spacer') {
1347 unset($menuItems[$key]);
1348 }
1349 // Return processed menu items:
1350 return $menuItems;
1351 }
1352
1353 /**
1354 * Get label from locallang_core.php:cm.*
1355 *
1356 * @param string $label The "cm."-suffix to get.
1357 * @return string
1358 * @todo Define visibility
1359 */
1360 public function label($label) {
1361 return $GLOBALS['LANG']->makeEntities($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.' . $label, 1));
1362 }
1363
1364 /**
1365 * Returns TRUE if there should be writing to the div-layers (commands sent to clipboard MUST NOT write to div-layers)
1366 *
1367 * @return boolean
1368 * @todo Define visibility
1369 */
1370 public function isCMlayers() {
1371 if ($this->ajax) {
1372 return !$this->CB;
1373 } else {
1374 return $GLOBALS['SOBE']->doc->isCMlayers() && !$this->CB;
1375 }
1376 }
1377
1378 /**
1379 * Appends ".location" to input string
1380 *
1381 * @param string $str Input string, probably a JavaScript document reference
1382 * @return string
1383 * @todo Define visibility
1384 */
1385 public function frameLocation($str) {
1386 return $str . '.location';
1387 }
1388
1389 }
1390
1391
1392 ?>