ShortcutRepository::initShortcuts()   F
last analyzed

Complexity

Conditions 32
Paths 449

Size

Total Lines 152
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 92
c 0
b 0
f 0
dl 0
loc 152
rs 0.7652
cc 32
nc 449
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
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
namespace TYPO3\CMS\Backend\Backend\Shortcut;
19
20
use Symfony\Component\Routing\Route;
21
use TYPO3\CMS\Backend\Module\ModuleLoader;
22
use TYPO3\CMS\Backend\Routing\Router;
23
use TYPO3\CMS\Backend\Routing\UriBuilder;
24
use TYPO3\CMS\Backend\Utility\BackendUtility;
25
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
26
use TYPO3\CMS\Core\Database\Connection;
27
use TYPO3\CMS\Core\Database\ConnectionPool;
28
use TYPO3\CMS\Core\Imaging\Icon;
29
use TYPO3\CMS\Core\Imaging\IconFactory;
30
use TYPO3\CMS\Core\Localization\LanguageService;
31
use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
32
use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
33
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
34
use TYPO3\CMS\Core\Resource\ResourceFactory;
35
use TYPO3\CMS\Core\Resource\StorageRepository;
36
use TYPO3\CMS\Core\Type\Bitmask\Permission;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
39
/**
40
 * Repository for backend shortcuts
41
 *
42
 * @internal This class is a specific Backend implementation and is not considered part of the Public TYPO3 API.
43
 */
