TYPO3 CMS  TYPO3_7-6
ClickMenu.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
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.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
29 
34 class ClickMenu
35 {
42  public $cmLevel = 0;
43 
49  public $CB;
50 
56  public $listFrame = false;
57 
63  public $isDBmenu = false;
64 
70  public $alwaysContentFrame = false;
71 
80  public $iParts = [];
81 
87  public $disabledItems = [];
88 
94  public $leftIcons = false;
95 
102  public $extClassArray = [];
103 
109  public $editPageIconSet = false;
110 
116  public $editOK = false;
117 
123  public $rec = [];
124 
131  public $clipObj;
132 
137  protected $pageinfo;
138 
144  protected $languageService;
145 
149  protected $backendUser;
150 
154  protected $iconFactory;
155 
161  {
162  $this->languageService = $languageService ?: $GLOBALS['LANG'];
163  $this->backendUser = $backendUser ?: $GLOBALS['BE_USER'];
164  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
165  }
166 
172  public function init()
173  {
174  $CMcontent = '';
175  // Setting GPvars:
176  $this->cmLevel = (int)GeneralUtility::_GP('cmLevel');
177  $this->CB = GeneralUtility::_GP('CB');
178 
179  // Deal with Drag&Drop context menus
180  if ((string)GeneralUtility::_GP('dragDrop') !== '') {
181  return $this->printDragDropClickMenu(GeneralUtility::_GP('dragDrop'), GeneralUtility::_GP('srcId'), GeneralUtility::_GP('dstId'));
182  }
183  // Can be set differently as well
184  $this->iParts[0] = GeneralUtility::_GP('table');
185  $this->iParts[1] = GeneralUtility::_GP('uid');
186  $this->iParts[2] = GeneralUtility::_GP('listFr');
187  $this->iParts[3] = GeneralUtility::_GP('enDisItems');
188  // Setting flags:
189  if ($this->iParts[2]) {
190  $this->listFrame = true;
191  }
192  if ($this->iParts[2] == 2) {
193  $this->alwaysContentFrame = true;
194  }
195  if (isset($this->iParts[1]) && $this->iParts[1] !== '') {
196  $this->isDBmenu = true;
197  }
198  $TSkey = ($this->isDBmenu ? 'page' : 'folder') . ($this->listFrame ? 'List' : 'Tree');
199  $this->disabledItems = GeneralUtility::trimExplode(',', $this->backendUser->getTSConfigVal('options.contextMenu.' . $TSkey . '.disableItems'), true);
200  $this->leftIcons = (bool)$this->backendUser->getTSConfigVal('options.contextMenu.options.leftIcons');
201  // &cmLevel flag detected (2nd level menu)
202  if (!$this->cmLevel) {
203  // Make 1st level clickmenu:
204  if ($this->isDBmenu) {
205  $CMcontent = $this->printDBClickMenu($this->iParts[0], $this->iParts[1]);
206  } else {
207  $CMcontent = $this->printFileClickMenu($this->iParts[0]);
208  }
209  } else {
210  // Make 2nd level clickmenu (only for DBmenus)
211  if ($this->isDBmenu) {
212  $CMcontent = $this->printNewDBLevel($this->iParts[0], $this->iParts[1]);
213  }
214  }
215  // Return clickmenu content:
216  return $CMcontent;
217  }
218 
219  /***************************************
220  *
221  * DATABASE
222  *
223  ***************************************/
231  public function printDBClickMenu($table, $uid)
232  {
233  $uid = (int)$uid;
234  // Get record:
235  $this->rec = BackendUtility::getRecordWSOL($table, $uid);
236  $menuItems = [];
237  $root = 0;
238  $DBmount = false;
239  // Rootlevel
240  if ($table === 'pages' && $uid === 0) {
241  $root = 1;
242  }
243  // DB mount
244  if ($table === 'pages' && in_array($uid, $this->backendUser->returnWebmounts())) {
245  $DBmount = true;
246  }
247  // Used to hide cut,copy icons for l10n-records
248  $l10nOverlay = false;
249  // Should only be performed for overlay-records within the same table
250  if (BackendUtility::isTableLocalizable($table) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
251  $l10nOverlay = (int)$this->rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0;
252  }
253  // If record found (or root), go ahead and fill the $menuItems array which will contain data for the elements to render.
254  if (is_array($this->rec) || $root) {
255  // Get permissions
256  $lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? (int)$this->rec['uid'] : (int)$this->rec['pid']));
257  // View
258  if (!in_array('view', $this->disabledItems, true)) {
259  if ($table === 'pages') {
260  $menuItems['view'] = $this->DB_view($uid);
261  }
262  if ($table === 'tt_content') {
263  $ws_rec = BackendUtility::getRecordWSOL($table, (int)$this->rec['uid']);
264  $menuItems['view'] = $this->DB_view((int)$ws_rec['pid']);
265  }
266  }
267  // Edit:
268  if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
269  if (!in_array('edit', $this->disabledItems, true)) {
270  $menuItems['edit'] = $this->DB_edit($table, $uid);
271  }
272  $this->editOK = true;
273  }
274  // New:
275  if (!in_array('new', $this->disabledItems, true) && $this->backendUser->isPSet($lCP, $table, 'new')) {
276  $menuItems['new'] = $this->DB_new($table, $uid);
277  }
278  // Info:
279  if (!in_array('info', $this->disabledItems, true) && !$root) {
280  $menuItems['info'] = $this->DB_info($table, $uid);
281  }
282  $menuItems['spacer1'] = 'spacer';
283  // Copy:
284  if (!in_array('copy', $this->disabledItems, true) && !$root && !$DBmount && !$l10nOverlay) {
285  $menuItems['copy'] = $this->DB_copycut($table, $uid, 'copy');
286  }
287  // Cut:
288  if (!in_array('cut', $this->disabledItems, true) && !$root && !$DBmount && !$l10nOverlay && $this->editOK) {
289  $menuItems['cut'] = $this->DB_copycut($table, $uid, 'cut');
290  }
291  // Paste:
292  $elFromAllTables = count($this->clipObj->elFromTable(''));
293  if (!in_array('paste', $this->disabledItems, true) && $elFromAllTables) {
294  $selItem = $this->clipObj->getSelectedRecord();
295  $elInfo = [
296  GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->backendUser->uc['titleLen']),
297  $root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen']),
298  $this->clipObj->currentMode()
299  ];
300  if ($table === 'pages' && $lCP & Permission::PAGE_NEW) {
301  if ($elFromAllTables) {
302  $menuItems['pasteinto'] = $this->DB_paste('', $uid, 'into', $elInfo);
303  }
304  }
305  $elFromTable = count($this->clipObj->elFromTable($table));
306  if (!$root && !$DBmount && $elFromTable && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
307  $menuItems['pasteafter'] = $this->DB_paste($table, -$uid, 'after', $elInfo);
308  }
309  }
310 
311  // Delete:
312  $elInfo = [GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen'])];
313  $disableDeleteTS = $this->backendUser->getTSConfig('options.disableDelete');
314  $disableDelete = (bool) trim(isset($disableDeleteTS['properties'][$table]) ? $disableDeleteTS['properties'][$table] : $disableDeleteTS['value']);
315  if (!in_array('delete', $this->disabledItems, true) && !$root && !$DBmount && $this->backendUser->isPSet($lCP, $table, 'delete') && !$disableDelete) {
316  $menuItems['spacer2'] = 'spacer';
317  $menuItems['delete'] = $this->DB_delete($table, $uid, $elInfo);
318  }
319  if (!in_array('history', $this->disabledItems, true)) {
320  $menuItems['history'] = $this->DB_history($table, $uid);
321  }
322 
323  $localItems = [];
324  if (!$this->cmLevel && !in_array('moreoptions', $this->disabledItems, true)) {
325  // Creating menu items here:
326  if ($this->editOK) {
327  $localItems['spacer3'] = 'spacer';
328  $localItems['moreoptions'] = $this->linkItem(
329  $this->label('more'),
330  '',
331  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript() . '&cmLevel=1&subname=moreoptions') . ');return false;',
332  false,
333  true
334  );
335  $menuItemHideUnhideAllowed = false;
336  $hiddenField = '';
337  // Check if column for disabled is defined
338  if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
339  $hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
340  if (
341  $hiddenField !== '' && !empty($GLOBALS['TCA'][$table]['columns'][$hiddenField]['exclude'])
342  && $this->backendUser->check('non_exclude_fields', $table . ':' . $hiddenField)
343  ) {
344  $menuItemHideUnhideAllowed = true;
345  }
346  }
347  if ($menuItemHideUnhideAllowed && !in_array('hide', $this->disabledItems, true)) {
348  $localItems['hide'] = $this->DB_hideUnhide($table, $this->rec, $hiddenField);
349  }
350  $anyEnableColumnsFieldAllowed = false;
351  // Check if columns are defined
352  if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
353  $columnsToCheck = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
354  if ($table === 'pages' && !empty($columnsToCheck)) {
355  $columnsToCheck[] = 'extendToSubpages';
356  }
357  foreach ($columnsToCheck as $currentColumn) {
358  if (
359  !empty($GLOBALS['TCA'][$table]['columns'][$currentColumn]['exclude'])
360  && $this->backendUser->check('non_exclude_fields', $table . ':' . $currentColumn)
361  ) {
362  $anyEnableColumnsFieldAllowed = true;
363  }
364  }
365  }
366  if ($anyEnableColumnsFieldAllowed && !in_array('edit_access', $this->disabledItems, true)) {
367  $localItems['edit_access'] = $this->DB_editAccess($table, $uid);
368  }
369  if ($table === 'pages' && $this->editPageIconSet && !in_array('edit_pageproperties', $this->disabledItems, true)) {
370  $localItems['edit_pageproperties'] = $this->DB_editPageProperties($uid);
371  }
372  }
373  // Find delete element among the input menu items and insert the local items just before that:
374  $c = 0;
375  $deleteFound = false;
376  foreach ($menuItems as $key => $value) {
377  $c++;
378  if ($key === 'delete') {
379  $deleteFound = true;
380  break;
381  }
382  }
383  if ($deleteFound) {
384  // .. subtract two... (delete item + its spacer element...)
385  $c -= 2;
386  // and insert the items just before the delete element.
387  array_splice($menuItems, $c, 0, $localItems);
388  } else {
389  $menuItems = array_merge($menuItems, $localItems);
390  }
391  }
392  }
393  // Adding external elements to the menuItems array
394  $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
395  // Processing by external functions?
396  $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
397  if (!is_array($this->rec)) {
398  $this->rec = [];
399  }
400 
401  // Return the printed elements:
402  return $this->printItems($menuItems);
403  }
404 
412  public function printNewDBLevel($table, $uid)
413  {
414  $localItems = [];
415  $uid = (int)$uid;
416  // Setting internal record to the table/uid :
417  $this->rec = BackendUtility::getRecordWSOL($table, $uid);
418  $menuItems = [];
419  $root = 0;
420  // Rootlevel
421  if ($table === 'pages' && $uid === 0) {
422  $root = 1;
423  }
424  // If record was found, check permissions and get menu items.
425  if (is_array($this->rec) || $root) {
426  $lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? (int)$this->rec['uid'] : (int)$this->rec['pid']));
427  // Edit:
428  if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
429  $this->editOK = true;
430  }
431  $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
432  }
433 
434  $subname = GeneralUtility::_GP('subname');
435  if ($subname === 'moreoptions') {
436  // If the page can be edited, then show this:
437  if ($this->editOK) {
438  if (($table === 'pages' || $table === 'tt_content') && !in_array('move_wizard', $this->disabledItems, true)) {
439  $localItems['move_wizard'] = $this->DB_moveWizard($table, $uid, $this->rec);
440  }
441  if (($table === 'pages' || $table === 'tt_content') && !in_array('new_wizard', $this->disabledItems, true)) {
442  $localItems['new_wizard'] = $this->DB_newWizard($table, $uid, $this->rec);
443  }
444  if ($table === 'pages' && !in_array('perms', $this->disabledItems, true) && $this->backendUser->check('modules', 'system_BeuserTxPermission')) {
445  $localItems['perms'] = $this->DB_perms($table, $uid, $this->rec);
446  }
447  if (!in_array('db_list', $this->disabledItems, true) && $this->backendUser->check('modules', 'web_list')) {
448  $localItems['db_list'] = $this->DB_db_list($table, $uid, $this->rec);
449  }
450  }
451  // Temporary mount point item:
452  if ($table === 'pages') {
453  $localItems['temp_mount_point'] = $this->DB_tempMountPoint($uid);
454  }
455  // Merge the locally created items into the current menu items passed to this function.
456  $menuItems = array_merge($menuItems, $localItems);
457  }
458 
459  // Return the printed elements:
460  if (!is_array($menuItems)) {
461  $menuItems = [];
462  }
463  return $this->printItems($menuItems);
464  }
465 
472  public function externalProcessingOfDBMenuItems($menuItems)
473  {
474  return $menuItems;
475  }
476 
485  public function processingByExtClassArray($menuItems, $table, $uid)
486  {
487  if (is_array($this->extClassArray)) {
488  foreach ($this->extClassArray as $conf) {
489  $obj = GeneralUtility::makeInstance($conf['name']);
490  $menuItems = $obj->main($this, $menuItems, $table, $uid);
491  }
492  }
493  return $menuItems;
494  }
495 
505  public function urlRefForCM($url, $retUrl = '', $hideCM = true, $overrideLoc = '')
506  {
507  $loc = 'top.content.list_frame';
508  return ($overrideLoc ? 'var docRef=' . $overrideLoc : 'var docRef=(top.content.list_frame)?top.content.list_frame:' . $loc)
509  . '; docRef.location.href=' . GeneralUtility::quoteJSvalue($url) . ($retUrl ? '+' . GeneralUtility::quoteJSvalue('&' . $retUrl . '=') . '+top.rawurlencode('
510  . $this->frameLocation('docRef.document') . '.pathname+' . $this->frameLocation('docRef.document') . '.search)' : '')
511  . ';';
512  }
513 
523  public function DB_copycut($table, $uid, $type)
524  {
525  $isSel = '';
526  if ($this->clipObj->current === 'normal') {
527  $isSel = $this->clipObj->isSelected($table, $uid);
528  }
529  $addParam = [];
530  if ($this->listFrame) {
531  $addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
532  }
533  $icon = $this->iconFactory->getIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : ''), Icon::SIZE_SMALL)->render();
534  return $this->linkItem(
535  $this->label($type),
536  $icon,
537  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB($table, $uid, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;'
538  );
539  }
540 
553  public function DB_paste($table, $uid, $type, $elInfo)
554  {
555  $loc = 'top.content.list_frame';
556  $jsCode = $loc . '.location.href='
557  . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl($table, $uid, 0) . '&redirect=')
558  . ' + top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+'
559  . $this->frameLocation($loc . '.document') . '.search);';
560 
561  if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
562  $title = $this->languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:clip_paste');
563  $lllKey = ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_' . $type;
564  $confirmMessage = sprintf(
565  $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.' . $lllKey),
566  $elInfo[0],
567  $elInfo[1]
568  );
569  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
570  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
571  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
572  . $jsCode
573  . '} top.TYPO3.Modal.dismiss(); });';
574  }
575  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
576  return $this->linkItem(
577  $this->label('paste' . $type),
578  $this->iconFactory->getIcon('actions-document-paste-' . $type, Icon::SIZE_SMALL)->render(),
579  $editOnClick . 'return false;'
580  );
581  }
582 
591  public function DB_info($table, $uid)
592  {
593  return $this->linkItem(
594  $this->label('info'),
595  $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render(),
596  'top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($uid) . ');'
597  );
598  }
599 
608  public function DB_history($table, $uid)
609  {
610  $url = BackendUtility::getModuleUrl('record_history', ['element' => $table . ':' . $uid]);
611  return $this->linkItem(
612  $this->languageService->makeEntities($this->languageService->getLL('CM_history')),
613  $this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL)->render(),
614  $this->urlRefForCM($url, 'returnUrl')
615  );
616  }
617 
627  public function DB_perms($table, $uid, $rec)
628  {
629  if (!ExtensionManagementUtility::isLoaded('beuser')) {
630  return '';
631  }
632 
633  $parameters = [
634  'id' => $uid,
635  ];
636 
637  if ($rec['perms_userid'] == $this->backendUser->user['uid'] || $this->backendUser->isAdmin()) {
638  $parameters['returnId'] = $uid;
639  $parameters['tx_beuser_system_beusertxpermission'] = ['action' => 'edit'];
640  }
641 
642  $url = BackendUtility::getModuleUrl('system_BeuserTxPermission', $parameters);
643  return $this->linkItem(
644  $this->languageService->makeEntities($this->languageService->getLL('CM_perms')),
645  $this->iconFactory->getIcon('status-status-locked', Icon::SIZE_SMALL)->render(),
646  $this->urlRefForCM($url)
647  );
648  }
649 
659  public function DB_db_list($table, $uid, $rec)
660  {
661  $urlParams = [];
662  $urlParams['id'] = $table === 'pages' ? $uid : $rec['pid'];
663  $urlParams['table'] = $table === 'pages' ? '' : $table;
664  $url = BackendUtility::getModuleUrl('web_list', $urlParams, '', true);
665  return $this->linkItem(
666  $this->languageService->makeEntities($this->languageService->getLL('CM_db_list')),
667  $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render(),
668  'top.nextLoadModuleUrl=' . GeneralUtility::quoteJSvalue($url) . ';top.goToModule(\'web_list\', 1);'
669  );
670  }
671 
681  public function DB_moveWizard($table, $uid, $rec)
682  {
683  // Hardcoded field for tt_content elements.
684  $url = BackendUtility::getModuleUrl('move_element') . '&table=' . $table . '&uid=' . $uid;
685  $url .= ($table === 'tt_content' ? '&sys_language_uid=' . (int)$rec['sys_language_uid'] : '');
686  return $this->linkItem(
687  $this->languageService->makeEntities($this->languageService->getLL('CM_moveWizard' . ($table === 'pages' ? '_page' : ''))),
688  $this->iconFactory->getIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-move', Icon::SIZE_SMALL)->render(),
689  $this->urlRefForCM($url, 'returnUrl')
690  );
691  }
692 
702  public function DB_newWizard($table, $uid, $rec)
703  {
704  if ($table === 'pages') {
705  $url = BackendUtility::getModuleUrl('db_new', ['id' => $uid, 'pagesOnly' => 1]);
706  } else {
707  // If mod.newContentElementWizard.override is set, use a custom module instead
708  $tsConfig = BackendUtility::getModTSconfig((int)$this->pageinfo['uid'], 'mod');
709  $newContentWizardModuleName = isset($tsConfig['properties']['newContentElementWizard.']['override'])
710  ? $tsConfig['properties']['newContentElementWizard.']['override']
711  : 'new_content_element';
712  $url = BackendUtility::getModuleUrl($newContentWizardModuleName, ['id' => $rec['pid'], 'sys_language_uid' => (int)$rec['sys_language_uid']]);
713  }
714  return $this->linkItem(
715  $this->languageService->makeEntities($this->languageService->getLL('CM_newWizard')),
716  $this->iconFactory->getIcon(($table === 'pages' ? 'actions-page-new' : 'actions-document-new'), Icon::SIZE_SMALL)->render(),
717  $this->urlRefForCM($url, 'returnUrl')
718  );
719  }
720 
729  public function DB_editAccess($table, $uid)
730  {
731  $url = BackendUtility::getModuleUrl('record_edit', [
732  'columnsOnly' => (implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table === 'pages' ? ',extendToSubpages' : '')),
733  'edit[' . $table . '][' . $uid . ']' => 'edit'
734  ]);
735  return $this->linkItem(
736  $this->languageService->makeEntities($this->languageService->getLL('CM_editAccess')),
737  $this->iconFactory->getIcon('actions-document-edit-access', Icon::SIZE_SMALL)->render(),
738  $this->urlRefForCM($url, 'returnUrl'),
739  1
740  );
741  }
742 
750  public function DB_editPageProperties($uid)
751  {
752  $url = BackendUtility::getModuleUrl('record_edit', [
753  'edit[pages][' . $uid . ']' => 'edit'
754  ]);
755  return $this->linkItem(
756  $this->languageService->makeEntities($this->languageService->getLL('CM_editPageProperties')),
757  $this->iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL)->render(),
758  $this->urlRefForCM($url, 'returnUrl'),
759  1
760  );
761  }
762 
771  public function DB_edit($table, $uid)
772  {
773  // If another module was specified, replace the default Page module with the new one
774  $newPageModule = trim($this->backendUser->getTSConfigVal('options.overridePageModule'));
775  $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
776  $loc = 'top.content.list_frame';
777  $theIcon = $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render();
778 
779  $link = BackendUtility::getModuleUrl('record_edit', [
780  'edit[' . $table . '][' . $uid . ']' => 'edit'
781  ]);
782 
783  if ($this->iParts[0] === 'pages' && $this->iParts[1] && $this->backendUser->check('modules', $pageModule)) {
784  $this->editPageIconSet = true;
785  }
786  $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($link . '&returnUrl=') . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search);}';
787  return $this->linkItem($this->label('edit'), $theIcon, $editOnClick . ';');
788  }
789 
798  public function DB_new($table, $uid)
799  {
800  $frame = 'top.content.list_frame';
801  $location = $this->frameLocation($frame . '.document');
802  $module = $this->listFrame
803  ? GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('record_edit', ['edit[' . $table . '][-' . $uid . ']' => 'new']) . '&returnUrl=') . '+top.rawurlencode(' . $location . '.pathname+' . $location . '.search)'
804  : GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('db_new', ['id' => (int)$uid]));
805  $editOnClick = 'if(' . $frame . '){' . $frame . '.location.href=' . $module . ';}';
806  $icon = $this->iconFactory->getIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-new', Icon::SIZE_SMALL)->render();
807  return $this->linkItem($this->label('new'), $icon, $editOnClick);
808  }
809 
819  public function DB_delete($table, $uid, $elInfo)
820  {
821  $loc = 'top.content.list_frame';
822  $jsCode = $loc . '.location.href='
823  . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=')
824  . '+top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+'
825  . $this->frameLocation($loc . '.document') . '.search)+'
827  '&cmd[' . $table . '][' . $uid . '][delete]=1&prErr=1&vC=' . $this->backendUser->veriCode()
828  )
829  . ';';
830 
831  if ($table === 'pages') {
832  $jsCode .= 'top.nav.refresh.defer(500, top.nav);';
833  }
834 
835  if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
836  $title = $this->languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:delete');
837  $confirmMessage = sprintf(
838  $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.delete'),
839  $elInfo[0]
840  );
841  $confirmMessage .= BackendUtility::referenceCount(
842  $table,
843  $uid,
844  ' ' . $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.referencesToRecord')
845  );
846  $confirmMessage .= BackendUtility::translationCount(
847  $table,
848  $uid,
849  ' ' . $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord')
850  );
851  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
852  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
853  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
854  . $jsCode
855  . '} top.TYPO3.Modal.dismiss(); });';
856  }
857  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
858  return $this->linkItem(
859  $this->label('delete'),
860  $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(),
861  $editOnClick . 'return false;'
862  );
863  }
864 
873  public function DB_view($id, $anchor = '')
874  {
875  $icon = $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render();
876  return $this->linkItem($this->label('view'), $icon, BackendUtility::viewOnClick($id, '', null, $anchor) . ';');
877  }
878 
886  public function DB_tempMountPoint($page_id)
887  {
888  return $this->linkItem(
889  $this->label('tempMountPoint'),
890  $this->iconFactory->getIcon('actions-pagetree-mountroot', Icon::SIZE_SMALL)->render(),
891  'if (top.content.nav_frame) {
892  var node = top.TYPO3.Backend.NavigationContainer.PageTree.getSelected();
893  if (node === null) {
894  return false;
895  }
896 
897  var useNode = {
898  attributes: {
899  nodeData: {
900  id: ' . (int)$page_id . '
901  }
902  }
903  };
904 
905  node.ownerTree.commandProvider.mountAsTreeRoot(useNode, node.ownerTree);
906  }
907  ');
908  }
909 
919  public function DB_hideUnhide($table, $rec, $hideField)
920  {
921  return $this->DB_changeFlag($table, $rec, $hideField, $this->label(($rec[$hideField] ? 'un' : '') . 'hide'));
922  }
923 
933  public function DB_changeFlag($table, $rec, $flagField, $title)
934  {
935  $uid = $rec['_ORIG_uid'] ?: $rec['uid'];
936  $loc = 'top.content.list_frame';
937  $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' .
938  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
939  $this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
941  '&data[' . $table . '][' . $uid . '][' . $flagField . ']=' . ($rec[$flagField] ? 0 : 1) . '&prErr=1&vC=' . $this->backendUser->veriCode()
942  ) . ';};';
943  if ($table === 'pages') {
944  $editOnClick .= 'top.nav.refresh.defer(500, top.nav);';
945  }
946  return $this->linkItem(
947  $title,
948  $this->iconFactory->getIcon('actions-edit-' . ($rec[$flagField] ? 'un' : '') . 'hide', Icon::SIZE_SMALL)->render(),
949  $editOnClick . 'return false;',
950  1
951  );
952  }
953 
954  /***************************************
955  *
956  * FILE
957  *
958  ***************************************/
966  public function printFileClickMenu($combinedIdentifier)
967  {
968  $identifier = '';
969  $menuItems = [];
970  $combinedIdentifier = rawurldecode($combinedIdentifier);
971  $fileObject = ResourceFactory::getInstance()
972  ->retrieveFileOrFolderObject($combinedIdentifier);
973  if ($fileObject) {
974  $folder = false;
975  $isStorageRoot = false;
976  $isOnline = true;
977  $userMayViewStorage = false;
978  $userMayEditStorage = false;
979  $identifier = $fileObject->getCombinedIdentifier();
980  if ($fileObject instanceof Folder) {
981  $folder = true;
982  if ($fileObject->getIdentifier() === $fileObject->getStorage()->getRootLevelFolder()->getIdentifier()) {
983  $isStorageRoot = true;
984  if ($this->backendUser->check('tables_select', 'sys_file_storage')) {
985  $userMayViewStorage = true;
986  }
987  if ($this->backendUser->check('tables_modify', 'sys_file_storage')) {
988  $userMayEditStorage = true;
989  }
990  }
991  if (!$fileObject->getStorage()->isOnline()) {
992  $isOnline = false;
993  }
994  }
995  // Hide
996  if (!in_array('hide', $this->disabledItems, true) && $isStorageRoot && $userMayEditStorage) {
997  $record = BackendUtility::getRecord('sys_file_storage', $fileObject->getStorage()->getUid());
998  $menuItems['hide'] = $this->DB_changeFlag(
999  'sys_file_storage',
1000  $record,
1001  'is_online',
1002  $this->label($record['is_online'] ? 'offline' : 'online')
1003  );
1004  }
1005  // Edit
1006  if (!in_array('edit', $this->disabledItems, true) && $fileObject->checkActionPermission('write')) {
1007  if (!$folder && !$isStorageRoot && $fileObject->isIndexed() && $this->backendUser->check('tables_modify', 'sys_file_metadata')) {
1008  $metaData = $fileObject->_getMetaData();
1009  $menuItems['edit2'] = $this->DB_edit('sys_file_metadata', $metaData['uid']);
1010  }
1011  if (!$folder && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $fileObject->getExtension()) && $fileObject->checkActionPermission('write')) {
1012  $menuItems['edit'] = $this->FILE_launch($identifier, 'file_edit', 'editcontent', 'actions-page-open');
1013  } elseif ($isStorageRoot && $userMayEditStorage) {
1014  $menuItems['edit'] = $this->DB_edit('sys_file_storage', $fileObject->getStorage()->getUid());
1015  }
1016  }
1017  // Rename
1018  if (!in_array('rename', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('rename')) {
1019  $menuItems['rename'] = $this->FILE_launch($identifier, 'file_rename', 'rename', 'actions-edit-rename');
1020  }
1021  // Upload
1022  if (!in_array('upload', $this->disabledItems, true) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
1023  $menuItems['upload'] = $this->FILE_launch($identifier, 'file_upload', 'upload', 'actions-edit-upload');
1024  }
1025  // New
1026  if (!in_array('new', $this->disabledItems, true) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
1027  $menuItems['new'] = $this->FILE_launch($identifier, 'file_newfolder', 'new', 'actions-document-new');
1028  }
1029  // Info
1030  if (!in_array('info', $this->disabledItems, true) && $fileObject->checkActionPermission('read')) {
1031  if ($isStorageRoot && $userMayViewStorage) {
1032  $menuItems['info'] = $this->DB_info('sys_file_storage', $fileObject->getStorage()->getUid());
1033  } elseif (!$folder) {
1034  $menuItems['info'] = $this->fileInfo($identifier);
1035  }
1036  }
1037  $menuItems[] = 'spacer';
1038  // Copy:
1039  if (!in_array('copy', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('read')) {
1040  $menuItems['copy'] = $this->FILE_copycut($identifier, 'copy');
1041  }
1042  // Cut:
1043  if (!in_array('cut', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('move')) {
1044  $menuItems['cut'] = $this->FILE_copycut($identifier, 'cut');
1045  }
1046  // Paste:
1047  $elFromAllTables = count($this->clipObj->elFromTable('_FILE'));
1048  if (!in_array('paste', $this->disabledItems, true) && $elFromAllTables && $folder && $fileObject->checkActionPermission('write')) {
1049  $elArr = $this->clipObj->elFromTable('_FILE');
1050  $selItem = reset($elArr);
1051  $clickedFileOrFolder = ResourceFactory::getInstance()->retrieveFileOrFolderObject($combinedIdentifier);
1052  $fileOrFolderInClipBoard = ResourceFactory::getInstance()->retrieveFileOrFolderObject($selItem);
1053  $elInfo = [
1054  $fileOrFolderInClipBoard->getName(),
1055  $clickedFileOrFolder->getName(),
1056  $this->clipObj->currentMode()
1057  ];
1058  if (!$fileOrFolderInClipBoard instanceof Folder || !$fileOrFolderInClipBoard->getStorage()->isWithinFolder($fileOrFolderInClipBoard, $clickedFileOrFolder)) {
1059  $menuItems['pasteinto'] = $this->FILE_paste($identifier, $selItem, $elInfo);
1060  }
1061  }
1062  $menuItems[] = 'spacer';
1063  // Delete:
1064  if (!in_array('delete', $this->disabledItems, true) && $fileObject->checkActionPermission('delete')) {
1065  if ($isStorageRoot && $userMayEditStorage) {
1066  $elInfo = [GeneralUtility::fixed_lgd_cs($fileObject->getStorage()->getName(), $this->backendUser->uc['titleLen'])];
1067  $menuItems['delete'] = $this->DB_delete('sys_file_storage', $fileObject->getStorage()->getUid(), $elInfo);
1068  } elseif (!$isStorageRoot) {
1069  $menuItems['delete'] = $this->FILE_delete($identifier);
1070  }
1071  }
1072  }
1073  // Adding external elements to the menuItems array
1074  $menuItems = $this->processingByExtClassArray($menuItems, $identifier, 0);
1075  // Processing by external functions?
1076  $menuItems = $this->externalProcessingOfFileMenuItems($menuItems);
1077  // Return the printed elements:
1078  return $this->printItems($menuItems);
1079  }
1080 
1087  public function externalProcessingOfFileMenuItems($menuItems)
1088  {
1089  return $menuItems;
1090  }
1091 
1103  public function FILE_launch($path, $moduleName, $type, $iconName, $noReturnUrl = false)
1104  {
1105  $loc = 'top.content.list_frame';
1106 
1107  if (strpos($moduleName, '.php') !== false) {
1109  'Using a php file directly in ClickMenu is deprecated since TYPO3 CMS 7, and will be removed in CMS 8.'
1110  . ' Register the class as module and use BackendUtility::getModuleUrl() to get the right link.'
1111  . ' For examples how to do this see ext_tables.php of EXT:backend.'
1112  );
1113  $scriptUrl = $moduleName;
1114  } else {
1115  $scriptUrl = BackendUtility::getModuleUrl($moduleName);
1116  }
1117 
1118  $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($scriptUrl . '&target=' . rawurlencode($path)) . ($noReturnUrl ? '' : '+\'&returnUrl=\'+top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation($loc . '.document') . '.search)') . ';}';
1119  return $this->linkItem(
1120  $this->label($type),
1121  $this->iconFactory->getIcon($iconName, Icon::SIZE_SMALL)->render(),
1122  $editOnClick
1123  );
1124  }
1125 
1134  public function FILE_copycut($path, $type)
1135  {
1136  $isSel = '';
1137  // Pseudo table name for use in the clipboard.
1138  $table = '_FILE';
1139  $uid = GeneralUtility::shortmd5($path);
1140  if ($this->clipObj->current === 'normal') {
1141  $isSel = $this->clipObj->isSelected($table, $uid);
1142  }
1143  $addParam = [];
1144  if ($this->listFrame) {
1145  $addParam['reloadListFrame'] = $this->alwaysContentFrame ? 2 : 1;
1146  }
1147  return $this->linkItem(
1148  $this->label($type),
1149  $this->iconFactory->getIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : ''), Icon::SIZE_SMALL)->render(),
1150  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlFile($path, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;'
1151  );
1152  }
1153 
1161  public function FILE_delete($path)
1162  {
1163  $loc = 'top.content.list_frame';
1164  $jsCode = $loc . '.location.href='
1165  . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_file') . '&redirect=')
1166  . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document'))
1167  . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1169  '&file[delete][0][data]=' . rawurlencode($path) . '&vC=' . $this->backendUser->veriCode()
1170  );
1171  if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
1172  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($path);
1173  $title = $this->languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:delete');
1174  $confirmMessage = sprintf(
1175  $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.delete'),
1176  $fileOrFolderObject->getName()
1177  );
1178  if ($fileOrFolderObject instanceof Folder) {
1179  $confirmMessage .= BackendUtility::referenceCount('_FILE', $fileOrFolderObject->getIdentifier(), ' ' . $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.referencesToFolder'));
1180  } else {
1181  $confirmMessage .= BackendUtility::referenceCount('sys_file', $fileOrFolderObject->getUid(), ' ' . $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.referencesToFile'));
1182  }
1183  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
1184  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
1185  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
1186  . $jsCode
1187  . '} top.TYPO3.Modal.dismiss(); });';
1188  }
1189  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
1190  return $this->linkItem(
1191  $this->label('delete'),
1192  $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(),
1193  $editOnClick . 'return false;'
1194  );
1195  }
1196 
1206  public function FILE_paste($path, $target, $elInfo)
1207  {
1208  $loc = 'top.content.list_frame';
1209 
1210  $jsCode = $loc . '.location.href='
1211  . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl('_FILE', $path, 0) . '&redirect=')
1212  . '+top.rawurlencode(' . $this->frameLocation($loc . '.document')
1213  . '.pathname+' . $this->frameLocation($loc . '.document') . '.search);';
1214 
1215  if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
1216  $title = $this->languageService->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:clip_paste');
1217 
1218  $confirmMessage = sprintf(
1219  $this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.'
1220  . ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_into'),
1221  $elInfo[0],
1222  $elInfo[1]
1223  );
1224 
1225  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
1226  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
1227  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
1228  . $jsCode
1229  . '} top.TYPO3.Modal.dismiss(); });';
1230  }
1231  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
1232  return $this->linkItem(
1233  $this->label('pasteinto'),
1234  $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render(),
1235  $editOnClick . 'return false;'
1236  );
1237  }
1238 
1245  protected function fileInfo($identifier)
1246  {
1247  return $this->DB_info('_FILE', $identifier);
1248  }
1249 
1250  /***************************************
1251  *
1252  * DRAG AND DROP
1253  *
1254  ***************************************/
1263  public function printDragDropClickMenu($table, $srcId, $dstId)
1264  {
1265  $menuItems = [];
1266  // If the drag and drop menu should apply to PAGES use this set of menu items
1267  if ($table === 'pages') {
1268  // Move Into:
1269  $menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into');
1270  // Move After:
1271  $menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after');
1272  // Copy Into:
1273  $menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into');
1274  // Copy After:
1275  $menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after');
1276  }
1277  // If the drag and drop menu should apply to FOLDERS use this set of menu items
1278  if ($table === 'folders') {
1279  // Move Into:
1280  $menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move');
1281  // Copy Into:
1282  $menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy');
1283  }
1284  // Adding external elements to the menuItems array
1285  $menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId);
1286  // to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar
1287  // Processing by external functions?
1288  $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
1289  // Return the printed elements:
1290  return $this->printItems($menuItems);
1291  }
1292 
1299  public function externalProcessingOfDragDropMenuItems($menuItems)
1300  {
1301  return $menuItems;
1302  }
1303 
1314  public function dragDrop_copymovepage($srcUid, $dstUid, $action, $into)
1315  {
1316  $negativeSign = $into === 'into' ? '' : '-';
1317  $loc = 'top.content.list_frame';
1318  $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=' .
1319  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
1320  $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1322  '&cmd[pages][' . $srcUid . '][' . $action . ']=' . $negativeSign . $dstUid . '&prErr=1&vC=' .
1323  $this->backendUser->veriCode()
1324  ) . ';};';
1325  return $this->linkItem(
1326  $this->label($action . 'Page_' . $into),
1327  $this->iconFactory->getIcon('actions-document-paste-' . $into, Icon::SIZE_SMALL)->render(),
1328  $editOnClick . 'return false;'
1329  );
1330  }
1331 
1341  public function dragDrop_copymovefolder($srcPath, $dstPath, $action)
1342  {
1343  $loc = 'top.content.list_frame';
1344  $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=' .
1345  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_file') . '&redirect=') . '+top.rawurlencode(' .
1346  $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1348  '&file[' . $action . '][0][data]=' . $srcPath . '&file[' . $action . '][0][target]=' . $dstPath . '&prErr=1&vC=' .
1349  $this->backendUser->veriCode()
1350  ) . ';};';
1351  return $this->linkItem(
1352  $this->label($action . 'Folder_into'),
1353  $this->iconFactory->getIcon('apps-pagetree-drag-move-into', Icon::SIZE_SMALL)->render(),
1354  $editOnClick . 'return false;'
1355  );
1356  }
1357 
1358  /***************************************
1359  *
1360  * COMMON
1361  *
1362  **************************************/
1369  public function printItems($menuItems)
1370  {
1371  // Enable/Disable items
1372  $menuItems = $this->enableDisableItems($menuItems);
1373  // Clean up spacers
1374  $menuItems = $this->cleanUpSpacers($menuItems);
1375  // Adding JS part and return the content
1376  return $this->printLayerJScode($menuItems);
1377  }
1378 
1385  public function printLayerJScode($menuItems)
1386  {
1387  // Clipboard must not be submitted - then it's probably a copy/cut situation.
1388  if ($this->isCMlayers()) {
1389  // Create the table displayed in the clickmenu layer:
1390  // Wrap the inner table in another table to create outer border:
1391  $CMtable = '
1392  <div class="typo3-CSM-wrapperCM">
1393  <table border="0" cellpadding="0" cellspacing="0" class="typo3-CSM">
1394  ' . implode('', $this->menuItemsForClickMenu($menuItems)) . '
1395  </table></div>';
1396  return '<data><clickmenu><htmltable><![CDATA[' . $CMtable . ']]></htmltable><cmlevel>' . $this->cmLevel . '</cmlevel></clickmenu></data>';
1397  }
1398  }
1399 
1408  public function wrapColorTableCM($str)
1409  {
1411  return '<div class="typo3-CSM-wrapperCM">
1412  ' . $str . '
1413  </div>';
1414  }
1415 
1422  public function menuItemsForClickMenu($menuItems)
1423  {
1424  $out = [];
1425  foreach ($menuItems as $cc => $i) {
1426  // MAKE horizontal spacer
1427  if (is_string($i) && $i === 'spacer') {
1428  $out[] = '
1429  <tr style="height: 1px;" class="bgColor2">
1430  <td colspan="2"></td>
1431  </tr>';
1432  } else {
1433  // Just make normal element:
1434  $onClick = $i[3];
1435  $onClick = preg_replace('/return[[:space:]]+hideCM\\(\\)[[:space:]]*;/i', '', $onClick);
1436  $onClick = preg_replace('/return[[:space:]]+false[[:space:]]*;/i', '', $onClick);
1437  $onClick = preg_replace('/hideCM\\(\\);/i', '', $onClick);
1438  if (!$i[5]) {
1439  $onClick .= 'TYPO3.ClickMenu.hideAll();';
1440  }
1441  $CSM = ' oncontextmenu="this.click();return false;"';
1442  $out[] = '
1443  <tr class="typo3-CSM-itemRow" onclick="' . htmlspecialchars($onClick) . '"' . $CSM . '>
1444  ' . (!$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>') . '
1445  </tr>';
1446  }
1447  }
1448  return $out;
1449  }
1450 
1460  public function addMenuItems($menuItems, $newMenuItems, $position = '')
1461  {
1462  if (is_array($newMenuItems)) {
1463  $pointer = 0;
1464  if ($position) {
1465  $posArr = GeneralUtility::trimExplode(',', $position, true);
1466  foreach ($posArr as $pos) {
1467  list($place, $menuEntry) = GeneralUtility::trimExplode(':', $pos, true);
1468  list($place, $placeExtra) = GeneralUtility::trimExplode('-', $place, true);
1469  // Bottom
1470  $pointer = count($menuItems);
1471  $found = false;
1472  if ($place) {
1473  switch (strtolower($place)) {
1474  case 'after':
1475  case 'before':
1476  if ($menuEntry) {
1477  $p = 1;
1478  reset($menuItems);
1479  while (true) {
1480  if ((string)key($menuItems) === $menuEntry) {
1481  $pointer = $p;
1482  $found = true;
1483  break;
1484  }
1485  if (!next($menuItems)) {
1486  break;
1487  }
1488  $p++;
1489  }
1490  if (!$found) {
1491  break;
1492  }
1493  if ($place === 'before') {
1494  $pointer--;
1495  if ($placeExtra === 'spacer' and prev($menuItems) === 'spacer') {
1496  $pointer--;
1497  }
1498  } elseif ($place === 'after') {
1499  if ($placeExtra === 'spacer' and next($menuItems) === 'spacer') {
1500  $pointer++;
1501  }
1502  }
1503  }
1504  break;
1505  default:
1506  if (strtolower($place) === 'top') {
1507  $pointer = 0;
1508  } else {
1509  $pointer = count($menuItems);
1510  }
1511  $found = true;
1512  }
1513  }
1514  if ($found) {
1515  break;
1516  }
1517  }
1518  }
1519  $pointer = max(0, $pointer);
1520  $menuItemsBefore = array_slice($menuItems, 0, $pointer ?: 0);
1521  $menuItemsAfter = array_slice($menuItems, $pointer);
1522  $menuItems = $menuItemsBefore + $newMenuItems + $menuItemsAfter;
1523  }
1524  return $menuItems;
1525  }
1526 
1537  public function linkItem($str, $icon, $onClick, $onlyCM = 0, $dontHide = 0)
1538  {
1539  $onClick = str_replace('top.loadTopMenu', 'showClickmenu_raw', $onClick);
1540  return [
1541  '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $str . $icon . '</a>',
1542  $str,
1543  $icon,
1544  $onClick,
1545  $onlyCM,
1546  $dontHide
1547  ];
1548  }
1549 
1557  public function excludeIcon($iconCode)
1558  {
1560  return $this->backendUser->uc['noMenuMode'] && $this->backendUser->uc['noMenuMode'] !== 'icons' ? '' : ' ' . $iconCode;
1561  }
1562 
1569  public function enableDisableItems($menuItems)
1570  {
1571  if ($this->iParts[3]) {
1572  // Detect "only" mode: (only showing listed items)
1573  if ($this->iParts[3][0] === '+') {
1574  $this->iParts[3] = substr($this->iParts[3], 1);
1575  $only = true;
1576  } else {
1577  $only = false;
1578  }
1579  // Do filtering:
1580  // Transfer ONLY elements which are mentioned (or are spacers)
1581  if ($only) {
1582  $newMenuArray = [];
1583  foreach ($menuItems as $key => $value) {
1584  if (GeneralUtility::inList($this->iParts[3], $key) || is_string($value) && $value === 'spacer') {
1585  $newMenuArray[$key] = $value;
1586  }
1587  }
1588  $menuItems = $newMenuArray;
1589  } else {
1590  // Traverse all elements except those listed (just unsetting them):
1591  $elements = GeneralUtility::trimExplode(',', $this->iParts[3], true);
1592  foreach ($elements as $value) {
1593  unset($menuItems[$value]);
1594  }
1595  }
1596  }
1597  // Return processed menu items:
1598  return $menuItems;
1599  }
1600 
1607  public function cleanUpSpacers($menuItems)
1608  {
1609  // Remove doubles:
1610  $prevItemWasSpacer = false;
1611  foreach ($menuItems as $key => $value) {
1612  if (is_string($value) && $value === 'spacer') {
1613  if ($prevItemWasSpacer) {
1614  unset($menuItems[$key]);
1615  }
1616  $prevItemWasSpacer = true;
1617  } else {
1618  $prevItemWasSpacer = false;
1619  }
1620  }
1621  // Remove first:
1622  reset($menuItems);
1623  $key = key($menuItems);
1624  $value = current($menuItems);
1625  if (is_string($value) && $value === 'spacer') {
1626  unset($menuItems[$key]);
1627  }
1628  // Remove last:
1629  end($menuItems);
1630  $key = key($menuItems);
1631  $value = current($menuItems);
1632  if (is_string($value) && $value === 'spacer') {
1633  unset($menuItems[$key]);
1634  }
1635  // Return processed menu items:
1636  return $menuItems;
1637  }
1638 
1645  public function label($label)
1646  {
1647  return $this->languageService->makeEntities($this->languageService->sL('LLL:EXT:lang/locallang_core.xlf:cm.' . $label, true));
1648  }
1649 
1655  public function isCMlayers()
1656  {
1657  return !$this->CB;
1658  }
1659 
1666  public function frameLocation($str)
1667  {
1668  return $str . '.location';
1669  }
1670 }
static translationCount($table, $ref, $msg='')
FILE_launch($path, $moduleName, $type, $iconName, $noReturnUrl=false)
Definition: ClickMenu.php:1103
printFileClickMenu($combinedIdentifier)
Definition: ClickMenu.php:966
FILE_paste($path, $target, $elInfo)
Definition: ClickMenu.php:1206
addMenuItems($menuItems, $newMenuItems, $position='')
Definition: ClickMenu.php:1460
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static linkThisScript(array $getParams=[])
__construct(LanguageService $languageService=null, BackendUserAuthentication $backendUser=null)
Definition: ClickMenu.php:160
DB_changeFlag($table, $rec, $flagField, $title)
Definition: ClickMenu.php:933
dragDrop_copymovepage($srcUid, $dstUid, $action, $into)
Definition: ClickMenu.php:1314
dragDrop_copymovefolder($srcPath, $dstPath, $action)
Definition: ClickMenu.php:1341
DB_paste($table, $uid, $type, $elInfo)
Definition: ClickMenu.php:553
static referenceCount($table, $ref, $msg='', $count=null)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
urlRefForCM($url, $retUrl='', $hideCM=true, $overrideLoc='')
Definition: ClickMenu.php:505
processingByExtClassArray($menuItems, $table, $uid)
Definition: ClickMenu.php:485
static viewOnClick($pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
linkItem($str, $icon, $onClick, $onlyCM=0, $dontHide=0)
Definition: ClickMenu.php:1537
static fixed_lgd_cs($string, $chars, $appendString='...')
$uid
Definition: server.php:38
static getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static getRecordWSOL($table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
DB_hideUnhide($table, $rec, $hideField)
Definition: ClickMenu.php:919
DB_delete($table, $uid, $elInfo)
Definition: ClickMenu.php:819
printDragDropClickMenu($table, $srcId, $dstId)
Definition: ClickMenu.php:1263