TYPO3  7.6
ShortcutToolbarItem.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
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 
26 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
31 
36 {
40  const SUPERGLOBAL_GROUP = -100;
41 
45  public $perms_clause;
46 
50  public $fieldArray;
51 
57  protected $shortcuts;
58 
62  protected $shortcutGroups;
63 
70  protected $groupLabels;
71 
75  protected $iconFactory;
76 
80  public function __construct()
81  {
82  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
83  if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
84  $this->getLanguageService()->includeLLFile('EXT:lang/locallang_misc.xlf');
85  // Needed to get the correct icons when reloading the menu after saving it
86  $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
87  $loadModules->load($GLOBALS['TBE_MODULES']);
88  }
89 
90  // By default, 5 groups are set
91  $this->shortcutGroups = array(
92  1 => '1',
93  2 => '1',
94  3 => '1',
95  4 => '1',
96  5 => '1'
97  );
98  $this->shortcutGroups = $this->initShortcutGroups();
99  $this->shortcuts = $this->initShortcuts();
100 
101  $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ShortcutMenu');
102  }
103 
109  public function checkAccess()
110  {
111  return (bool)$this->getBackendUser()->getTSConfigVal('options.enableBookmarks');
112  }
113 
119  public function getItem()
120  {
121  $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', true);
122  return '<span title="' . $title . '">' . $this->iconFactory->getIcon('apps-toolbar-menu-shortcut', Icon::SIZE_SMALL)->render('inline') . '</span>';
123  }
124 
130  public function getDropDown()
131  {
132  $languageService = $this->getLanguageService();
133  $shortcutGroup = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksGroup', true);
134  $shortcutEdit = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksEdit', true);
135  $shortcutDelete = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksDelete', true);
136  $editIcon = '<a href="#" class="dropdown-list-link-edit shortcut-edit" ' . $shortcutEdit . '>'
137  . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render('inline') . '</a>';
138  $deleteIcon = '<a href="#" class="dropdown-list-link-delete shortcut-delete" title="' . $shortcutDelete . '">'
139  . $this->iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)->render('inline') . '</a>';
140 
141  $shortcutMenu[] = '<ul class="dropdown-list">';
142 
143  // Render shortcuts with no group (group id = 0) first
144  $noGroupShortcuts = $this->getShortcutsByGroup(0);
145  foreach ($noGroupShortcuts as $shortcut) {
146  $shortcutMenu[] = '
147  <li class="shortcut" data-shortcutid="' . (int)$shortcut['raw']['uid'] . '">
148  <a class="dropdown-list-link dropdown-link-list-add-editdelete" href="#" onclick="' . htmlspecialchars($shortcut['action']) . ' return false;">' .
149  $shortcut['icon'] . ' ' .
150  htmlspecialchars($shortcut['label']) .
151  '</a>
152  ' . $editIcon . $deleteIcon . '
153  </li>';
154  }
155  // Now render groups and the contained shortcuts
156  $groups = $this->getGroupsFromShortcuts();
157  krsort($groups, SORT_NUMERIC);
158  foreach ($groups as $groupId => $groupLabel) {
159  if ($groupId != 0) {
160  $shortcutGroup = '';
161  if (count($shortcutMenu) > 1) {
162  $shortcutGroup .= '<li class="divider"></li>';
163  }
164  $shortcutGroup .= '
165  <li class="dropdown-header" id="shortcut-group-' . (int)$groupId . '">
166  ' . $groupLabel . '
167  </li>';
168  $shortcuts = $this->getShortcutsByGroup($groupId);
169  $i = 0;
170  foreach ($shortcuts as $shortcut) {
171  $i++;
172  $shortcutGroup .= '
173  <li class="shortcut" data-shortcutid="' . (int)$shortcut['raw']['uid'] . '" data-shortcutgroup="' . (int)$groupId . '">
174  <a class="dropdown-list-link dropdown-link-list-add-editdelete" href="#" onclick="' . htmlspecialchars($shortcut['action']) . ' return false;">' .
175  $shortcut['icon'] . ' ' .
176  htmlspecialchars($shortcut['label']) .
177  '</a>
178  ' . $editIcon . $deleteIcon . '
179  </li>';
180  }
181  $shortcutMenu[] = $shortcutGroup;
182  }
183  }
184  $shortcutMenu[] = '</ul>';
185 
186  if (count($shortcutMenu) === 2) {
187  // No shortcuts added yet, show a small help message how to add shortcuts
188  $title = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', true);
189  $icon = '<span title="' . $title . '">' . $this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render('inline') . '</span>';
190  $label = str_replace('%icon%', $icon, $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmarkDescription', true));
191  $compiledShortcutMenu = '<p>' . $label . '</p>';
192  } else {
193  $compiledShortcutMenu = implode(LF, $shortcutMenu);
194  }
195 
196  return $compiledShortcutMenu;
197  }
198 
207  {
208  $menuContent = $this->getDropDown();
209 
210  $response->getBody()->write($menuContent);
211  $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
212  return $response;
213  }
214 
220  public function getAdditionalAttributes()
221  {
222  return array();
223  }
224 
230  public function hasDropDown()
231  {
232  return true;
233  }
234 
240  protected function initShortcuts()
241  {
242  $databaseConnection = $this->getDatabaseConnection();
243  $globalGroupIdList = implode(',', array_keys($this->getGlobalShortcutGroups()));
244  $backendUser = $this->getBackendUser();
245  $res = $databaseConnection->exec_SELECTquery(
246  '*',
247  'sys_be_shortcuts',
248  '(userid = ' . (int)$backendUser->user['uid'] . ' AND sc_group>=0) OR sc_group IN (' . $globalGroupIdList . ')',
249  '',
250  'sc_group,sorting'
251  );
252  // Traverse shortcuts
253  $lastGroup = 0;
254  $shortcuts = array();
255  while ($row = $databaseConnection->sql_fetch_assoc($res)) {
256  $shortcut = array('raw' => $row);
257 
258  list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
259 
260  $queryParts = parse_url($row['url']);
261  $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
262  if ($row['module_name'] === 'xMOD_alt_doc.php' && is_array($queryParameters['edit'])) {
263  $shortcut['table'] = key($queryParameters['edit']);
264  $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
265  if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'edit') {
266  $shortcut['type'] = 'edit';
267  } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'new') {
268  $shortcut['type'] = 'new';
269  }
270  if (substr($shortcut['recordid'], -1) === ',') {
271  $shortcut['recordid'] = substr($shortcut['recordid'], 0, -1);
272  }
273  } else {
274  $shortcut['type'] = 'other';
275  }
276  // Check for module access
277  $moduleName = $row['M_module_name'] ?: $row['module_name'];
278  if (!$backendUser->isAdmin()) {
279  if (!isset($this->getLanguageService()->moduleLabels['tabs_images'][$moduleName . '_tab'])) {
280  // Nice hack to check if the user has access to this module
281  // - otherwise the translation label would not have been loaded :-)
282  continue;
283  }
284  $pageId = $this->getLinkedPageId($row['url']);
286  // Check for webmount access
287  if (!$backendUser->isInWebMount($pageId)) {
288  continue;
289  }
290  // Check for record access
291  $pageRow = BackendUtility::getRecord('pages', $pageId);
292  if (!$backendUser->doesUserHaveAccess($pageRow, ($perms = 1))) {
293  continue;
294  }
295  }
296  }
297  $moduleParts = explode('_', $moduleName);
298  $shortcutGroup = (int)$row['sc_group'];
299  if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
300  $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
301  }
302  $lastGroup = $shortcutGroup;
303 
304  if ($row['description']) {
305  $shortcut['label'] = $row['description'];
306  } else {
307  $shortcut['label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts['query']), 150);
308  }
309  $shortcut['group'] = $shortcutGroup;
310  $shortcut['icon'] = $this->getShortcutIcon($row, $shortcut);
311  $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcut['label'], $row['module_name'], $row['M_module_name']);
312  $shortcut['action'] = 'jump(' . GeneralUtility::quoteJSvalue($this->getTokenUrl($row['url'])) . ',' . GeneralUtility::quoteJSvalue($moduleName) . ',' . GeneralUtility::quoteJSvalue($moduleParts[0]) . ', ' . (int)$pageId . ');';
313 
314  $shortcuts[] = $shortcut;
315  }
316  return $shortcuts;
317  }
318 
325  protected function getTokenUrl($url)
326  {
327  $parsedUrl = parse_url($url);
328  parse_str($parsedUrl['query'], $parameters);
329 
330  // parse the returnUrl and replace the module token of it
331  if (isset($parameters['returnUrl'])) {
332  $parsedReturnUrl = parse_url($parameters['returnUrl']);
333  parse_str($parsedReturnUrl['query'], $returnUrlParameters);
334  if (strpos($parsedReturnUrl['path'], 'index.php') !== false && isset($returnUrlParameters['M'])) {
335  $module = $returnUrlParameters['M'];
336  $returnUrl = BackendUtility::getModuleUrl($module, $returnUrlParameters);
337  $parameters['returnUrl'] = $returnUrl;
338  $url = $parsedUrl['path'] . '?' . http_build_query($parameters);
339  }
340  }
341 
342  if (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['M'])) {
343  $module = $parameters['M'];
344  $url = BackendUtility::getModuleUrl($module, $parameters);
345  } elseif (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['route'])) {
346  $routePath = $parameters['route'];
348  $router = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Router::class);
349  try {
350  $route = $router->match($routePath);
351  if ($route) {
352  $routeIdentifier = $route->getOption('_identifier');
354  $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
355  unset($parameters['route']);
356  $url = (string)$uriBuilder->buildUriFromRoute($routeIdentifier, $parameters);
357  }
358  } catch (\TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException $e) {
359  $url = '';
360  }
361  }
362  return $url;
363  }
364 
371  protected function getShortcutsByGroup($groupId)
372  {
373  $shortcuts = array();
374  foreach ($this->shortcuts as $shortcut) {
375  if ($shortcut['group'] == $groupId) {
376  $shortcuts[] = $shortcut;
377  }
378  }
379  return $shortcuts;
380  }
381 
388  protected function getShortcutById($shortcutId)
389  {
390  $returnShortcut = false;
391  foreach ($this->shortcuts as $shortcut) {
392  if ($shortcut['raw']['uid'] == (int)$shortcutId) {
393  $returnShortcut = $shortcut;
394  continue;
395  }
396  }
397  return $returnShortcut;
398  }
399 
405  protected function initShortcutGroups()
406  {
407  $languageService = $this->getLanguageService();
408  $backendUser = $this->getBackendUser();
409  // Groups from TSConfig
410  $bookmarkGroups = $backendUser->getTSConfigProp('options.bookmarkGroups');
411  if (is_array($bookmarkGroups) && !empty($bookmarkGroups)) {
412  foreach ($bookmarkGroups as $groupId => $label) {
413  if (!empty($label)) {
414  $this->shortcutGroups[$groupId] = (string)$label;
415  } elseif ($backendUser->isAdmin()) {
416  unset($this->shortcutGroups[$groupId]);
417  }
418  }
419  }
420  // Generate global groups, all global groups have negative IDs.
421  if (!empty($this->shortcutGroups)) {
422  $groups = $this->shortcutGroups;
423  foreach ($groups as $groupId => $groupLabel) {
424  $this->shortcutGroups[$groupId * -1] = $groupLabel;
425  }
426  }
427  // Group -100 is kind of superglobal and can't be changed.
428  $this->shortcutGroups[self::SUPERGLOBAL_GROUP] = 1;
429  // Add labels
430  foreach ($this->shortcutGroups as $groupId => $groupLabel) {
431  $groupId = (int)$groupId;
432  $label = $groupLabel;
433  if ($groupLabel == '1') {
434  $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_group_' . abs($groupId), true);
435  if (empty($label)) {
436  // Fallback label
437  $label = $languageService->getLL('bookmark_group', true) . ' ' . abs($groupId);
438  }
439  }
440  if ($groupId < 0) {
441  // Global group
442  $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_global', true) . ': ' . (!empty($label) ? $label : abs($groupId));
443  if ($groupId === self::SUPERGLOBAL_GROUP) {
444  $label = $languageService->getLL('bookmark_global', true) . ': ' . $languageService->getLL('bookmark_all', true);
445  }
446  }
447  $this->shortcutGroups[$groupId] = $label;
448  }
449  return $this->shortcutGroups;
450  }
451 
460  {
461  $parsedBody = $request->getParsedBody();
462  $queryParams = $request->getQueryParams();
463 
464  $selectedShortcutId = (int)(isset($parsedBody['shortcutId']) ? $parsedBody['shortcutId'] : $queryParams['shortcutId']);
465  $selectedShortcutGroupId = (int)(isset($parsedBody['shortcutGroup']) ? $parsedBody['shortcutGroup'] : $queryParams['shortcutGroup']);
466  $selectedShortcut = $this->getShortcutById($selectedShortcutId);
467 
469  if (!$this->getBackendUser()->isAdmin()) {
470  foreach ($shortcutGroups as $groupId => $groupName) {
471  if ((int)$groupId < 0) {
472  unset($shortcutGroups[$groupId]);
473  }
474  }
475  }
476 
477  // build the form
478  $content = '
479  <form class="shortcut-form" role="form">
480  <div class="form-group">
481  <input type="text" class="form-control" name="shortcut-title" value="' . htmlspecialchars($selectedShortcut['label']) . '">
482  </div>';
483 
484  $content .= '
485  <div class="form-group">
486  <select class="form-control" name="shortcut-group">';
487  foreach ($shortcutGroups as $shortcutGroupId => $shortcutGroupTitle) {
488  $content .= '<option value="' . (int)$shortcutGroupId . '"' . ($selectedShortcutGroupId == $shortcutGroupId ? ' selected="selected"' : '') . '>' . htmlspecialchars($shortcutGroupTitle) . '</option>';
489  }
490  $content .= '
491  </select>
492  </div>
493  <input type="button" class="btn btn-default shortcut-form-cancel" value="Cancel">
494  <input type="button" class="btn btn-success shortcut-form-save" value="Save">
495  </form>';
496 
497  $response->getBody()->write($content);
498  $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
499  return $response;
500  }
501 
510  {
511  $parsedBody = $request->getParsedBody();
512  $queryParams = $request->getQueryParams();
513 
514  $databaseConnection = $this->getDatabaseConnection();
515  $shortcutId = (int)(isset($parsedBody['shortcutId']) ? $parsedBody['shortcutId'] : $queryParams['shortcutId']);
516  $fullShortcut = $this->getShortcutById($shortcutId);
517  $success = false;
518  if ($fullShortcut['raw']['userid'] == $this->getBackendUser()->user['uid']) {
519  $databaseConnection->exec_DELETEquery('sys_be_shortcuts', 'uid = ' . $shortcutId);
520  if ($databaseConnection->sql_affected_rows() === 1) {
521  $success = true;
522  }
523  }
524  $response->getBody()->write(json_encode(['success' => $success]));
525  return $response;
526  }
527 
536  {
537  $languageService = $this->getLanguageService();
538  $parsedBody = $request->getParsedBody();
539  $queryParams = $request->getQueryParams();
540 
541  // Default name
542  $shortcutName = 'Shortcut';
543  $shortcutNamePrepend = '';
544  $url = isset($parsedBody['url']) ? $parsedBody['url'] : $queryParams['url'];
545 
546  // Use given display name
547  if (!empty($parsedBody['displayName'])) {
548  $shortcutName = $parsedBody['displayName'];
549  }
550 
551  // Determine shortcut type
552  $url = rawurldecode($url);
553  $queryParts = parse_url($url);
554  $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], true);
555 
556  // Proceed only if no scheme is defined, as URL is expected to be relative
557  if (empty($queryParts['scheme'])) {
558  if (is_array($queryParameters['edit'])) {
559  $shortcut['table'] = key($queryParameters['edit']);
560  $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
561  $shortcut['pid'] = BackendUtility::getRecord($shortcut['table'], $shortcut['recordid'])['pid'];
562  if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'edit') {
563  $shortcut['type'] = 'edit';
564  $shortcutNamePrepend = $languageService->getLL('shortcut_edit', true);
565  } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'new') {
566  $shortcut['type'] = 'new';
567  $shortcutNamePrepend = $languageService->getLL('shortcut_create', true);
568  }
569  } else {
570  $shortcut['type'] = 'other';
571  $shortcut['table'] = '';
572  $shortcut['recordid'] = 0;
573  }
574 
575  // Check if given id is a combined identifier
576  if (!empty($queryParameters['id']) && preg_match('/^[0-9]+:/', $queryParameters['id'])) {
577  try {
578  $resourceFactory = ResourceFactory::getInstance();
579  $resource = $resourceFactory->getObjectFromCombinedIdentifier($queryParameters['id']);
580  $shortcutName = trim($shortcutNamePrepend . ' ' . $resource->getName());
581  } catch (ResourceDoesNotExistException $e) {}
582  } else {
583  // Lookup the title of this page and use it as default description
584  $pageId = (int)($shortcut['pid'] ?: ($shortcut['recordid'] ?: $this->getLinkedPageId($url)));
585  $page = FALSE;
586  if ($pageId) {
587  $page = BackendUtility::getRecord('pages', $pageId);
588  }
589  if (!empty($page)) {
590  // Set the name to the title of the page
591  if ($shortcut['type'] === 'other') {
592  if (empty($shortcutName)) {
593  $shortcutName = $page['title'];
594  } else {
595  $shortcutName .= ' (' . $page['title'] . ')';
596  }
597  } else {
598  $shortcutName = $shortcutNamePrepend . ' ' .
599  $languageService->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) .
600  ' (' . $page['title'] . ')';
601  }
602  } elseif ($shortcut['table'] !== '' && $shortcut['type'] !== 'other') {
603  $shortcutName = $shortcutNamePrepend . ' ' .
604  $languageService->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']);
605  }
606  }
607 
608  return $this->tryAddingTheShortcut($response, $url, $shortcutName);
609  }
610  }
611 
620  protected function tryAddingTheShortcut(ResponseInterface $response, $url, $shortcutName)
621  {
622  $module = GeneralUtility::_POST('module');
623  $shortcutCreated = 'failed';
624 
625  if (!empty($module) && !empty($url)) {
626  $shortcutCreated = 'alreadyExists';
627 
629  $shortcutCreated = $this->addShortcut($url, $shortcutName, $module);
630  }
631  }
632 
633  $response->getBody()->write($shortcutCreated);
634  $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
635  return $response;
636  }
637 
647  protected function addShortcut($url, $shortcutName, $module)
648  {
649  // Shorts
650  $db = $this->getDatabaseConnection();
651  $lS = $this->getLanguageService();
652 
653  if ($shortcutName === 'Shortcut' && !empty($lS->moduleLabels['labels'][$module . '_tablabel'])) {
654  $shortcutName = $lS->moduleLabels['labels'][$module . '_tablabel'];
655  }
656 
657  $motherModule = GeneralUtility::_POST('motherModName');
658  $fieldValues = [
659  'userid' => $this->getBackendUser()->user['uid'],
660  'module_name' => $module . '|' . $motherModule,
661  'url' => $url,
662  'description' => $shortcutName,
663  'sorting' => $GLOBALS['EXEC_TIME']
664  ];
665 
666  $db->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
667 
668  $shortcutCreated = 'failed';
669  if ($db->sql_affected_rows() === 1) {
670  $shortcutCreated = 'success';
671  }
672 
673  return $shortcutCreated;
674  }
675 
683  protected function shortcutExists($url)
684  {
685  $statement = $this->getDatabaseConnection()->prepare_SELECTquery(
686  'uid',
687  'sys_be_shortcuts',
688  'userid = :userid AND url = :url'
689  );
690 
691  $statement->bindValues([
692  ':userid' => $this->getBackendUser()->user['uid'],
693  ':url' => $url
694  ]);
695 
696  $statement->execute();
697  $rows = $statement->fetch(PreparedStatement::FETCH_ASSOC);
698  $statement->free();
699 
700  return !empty($rows);
701  }
702 
712  {
713  $parsedBody = $request->getParsedBody();
714  $queryParams = $request->getQueryParams();
715 
716  $databaseConnection = $this->getDatabaseConnection();
717  $backendUser = $this->getBackendUser();
718  $shortcutId = (int)(isset($parsedBody['shortcutId']) ? $parsedBody['shortcutId'] : $queryParams['shortcutId']);
719  $shortcutName = strip_tags(isset($parsedBody['shortcutTitle']) ? $parsedBody['shortcutTitle'] : $queryParams['shortcutTitle']);
720  $shortcutGroupId = (int)(isset($parsedBody['shortcutGroup']) ? $parsedBody['shortcutGroup'] : $queryParams['shortcutGroup']);
721  // Users can only modify their own shortcuts (except admins)
722  $addUserWhere = !$backendUser->isAdmin() ? ' AND userid=' . (int)$backendUser->user['uid'] : '';
723  $fieldValues = array(
724  'description' => $shortcutName,
725  'sc_group' => $shortcutGroupId
726  );
727  if ($fieldValues['sc_group'] < 0 && !$backendUser->isAdmin()) {
728  $fieldValues['sc_group'] = 0;
729  }
730  $databaseConnection->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
731  $affectedRows = $databaseConnection->sql_affected_rows();
732  if ($affectedRows == 1) {
733  $response->getBody()->write($shortcutName);
734  } else {
735  $response->getBody()->write('failed');
736  }
737  return $response->withHeader('Content-Type', 'html');
738  }
739 
746  protected function getShortcutGroupLabel($groupId)
747  {
748  return isset($this->shortcutGroups[$groupId]) ? $this->shortcutGroups[$groupId] : '';
749  }
750 
756  protected function getGlobalShortcutGroups()
757  {
758  $globalGroups = array();
759  foreach ($this->shortcutGroups as $groupId => $groupLabel) {
760  if ($groupId < 0) {
761  $globalGroups[$groupId] = $groupLabel;
762  }
763  }
764  return $globalGroups;
765  }
766 
772  protected function getGroupsFromShortcuts()
773  {
774  $groups = array();
775  foreach ($this->shortcuts as $shortcut) {
776  $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
777  }
778  return array_unique($groups);
779  }
780 
788  protected function getShortcutIcon($row, $shortcut)
789  {
790  $databaseConnection = $this->getDatabaseConnection();
791  $languageService = $this->getLanguageService();
792  $titleAttribute = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', true);
793  switch ($row['module_name']) {
794  case 'xMOD_alt_doc.php':
795  $table = $shortcut['table'];
796  $recordid = $shortcut['recordid'];
797  $icon = '';
798  if ($shortcut['type'] == 'edit') {
799  // Creating the list of fields to include in the SQL query:
800  $selectFields = $this->fieldArray;
801  $selectFields[] = 'uid';
802  $selectFields[] = 'pid';
803  if ($table == 'pages') {
804  $selectFields[] = 'module';
805  $selectFields[] = 'extendToSubpages';
806  $selectFields[] = 'doktype';
807  }
808  if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
809  $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
810  }
811  if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
812  $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
813  }
814  if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
815  $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
816  }
817  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
818  $selectFields[] = 't3ver_state';
819  }
820  // Unique list!
821  $selectFields = array_unique($selectFields);
822  $permissionClause = $table === 'pages' && $this->perms_clause ? ' AND ' . $this->perms_clause : '';
823  $sqlQueryParts = array(
824  'SELECT' => implode(',', $selectFields),
825  'FROM' => $table,
826  'WHERE' => 'uid IN (' . $recordid . ') ' . $permissionClause . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table)
827  );
828  $result = $databaseConnection->exec_SELECT_queryArray($sqlQueryParts);
829  $row = $databaseConnection->sql_fetch_assoc($result);
830  $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIconForRecord($table, (array)$row, Icon::SIZE_SMALL)->render() . '</span>';
831  } elseif ($shortcut['type'] == 'new') {
832  $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIconForRecord($table, array(), Icon::SIZE_SMALL)->render() . '</span>';
833  }
834  break;
835  case 'file_edit':
836  $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon('mimetypes-text-html', Icon::SIZE_SMALL)->render() . '</span>';
837  break;
838  case 'wizard_rte':
839  $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon('mimetypes-word', Icon::SIZE_SMALL)->render() . '</span>';
840  break;
841  default:
842  if ($languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab']) {
843  $icon = $languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab'];
844  // Change icon of fileadmin references - otherwise it doesn't differ with Web->List
845  $icon = str_replace('mod/file/list/list.gif', 'mod/file/file.gif', $icon);
846  if (GeneralUtility::isAbsPath($icon)) {
847  $icon = '../' . PathUtility::stripPathSitePrefix($icon);
848  }
849  // @todo: hardcoded width as we don't have a way to address module icons with an API yet.
850  $icon = '<img src="' . htmlspecialchars($icon) . '" alt="' . $titleAttribute . '" width="16">';
851  } else {
852  $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>';
853  }
854  }
855  return $icon;
856  }
857 
866  protected function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '')
867  {
868  $languageService = $this->getLanguageService();
869  if (substr($moduleName, 0, 5) == 'xMOD_') {
870  $title = substr($moduleName, 5);
871  } else {
872  $splitModuleName = explode('_', $moduleName);
873  $title = $languageService->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
874  if (count($splitModuleName) > 1) {
875  $title .= '>' . $languageService->moduleLabels['tabs'][($moduleName . '_tab')];
876  }
877  }
878  if ($parentModuleName) {
879  $title .= ' (' . $parentModuleName . ')';
880  }
881  $title .= ': ' . $shortcutLabel;
882  return $title;
883  }
884 
891  protected function getLinkedPageId($url)
892  {
893  return preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
894  }
895 
901  public function getIndex()
902  {
903  return 20;
904  }
905 
911  protected function getBackendUser()
912  {
913  return $GLOBALS['BE_USER'];
914  }
915 
921  protected function getPageRenderer()
922  {
923  return GeneralUtility::makeInstance(PageRenderer::class);
924  }
925 
931  protected function getLanguageService()
932  {
933  return $GLOBALS['LANG'];
934  }
935 
941  protected function getDatabaseConnection()
942  {
943  return $GLOBALS['TYPO3_DB'];
944  }
945 }