44
class ShortcutRepository
45
{
46
    /**
47
     * @var int Number of super global (All) group
48
     */
49
    protected const SUPERGLOBAL_GROUP = -100;
50
51
    protected const TABLE_NAME = 'sys_be_shortcuts';
52
53
    protected array $shortcuts;
54
55
    protected array $shortcutGroups;
56
57
    protected ConnectionPool $connectionPool;
58
59
    protected IconFactory $iconFactory;
60
61
    protected ModuleLoader $moduleLoader;
62
63
    public function __construct(ConnectionPool $connectionPool, IconFactory $iconFactory, ModuleLoader $moduleLoader)
64
    {
65
        $this->connectionPool = $connectionPool;
66
        $this->iconFactory = $iconFactory;
67
        $this->moduleLoader = $moduleLoader;
68
        $this->moduleLoader->load($GLOBALS['TBE_MODULES']);
69
70
        $this->shortcutGroups = $this->initShortcutGroups();
71
        $this->shortcuts = $this->initShortcuts();
72
    }
73
74
    /**
75
     * Gets a shortcut by its uid
76
     *
77
     * @param int $shortcutId Shortcut id to get the complete shortcut for
78
     * @return mixed An array containing the shortcut's data on success or FALSE on failure
79
     */
80
    public function getShortcutById(int $shortcutId)
81
    {
82
        foreach ($this->shortcuts as $shortcut) {
83
            if ($shortcut['raw']['uid'] === $shortcutId) {
84
                return $shortcut;
85
            }
86
        }
87
88
        return false;
89
    }
90
91
    /**
92
     * Gets shortcuts for a specific group
93
     *
94
     * @param int $groupId Group Id
95
     * @return array Array of shortcuts that matched the group
96
     */
97
    public function getShortcutsByGroup(int $groupId): array
98
    {
99
        $shortcuts = [];
100
101
        foreach ($this->shortcuts as $shortcut) {
102
            if ($shortcut['group'] === $groupId) {
103
                $shortcuts[] = $shortcut;
104
            }
105
        }
106
107
        return $shortcuts;
108
    }
109
110
    /**
111
     * Get shortcut groups the current user has access to
112
     *
113
     * @return array
114
     */
115
    public function getShortcutGroups(): array
116
    {
117
        $shortcutGroups = $this->shortcutGroups;
118
119
        if (!$this->getBackendUser()->isAdmin()) {
120
            foreach ($shortcutGroups as $groupId => $groupName) {
121
                if ((int)$groupId < 0) {
122
                    unset($shortcutGroups[$groupId]);
123
                }
124
            }
125
        }
126
127
        return $shortcutGroups;
128
    }
129
130
    /**
131
     * runs through the available shortcuts and collects their groups
132
     *
133
     * @return array Array of groups which have shortcuts
134
     */
135
    public function getGroupsFromShortcuts(): array
136
    {
137
        $groups = [];
138
139
        foreach ($this->shortcuts as $shortcut) {
140
            $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']] ?? '';
141
        }
142
143
        return array_unique($groups);
144
    }
145
146
    /**
147
     * Returns if there already is a shortcut entry for a given TYPO3 URL
148
     *
149
     * @param string $routeIdentifier
150
     * @param string $arguments
151
     * @return bool
152
     */
153
    public function shortcutExists(string $routeIdentifier, string $arguments): bool
154
    {
155
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
156
        $queryBuilder->getRestrictions()->removeAll();
157
158
        $uid = $queryBuilder->select('uid')
159
            ->from(self::TABLE_NAME)
160
            ->where(
161
                $queryBuilder->expr()->eq(
162
                    'userid',
163
                    $queryBuilder->createNamedParameter($this->getBackendUser()->user['uid'], \PDO::PARAM_INT)
164
                ),
165
                $queryBuilder->expr()->eq('route', $queryBuilder->createNamedParameter($routeIdentifier)),
166
                $queryBuilder->expr()->eq('arguments', $queryBuilder->createNamedParameter($arguments))
167
            )
168
            ->execute()
169
            ->fetchOne();
170
171
        return (bool)$uid;
172
    }
173
174
    /**
175
     * Add a shortcut
176
     *
177
     * @param string $routeIdentifier route identifier of the new shortcut
178
     * @param string $arguments arguments of the new shortcut
179
     * @param string $title title of the new shortcut
180
     * @return bool
181
     * @throws \RuntimeException if the given URL is invalid
182
     */
183
    public function addShortcut(string $routeIdentifier, string $arguments = '', string $title = ''): bool
184
    {
185
        // Do not add shortcuts for routes which do not exist
186
        if (!$this->routeExists($routeIdentifier)) {
187
            return false;
188
        }
189
190
        $languageService = $this->getLanguageService();
191
192
        // Only apply "magic" if title is not set
193
        // @todo This is deprecated and can be removed in v12
194
        if ($title === '') {
195
            $queryParameters = json_decode($arguments, true);
196
            $titlePrefix = '';
197
            $type = 'other';
198
            $table = '';
199
            $recordId = 0;
200
            $pageId = 0;
201
202
            if ($queryParameters && is_array($queryParameters['edit'])) {
203
                $table = (string)key($queryParameters['edit']);
204
                $recordId = (int)key($queryParameters['edit'][$table]);
205
                $pageId = (int)BackendUtility::getRecord($table, $recordId)['pid'];
206
                $languageFile = 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
207
                $action = $queryParameters['edit'][$table][$recordId];
208
209
                switch ($action) {
210
                    case 'edit':
211
                        $type = 'edit';
212
                        $titlePrefix = $languageService->sL($languageFile . ':shortcut_edit');
213
                        break;
214
                    case 'new':
215
                        $type = 'new';
216
                        $titlePrefix = $languageService->sL($languageFile . ':shortcut_create');
217
                        break;
218
                }
219
            }
220
221
            $moduleName = $this->getModuleNameFromRouteIdentifier($routeIdentifier);
222
            $id = (string)($queryParameters['id'] ?? '');
223
            if ($moduleName === 'file_FilelistList' && $id !== '') {
224
                try {
225
                    $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
226
                    $resource = $resourceFactory->getObjectFromCombinedIdentifier($queryParameters['id']);
227
                    $title = trim(sprintf(
228
                        '%s (%s)',
229
                        $titlePrefix,
230
                        $resource->getName()
231
                    ));
232
                } catch (ResourceDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
233
                }
234
            } else {
235
                // Lookup the title of this page and use it as default description
236
                $pageId = $pageId ?: $recordId ?: (int)$id;
237
                $page = $pageId ? BackendUtility::getRecord('pages', $pageId) : null;
238
239
                if (!empty($page)) {
240
                    // Set the name to the title of the page
241
                    if ($type === 'other') {
242
                        $title = sprintf(
243
                            '%s (%s)',
244
                            $title,
245
                            $page['title']
246
                        );
247
                    } else {
248
                        $title = sprintf(
249
                            '%s %s (%s)',
250
                            $titlePrefix,
251
                            $languageService->sL($GLOBALS['TCA'][$table]['ctrl']['title']),
252
                            $page['title']
253
                        );
254
                    }
255
                } elseif (!empty($table)) {
256
                    $title = trim(sprintf(
257
                        '%s %s',
258
                        $titlePrefix,
259
                        $languageService->sL($GLOBALS['TCA'][$table]['ctrl']['title'])
260
                    ));
261
                }
262
            }
263
        }
264
265
        // In case title is still empty try to set the modules short description label
266
        // @todo This is deprecated and can be removed in v12
267
        if ($title === '') {
268
            $moduleLabels = $this->moduleLoader->getLabelsForModule($this->getModuleNameFromRouteIdentifier($routeIdentifier));
269
            if (!empty($moduleLabels['shortdescription'])) {
270
                $title = $this->getLanguageService()->sL($moduleLabels['shortdescription']);
271
            }
272
        }
273
274
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
275
        $affectedRows = $queryBuilder
276
            ->insert(self::TABLE_NAME)
277
            ->values([
278
                'userid' => $this->getBackendUser()->user['uid'],
279
                'route' => $routeIdentifier,
280
                'arguments' => $arguments,
281
                'description' => $title ?: 'Shortcut',
282
                'sorting' => $GLOBALS['EXEC_TIME'],
283
            ])
284
            ->execute();
285
286
        return $affectedRows === 1;
287
    }
288
289
    /**
290
     * Update a shortcut
291
     *
292
     * @param int $id identifier of a shortcut
293
     * @param string $title new title of the shortcut
294
     * @param int $groupId new group identifier of the shortcut
295
     * @return bool
296
     */
297
    public function updateShortcut(int $id, string $title, int $groupId): bool
298
    {
299
        $backendUser = $this->getBackendUser();
300
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
301
        $queryBuilder->update(self::TABLE_NAME)
302
            ->where(
303
                $queryBuilder->expr()->eq(
304
                    'uid',
305
                    $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
306
                )
307
            )
308
            ->set('description', $title)
309
            ->set('sc_group', $groupId);
310
311
        if (!$backendUser->isAdmin()) {
312
            // Users can only modify their own shortcuts
313
            $queryBuilder->andWhere(
314
                $queryBuilder->expr()->eq(
315
                    'userid',
316
                    $queryBuilder->createNamedParameter($backendUser->user['uid'], \PDO::PARAM_INT)
317
                )
318
            );
319
320
            if ($groupId < 0) {
321
                $queryBuilder->set('sc_group', 0);
322
            }
323
        }
324
325
        $affectedRows = $queryBuilder->execute();
326
327
        return $affectedRows === 1;
328
    }
329
330
    /**
331
     * Remove a shortcut
332
     *
333
     * @param int $id identifier of a shortcut
334
     * @return bool
335
     */
336
    public function removeShortcut(int $id): bool
337
    {
338
        $shortcut = $this->getShortcutById($id);
339
        $success = false;
340
341
        if ((int)$shortcut['raw']['userid'] === (int)$this->getBackendUser()->user['uid']) {
342
            $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
343
            $affectedRows = $queryBuilder->delete(self::TABLE_NAME)
344
                ->where(
345
                    $queryBuilder->expr()->eq(
346
                        'uid',
347
                        $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)
348
                    )
349
                )
350
                ->execute();
351
352
            if ($affectedRows === 1) {
0 ignored issues
show
introduced by
The condition $affectedRows === 1 is always false.
Loading history...
353
                $success = true;
354
            }
355
        }
356
357
        return $success;
358
    }
