2 namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
26 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
83 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
87 $loadModules->load(
$GLOBALS[
'TBE_MODULES']);
91 $this->shortcutGroups = array(
101 $this->
getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/Toolbar/ShortcutMenu');
111 return (
bool)$this->
getBackendUser()->getTSConfigVal(
'options.enableBookmarks');
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>';
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>';
141 $shortcutMenu[] =
'<ul class="dropdown-list">';
145 foreach ($noGroupShortcuts as $shortcut) {
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']) .
152 ' . $editIcon . $deleteIcon .
'
157 krsort($groups, SORT_NUMERIC);
158 foreach ($groups as $groupId => $groupLabel) {
161 if (count($shortcutMenu) > 1) {
162 $shortcutGroup .=
'<li class="divider"></li>';
165 <li class="dropdown-header" id="shortcut-group-' . (int)$groupId .
'">
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']) .
178 ' . $editIcon . $deleteIcon .
'
181 $shortcutMenu[] = $shortcutGroup;
184 $shortcutMenu[] =
'</ul>';
186 if (count($shortcutMenu) === 2) {
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>';
193 $compiledShortcutMenu = implode(LF, $shortcutMenu);
196 return $compiledShortcutMenu;
210 $response->
getBody()->write($menuContent);
211 $response = $response->
withHeader(
'Content-Type',
'text/html; charset=utf-8');
245 $res = $databaseConnection->exec_SELECTquery(
248 '(userid = ' . (
int)$backendUser->user[
'uid'] .
' AND sc_group>=0) OR sc_group IN (' . $globalGroupIdList .
')',
255 while ($row = $databaseConnection->sql_fetch_assoc($res)) {
256 $shortcut = array(
'raw' => $row);
258 list($row[
'module_name'], $row[
'M_module_name']) = explode(
'|', $row[
'module_name']);
260 $queryParts = parse_url($row[
'url']);
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';
270 if (substr($shortcut[
'recordid'], -1) ===
',') {
271 $shortcut[
'recordid'] = substr($shortcut[
'recordid'], 0, -1);
274 $shortcut[
'type'] =
'other';
277 $moduleName = $row[
'M_module_name'] ?: $row[
'module_name'];
278 if (!$backendUser->isAdmin()) {
279 if (!isset($this->
getLanguageService()->moduleLabels[
'tabs_images'][$moduleName .
'_tab'])) {
287 if (!$backendUser->isInWebMount($pageId)) {
292 if (!$backendUser->doesUserHaveAccess($pageRow, ($perms = 1))) {
297 $moduleParts = explode(
'_', $moduleName);
298 $shortcutGroup = (int)$row[
'sc_group'];
299 if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
302 $lastGroup = $shortcutGroup;
304 if ($row[
'description']) {
305 $shortcut[
'label'] = $row[
'description'];
309 $shortcut[
'group'] = $shortcutGroup;
311 $shortcut[
'iconTitle'] = $this->
getShortcutIconTitle($shortcut[
'label'], $row[
'module_name'], $row[
'M_module_name']);
325 protected function getTokenUrl(
$url)
327 $parsedUrl = parse_url(
$url);
328 parse_str($parsedUrl[
'query'], $parameters);
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);
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'];
350 $route = $router->match($routePath);
352 $routeIdentifier = $route->getOption(
'_identifier');
355 unset($parameters[
'route']);
356 $url = (string)$uriBuilder->buildUriFromRoute($routeIdentifier, $parameters);
358 }
catch (\TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException $e) {
374 foreach ($this->shortcuts as $shortcut) {
375 if ($shortcut[
'group'] == $groupId) {
390 $returnShortcut =
false;
391 foreach ($this->shortcuts as $shortcut) {
392 if ($shortcut[
'raw'][
'uid'] == (
int)$shortcutId) {
393 $returnShortcut = $shortcut;
397 return $returnShortcut;
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]);
421 if (!empty($this->shortcutGroups)) {
423 foreach ($groups as $groupId => $groupLabel) {
424 $this->shortcutGroups[$groupId * -1] = $groupLabel;
428 $this->shortcutGroups[self::SUPERGLOBAL_GROUP] = 1;
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);
437 $label = $languageService->getLL(
'bookmark_group',
true) .
' ' . abs($groupId);
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);
447 $this->shortcutGroups[$groupId] = $label;
464 $selectedShortcutId = (int)(isset($parsedBody[
'shortcutId']) ? $parsedBody[
'shortcutId'] : $queryParams[
'shortcutId']);
465 $selectedShortcutGroupId = (int)(isset($parsedBody[
'shortcutGroup']) ? $parsedBody[
'shortcutGroup'] : $queryParams[
'shortcutGroup']);
471 if ((
int)$groupId < 0) {
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']) .
'">
485 <div class="form-group">
486 <select class="form-control" name="shortcut-group">';
488 $content .=
'<option value="' . (int)$shortcutGroupId .
'"' . ($selectedShortcutGroupId == $shortcutGroupId ?
' selected="selected"' :
'') .
'>' . htmlspecialchars($shortcutGroupTitle) .
'</option>';
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">
497 $response->
getBody()->write($content);
498 $response = $response->
withHeader(
'Content-Type',
'text/html; charset=utf-8');
515 $shortcutId = (int)(isset($parsedBody[
'shortcutId']) ? $parsedBody[
'shortcutId'] : $queryParams[
'shortcutId']);
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) {
524 $response->
getBody()->write(json_encode([
'success' => $success]));
542 $shortcutName =
'Shortcut';
543 $shortcutNamePrepend =
'';
544 $url = isset($parsedBody[
'url']) ? $parsedBody[
'url'] : $queryParams[
'url'];
547 if (!empty($parsedBody[
'displayName'])) {
548 $shortcutName = $parsedBody[
'displayName'];
553 $queryParts = parse_url(
$url);
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']]);
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);
570 $shortcut[
'type'] =
'other';
571 $shortcut[
'table'] =
'';
572 $shortcut[
'recordid'] = 0;
576 if (!empty($queryParameters[
'id']) && preg_match(
'/^[0-9]+:/', $queryParameters[
'id'])) {
579 $resource = $resourceFactory->getObjectFromCombinedIdentifier($queryParameters[
'id']);
580 $shortcutName = trim($shortcutNamePrepend .
' ' . $resource->getName());
584 $pageId = (int)($shortcut[
'pid'] ?: ($shortcut[
'recordid'] ?: $this->
getLinkedPageId(
$url)));
591 if ($shortcut[
'type'] ===
'other') {
592 if (empty($shortcutName)) {
593 $shortcutName = $page[
'title'];
595 $shortcutName .=
' (' . $page[
'title'] .
')';
598 $shortcutName = $shortcutNamePrepend .
' ' .
599 $languageService->sL(
$GLOBALS[
'TCA'][$shortcut[
'table']][
'ctrl'][
'title']) .
600 ' (' . $page[
'title'] .
')';
602 }
elseif ($shortcut[
'table'] !==
'' && $shortcut[
'type'] !==
'other') {
603 $shortcutName = $shortcutNamePrepend .
' ' .
604 $languageService->sL(
$GLOBALS[
'TCA'][$shortcut[
'table']][
'ctrl'][
'title']);
623 $shortcutCreated =
'failed';
625 if (!empty($module) && !empty(
$url)) {
626 $shortcutCreated =
'alreadyExists';
633 $response->
getBody()->write($shortcutCreated);
634 $response = $response->
withHeader(
'Content-Type',
'text/html; charset=utf-8');
653 if ($shortcutName ===
'Shortcut' && !empty($lS->moduleLabels[
'labels'][$module .
'_tablabel'])) {
654 $shortcutName = $lS->moduleLabels[
'labels'][$module .
'_tablabel'];
660 'module_name' => $module .
'|' . $motherModule,
662 'description' => $shortcutName,
666 $db->exec_INSERTquery(
'sys_be_shortcuts', $fieldValues);
668 $shortcutCreated =
'failed';
669 if ($db->sql_affected_rows() === 1) {
670 $shortcutCreated =
'success';
673 return $shortcutCreated;
688 'userid = :userid AND url = :url'
691 $statement->bindValues([
696 $statement->execute();
700 return !empty($rows);
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']);
722 $addUserWhere = !$backendUser->isAdmin() ?
' AND userid=' . (int)$backendUser->user[
'uid'] :
'';
723 $fieldValues = array(
724 'description' => $shortcutName,
725 'sc_group' => $shortcutGroupId
727 if ($fieldValues[
'sc_group'] < 0 && !$backendUser->isAdmin()) {
728 $fieldValues[
'sc_group'] = 0;
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);
735 $response->
getBody()->write(
'failed');
737 return $response->
withHeader(
'Content-Type',
'html');
748 return isset($this->shortcutGroups[$groupId]) ? $this->shortcutGroups[$groupId] :
'';
758 $globalGroups = array();
759 foreach ($this->shortcutGroups as $groupId => $groupLabel) {
761 $globalGroups[$groupId] = $groupLabel;
764 return $globalGroups;
775 foreach ($this->shortcuts as $shortcut) {
776 $groups[$shortcut[
'group']] = $this->shortcutGroups[$shortcut[
'group']];
778 return array_unique($groups);
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'];
798 if ($shortcut[
'type'] ==
'edit') {
801 $selectFields[] =
'uid';
802 $selectFields[] =
'pid';
803 if ($table ==
'pages') {
804 $selectFields[] =
'module';
805 $selectFields[] =
'extendToSubpages';
806 $selectFields[] =
'doktype';
808 if (is_array(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns'])) {
809 $selectFields = array_merge($selectFields,
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns']);
811 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'type']) {
812 $selectFields[] =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'type'];
814 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'typeicon_column']) {
815 $selectFields[] =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'typeicon_column'];
817 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS']) {
818 $selectFields[] =
't3ver_state';
821 $selectFields = array_unique($selectFields);
822 $permissionClause = $table ===
'pages' && $this->perms_clause ?
' AND ' . $this->perms_clause :
'';
823 $sqlQueryParts = array(
824 'SELECT' => implode(
',', $selectFields),
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>';
836 $icon =
'<span title="' . $titleAttribute .
'">' . $this->iconFactory->getIcon(
'mimetypes-text-html',
Icon::SIZE_SMALL)->render() .
'</span>';
839 $icon =
'<span title="' . $titleAttribute .
'">' . $this->iconFactory->getIcon(
'mimetypes-word',
Icon::SIZE_SMALL)->render() .
'</span>';
842 if ($languageService->moduleLabels[
'tabs_images'][$row[
'module_name'] .
'_tab']) {
843 $icon = $languageService->moduleLabels[
'tabs_images'][$row[
'module_name'] .
'_tab'];
845 $icon = str_replace(
'mod/file/list/list.gif',
'mod/file/file.gif', $icon);
850 $icon =
'<img src="' . htmlspecialchars($icon) .
'" alt="' . $titleAttribute .
'" width="16">';
852 $icon =
'<span title="' . $titleAttribute .
'">' . $this->iconFactory->getIcon(
'empty-empty',
Icon::SIZE_SMALL)->render() .
'</span>';
869 if (substr($moduleName, 0, 5) ==
'xMOD_') {
870 $title = substr($moduleName, 5);
872 $splitModuleName = explode(
'_', $moduleName);
873 $title = $languageService->moduleLabels[
'tabs'][$splitModuleName[0] .
'_tab'];
874 if (count($splitModuleName) > 1) {
875 $title .=
'>' . $languageService->moduleLabels[
'tabs'][($moduleName .
'_tab')];
878 if ($parentModuleName) {
879 $title .=
' (' . $parentModuleName .
')';
881 $title .=
': ' . $shortcutLabel;
893 return preg_replace(
'/.*[\\?&]id=([^&]+).*/',
'$1',
$url);