[!!!][TASK] Remove non-route variants for BE calls
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Backend / Shortcut / ShortcutRepository.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Backend\Backend\Shortcut;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Backend\Module\ModuleLoader;
19 use TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException;
20 use TYPO3\CMS\Backend\Routing\Router;
21 use TYPO3\CMS\Backend\Routing\UriBuilder;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
24 use TYPO3\CMS\Core\Database\Connection;
25 use TYPO3\CMS\Core\Database\ConnectionPool;
26 use TYPO3\CMS\Core\Imaging\Icon;
27 use TYPO3\CMS\Core\Imaging\IconFactory;
28 use TYPO3\CMS\Core\Localization\LanguageService;
29 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
30 use TYPO3\CMS\Core\Resource\ResourceFactory;
31 use TYPO3\CMS\Core\Type\Bitmask\Permission;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33 use TYPO3\CMS\Core\Utility\MathUtility;
34
35 /**
36 * Repository for backend shortcuts
37 *
38 * @internal This class is a specific Backend implementation and is not considered part of the Public TYPO3 API.
39 */
40 class ShortcutRepository
41 {
42 /**
43 * @var int Number of super global (All) group
44 */
45 protected const SUPERGLOBAL_GROUP = -100;
46
47 /**
48 * @var array
49 */
50 protected $shortcuts;
51
52 /**
53 * @var array
54 */
55 protected $shortcutGroups;
56
57 /**
58 * @var IconFactory
59 */
60 protected $iconFactory;
61
62 /**
63 * @var ModuleLoader
64 */
65 protected $moduleLoader;
66
67 /**
68 * Constructor
69 */
70 public function __construct()
71 {
72 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
73 $this->moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
74 $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
75
76 $this->shortcutGroups = $this->initShortcutGroups();
77 $this->shortcuts = $this->initShortcuts();
78 }
79
80 /**
81 * Gets a shortcut by its uid
82 *
83 * @param int $shortcutId Shortcut id to get the complete shortcut for
84 * @return mixed An array containing the shortcut's data on success or FALSE on failure
85 */
86 public function getShortcutById(int $shortcutId)
87 {
88 foreach ($this->shortcuts as $shortcut) {
89 if ($shortcut['raw']['uid'] === $shortcutId) {
90 return $shortcut;
91 }
92 }
93
94 return false;
95 }
96
97 /**
98 * Gets shortcuts for a specific group
99 *
100 * @param int $groupId Group Id
101 * @return array Array of shortcuts that matched the group
102 */
103 public function getShortcutsByGroup(int $groupId): array
104 {
105 $shortcuts = [];
106
107 foreach ($this->shortcuts as $shortcut) {
108 if ($shortcut['group'] === $groupId) {
109 $shortcuts[] = $shortcut;
110 }
111 }
112
113 return $shortcuts;
114 }
115
116 /**
117 * Get shortcut groups the current user has access to
118 *
119 * @return array
120 */
121 public function getShortcutGroups(): array
122 {
123 $shortcutGroups = $this->shortcutGroups;
124
125 if (!$this->getBackendUser()->isAdmin()) {
126 foreach ($shortcutGroups as $groupId => $groupName) {
127 if ((int)$groupId < 0) {
128 unset($shortcutGroups[$groupId]);
129 }
130 }
131 }
132
133 return $shortcutGroups;
134 }
135
136 /**
137 * runs through the available shortcuts an collects their groups
138 *
139 * @return array Array of groups which have shortcuts
140 */
141 public function getGroupsFromShortcuts(): array
142 {
143 $groups = [];
144
145 foreach ($this->shortcuts as $shortcut) {
146 $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
147 }
148
149 return array_unique($groups);
150 }
151
152 /**
153 * Returns if there already is a shortcut entry for a given TYPO3 URL
154 *
155 * @param string $url
156 * @return bool
157 */
158 public function shortcutExists(string $url): bool
159 {
160 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
161 ->getQueryBuilderForTable('sys_be_shortcuts');
162 $queryBuilder->getRestrictions()->removeAll();
163
164 $uid = $queryBuilder->select('uid')
165 ->from('sys_be_shortcuts')
166 ->where(
167 $queryBuilder->expr()->eq(
168 'userid',
169 $queryBuilder->createNamedParameter($this->getBackendUser()->user['uid'], \PDO::PARAM_INT)
170 ),
171 $queryBuilder->expr()->eq(
172 'url',
173 $queryBuilder->createNamedParameter($url, \PDO::PARAM_STR)
174 )
175 )
176 ->execute()
177 ->fetchColumn();
178
179 return (bool)$uid;
180 }
181
182 /**
183 * Add a shortcut
184 *
185 * @param string $url URL of the new shortcut
186 * @param string $module module identifier of the new shortcut
187 * @param string $parentModule parent module identifier of the new shortcut
188 * @param string $title title of the new shortcut
189 * @return bool
190 * @throws \RuntimeException if the given URL is invalid
191 */
192 public function addShortcut(string $url, string $module, string $parentModule = '', string $title = ''): bool
193 {
194 if (empty($url) || empty($module)) {
195 return false;
196 }
197
198 $queryParts = parse_url($url);
199 $queryParameters = [];
200 parse_str($queryParts['query'], $queryParameters);
201
202 if (!empty($queryParameters['scheme'])) {
203 throw new \RuntimeException('Shortcut URLs must be relative', 1518785877);
204 }
205
206 $languageService = $this->getLanguageService();
207 $title = $title ?: 'Shortcut';
208 $titlePrefix = '';
209 $type = 'other';
210 $table = '';
211 $recordId = 0;
212 $pageId = 0;
213
214 if (is_array($queryParameters['edit'])) {
215 $table = key($queryParameters['edit']);
216 $recordId = (int)key($queryParameters['edit'][$table]);
217 $pageId = (int)BackendUtility::getRecord($table, $recordId)['pid'];
218 $languageFile = 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
219 $action = $queryParameters['edit'][$table][$recordId];
220
221 switch ($action) {
222 case 'edit':
223 $type = 'edit';
224 $titlePrefix = $languageService->sL($languageFile . ':shortcut_edit');
225 break;
226 case 'new':
227 $type = 'new';
228 $titlePrefix = $languageService->sL($languageFile . ':shortcut_create');
229 break;
230 }
231 }
232
233 // Check if given id is a combined identifier
234 if (!empty($queryParameters['id']) && preg_match('/^[\d]+:/', $queryParameters['id'])) {
235 try {
236 $resourceFactory = ResourceFactory::getInstance();
237 $resource = $resourceFactory->getObjectFromCombinedIdentifier($queryParameters['id']);
238 $title = trim(sprintf(
239 '%s (%s)',
240 $titlePrefix,
241 $resource->getName()
242 ));
243 } catch (ResourceDoesNotExistException $e) {
244 }
245 } else {
246 // Lookup the title of this page and use it as default description
247 $pageId = $pageId ?: $recordId ?: $this->extractPageIdFromShortcutUrl($url);
248 $page = $pageId ? BackendUtility::getRecord('pages', $pageId) : null;
249
250 if (!empty($page)) {
251 // Set the name to the title of the page
252 if ($type === 'other') {
253 $title = sprintf(
254 '%s (%s)',
255 $title,
256 $page['title']
257 );
258 } else {
259 $title = sprintf(
260 '%s %s (%s)',
261 $titlePrefix,
262 $languageService->sL($GLOBALS['TCA'][$table]['ctrl']['title']),
263 $page['title']
264 );
265 }
266 } elseif (!empty($table)) {
267 $title = trim(sprintf(
268 '%s %s',
269 $titlePrefix,
270 $languageService->sL($GLOBALS['TCA'][$table]['ctrl']['title'])
271 ));
272 }
273 }
274
275 if ($title === 'Shortcut') {
276 $moduleLabels = $this->moduleLoader->getLabelsForModule($module);
277
278 if (!empty($moduleLabels['shortdescription'])) {
279 $title = $this->getLanguageService()->sL($moduleLabels['shortdescription']);
280 }
281 }
282
283 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
284 ->getQueryBuilderForTable('sys_be_shortcuts');
285 $affectedRows = $queryBuilder
286 ->insert('sys_be_shortcuts')
287 ->values([
288 'userid' => $this->getBackendUser()->user['uid'],
289 'module_name' => $module . '|' . $parentModule,
290 'url' => $url,
291 'description' => $title,
292 'sorting' => $GLOBALS['EXEC_TIME'],
293 ])
294 ->execute();
295
296 return $affectedRows === 1;
297 }
298
299 /**
300 * Update a shortcut
301 *
302 * @param int $id identifier of a shortcut
303 * @param string $title new title of the shortcut
304 * @param int $groupId new group identifier of the shortcut
305 * @return bool
306 */
307 public function updateShortcut(int $id, string $title, int $groupId): bool
308 {
309 $backendUser = $this->getBackendUser();
310 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
311 ->getQueryBuilderForTable('sys_be_shortcuts');
312 $queryBuilder->update('sys_be_shortcuts')
313 ->where(
314 $queryBuilder->expr()->eq(
315 'uid',
316 $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
317 )
318 )
319 ->set('description', $title)
320 ->set('sc_group', $groupId);
321
322 if (!$backendUser->isAdmin()) {
323 // Users can only modify their own shortcuts
324 $queryBuilder->andWhere(
325 $queryBuilder->expr()->eq(
326 'userid',
327 $queryBuilder->createNamedParameter($backendUser->user['uid'], \PDO::PARAM_INT)
328 )
329 );
330
331 if ($groupId < 0) {
332 $queryBuilder->set('sc_group', 0);
333 }
334 }
335
336 $affectedRows = $queryBuilder->execute();
337
338 return $affectedRows === 1;
339 }
340
341 /**
342 * Remove a shortcut
343 *
344 * @param int $id identifier of a shortcut
345 * @return bool
346 */
347 public function removeShortcut(int $id): bool
348 {
349 $shortcut = $this->getShortcutById($id);
350 $success = false;
351
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')
356 ->where(
357 $queryBuilder->expr()->eq(
358 'uid',
359 $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
360 )
361 )
362 ->execute();
363
364 if ($affectedRows === 1) {
365 $success = true;
366 }
367 }
368
369 return $success;
370 }
371
372 /**
373 * Gets the available shortcut groups from default groups, user TSConfig, and global groups
374 *
375 * @return array
376 */
377 protected function initShortcutGroups(): array
378 {
379 $languageService = $this->getLanguageService();
380 $backendUser = $this->getBackendUser();
381 // By default, 5 groups are set
382 $shortcutGroups = [
383 1 => '1',
384 2 => '1',
385 3 => '1',
386 4 => '1',
387 5 => '1',
388 ];
389
390 // Groups from TSConfig
391 $bookmarkGroups = $backendUser->getTSConfig()['options.']['bookmarkGroups.'] ?? [];
392
393 if (is_array($bookmarkGroups)) {
394 foreach ($bookmarkGroups as $groupId => $label) {
395 if (!empty($label)) {
396 $shortcutGroups[$groupId] = (string)$label;
397 } elseif ($backendUser->isAdmin()) {
398 unset($shortcutGroups[$groupId]);
399 }
400 }
401 }
402
403 // Generate global groups, all global groups have negative IDs.
404 if (!empty($shortcutGroups)) {
405 foreach ($shortcutGroups as $groupId => $groupLabel) {
406 $shortcutGroups[$groupId * -1] = $groupLabel;
407 }
408 }
409
410 // Group -100 is kind of superglobal and can't be changed.
411 $shortcutGroups[self::SUPERGLOBAL_GROUP] = '1';
412
413 // Add labels
414 $languageFile = 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
415
416 foreach ($shortcutGroups as $groupId => $groupLabel) {
417 $groupId = (int)$groupId;
418 $label = $groupLabel;
419
420 if ($groupLabel === '1') {
421 $label = $languageService->sL($languageFile . ':bookmark_group_' . abs($groupId));
422
423 if (empty($label)) {
424 // Fallback label
425 $label = $languageService->sL($languageFile . ':bookmark_group') . ' ' . abs($groupId);
426 }
427 }
428
429 if ($groupId < 0) {
430 // Global group
431 $label = $languageService->sL($languageFile . ':bookmark_global') . ': ' . (!empty($label) ? $label : abs($groupId));
432
433 if ($groupId === self::SUPERGLOBAL_GROUP) {
434 $label = $languageService->sL($languageFile . ':bookmark_global') . ': ' . $languageService->sL($languageFile . ':bookmark_all');
435 }
436 }
437
438 $shortcutGroups[$groupId] = htmlspecialchars($label);
439 }
440
441 return $shortcutGroups;
442 }
443
444 /**
445 * Retrieves the shortcuts for the current user
446 *
447 * @return array Array of shortcuts
448 */
449 protected function initShortcuts(): array
450 {
451 $backendUser = $this->getBackendUser();
452 // Traverse shortcuts
453 $lastGroup = 0;
454 $shortcuts = [];
455 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
456 ->getQueryBuilderForTable('sys_be_shortcuts');
457 $result = $queryBuilder->select('*')
458 ->from('sys_be_shortcuts')
459 ->where(
460 $queryBuilder->expr()->andX(
461 $queryBuilder->expr()->eq(
462 'userid',
463 $queryBuilder->createNamedParameter($backendUser->user['uid'], \PDO::PARAM_INT)
464 ),
465 $queryBuilder->expr()->gte(
466 'sc_group',
467 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
468 )
469 )
470 )
471 ->orWhere(
472 $queryBuilder->expr()->in(
473 'sc_group',
474 $queryBuilder->createNamedParameter(
475 array_keys($this->getGlobalShortcutGroups()),
476 Connection::PARAM_INT_ARRAY
477 )
478 )
479 )
480 ->orderBy('sc_group')
481 ->addOrderBy('sorting')
482 ->execute();
483
484 while ($row = $result->fetch()) {
485 $shortcut = ['raw' => $row];
486
487 list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
488
489 $queryParts = parse_url($row['url']);
490 // Explode GET vars recursively
491 $queryParameters = [];
492 parse_str($queryParts['query'], $queryParameters);
493
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']]);
497
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';
502 }
503
504 if (substr((string)$shortcut['recordid'], -1) === ',') {
505 $shortcut['recordid'] = substr((string)$shortcut['recordid'], 0, -1);
506 }
507 } else {
508 $shortcut['type'] = 'other';
509 }
510
511 // Check for module access
512 $moduleName = $row['M_module_name'] ?: $row['module_name'];
513
514 // Check if the user has access to this module
515 if (!is_array($this->moduleLoader->checkMod($moduleName))) {
516 continue;
517 }
518
519 $pageId = $this->extractPageIdFromShortcutUrl($row['url']);
520
521 if (!$backendUser->isAdmin()) {
522 if (MathUtility::canBeInterpretedAsInteger($pageId)) {
523 // Check for webmount access
524 if ($backendUser->isInWebMount($pageId) === null) {
525 continue;
526 }
527 // Check for record access
528 $pageRow = BackendUtility::getRecord('pages', $pageId);
529
530 if ($pageRow === null) {
531 continue;
532 }
533
534 if (!$backendUser->doesUserHaveAccess($pageRow, Permission::PAGE_SHOW)) {
535 continue;
536 }
537 }
538 }
539
540 $moduleParts = explode('_', $moduleName);
541 $shortcutGroup = (int)$row['sc_group'];
542
543 if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
544 $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
545 }
546
547 $lastGroup = $shortcutGroup;
548
549 if ($row['description']) {
550 $shortcut['label'] = $row['description'];
551 } else {
552 $shortcut['label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts['query']), 150);
553 }
554
555 $shortcut['group'] = $shortcutGroup;
556 $shortcut['icon'] = $this->getShortcutIcon($row, $shortcut);
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 . ');';
559
560 $shortcuts[] = $shortcut;
561 }
562
563 return $shortcuts;
564 }
565
566 /**
567 * Gets a list of global groups, shortcuts in these groups are available to all users
568 *
569 * @return array Array of global groups
570 */
571 protected function getGlobalShortcutGroups(): array
572 {
573 $globalGroups = [];
574
575 foreach ($this->shortcutGroups as $groupId => $groupLabel) {
576 if ($groupId < 0) {
577 $globalGroups[$groupId] = $groupLabel;
578 }
579 }
580
581 return $globalGroups;
582 }
583
584 /**
585 * Gets the label for a shortcut group
586 *
587 * @param int $groupId A shortcut group id
588 * @return string The shortcut group label, can be an empty string if no group was found for the id
589 */
590 protected function getShortcutGroupLabel(int $groupId): string
591 {
592 return $this->shortcutGroups[$groupId] ?? '';
593 }
594
595 /**
596 * Gets the icon for the shortcut
597 *
598 * @param array $row
599 * @param array $shortcut
600 * @return string Shortcut icon as img tag
601 */
602 protected function getShortcutIcon(array $row, array $shortcut): string
603 {
604 switch ($row['module_name']) {
605 case 'xMOD_alt_doc.php':
606 $table = $shortcut['table'];
607 $recordid = $shortcut['recordid'];
608 $icon = '';
609
610 if ($shortcut['type'] === 'edit') {
611 // Creating the list of fields to include in the SQL query:
612 $selectFields[] = 'uid';
613 $selectFields[] = 'pid';
614
615 if ($table === 'pages') {
616 $selectFields[] = 'module';
617 $selectFields[] = 'extendToSubpages';
618 $selectFields[] = 'doktype';
619 }
620
621 if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
622 $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
623 }
624
625 if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
626 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
627 }
628
629 if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
630 $selectFields[] = 't3ver_state';
631 }
632
633 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
634 ->getQueryBuilderForTable($table);
635 $queryBuilder->select(...array_unique(array_values($selectFields)))
636 ->from($table)
637 ->where(
638 $queryBuilder->expr()->in(
639 'uid',
640 $queryBuilder->createNamedParameter($recordid, \PDO::PARAM_INT)
641 )
642 );
643
644 $row = $queryBuilder->execute()->fetch();
645
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();
649 }
650 break;
651 case 'file_edit':
652 $icon = $this->iconFactory->getIcon('mimetypes-text-html', Icon::SIZE_SMALL)->render();
653 break;
654 case 'wizard_rte':
655 $icon = $this->iconFactory->getIcon('mimetypes-word', Icon::SIZE_SMALL)->render();
656 break;
657 default:
658 $iconIdentifier = '';
659 $moduleName = $row['module_name'];
660
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'];
666 }
667
668 if (!$iconIdentifier) {
669 $iconIdentifier = 'empty-empty';
670 }
671
672 $icon = $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL)->render();
673 }
674
675 return $icon;
676 }
677
678 /**
679 * Returns title for the shortcut icon
680 *
681 * @param string $shortcutLabel Shortcut label
682 * @param string $moduleName Backend module name (key)
683 * @param string $parentModuleName Parent module label
684 * @return string Title for the shortcut icon
685 */
686 protected function getShortcutIconTitle(string $shortcutLabel, string $moduleName, string $parentModuleName = ''): string
687 {
688 $languageService = $this->getLanguageService();
689
690 if (strpos($moduleName, 'xMOD_') === 0) {
691 $title = substr($moduleName, 5);
692 } else {
693 list($mainModule, $subModule) = explode('_', $moduleName);
694 $mainModuleLabels = $this->moduleLoader->getLabelsForModule($mainModule);
695 $title = $languageService->sL($mainModuleLabels['title']);
696
697 if (!empty($subModule)) {
698 $subModuleLabels = $this->moduleLoader->getLabelsForModule($moduleName);
699 $title .= '>' . $languageService->sL($subModuleLabels['title']);
700 }
701 }
702
703 if ($parentModuleName) {
704 $title .= ' (' . $parentModuleName . ')';
705 }
706
707 $title .= ': ' . $shortcutLabel;
708
709 return $title;
710 }
711
712 /**
713 * Return the ID of the page in the URL if found.
714 *
715 * @param string $url The URL of the current shortcut link
716 * @return int If a page ID was found, it is returned. Otherwise: 0
717 */
718 protected function extractPageIdFromShortcutUrl(string $url): int
719 {
720 return (int)preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
721 }
722
723 /**
724 * Adds the correct token, if the url is an index.php script
725 * @todo: this needs love
726 *
727 * @param string $url
728 * @return string
729 */
730 protected function getTokenUrl(string $url): string
731 {
732 $parsedUrl = parse_url($url);
733 $parameters = [];
734 parse_str($parsedUrl['query'], $parameters);
735
736 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
737 // parse the returnUrl and replace the module token of it
738 if (isset($parameters['returnUrl'])) {
739 $parsedReturnUrl = parse_url($parameters['returnUrl']);
740 $returnUrlParameters = [];
741 parse_str($parsedReturnUrl['query'], $returnUrlParameters);
742
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);
747 }
748 }
749
750 if (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['route'])) {
751 $routePath = $parameters['route'];
752 /** @var \TYPO3\CMS\Backend\Routing\Router $router */
753 $router = GeneralUtility::makeInstance(Router::class);
754
755 try {
756 $route = $router->match($routePath);
757
758 if ($route) {
759 $routeIdentifier = $route->getOption('_identifier');
760 unset($parameters['route']);
761 $url = (string)$uriBuilder->buildUriFromRoute($routeIdentifier, $parameters);
762 }
763 } catch (ResourceNotFoundException $e) {
764 $url = '';
765 }
766 }
767 return $url;
768 }
769
770 /**
771 * Returns the current BE user.
772 *
773 * @return BackendUserAuthentication
774 */
775 protected function getBackendUser(): BackendUserAuthentication
776 {
777 return $GLOBALS['BE_USER'];
778 }
779
780 /**
781 * @return LanguageService
782 */
783 protected function getLanguageService(): LanguageService
784 {
785 return $GLOBALS['LANG'];
786 }
787 }