359
360
    /**
361
     * Gets the available shortcut groups from default groups, user TSConfig, and global groups
362
     *
363
     * @return array
364
     */
365
    protected function initShortcutGroups(): array
366
    {
367
        $languageService = $this->getLanguageService();
368
        $backendUser = $this->getBackendUser();
369
        // By default, 5 groups are set
370
        $shortcutGroups = [
371
            1 => '1',
372
            2 => '1',
373
            3 => '1',
374
            4 => '1',
375
            5 => '1',
376
        ];
377
378
        // Groups from TSConfig
379
        $bookmarkGroups = $backendUser->getTSConfig()['options.']['bookmarkGroups.'] ?? [];
380
381
        if (is_array($bookmarkGroups)) {
382
            foreach ($bookmarkGroups as $groupId => $label) {
383
                if (!empty($label)) {
384
                    $label = (string)$label;
385
                    $shortcutGroups[$groupId] = strpos($label, 'LLL:') === 0 ? $languageService->sL($label) : $label;
386
                } elseif ($backendUser->isAdmin()) {
387
                    unset($shortcutGroups[$groupId]);
388
                }
389
            }
390
        }
391
392
        // Generate global groups, all global groups have negative IDs.
393
        if (!empty($shortcutGroups)) {
394
            foreach ($shortcutGroups as $groupId => $groupLabel) {
395
                $shortcutGroups[$groupId * -1] = $groupLabel;
396
            }
397
        }
398
399
        // Group -100 is kind of superglobal and can't be changed.
400
        $shortcutGroups[self::SUPERGLOBAL_GROUP] = '1';
401
402
        // Add labels
403
        $languageFile = 'LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf';
404
405
        foreach ($shortcutGroups as $groupId => $groupLabel) {
406
            $groupId = (int)$groupId;
407
            $label = $groupLabel;
408
409
            if ($groupLabel === '1') {
410
                $label = $languageService->sL($languageFile . ':bookmark_group_' . abs($groupId));
411
412
                if (empty($label)) {
413
                    // Fallback label
414
                    $label = $languageService->sL($languageFile . ':bookmark_group') . ' ' . abs($groupId);
415
                }
416
            }
417
418
            if ($groupId < 0) {
419
                // Global group
420
                $label = $languageService->sL($languageFile . ':bookmark_global') . ': ' . (!empty($label) ? $label : abs($groupId));
421
422
                if ($groupId === self::SUPERGLOBAL_GROUP) {
423
                    $label = $languageService->sL($languageFile . ':bookmark_global') . ': ' . $languageService->sL($languageFile . ':bookmark_all');
424
                }
425
            }
426
427
            $shortcutGroups[$groupId] = htmlspecialchars($label);
428
        }
429
430
        return $shortcutGroups;
431
    }
