2 declare(strict_types = 1);
72 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
73 $this->moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
74 $this->moduleLoader->load(
$GLOBALS[
'TBE_MODULES']);
88 foreach ($this->shortcuts as $shortcut) {
89 if ($shortcut[
'raw'][
'uid'] === $shortcutId) {
107 foreach ($this->shortcuts as $shortcut) {
108 if ($shortcut[
'group'] === $groupId) {
127 if ((
int)$groupId < 0) {
145 foreach ($this->shortcuts as $shortcut) {
146 $groups[$shortcut[
'group']] = $this->shortcutGroups[$shortcut[
'group']];
149 return array_unique($groups);
160 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
161 ->getQueryBuilderForTable(
'sys_be_shortcuts');
162 $queryBuilder->getRestrictions()->removeAll();
164 $uid = $queryBuilder->select(
'uid')
165 ->from(
'sys_be_shortcuts')
167 $queryBuilder->expr()->eq(
169 $queryBuilder->createNamedParameter($this->getBackendUser()->user[
'uid'], \PDO::PARAM_INT)
171 $queryBuilder->expr()->eq(
173 $queryBuilder->createNamedParameter($url, \PDO::PARAM_STR)
192 public function addShortcut(
string $url,
string $module,
string $parentModule =
'',
string $title =
''): bool
194 if (empty($url) || empty($module)) {
198 $queryParts = parse_url($url);
199 $queryParameters = [];
200 parse_str($queryParts[
'query'] ??
'', $queryParameters);
202 if (!empty($queryParameters[
'scheme'])) {
203 throw new \RuntimeException(
'Shortcut URLs must be relative', 1518785877);
207 $title = $title ?:
'Shortcut';
214 if (is_array($queryParameters[
'edit'])) {
215 $table = key($queryParameters[
'edit']);
216 $recordId = (int)key($queryParameters[
'edit'][$table]);
218 $languageFile =
'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
219 $action = $queryParameters[
'edit'][$table][$recordId];
224 $titlePrefix = $languageService->sL($languageFile .
':shortcut_edit');
228 $titlePrefix = $languageService->sL($languageFile .
':shortcut_create');
234 if (!empty($queryParameters[
'id']) && preg_match(
'/^[\d]+:/', $queryParameters[
'id'])) {
237 $resource = $resourceFactory->getObjectFromCombinedIdentifier($queryParameters[
'id']);
238 $title = trim(sprintf(
243 }
catch (ResourceDoesNotExistException $e) {
252 if ($type ===
'other') {
262 $languageService->sL(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'title']),
266 } elseif (!empty($table)) {
267 $title = trim(sprintf(
270 $languageService->sL(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'title'])
275 if ($title ===
'Shortcut') {
276 $moduleLabels = $this->moduleLoader->getLabelsForModule($module);
278 if (!empty($moduleLabels[
'shortdescription'])) {
283 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
284 ->getQueryBuilderForTable(
'sys_be_shortcuts');
285 $affectedRows = $queryBuilder
286 ->insert(
'sys_be_shortcuts')
289 'module_name' => $module .
'|' . $parentModule,
291 'description' => $title,
296 return $affectedRows === 1;
307 public function updateShortcut(
int $id,
string $title,
int $groupId): bool
310 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
311 ->getQueryBuilderForTable(
'sys_be_shortcuts');
312 $queryBuilder->update(
'sys_be_shortcuts')
314 $queryBuilder->expr()->eq(
316 $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
319 ->set(
'description', $title)
320 ->set(
'sc_group', $groupId);
322 if (!$backendUser->isAdmin()) {
324 $queryBuilder->andWhere(
325 $queryBuilder->expr()->eq(
327 $queryBuilder->createNamedParameter($backendUser->user[
'uid'], \PDO::PARAM_INT)
332 $queryBuilder->set(
'sc_group', 0);
336 $affectedRows = $queryBuilder->execute();
338 return $affectedRows === 1;
352 if ($shortcut[
'raw'][
'userid'] == $this->
getBackendUser()->user[
'uid']) {
353 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
354 ->getQueryBuilderForTable(
'sys_be_shortcuts');
355 $affectedRows = $queryBuilder->delete(
'sys_be_shortcuts')
357 $queryBuilder->expr()->eq(
359 $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
364 if ($affectedRows === 1) {
391 $bookmarkGroups = $backendUser->getTSConfig()[
'options.'][
'bookmarkGroups.'] ?? [];
393 if (is_array($bookmarkGroups)) {
394 foreach ($bookmarkGroups as $groupId => $label) {
395 if (!empty($label)) {
397 } elseif ($backendUser->isAdmin()) {
414 $languageFile =
'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
417 $groupId = (int)$groupId;
418 $label = $groupLabel;
420 if ($groupLabel ===
'1') {
421 $label = $languageService->sL($languageFile .
':bookmark_group_' . abs($groupId));
425 $label = $languageService->sL($languageFile .
':bookmark_group') .
' ' . abs($groupId);
431 $label = $languageService->sL($languageFile .
':bookmark_global') .
': ' . (!empty($label) ? $label : abs($groupId));
433 if ($groupId === self::SUPERGLOBAL_GROUP) {
434 $label = $languageService->sL($languageFile .
':bookmark_global') .
': ' . $languageService->sL($languageFile .
':bookmark_all');
455 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
456 ->getQueryBuilderForTable(
'sys_be_shortcuts');
457 $result = $queryBuilder->select(
'*')
458 ->from(
'sys_be_shortcuts')
460 $queryBuilder->expr()->andX(
461 $queryBuilder->expr()->eq(
463 $queryBuilder->createNamedParameter($backendUser->user[
'uid'], \PDO::PARAM_INT)
465 $queryBuilder->expr()->gte(
467 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
472 $queryBuilder->expr()->in(
474 $queryBuilder->createNamedParameter(
476 Connection::PARAM_INT_ARRAY
480 ->orderBy(
'sc_group')
481 ->addOrderBy(
'sorting')
484 while ($row = $result->fetch()) {
485 $shortcut = [
'raw' => $row];
487 list($row[
'module_name'], $row[
'M_module_name']) = explode(
'|', $row[
'module_name']);
489 $queryParts = parse_url($row[
'url']);
491 $queryParameters = [];
492 parse_str($queryParts[
'query'] ??
'', $queryParameters);
494 if ($row[
'module_name'] ===
'xMOD_alt_doc.php' && is_array($queryParameters[
'edit'])) {
495 $shortcut[
'table'] = key($queryParameters[
'edit']);
496 $shortcut[
'recordid'] = key($queryParameters[
'edit'][$shortcut[
'table']]);
498 if ($queryParameters[
'edit'][$shortcut[
'table']][$shortcut[
'recordid']] ===
'edit') {
499 $shortcut[
'type'] =
'edit';
500 } elseif ($queryParameters[
'edit'][$shortcut[
'table']][$shortcut[
'recordid']] ===
'new') {
501 $shortcut[
'type'] =
'new';
504 if (substr((
string)$shortcut[
'recordid'], -1) ===
',') {
505 $shortcut[
'recordid'] = substr((
string)$shortcut[
'recordid'], 0, -1);
508 $shortcut[
'type'] =
'other';
512 $moduleName = $row[
'M_module_name'] ?: $row[
'module_name'];
515 if (!is_array($this->moduleLoader->checkMod($moduleName))) {
521 if (!$backendUser->isAdmin()) {
524 if ($backendUser->isInWebMount($pageId) ===
null) {
530 if ($pageRow ===
null) {
540 $moduleParts = explode(
'_', $moduleName);
541 $shortcutGroup = (int)$row[
'sc_group'];
543 if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
547 $lastGroup = $shortcutGroup;
549 if ($row[
'description']) {
550 $shortcut[
'label'] = $row[
'description'];
552 $shortcut[
'label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts[
'query']), 150);
555 $shortcut[
'group'] = $shortcutGroup;
557 $shortcut[
'iconTitle'] = $this->
getShortcutIconTitle($shortcut[
'label'], $row[
'module_name'], $row[
'M_module_name']);
558 $shortcut[
'action'] =
'jump(' . GeneralUtility::quoteJSvalue($this->
getTokenUrl($row[
'url'])) .
',' . GeneralUtility::quoteJSvalue($moduleName) .
',' . GeneralUtility::quoteJSvalue($moduleParts[0]) .
', ' . (int)$pageId .
');';
575 foreach ($this->shortcutGroups as $groupId => $groupLabel) {
577 $globalGroups[$groupId] = $groupLabel;
581 return $globalGroups;
592 return $this->shortcutGroups[$groupId] ??
'';
604 switch ($row[
'module_name']) {
605 case 'xMOD_alt_doc.php':
606 $table = $shortcut[
'table'];
607 $recordid = $shortcut[
'recordid'];
610 if ($shortcut[
'type'] ===
'edit') {
612 $selectFields[] =
'uid';
613 $selectFields[] =
'pid';
615 if ($table ===
'pages') {
616 $selectFields[] =
'module';
617 $selectFields[] =
'extendToSubpages';
618 $selectFields[] =
'doktype';
621 if (is_array(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns'])) {
622 $selectFields = array_merge($selectFields,
$GLOBALS[
'TCA'][$table][
'ctrl'][
'enablecolumns']);
625 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'typeicon_column']) {
626 $selectFields[] =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'typeicon_column'];
629 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS']) {
630 $selectFields[] =
't3ver_state';
633 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
634 ->getQueryBuilderForTable($table);
635 $queryBuilder->select(...array_unique(array_values($selectFields)))
638 $queryBuilder->expr()->in(
640 $queryBuilder->createNamedParameter($recordid, \PDO::PARAM_INT)
644 $row = $queryBuilder->execute()->fetch();
646 $icon = $this->iconFactory->getIconForRecord($table, (array)$row,
Icon::SIZE_SMALL)->render();
647 } elseif ($shortcut[
'type'] ===
'new') {
648 $icon = $this->iconFactory->getIconForRecord($table, [],
Icon::SIZE_SMALL)->render();
652 $icon = $this->iconFactory->getIcon(
'mimetypes-text-html',
Icon::SIZE_SMALL)->render();
655 $icon = $this->iconFactory->getIcon(
'mimetypes-word',
Icon::SIZE_SMALL)->render();
658 $iconIdentifier =
'';
659 $moduleName = $row[
'module_name'];
661 if (strpos($moduleName,
'_') !==
false) {
662 list($mainModule, $subModule) = explode(
'_', $moduleName, 2);
663 $iconIdentifier = $this->moduleLoader->modules[$mainModule][
'sub'][$subModule][
'iconIdentifier'];
664 } elseif (!empty($moduleName)) {
665 $iconIdentifier = $this->moduleLoader->modules[$moduleName][
'iconIdentifier'];
668 if (!$iconIdentifier) {
669 $iconIdentifier =
'empty-empty';
672 $icon = $this->iconFactory->getIcon($iconIdentifier,
Icon::SIZE_SMALL)->render();
686 protected function getShortcutIconTitle(
string $shortcutLabel,
string $moduleName,
string $parentModuleName =
''): string
690 if (strpos($moduleName,
'xMOD_') === 0) {
691 $title = substr($moduleName, 5);
693 list($mainModule, $subModule) = explode(
'_', $moduleName);
694 $mainModuleLabels = $this->moduleLoader->getLabelsForModule($mainModule);
695 $title = $languageService->sL($mainModuleLabels[
'title']);
697 if (!empty($subModule)) {
698 $subModuleLabels = $this->moduleLoader->getLabelsForModule($moduleName);
699 $title .=
'>' . $languageService->sL($subModuleLabels[
'title']);
703 if ($parentModuleName) {
704 $title .=
' (' . $parentModuleName .
')';
707 $title .=
': ' . $shortcutLabel;
720 return (
int)preg_replace(
'/.*[\\?&]id=([^&]+).*/',
'$1', $url);
732 $parsedUrl = parse_url($url);
734 parse_str($parsedUrl[
'query'] ??
'', $parameters);
736 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
738 if (!empty($parameters[
'returnUrl'])) {
739 $parsedReturnUrl = parse_url($parameters[
'returnUrl']);
740 $returnUrlParameters = [];
741 parse_str($parsedReturnUrl[
'query'] ??
'', $returnUrlParameters);
743 if (strpos($parsedReturnUrl[
'path'] ??
'',
'index.php') !==
false && !empty($returnUrlParameters[
'route'])) {
744 $module = $returnUrlParameters[
'route'];
745 $parameters[
'returnUrl'] = (string)$uriBuilder->buildUriFromRoutePath($module, $returnUrlParameters);
746 $url = $parsedUrl[
'path'] .
'?' . http_build_query($parameters,
'',
'&', PHP_QUERY_RFC3986);
750 if (isset($parameters[
'M']) && empty($parameters[
'route'])) {
751 $parameters[
'route'] = $parameters[
'M'];
752 unset($parameters[
'M']);
755 if (strpos($parsedUrl[
'path'],
'index.php') !==
false && isset($parameters[
'route'])) {
756 $routePath = $parameters[
'route'];
758 $router = GeneralUtility::makeInstance(Router::class);
761 $route = $router->match($routePath);
764 $routeIdentifier = $route->getOption(
'_identifier');
765 unset($parameters[
'route']);
766 $url = (string)$uriBuilder->buildUriFromRoute($routeIdentifier, $parameters);
768 }
catch (ResourceNotFoundException $e) {