TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ClickMenu.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\ClickMenu;
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 
73  public $iParts = [];
74 
80  public $disabledItems = [];
81 
88  public $extClassArray = [];
89 
95  public $editPageIconSet = false;
96 
102  public $editOK = false;
103 
109  public $rec = [];
110 
117  public $clipObj;
118 
123  protected $pageinfo;
124 
130  protected $languageService;
131 
135  protected $backendUser;
136 
140  protected $iconFactory;
141 
147  {
148  $this->languageService = $languageService ?: $GLOBALS['LANG'];
149  $this->backendUser = $backendUser ?: $GLOBALS['BE_USER'];
150  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
151  }
152 
158  public function init()
159  {
160  $CMcontent = '';
161  // Setting GPvars:
162  $this->cmLevel = (int)GeneralUtility::_GP('cmLevel');
163  $this->CB = GeneralUtility::_GP('CB');
164 
165  // Deal with Drag&Drop context menus
166  if ((string)GeneralUtility::_GP('dragDrop') !== '') {
167  return $this->printDragDropClickMenu(GeneralUtility::_GP('dragDrop'), GeneralUtility::_GP('srcId'), GeneralUtility::_GP('dstId'));
168  }
169  // Can be set differently as well
170  $this->iParts[0] = GeneralUtility::_GP('table');
171  $this->iParts[1] = GeneralUtility::_GP('uid');
172  $this->iParts[2] = GeneralUtility::_GP('listFr');
173  $this->iParts[3] = GeneralUtility::_GP('enDisItems');
174  // Setting flags:
175  if ($this->iParts[2]) {
176  $this->listFrame = true;
177  }
178  if (isset($this->iParts[1]) && $this->iParts[1] !== '') {
179  $this->isDBmenu = true;
180  }
181  $TSkey = ($this->isDBmenu ? 'page' : 'folder') . ($this->listFrame ? 'List' : 'Tree');
182  $this->disabledItems = GeneralUtility::trimExplode(',', $this->backendUser->getTSConfigVal('options.contextMenu.' . $TSkey . '.disableItems'), true);
183  // &cmLevel flag detected (2nd level menu)
184  if (!$this->cmLevel) {
185  // Make 1st level clickmenu:
186  if ($this->isDBmenu) {
187  $CMcontent = $this->printDBClickMenu($this->iParts[0], $this->iParts[1]);
188  } else {
189  $CMcontent = $this->printFileClickMenu($this->iParts[0]);
190  }
191  } else {
192  // Make 2nd level clickmenu (only for DBmenus)
193  if ($this->isDBmenu) {
194  $CMcontent = $this->printNewDBLevel($this->iParts[0], $this->iParts[1]);
195  }
196  }
197  // Return clickmenu content:
198  return $CMcontent;
199  }
200 
201  /***************************************
202  *
203  * DATABASE
204  *
205  ***************************************/
213  public function printDBClickMenu($table, $uid)
214  {
215  $uid = (int)$uid;
216  // Get record:
217  $this->rec = BackendUtility::getRecordWSOL($table, $uid);
218  $menuItems = [];
219  $root = 0;
220  $DBmount = false;
221  // Rootlevel
222  if ($table === 'pages' && $uid === 0) {
223  $root = 1;
224  }
225  // DB mount
226  if ($table === 'pages' && in_array($uid, $this->backendUser->returnWebmounts())) {
227  $DBmount = true;
228  }
229  // Used to hide cut,copy icons for l10n-records
230  $l10nOverlay = false;
231  // Should only be performed for overlay-records within the same table
232  if (BackendUtility::isTableLocalizable($table) && $table !== 'pages_language_overlay') {
233  $l10nOverlay = (int)$this->rec[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0;
234  }
235  // If record found (or root), go ahead and fill the $menuItems array which will contain data for the elements to render.
236  if (is_array($this->rec) || $root) {
237  // Get permissions
238  $lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? (int)$this->rec['uid'] : (int)$this->rec['pid']));
239  // View
240  if (!in_array('view', $this->disabledItems, true)) {
241  if ($table === 'pages') {
242  $menuItems['view'] = $this->DB_view($uid);
243  }
244  if ($table === 'tt_content') {
245  $ws_rec = BackendUtility::getRecordWSOL($table, (int)$this->rec['uid']);
246  $menuItems['view'] = $this->DB_view((int)$ws_rec['pid']);
247  }
248  }
249  // Edit:
250  if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
251  if (!in_array('edit', $this->disabledItems, true)) {
252  $menuItems['edit'] = $this->DB_edit($table, $uid);
253  }
254  $this->editOK = true;
255  }
256  // New:
257  if (!in_array('new', $this->disabledItems, true) && $this->backendUser->isPSet($lCP, $table, 'new')) {
258  $menuItems['new'] = $this->DB_new($table, $uid);
259  }
260  // Info:
261  if (!in_array('info', $this->disabledItems, true) && !$root) {
262  $menuItems['info'] = $this->DB_info($table, $uid);
263  }
264  $menuItems['spacer1'] = 'spacer';
265  // Copy:
266  if (!in_array('copy', $this->disabledItems, true) && !$root && !$DBmount && !$l10nOverlay) {
267  $menuItems['copy'] = $this->DB_copycut($table, $uid, 'copy');
268  }
269  // Cut:
270  if (!in_array('cut', $this->disabledItems, true) && !$root && !$DBmount && !$l10nOverlay && $this->editOK) {
271  $menuItems['cut'] = $this->DB_copycut($table, $uid, 'cut');
272  }
273  // Paste:
274  $elFromAllTables = count($this->clipObj->elFromTable(''));
275  if (!in_array('paste', $this->disabledItems, true) && $elFromAllTables) {
276  $selItem = $this->clipObj->getSelectedRecord();
277  $elInfo = [
278  GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->backendUser->uc['titleLen']),
279  $root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen']),
280  $this->clipObj->currentMode()
281  ];
282  if ($table === 'pages' && $lCP & Permission::PAGE_NEW) {
283  if ($elFromAllTables) {
284  $menuItems['pasteinto'] = $this->DB_paste('', $uid, 'into', $elInfo);
285  }
286  }
287  $elFromTable = count($this->clipObj->elFromTable($table));
288  if (!$root && !$DBmount && $elFromTable && $GLOBALS['TCA'][$table]['ctrl']['sortby']) {
289  $menuItems['pasteafter'] = $this->DB_paste($table, -$uid, 'after', $elInfo);
290  }
291  }
292 
293  // Delete:
294  $elInfo = [GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $this->rec), $this->backendUser->uc['titleLen'])];
295  $disableDeleteTS = $this->backendUser->getTSConfig('options.disableDelete');
296  $disableDelete = (bool) trim(isset($disableDeleteTS['properties'][$table]) ? $disableDeleteTS['properties'][$table] : $disableDeleteTS['value']);
297  if (!in_array('delete', $this->disabledItems, true) && !$root && !$DBmount && $this->backendUser->isPSet($lCP, $table, 'delete') && !$disableDelete) {
298  $menuItems['spacer2'] = 'spacer';
299  $menuItems['delete'] = $this->DB_delete($table, $uid, $elInfo);
300  }
301  if (!in_array('history', $this->disabledItems, true)) {
302  $menuItems['history'] = $this->DB_history($table, $uid);
303  }
304 
305  $localItems = [];
306  if (!$this->cmLevel && !in_array('moreoptions', $this->disabledItems, true)) {
307  // Creating menu items here:
308  if ($this->editOK) {
309  $localItems['spacer3'] = 'spacer';
310  $localItems['moreoptions'] = $this->linkItem(
311  $this->label('more') . '&nbsp;&nbsp;<span class="fa fa-caret-right"></span>',
312  '<span class="fa fa-fw"></span>',
313  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript() . '&cmLevel=1&subname=moreoptions') . ');return false;',
314  false,
315  true
316  );
317  $menuItemHideUnhideAllowed = false;
318  $hiddenField = '';
319  // Check if column for disabled is defined
320  if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'])) {
321  $hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
322  if (
323  $hiddenField !== '' && !empty($GLOBALS['TCA'][$table]['columns'][$hiddenField]['exclude'])
324  && $this->backendUser->check('non_exclude_fields', $table . ':' . $hiddenField)
325  ) {
326  $menuItemHideUnhideAllowed = true;
327  }
328  }
329  if ($menuItemHideUnhideAllowed && !in_array('hide', $this->disabledItems, true)) {
330  $localItems['hide'] = $this->DB_hideUnhide($table, $this->rec, $hiddenField);
331  }
332  $anyEnableColumnsFieldAllowed = false;
333  // Check if columns are defined
334  if (isset($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
335  $columnsToCheck = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
336  if ($table === 'pages' && !empty($columnsToCheck)) {
337  $columnsToCheck[] = 'extendToSubpages';
338  }
339  foreach ($columnsToCheck as $currentColumn) {
340  if (
341  !empty($GLOBALS['TCA'][$table]['columns'][$currentColumn]['exclude'])
342  && $this->backendUser->check('non_exclude_fields', $table . ':' . $currentColumn)
343  ) {
344  $anyEnableColumnsFieldAllowed = true;
345  }
346  }
347  }
348  if ($anyEnableColumnsFieldAllowed && !in_array('edit_access', $this->disabledItems, true)) {
349  $localItems['edit_access'] = $this->DB_editAccess($table, $uid);
350  }
351  }
352  // Find delete element among the input menu items and insert the local items just before that:
353  $c = 0;
354  $deleteFound = false;
355  foreach ($menuItems as $key => $value) {
356  $c++;
357  if ($key === 'delete') {
358  $deleteFound = true;
359  break;
360  }
361  }
362  if ($deleteFound) {
363  // .. subtract two... (delete item + its spacer element...)
364  $c -= 2;
365  // and insert the items just before the delete element.
366  array_splice($menuItems, $c, 0, $localItems);
367  } else {
368  $menuItems = array_merge($menuItems, $localItems);
369  }
370  }
371  }
372  // Adding external elements to the menuItems array
373  $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
374  // Processing by external functions?
375  $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
376  if (!is_array($this->rec)) {
377  $this->rec = [];
378  }
379 
380  // Return the printed elements:
381  return $this->printItems($menuItems);
382  }
383 
391  public function printNewDBLevel($table, $uid)
392  {
393  $localItems = [];
394  $uid = (int)$uid;
395  // Setting internal record to the table/uid :
396  $this->rec = BackendUtility::getRecordWSOL($table, $uid);
397  $menuItems = [];
398  $root = 0;
399  // Rootlevel
400  if ($table === 'pages' && $uid === 0) {
401  $root = 1;
402  }
403  // If record was found, check permissions and get menu items.
404  if (is_array($this->rec) || $root) {
405  $lCP = $this->backendUser->calcPerms(BackendUtility::getRecord('pages', $table === 'pages' ? (int)$this->rec['uid'] : (int)$this->rec['pid']));
406  // Edit:
407  if (!$root && ($this->backendUser->isPSet($lCP, $table, 'edit') || $this->backendUser->isPSet($lCP, $table, 'editcontent'))) {
408  $this->editOK = true;
409  }
410  $menuItems = $this->processingByExtClassArray($menuItems, $table, $uid);
411  }
412 
413  $subname = GeneralUtility::_GP('subname');
414  if ($subname === 'moreoptions') {
415  // If the page can be edited, then show this:
416  if ($this->editOK) {
417  if (($table === 'pages' || $table === 'tt_content') && !in_array('move_wizard', $this->disabledItems, true)) {
418  $localItems['move_wizard'] = $this->DB_moveWizard($table, $uid, $this->rec);
419  }
420  if (($table === 'pages' || $table === 'tt_content') && !in_array('new_wizard', $this->disabledItems, true)) {
421  $localItems['new_wizard'] = $this->DB_newWizard($table, $uid, $this->rec);
422  }
423  if ($table === 'pages' && !in_array('perms', $this->disabledItems, true) && $this->backendUser->check('modules', 'system_BeuserTxPermission')) {
424  $localItems['perms'] = $this->DB_perms($table, $uid, $this->rec);
425  }
426  if (!in_array('db_list', $this->disabledItems, true) && $this->backendUser->check('modules', 'web_list')) {
427  $localItems['db_list'] = $this->DB_db_list($table, $uid, $this->rec);
428  }
429  }
430  // Temporary mount point item:
431  if ($table === 'pages') {
432  $localItems['temp_mount_point'] = $this->DB_tempMountPoint($uid);
433  }
434  // Merge the locally created items into the current menu items passed to this function.
435  $menuItems = array_merge($menuItems, $localItems);
436  }
437 
438  // Return the printed elements:
439  if (!is_array($menuItems)) {
440  $menuItems = [];
441  }
442  return $this->printItems($menuItems);
443  }
444 
451  public function externalProcessingOfDBMenuItems($menuItems)
452  {
453  return $menuItems;
454  }
455 
464  public function processingByExtClassArray($menuItems, $table, $uid)
465  {
466  if (is_array($this->extClassArray)) {
467  foreach ($this->extClassArray as $conf) {
468  $obj = GeneralUtility::makeInstance($conf['name']);
469  $menuItems = $obj->main($this, $menuItems, $table, $uid);
470  }
471  }
472  return $menuItems;
473  }
474 
484  public function urlRefForCM($url, $retUrl = '', $hideCM = true, $overrideLoc = '')
485  {
486  $loc = 'top.list_frame';
487  return ($overrideLoc ? 'var docRef=' . $overrideLoc : 'var docRef=(top.list_frame)?top.list_frame:' . $loc)
488  . '; docRef.location.href=' . GeneralUtility::quoteJSvalue($url) . ($retUrl ? '+' . GeneralUtility::quoteJSvalue('&' . $retUrl . '=') . '+top.rawurlencode('
489  . $this->frameLocation('docRef.document') . '.pathname+' . $this->frameLocation('docRef.document') . '.search)' : '')
490  . ';';
491  }
492 
502  public function DB_copycut($table, $uid, $type)
503  {
504  $isSel = '';
505  if ($this->clipObj->current === 'normal') {
506  $isSel = $this->clipObj->isSelected($table, $uid);
507  }
508  $addParam = [];
509  if ($this->listFrame) {
510  $addParam['reloadListFrame'] = 1;
511  }
512  $icon = $this->iconFactory->getIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : ''), Icon::SIZE_SMALL)->render();
513  return $this->linkItem(
514  $this->label($type),
515  $icon,
516  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB($table, $uid, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;'
517  );
518  }
519 
532  public function DB_paste($table, $uid, $type, $elInfo)
533  {
534  $loc = 'top.list_frame';
535  $jsCode = $loc . '.location.href='
536  . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl($table, $uid, 0) . '&redirect=')
537  . ' + top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+'
538  . $this->frameLocation($loc . '.document') . '.search);';
539 
540  if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
541  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:clip_paste');
542  $lllKey = ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_' . $type;
543  $confirmMessage = sprintf(
544  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.' . $lllKey),
545  $elInfo[0],
546  $elInfo[1]
547  );
548  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
549  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
550  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
551  . $jsCode
552  . '} top.TYPO3.Modal.dismiss(); });';
553  }
554  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
555  return $this->linkItem(
556  $this->label('paste' . $type),
557  $this->iconFactory->getIcon('actions-document-paste-' . $type, Icon::SIZE_SMALL)->render(),
558  $editOnClick . 'return false;'
559  );
560  }
561 
570  public function DB_info($table, $uid)
571  {
572  return $this->linkItem(
573  $this->label('info'),
574  $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render(),
575  'top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($uid) . ');'
576  );
577  }
578 
587  public function DB_history($table, $uid)
588  {
589  $url = BackendUtility::getModuleUrl('record_history', ['element' => $table . ':' . $uid]);
590  return $this->linkItem(
591  htmlspecialchars($this->languageService->getLL('CM_history')),
592  $this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL)->render(),
593  $this->urlRefForCM($url, 'returnUrl')
594  );
595  }
596 
606  public function DB_perms($table, $uid, $rec)
607  {
608  if (!ExtensionManagementUtility::isLoaded('beuser')) {
609  return '';
610  }
611 
612  $parameters = [
613  'id' => $uid,
614  ];
615 
616  if ($rec['perms_userid'] == $this->backendUser->user['uid'] || $this->backendUser->isAdmin()) {
617  $parameters['return_id'] = $uid;
618  $parameters['edit'] = '1';
619  }
620 
621  $url = BackendUtility::getModuleUrl('system_BeuserTxPermission', $parameters);
622  return $this->linkItem(
623  htmlspecialchars($this->languageService->getLL('CM_perms')),
624  $this->iconFactory->getIcon('status-status-locked', Icon::SIZE_SMALL)->render(),
625  $this->urlRefForCM($url)
626  );
627  }
628 
638  public function DB_db_list($table, $uid, $rec)
639  {
640  $urlParams = [];
641  $urlParams['id'] = $table === 'pages' ? $uid : $rec['pid'];
642  $urlParams['table'] = $table === 'pages' ? '' : $table;
643  $url = BackendUtility::getModuleUrl('web_list', $urlParams);
644  return $this->linkItem(
645  htmlspecialchars($this->languageService->getLL('CM_db_list')),
646  $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render(),
647  'top.nextLoadModuleUrl=' . GeneralUtility::quoteJSvalue($url) . ';top.goToModule(\'web_list\', 1);'
648  );
649  }
650 
660  public function DB_moveWizard($table, $uid, $rec)
661  {
662  // Hardcoded field for tt_content elements.
663  $url = BackendUtility::getModuleUrl('move_element') . '&table=' . $table . '&uid=' . $uid;
664  $url .= ($table === 'tt_content' ? '&sys_language_uid=' . (int)$rec['sys_language_uid'] : '');
665  return $this->linkItem(
666  htmlspecialchars($this->languageService->getLL('CM_moveWizard' . ($table === 'pages' ? '_page' : ''))),
667  $this->iconFactory->getIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-move', Icon::SIZE_SMALL)->render(),
668  $this->urlRefForCM($url, 'returnUrl')
669  );
670  }
671 
681  public function DB_newWizard($table, $uid, $rec)
682  {
683  if ($table === 'pages') {
684  $url = BackendUtility::getModuleUrl('db_new', ['id' => $uid, 'pagesOnly' => 1]);
685  } else {
686  // If mod.newContentElementWizard.override is set, use a custom module instead
687  $tsConfig = BackendUtility::getModTSconfig((int)$this->pageinfo['uid'], 'mod');
688  $newContentWizardModuleName = isset($tsConfig['properties']['newContentElementWizard.']['override'])
689  ? $tsConfig['properties']['newContentElementWizard.']['override']
690  : 'new_content_element';
691  $url = BackendUtility::getModuleUrl($newContentWizardModuleName, ['id' => $rec['pid'], 'sys_language_uid' => (int)$rec['sys_language_uid']]);
692  }
693  return $this->linkItem(
694  htmlspecialchars($this->languageService->getLL('CM_newWizard')),
695  $this->iconFactory->getIcon(($table === 'pages' ? 'actions-page-new' : 'actions-document-new'), Icon::SIZE_SMALL)->render(),
696  $this->urlRefForCM($url, 'returnUrl')
697  );
698  }
699 
708  public function DB_editAccess($table, $uid)
709  {
710  $url = BackendUtility::getModuleUrl('record_edit', [
711  'columnsOnly' => (implode(',', $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']) . ($table === 'pages' ? ',extendToSubpages' : '')),
712  'edit[' . $table . '][' . $uid . ']' => 'edit'
713  ]);
714  return $this->linkItem(
715  htmlspecialchars($this->languageService->getLL('CM_editAccess')),
716  $this->iconFactory->getIcon('actions-document-edit-access', Icon::SIZE_SMALL)->render(),
717  $this->urlRefForCM($url, 'returnUrl'),
718  1
719  );
720  }
721 
730  public function DB_editPageProperties($uid)
731  {
733  $url = BackendUtility::getModuleUrl('record_edit', [
734  'edit[pages][' . $uid . ']' => 'edit'
735  ]);
736  return $this->linkItem(
737  htmlspecialchars($this->languageService->getLL('CM_editPageProperties')),
738  $this->iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL)->render(),
739  $this->urlRefForCM($url, 'returnUrl'),
740  1
741  );
742  }
743 
752  public function DB_edit($table, $uid)
753  {
754  // If another module was specified, replace the default Page module with the new one
755  $newPageModule = trim($this->backendUser->getTSConfigVal('options.overridePageModule'));
756  $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
757  $loc = 'top.list_frame';
758  $iconName = 'actions-open';
759  if ($table === 'pages') {
760  $iconName = 'actions-page-open';
761  }
762  $theIcon = $this->iconFactory->getIcon($iconName, Icon::SIZE_SMALL)->render();
763 
764  $link = BackendUtility::getModuleUrl('record_edit', [
765  'edit[' . $table . '][' . $uid . ']' => 'edit'
766  ]);
767 
768  if ($this->iParts[0] === 'pages' && $this->iParts[1] && $this->backendUser->check('modules', $pageModule)) {
769  $this->editPageIconSet = true;
770  }
771  $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' . GeneralUtility::quoteJSvalue($link . '&returnUrl=') . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search);}';
772  return $this->linkItem($this->label('edit'), $theIcon, $editOnClick . ';');
773  }
774 
783  public function DB_new($table, $uid)
784  {
785  $frame = 'top.list_frame';
786  $location = $this->frameLocation($frame . '.document');
787  $module = $this->listFrame
788  ? GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('record_edit', ['edit[' . $table . '][-' . $uid . ']' => 'new']) . '&returnUrl=') . '+top.rawurlencode(' . $location . '.pathname+' . $location . '.search)'
789  : GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('db_new', ['id' => (int)$uid]));
790  $editOnClick = 'if(' . $frame . '){' . $frame . '.location.href=' . $module . ';}';
791  $icon = $this->iconFactory->getIcon('actions-' . ($table === 'pages' ? 'page' : 'document') . '-new', Icon::SIZE_SMALL)->render();
792  return $this->linkItem($this->label('new'), $icon, $editOnClick);
793  }
794 
804  public function DB_delete($table, $uid, $elInfo)
805  {
806  $loc = 'top.list_frame';
807  $jsCode = $loc . '.location.href='
808  . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=')
809  . '+top.rawurlencode(' . $this->frameLocation($loc . '.document') . '.pathname+'
810  . $this->frameLocation($loc . '.document') . '.search)+'
812  '&cmd[' . $table . '][' . $uid . '][delete]=1&prErr=1&vC=' . $this->backendUser->veriCode()
813  );
814 
815  if ($table === 'pages') {
816  $jsCode .= 'top.nav.refresh.defer(500, top.nav);';
817  }
818 
819  if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
820  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:delete');
821  $confirmMessage = sprintf(
822  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.delete'),
823  $elInfo[0]
824  );
825  $confirmMessage .= BackendUtility::referenceCount(
826  $table,
827  $uid,
828  ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord')
829  );
830  $confirmMessage .= BackendUtility::translationCount(
831  $table,
832  $uid,
833  ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord')
834  );
835  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
836  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
837  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
838  . $jsCode
839  . '} top.TYPO3.Modal.dismiss(); });';
840  }
841  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
842  return $this->linkItem(
843  $this->label('delete'),
844  $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(),
845  $editOnClick . 'return false;'
846  );
847  }
848 
857  public function DB_view($id, $anchor = '')
858  {
859  $icon = $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render();
860  return $this->linkItem($this->label('view'), $icon, BackendUtility::viewOnClick($id, '', null, $anchor) . ';');
861  }
862 
870  public function DB_tempMountPoint($page_id)
871  {
872  return $this->linkItem(
873  $this->label('tempMountPoint'),
874  $this->iconFactory->getIcon('actions-pagetree-mountroot', Icon::SIZE_SMALL)->render(),
875  'if (top.nav_frame) {
876  var node = top.TYPO3.Backend.NavigationContainer.PageTree.getSelected();
877  if (node === null) {
878  return false;
879  }
880 
881  var useNode = {
882  attributes: {
883  nodeData: {
884  id: ' . (int)$page_id . '
885  }
886  }
887  };
888 
889  node.ownerTree.commandProvider.mountAsTreeRoot(useNode, node.ownerTree);
890  }
891  ');
892  }
893 
903  public function DB_hideUnhide($table, $rec, $hideField)
904  {
905  return $this->DB_changeFlag($table, $rec, $hideField, $this->label(($rec[$hideField] ? 'un' : '') . 'hide'));
906  }
907 
917  public function DB_changeFlag($table, $rec, $flagField, $title)
918  {
919  $uid = $rec['_ORIG_uid'] ?: $rec['uid'];
920  $loc = 'top.list_frame';
921  $editOnClick = 'if(' . $loc . '){' . $loc . '.location.href=' .
922  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
923  $this->frameLocation($loc . '.document') . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
925  '&data[' . $table . '][' . $uid . '][' . $flagField . ']=' . ($rec[$flagField] ? 0 : 1) . '&prErr=1&vC=' . $this->backendUser->veriCode()
926  ) . ';};';
927  if ($table === 'pages') {
928  $editOnClick .= 'top.nav.refresh.defer(500, top.nav);';
929  }
930  return $this->linkItem(
931  $title,
932  $this->iconFactory->getIcon('actions-edit-' . ($rec[$flagField] ? 'un' : '') . 'hide', Icon::SIZE_SMALL)->render(),
933  $editOnClick . 'return false;',
934  1
935  );
936  }
937 
938  /***************************************
939  *
940  * FILE
941  *
942  ***************************************/
950  public function printFileClickMenu($combinedIdentifier)
951  {
952  $identifier = '';
953  $menuItems = [];
954  $combinedIdentifier = rawurldecode($combinedIdentifier);
955  $fileObject = ResourceFactory::getInstance()
956  ->retrieveFileOrFolderObject($combinedIdentifier);
957  if ($fileObject) {
958  $folder = false;
959  $isStorageRoot = false;
960  $isOnline = true;
961  $userMayViewStorage = false;
962  $userMayEditStorage = false;
963  $identifier = $fileObject->getCombinedIdentifier();
964  if ($fileObject instanceof Folder) {
965  $folder = true;
966  if ($fileObject->getIdentifier() === $fileObject->getStorage()->getRootLevelFolder()->getIdentifier()) {
967  $isStorageRoot = true;
968  if ($this->backendUser->check('tables_select', 'sys_file_storage')) {
969  $userMayViewStorage = true;
970  }
971  if ($this->backendUser->check('tables_modify', 'sys_file_storage')) {
972  $userMayEditStorage = true;
973  }
974  }
975  if (!$fileObject->getStorage()->isOnline()) {
976  $isOnline = false;
977  }
978  }
979  // Hide
980  if (!in_array('hide', $this->disabledItems, true) && $isStorageRoot && $userMayEditStorage) {
981  $record = BackendUtility::getRecord('sys_file_storage', $fileObject->getStorage()->getUid());
982  $menuItems['hide'] = $this->DB_changeFlag(
983  'sys_file_storage',
984  $record,
985  'is_online',
986  $this->label($record['is_online'] ? 'offline' : 'online')
987  );
988  }
989  // Edit
990  if (!in_array('edit', $this->disabledItems, true) && $fileObject->checkActionPermission('write')) {
991  if (!$folder && !$isStorageRoot && $fileObject->isIndexed() && $this->backendUser->check('tables_modify', 'sys_file_metadata')) {
992  $metaData = $fileObject->_getMetaData();
993  $menuItems['edit2'] = $this->DB_edit('sys_file_metadata', $metaData['uid']);
994  }
995  if (!$folder && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'], $fileObject->getExtension()) && $fileObject->checkActionPermission('write')) {
996  $menuItems['edit'] = $this->FILE_launch($identifier, 'file_edit', 'editcontent', 'actions-page-open');
997  } elseif ($isStorageRoot && $userMayEditStorage) {
998  $menuItems['edit'] = $this->DB_edit('sys_file_storage', $fileObject->getStorage()->getUid());
999  }
1000  }
1001  // Rename
1002  if (!in_array('rename', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('rename')) {
1003  $menuItems['rename'] = $this->FILE_launch($identifier, 'file_rename', 'rename', 'actions-edit-rename');
1004  }
1005  // Upload
1006  if (!in_array('upload', $this->disabledItems, true) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
1007  $menuItems['upload'] = $this->FILE_launch($identifier, 'file_upload', 'upload', 'actions-edit-upload');
1008  }
1009  // New
1010  if (!in_array('new', $this->disabledItems, true) && $folder && $isOnline && $fileObject->checkActionPermission('write')) {
1011  $menuItems['new'] = $this->FILE_launch($identifier, 'file_newfolder', 'new', 'actions-document-new');
1012  }
1013  // Info
1014  if (!in_array('info', $this->disabledItems, true) && $fileObject->checkActionPermission('read')) {
1015  if ($isStorageRoot && $userMayViewStorage) {
1016  $menuItems['info'] = $this->DB_info('sys_file_storage', $fileObject->getStorage()->getUid());
1017  } elseif (!$folder) {
1018  $menuItems['info'] = $this->fileInfo($identifier);
1019  }
1020  }
1021  $menuItems[] = 'spacer';
1022  // Copy:
1023  if (!in_array('copy', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('read')) {
1024  $menuItems['copy'] = $this->FILE_copycut($identifier, 'copy');
1025  }
1026  // Cut:
1027  if (!in_array('cut', $this->disabledItems, true) && !$isStorageRoot && $fileObject->checkActionPermission('move')) {
1028  $menuItems['cut'] = $this->FILE_copycut($identifier, 'cut');
1029  }
1030  // Paste:
1031  $elFromAllTables = count($this->clipObj->elFromTable('_FILE'));
1032  if (!in_array('paste', $this->disabledItems, true) && $elFromAllTables && $folder && $fileObject->checkActionPermission('write')) {
1033  $elArr = $this->clipObj->elFromTable('_FILE');
1034  $selItem = reset($elArr);
1035  $clickedFileOrFolder = ResourceFactory::getInstance()->retrieveFileOrFolderObject($combinedIdentifier);
1036  $fileOrFolderInClipBoard = ResourceFactory::getInstance()->retrieveFileOrFolderObject($selItem);
1037  $elInfo = [
1038  $fileOrFolderInClipBoard->getName(),
1039  $clickedFileOrFolder->getName(),
1040  $this->clipObj->currentMode()
1041  ];
1042  if (!$fileOrFolderInClipBoard instanceof Folder || !$fileOrFolderInClipBoard->getStorage()->isWithinFolder($fileOrFolderInClipBoard, $clickedFileOrFolder)) {
1043  $menuItems['pasteinto'] = $this->FILE_paste($identifier, $selItem, $elInfo);
1044  }
1045  }
1046  $menuItems[] = 'spacer';
1047  // Delete:
1048  if (!in_array('delete', $this->disabledItems, true) && $fileObject->checkActionPermission('delete')) {
1049  if ($isStorageRoot && $userMayEditStorage) {
1050  $elInfo = [GeneralUtility::fixed_lgd_cs($fileObject->getStorage()->getName(), $this->backendUser->uc['titleLen'])];
1051  $menuItems['delete'] = $this->DB_delete('sys_file_storage', $fileObject->getStorage()->getUid(), $elInfo);
1052  } elseif (!$isStorageRoot) {
1053  $menuItems['delete'] = $this->FILE_delete($identifier);
1054  }
1055  }
1056  }
1057  // Adding external elements to the menuItems array
1058  $menuItems = $this->processingByExtClassArray($menuItems, $identifier, 0);
1059  // Processing by external functions?
1060  $menuItems = $this->externalProcessingOfFileMenuItems($menuItems);
1061  // Return the printed elements:
1062  return $this->printItems($menuItems);
1063  }
1064 
1071  public function externalProcessingOfFileMenuItems($menuItems)
1072  {
1073  return $menuItems;
1074  }
1075 
1087  public function FILE_launch($path, $moduleName, $type, $iconName, $noReturnUrl = false)
1088  {
1089  $loc = 'top.list_frame';
1090  $scriptUrl = BackendUtility::getModuleUrl($moduleName);
1091 
1092  $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)') . ';}';
1093  return $this->linkItem(
1094  $this->label($type),
1095  $this->iconFactory->getIcon($iconName, Icon::SIZE_SMALL)->render(),
1096  $editOnClick . 'top.nav.refresh();'
1097  );
1098  }
1099 
1108  public function FILE_copycut($path, $type)
1109  {
1110  $isSel = '';
1111  // Pseudo table name for use in the clipboard.
1112  $table = '_FILE';
1113  $uid = GeneralUtility::shortMD5($path);
1114  if ($this->clipObj->current === 'normal') {
1115  $isSel = $this->clipObj->isSelected($table, $uid);
1116  }
1117  $addParam = [];
1118  if ($this->listFrame) {
1119  $addParam['reloadListFrame'] = 1;
1120  }
1121  return $this->linkItem(
1122  $this->label($type),
1123  $this->iconFactory->getIcon('actions-edit-' . $type . ($isSel === $type ? '-release' : ''), Icon::SIZE_SMALL)->render(),
1124  'TYPO3.ClickMenu.fetch(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlFile($path, ($type === 'copy' ? 1 : 0), ($isSel == $type), $addParam)) . ');return false;'
1125  );
1126  }
1127 
1135  public function FILE_delete($path)
1136  {
1137  $loc = 'top.list_frame';
1138  $jsCode = $loc . '.location.href='
1139  . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_file') . '&redirect=')
1140  . '+top.rawurlencode(' . $this->frameLocation(($loc . '.document'))
1141  . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1143  '&file[delete][0][data]=' . rawurlencode($path) . '&vC=' . $this->backendUser->veriCode()
1144  );
1145  if ($this->backendUser->jsConfirmation(JsConfirmation::DELETE)) {
1146  $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($path);
1147  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:delete');
1148  $confirmMessage = sprintf(
1149  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.delete'),
1150  $fileOrFolderObject->getName()
1151  );
1152  if ($fileOrFolderObject instanceof Folder) {
1153  $confirmMessage .= BackendUtility::referenceCount('_FILE', $fileOrFolderObject->getIdentifier(), ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.referencesToFolder'));
1154  } else {
1155  $confirmMessage .= BackendUtility::referenceCount('sys_file', $fileOrFolderObject->getUid(), ' ' . $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.referencesToFile'));
1156  }
1157  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
1158  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
1159  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
1160  . $jsCode
1161  . '} top.TYPO3.Modal.dismiss(); });';
1162  }
1163  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
1164  return $this->linkItem(
1165  $this->label('delete'),
1166  $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(),
1167  $editOnClick . 'return false;'
1168  );
1169  }
1170 
1180  public function FILE_paste($path, $target, $elInfo)
1181  {
1182  $loc = 'top.list_frame';
1183 
1184  $jsCode = $loc . '.location.href='
1185  . GeneralUtility::quoteJSvalue($this->clipObj->pasteUrl('_FILE', $path, 0) . '&redirect=')
1186  . '+top.rawurlencode(' . $this->frameLocation($loc . '.document')
1187  . '.pathname+' . $this->frameLocation($loc . '.document') . '.search); top.nav.refresh();';
1188 
1189  if ($this->backendUser->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)) {
1190  $title = $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:clip_paste');
1191 
1192  $confirmMessage = sprintf(
1193  $this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.'
1194  . ($elInfo[2] === 'copy' ? 'copy' : 'move') . '_into'),
1195  $elInfo[0],
1196  $elInfo[1]
1197  );
1198 
1199  $jsCode = 'top.TYPO3.Modal.confirm(' . GeneralUtility::quoteJSvalue($title) . ', '
1200  . GeneralUtility::quoteJSvalue($confirmMessage) . ')'
1201  . '.on(\'button.clicked\', function(e) { if (e.target.name === \'ok\') {'
1202  . $jsCode
1203  . '} top.TYPO3.Modal.dismiss(); });';
1204  }
1205  $editOnClick = 'if(' . $loc . ') { ' . $jsCode . ' }';
1206  return $this->linkItem(
1207  $this->label('pasteinto'),
1208  $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render(),
1209  $editOnClick . 'return false;'
1210  );
1211  }
1212 
1219  protected function fileInfo($identifier)
1220  {
1221  return $this->DB_info('_FILE', $identifier);
1222  }
1223 
1224  /***************************************
1225  *
1226  * DRAG AND DROP
1227  *
1228  ***************************************/
1237  public function printDragDropClickMenu($table, $srcId, $dstId)
1238  {
1239  $menuItems = [];
1240  // If the drag and drop menu should apply to PAGES use this set of menu items
1241  if ($table === 'pages') {
1242  // Move Into:
1243  $menuItems['movePage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'into');
1244  // Move After:
1245  $menuItems['movePage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'move', 'after');
1246  // Copy Into:
1247  $menuItems['copyPage_into'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'into');
1248  // Copy After:
1249  $menuItems['copyPage_after'] = $this->dragDrop_copymovepage($srcId, $dstId, 'copy', 'after');
1250  }
1251  // If the drag and drop menu should apply to FOLDERS use this set of menu items
1252  if ($table === 'folders') {
1253  // Move Into:
1254  $menuItems['moveFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'move');
1255  // Copy Into:
1256  $menuItems['copyFolder_into'] = $this->dragDrop_copymovefolder($srcId, $dstId, 'copy');
1257  }
1258  // Adding external elements to the menuItems array
1259  $menuItems = $this->processingByExtClassArray($menuItems, 'dragDrop_' . $table, $srcId);
1260  // to extend this, you need to apply a Context Menu to a "virtual" table called "dragDrop_pages" or similar
1261  // Processing by external functions?
1262  $menuItems = $this->externalProcessingOfDBMenuItems($menuItems);
1263  // Return the printed elements:
1264  return $this->printItems($menuItems);
1265  }
1266 
1273  public function externalProcessingOfDragDropMenuItems($menuItems)
1274  {
1275  return $menuItems;
1276  }
1277 
1288  public function dragDrop_copymovepage($srcUid, $dstUid, $action, $into)
1289  {
1290  $negativeSign = $into === 'into' ? '' : '-';
1291  $loc = 'top.list_frame';
1292  $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=' .
1293  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_db') . '&redirect=') . '+top.rawurlencode(' .
1294  $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1296  '&cmd[pages][' . $srcUid . '][' . $action . ']=' . $negativeSign . $dstUid . '&prErr=1&vC=' .
1297  $this->backendUser->veriCode()
1298  ) . ';};top.nav.refresh();';
1299  return $this->linkItem(
1300  $this->label($action . 'Page_' . $into),
1301  $this->iconFactory->getIcon('actions-document-paste-' . $into, Icon::SIZE_SMALL)->render(),
1302  $editOnClick . 'return false;'
1303  );
1304  }
1305 
1315  public function dragDrop_copymovefolder($srcPath, $dstPath, $action)
1316  {
1317  $loc = 'top.list_frame';
1318  $editOnClick = 'if(' . $loc . '){' . $loc . '.document.location=' .
1319  GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('tce_file') . '&redirect=') . '+top.rawurlencode(' .
1320  $this->frameLocation(($loc . '.document')) . '.pathname+' . $this->frameLocation(($loc . '.document')) . '.search)+' .
1322  '&file[' . $action . '][0][data]=' . $srcPath . '&file[' . $action . '][0][target]=' . $dstPath . '&prErr=1&vC=' .
1323  $this->backendUser->veriCode()
1324  ) . ';};top.nav.refresh();';
1325  return $this->linkItem(
1326  $this->label($action . 'Folder_into'),
1327  $this->iconFactory->getIcon('apps-pagetree-drag-move-into', Icon::SIZE_SMALL)->render(),
1328  $editOnClick . 'return false;'
1329  );
1330  }
1331 
1332  /***************************************
1333  *
1334  * COMMON
1335  *
1336  **************************************/
1343  public function printItems($menuItems)
1344  {
1345  // Enable/Disable items
1346  $menuItems = $this->enableDisableItems($menuItems);
1347  // Clean up spacers
1348  $menuItems = $this->cleanUpSpacers($menuItems);
1349  // Adding JS part and return the content
1350  return $this->printLayerJScode($menuItems);
1351  }
1352 
1359  public function printLayerJScode($menuItems)
1360  {
1361  // Clipboard must not be submitted - then it's probably a copy/cut situation.
1362  if ($this->isCMlayers()) {
1363  // Create the table displayed in the clickmenu layer:
1364  // Wrap the inner table in another table to create outer border:
1365  return [
1366  'items' => $this->menuItemsForClickMenu($menuItems),
1367  'level' => $this->cmLevel
1368  ];
1369  }
1370  }
1371 
1378  public function menuItemsForClickMenu($menuItems)
1379  {
1380  $out = [];
1381  foreach ($menuItems as $cc => $i) {
1382  // MAKE horizontal spacer
1383  if (is_string($i) && $i === 'spacer') {
1384  $out[] = '<span class="list-group-item list-group-item-divider"></span>';
1385  } else {
1386  // Just make normal element:
1387  $onClick = $i[3];
1388  $onClick = preg_replace('/return[[:space:]]+hideCM\\(\\)[[:space:]]*;/i', '', $onClick);
1389  $onClick = preg_replace('/return[[:space:]]+false[[:space:]]*;/i', '', $onClick);
1390  $onClick = preg_replace('/hideCM\\(\\);/i', '', $onClick);
1391  if (!$i[5]) {
1392  $onClick .= 'TYPO3.ClickMenu.hideAll();';
1393  }
1394  $out[] = '
1395  <a href="javascript:;" class="list-group-item" onclick="' . htmlspecialchars($onClick) . '">
1396  <span class="list-group-item-icon">' . $i[2] . '</span> ' . $i[1] . '
1397  </a>';
1398  }
1399  }
1400  return $out;
1401  }
1402 
1412  public function addMenuItems($menuItems, $newMenuItems, $position = '')
1413  {
1414  if (is_array($newMenuItems)) {
1415  $pointer = 0;
1416  if ($position) {
1417  $posArr = GeneralUtility::trimExplode(',', $position, true);
1418  foreach ($posArr as $pos) {
1419  list($place, $menuEntry) = GeneralUtility::trimExplode(':', $pos, true);
1420  list($place, $placeExtra) = GeneralUtility::trimExplode('-', $place, true);
1421  // Bottom
1422  $pointer = count($menuItems);
1423  $found = false;
1424  if ($place) {
1425  switch (strtolower($place)) {
1426  case 'after':
1427  case 'before':
1428  if ($menuEntry) {
1429  $p = 1;
1430  reset($menuItems);
1431  while (true) {
1432  if ((string)key($menuItems) === $menuEntry) {
1433  $pointer = $p;
1434  $found = true;
1435  break;
1436  }
1437  if (!next($menuItems)) {
1438  break;
1439  }
1440  $p++;
1441  }
1442  if (!$found) {
1443  break;
1444  }
1445  if ($place === 'before') {
1446  $pointer--;
1447  if ($placeExtra === 'spacer' and prev($menuItems) === 'spacer') {
1448  $pointer--;
1449  }
1450  } elseif ($place === 'after') {
1451  if ($placeExtra === 'spacer' and next($menuItems) === 'spacer') {
1452  $pointer++;
1453  }
1454  }
1455  }
1456  break;
1457  default:
1458  if (strtolower($place) === 'top') {
1459  $pointer = 0;
1460  } else {
1461  $pointer = count($menuItems);
1462  }
1463  $found = true;
1464  }
1465  }
1466  if ($found) {
1467  break;
1468  }
1469  }
1470  }
1471  $pointer = max(0, $pointer);
1472  $menuItemsBefore = array_slice($menuItems, 0, $pointer ?: 0);
1473  $menuItemsAfter = array_slice($menuItems, $pointer);
1474  $menuItems = $menuItemsBefore + $newMenuItems + $menuItemsAfter;
1475  }
1476  return $menuItems;
1477  }
1478 
1489  public function linkItem($str, $icon, $onClick, $onlyCM = 0, $dontHide = 0)
1490  {
1491  return [
1492  '<a href="javascript:;" onclick="' . htmlspecialchars($onClick) . '">' . $str . $icon . '</a>',
1493  $str,
1494  $icon,
1495  $onClick,
1496  $onlyCM,
1497  $dontHide
1498  ];
1499  }
1500 
1507  public function enableDisableItems($menuItems)
1508  {
1509  if ($this->iParts[3]) {
1510  // Detect "only" mode: (only showing listed items)
1511  if ($this->iParts[3][0] === '+') {
1512  $this->iParts[3] = substr($this->iParts[3], 1);
1513  $only = true;
1514  } else {
1515  $only = false;
1516  }
1517  // Do filtering:
1518  // Transfer ONLY elements which are mentioned (or are spacers)
1519  if ($only) {
1520  $newMenuArray = [];
1521  foreach ($menuItems as $key => $value) {
1522  if (GeneralUtility::inList($this->iParts[3], $key) || is_string($value) && $value === 'spacer') {
1523  $newMenuArray[$key] = $value;
1524  }
1525  }
1526  $menuItems = $newMenuArray;
1527  } else {
1528  // Traverse all elements except those listed (just unsetting them):
1529  $elements = GeneralUtility::trimExplode(',', $this->iParts[3], true);
1530  foreach ($elements as $value) {
1531  unset($menuItems[$value]);
1532  }
1533  }
1534  }
1535  // Return processed menu items:
1536  return $menuItems;
1537  }
1538 
1545  public function cleanUpSpacers($menuItems)
1546  {
1547  // Remove doubles:
1548  $prevItemWasSpacer = false;
1549  foreach ($menuItems as $key => $value) {
1550  if (is_string($value) && $value === 'spacer') {
1551  if ($prevItemWasSpacer) {
1552  unset($menuItems[$key]);
1553  }
1554  $prevItemWasSpacer = true;
1555  } else {
1556  $prevItemWasSpacer = false;
1557  }
1558  }
1559  // Remove first:
1560  reset($menuItems);
1561  $key = key($menuItems);
1562  $value = current($menuItems);
1563  if (is_string($value) && $value === 'spacer') {
1564  unset($menuItems[$key]);
1565  }
1566  // Remove last:
1567  end($menuItems);
1568  $key = key($menuItems);
1569  $value = current($menuItems);
1570  if (is_string($value) && $value === 'spacer') {
1571  unset($menuItems[$key]);
1572  }
1573  // Return processed menu items:
1574  return $menuItems;
1575  }
1576 
1583  public function label($label)
1584  {
1585  return htmlspecialchars($this->languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.' . $label));
1586  }
1587 
1593  public function isCMlayers()
1594  {
1595  return !$this->CB;
1596  }
1597 
1604  public function frameLocation($str)
1605  {
1606  return $str . '.location';
1607  }
1608 }
printDragDropClickMenu($table, $srcId, $dstId)
Definition: ClickMenu.php:1237
addMenuItems($menuItems, $newMenuItems, $position= '')
Definition: ClickMenu.php:1412
static getRecordWSOL($table, $uid, $fields= '*', $where= '', $useDeleteClause=true, $unsetMovePointers=false)
printFileClickMenu($combinedIdentifier)
Definition: ClickMenu.php:950
urlRefForCM($url, $retUrl= '', $hideCM=true, $overrideLoc= '')
Definition: ClickMenu.php:484
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
FILE_launch($path, $moduleName, $type, $iconName, $noReturnUrl=false)
Definition: ClickMenu.php:1087
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
DB_changeFlag($table, $rec, $flagField, $title)
Definition: ClickMenu.php:917
DB_delete($table, $uid, $elInfo)
Definition: ClickMenu.php:804
FILE_paste($path, $target, $elInfo)
Definition: ClickMenu.php:1180
static viewOnClick($pageUid, $backPath= '', $rootLine=null, $anchorSection= '', $alternativeUrl= '', $additionalGetVars= '', $switchFocus=true)
DB_paste($table, $uid, $type, $elInfo)
Definition: ClickMenu.php:532
static getRecord($table, $uid, $fields= '*', $where= '', $useDeleteClause=true)
processingByExtClassArray($menuItems, $table, $uid)
Definition: ClickMenu.php:464
dragDrop_copymovefolder($srcPath, $dstPath, $action)
Definition: ClickMenu.php:1315
static linkThisScript(array $getParams=[])
dragDrop_copymovepage($srcUid, $dstUid, $action, $into)
Definition: ClickMenu.php:1288
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static referenceCount($table, $ref, $msg= '', $count=null)
linkItem($str, $icon, $onClick, $onlyCM=0, $dontHide=0)
Definition: ClickMenu.php:1489
__construct(LanguageService $languageService=null, BackendUserAuthentication $backendUser=null)
Definition: ClickMenu.php:146
DB_hideUnhide($table, $rec, $hideField)
Definition: ClickMenu.php:903