432
433
    /**
434
     * Retrieves the shortcuts for the current user
435
     *
436
     * @return array Array of shortcuts
437
     */
438
    protected function initShortcuts(): array
439
    {
440
        $backendUser = $this->getBackendUser();
441
        $lastGroup = 0;
442
        $shortcuts = [];
443
444
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
445
        $result = $queryBuilder->select('*')
446
            ->from(self::TABLE_NAME)
447
            ->where(
448
                $queryBuilder->expr()->andX(
449
                    $queryBuilder->expr()->eq(
450
                        'userid',
451
                        $queryBuilder->createNamedParameter($backendUser->user['uid'], \PDO::PARAM_INT)
452
                    ),
453
                    $queryBuilder->expr()->gte(
454
                        'sc_group',
455
                        $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
456
                    )
457
                )
458
            )
459
            ->orWhere(
460
                $queryBuilder->expr()->in(
461
                    'sc_group',
462
                    $queryBuilder->createNamedParameter(
463
                        array_keys($this->getGlobalShortcutGroups()),
464
                        Connection::PARAM_INT_ARRAY
465
                    )
466
                )
467
            )
468
            ->orderBy('sc_group')
469
            ->addOrderBy('sorting')
470
            ->execute();
471
472
        while ($row = $result->fetch()) {
473
            $pageId = 0;
474
            $shortcut = ['raw' => $row];
475
            $routeIdentifier = $row['route'] ?? '';
476
            $arguments = json_decode($row['arguments'] ?? '', true) ?? [];
477
478
            if ($routeIdentifier === 'record_edit' && is_array($arguments['edit'])) {
479
                $shortcut['table'] = (string)(key($arguments['edit']) ?? '');
480
                $shortcut['recordid'] = key($arguments['edit'][$shortcut['table']]);
481
482
                if ($arguments['edit'][$shortcut['table']][$shortcut['recordid']] === 'edit') {
483
                    $shortcut['type'] = 'edit';
484
                } elseif ($arguments['edit'][$shortcut['table']][$shortcut['recordid']] === 'new') {
485
                    $shortcut['type'] = 'new';
486
                }
487
488
                if (substr((string)$shortcut['recordid'], -1) === ',') {
489
                    $shortcut['recordid'] = substr((string)$shortcut['recordid'], 0, -1);
490
                }
491
            } else {
492
                $shortcut['type'] = 'other';
493
            }
494
495
            $moduleName = $this->getModuleNameFromRouteIdentifier($routeIdentifier);
496
497
            // Skip shortcut if module name can not be resolved
498
            if ($moduleName === '') {
499
                continue;
500
            }
501
502
            // Check if the user has access to this module
503
            // @todo Hack for EditDocumentController / FormEngine, see issues #91368 and #91210
504
            if ($routeIdentifier !== 'record_edit' && !is_array($this->moduleLoader->checkMod($moduleName))) {
505
                continue;
506
            }
507
508
            if ($moduleName === 'file_FilelistList') {
509
                $combinedIdentifier = (string)($arguments['id'] ?? '');
510
                if ($combinedIdentifier !== '') {
511
                    $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByCombinedIdentifier($combinedIdentifier);
512
                    if ($storage === null || $storage->getUid() === 0) {
513
                        // Continue, if invalid storage or disallowed fallback storage
514
                        continue;
515
                    }
516
                    $folderIdentifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1);
517
                    try {
518
                        // By using $storage->getFolder() we implicitly check whether the folder
519
                        // still exists and the user has necessary permissions to access it.
520
                        $storage->getFolder($folderIdentifier);
521
                    } catch (InsufficientFolderAccessPermissionsException $e) {
522
                        // Continue, since current user does not have access to the folder
523
                        continue;
524
                    } catch (FolderDoesNotExistException $e) {
525
                        // Folder does not longer exists. However, the shortcut
526
                        // is still displayed, allowing the user to remove it.
527
                    }
528
                }
529
            } else {
530
                if ($moduleName === 'record_edit' && isset($shortcut['table'], $shortcut['recordid'])) {
531
                    // Check if user is allowed to edit the requested record
532
                    if (!$backendUser->check('tables_modify', $shortcut['table'])) {
533
                        continue;
534
                    }
535
                    $record = BackendUtility::getRecord($shortcut['table'], (int)$shortcut['recordid']);
536
                    // Check if requested record exists
537
                    if ($record === null || $record === []) {
538
                        continue;
539
                    }
540
                    // Store the page id of the record in question
541
                    $pageId = ($shortcut['table'] === 'pages' ? (int)($record['uid'] ?? 0) : (int)($record['pid']));
542
                } else {
543
                    // In case this is no record edit shortcut, treat a possible "id" as page id
544
                    $pageId = (int)($arguments['id'] ?? 0);
545
                }
546
                if ($pageId > 0 && !$backendUser->isAdmin()) {
547
                    // Check for webmount access
548
                    if ($backendUser->isInWebMount($pageId) === null) {
549
                        continue;
550
                    }
551
                    // Check for record access
552
                    $pageRow = BackendUtility::getRecord('pages', $pageId);
553
                    if ($pageRow === null || !$backendUser->doesUserHaveAccess($pageRow, Permission::PAGE_SHOW)) {
554
                        continue;
555
                    }
556
                }
557
            }
558
559
            $shortcutGroup = (int)$row['sc_group'];
560
            if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
561
                $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
562
            }
