Passed
Push — master ( 62e46d...e4833f )
by
unknown
15:08
created

ShortcutRepository::routeExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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