563
            $lastGroup = $shortcutGroup;
564
565
            $description = $row['description'] ?? '';
566
            // Empty description should usually never happen since not defining such, is deprecated and a
567
            // fallback is in place, at least for v11. Only manual inserts could lead to an empty description.
568
            // @todo Can be removed in v12 since setting a display name is mandatory then
569
            if ($description === '') {
570
                $moduleLabel = (string)($this->moduleLoader->getLabelsForModule($moduleName)['shortdescription'] ?? '');
571
                if ($moduleLabel !== '') {
572
                    $description = $this->getLanguageService()->sL($moduleLabel);
573
                }
574
            }
575
576
            $shortcutUrl = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute($routeIdentifier, $arguments);
577
578
            $shortcut['group'] = $shortcutGroup;
579
            $shortcut['icon'] = $this->getShortcutIcon($routeIdentifier, $moduleName, $shortcut);
580
            $shortcut['label'] = $description;
581
            $shortcut['action'] = 'jump('
582
                . GeneralUtility::quoteJSvalue($shortcutUrl)
583
                . ',' . GeneralUtility::quoteJSvalue($moduleName)
584
                . ',' . GeneralUtility::quoteJSvalue($moduleName)
585
                . ', ' . $pageId . ');';
586
            $shortcuts[] = $shortcut;
587
        }
588
589
        return $shortcuts;
590
    }
591
592
    /**
593
     * Gets a list of global groups, shortcuts in these groups are available to all users
594
     *
595
     * @return array Array of global groups
596
     */
597
    protected function getGlobalShortcutGroups(): array
598
    {
599
        $globalGroups = [];
600
601
        foreach ($this->shortcutGroups as $groupId => $groupLabel) {
602
            if ($groupId < 0) {
603
                $globalGroups[$groupId] = $groupLabel;
604
            }
605
        }
606
607
        return $globalGroups;
608
    }
609
610
    /**
611
     * Gets the label for a shortcut group
612
     *
613
     * @param int $groupId A shortcut group id
614
     * @return string The shortcut group label, can be an empty string if no group was found for the id
615
     */
616
    protected function getShortcutGroupLabel(int $groupId): string
617
    {
618
        return $this->shortcutGroups[$groupId] ?? '';
619
    }
620
621
    /**
622
     * Gets the icon for the shortcut
623
     *
624
     * @param string $routeIdentifier
625
     * @param string $moduleName
626
     * @param array $shortcut
627
     * @return string Shortcut icon as img tag
628
     */
629
    protected function getShortcutIcon(string $routeIdentifier, string $moduleName, array $shortcut): string
630
    {
631
        switch ($routeIdentifier) {
632
            case 'record_edit':
633
                $table = $shortcut['table'];
634
                $recordid = $shortcut['recordid'];
635
                $icon = '';
636
637
                if ($shortcut['type'] === 'edit') {
638
                    $row = BackendUtility::getRecordWSOL($table, $recordid) ?? [];
639
                    $icon = $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render();
640
                } elseif ($shortcut['type'] === 'new') {
641
                    $icon = $this->iconFactory->getIconForRecord($table, [], Icon::SIZE_SMALL)->render();
642
                }
643
                break;
644
            case 'file_edit':
645
                $icon = $this->iconFactory->getIcon('mimetypes-text-html', Icon::SIZE_SMALL)->render();
646
                break;
647
            case 'wizard_rte':
648
                $icon = $this->iconFactory->getIcon('mimetypes-word', Icon::SIZE_SMALL)->render();
649
                break;
650
            default:
651
                $iconIdentifier = '';
652
653
                if (strpos($moduleName, '_') !== false) {
654
                    [$mainModule, $subModule] = explode('_', $moduleName, 2);
655
                    $iconIdentifier = $this->moduleLoader->modules[$mainModule]['sub'][$subModule]['iconIdentifier'] ?? '';
656
                } elseif ($moduleName !== '') {
657
                    $iconIdentifier = $this->moduleLoader->modules[$moduleName]['iconIdentifier'] ?? '';
658
                }
659
660
                if (!$iconIdentifier) {
661
                    $iconIdentifier = 'empty-empty';
662
                }
663
664
                $icon = $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL)->render();
665
        }
666
667
        return $icon;
668
    }
669
670
    /**
671
     * Get the module name from the resolved route or by static mapping for some special cases.
672
     *
673
     * @param string $routeIdentifier
674
     * @return string
675
     */
676
    protected function getModuleNameFromRouteIdentifier(string $routeIdentifier): string
677
    {
678
        if ($this->isSpecialRoute($routeIdentifier)) {
679
            return $routeIdentifier;
680
        }
681
682
        $route = $this->getRoute($routeIdentifier);
683
        return $route !== null ? (string)($route->getOption('moduleName') ?? '') : '';
684
    }
685
686
    /**
687
     * Get the route for a given route identifier
688
     *
689
     * @param string $routeIdentifier
690
     * @return Route|null
691
     */
692
    protected function getRoute(string $routeIdentifier): ?Route
693
    {
694
        return GeneralUtility::makeInstance(Router::class)->getRoutes()[$routeIdentifier] ?? null;
695
    }
696
697
    /**
698
     * Check if a route for the given identifier exists
699
     *
700
     * @param string $routeIdentifier
701
     * @return bool
702
     */
703
    protected function routeExists(string $routeIdentifier): bool
704
    {
705
        return $this->getRoute($routeIdentifier) !== null;
706
    }
707
708
    /**
709
     * Check if given route identifier is a special "no module" route
710
     *
711
     * @param string $routeIdentifier
712
     * @return bool
713
     */
714
    protected function isSpecialRoute(string $routeIdentifier): bool
715
    {
716
        return in_array($routeIdentifier, ['record_edit', 'file_edit', 'wizard_rte'], true);
717
    }
718
719
    /**
720
     * Returns the current BE user.
721
     *
722
     * @return BackendUserAuthentication
723
     */
724
    protected function getBackendUser(): BackendUserAuthentication
725
    {
726
        return $GLOBALS['BE_USER'];
727
    }
728
729
    /**
730
     * @return LanguageService
731
     */
732
    protected function getLanguageService(): LanguageService
733
    {
734
        return $GLOBALS['LANG'];
735
    }
736
}
737