Passed
Push — main ( 874e71...3076aa )
by Torben
12:08 queued 09:22
created

AdministrationController   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 435
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 196
c 5
b 0
f 0
dl 0
loc 435
rs 8.96
wmc 43

27 Methods

Rating   Name   Duplication   Size   Complexity  
A checkEventAccess() 0 10 2
A initializeAction() 0 3 1
A injectIconFactory() 0 3 1
A injectMaintenanceService() 0 3 1
A injectBeUserSessionService() 0 3 1
A injectCustomNotificationLogRepository() 0 4 1
A initializeListAction() 0 5 2
A injectExportService() 0 3 1
A injectModuleTemplateFactory() 0 3 1
A getCreateNewRecordUri() 0 16 5
A initModuleTemplateAndReturnResponse() 0 22 1
A injectPageRenderer() 0 3 1
A registerDocHeaderButtons() 0 51 3
A injectSettingsService() 0 3 1
B listAction() 0 70 7
A getLanguageService() 0 3 1
A settingsErrorAction() 0 3 1
A handleExpiredRegistrationsAction() 0 11 1
A getOrderByFields() 0 6 1
A indexNotifyAction() 0 21 1
A notifyAction() 0 16 1
A exportAction() 0 9 2
A getNotificationRecipients() 0 19 1
A isResetFilter() 0 8 2
A getErrorFlashMessage() 0 3 1
A getOrderDirections() 0 5 1
A getBackendUser() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like AdministrationController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AdministrationController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Controller;
13
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CustomNotification;
15
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
16
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
17
use DERHANSEN\SfEventMgt\Domain\Model\Event;
18
use DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository;
19
use DERHANSEN\SfEventMgt\Event\InitAdministrationModuleTemplateEvent;
20
use DERHANSEN\SfEventMgt\Event\ModifyAdministrationIndexNotifyViewVariablesEvent;
21
use DERHANSEN\SfEventMgt\Event\ModifyAdministrationListViewVariablesEvent;
22
use DERHANSEN\SfEventMgt\Service\BeUserSessionService;
23
use DERHANSEN\SfEventMgt\Service\ExportService;
24
use DERHANSEN\SfEventMgt\Service\MaintenanceService;
25
use DERHANSEN\SfEventMgt\Service\SettingsService;
26
use Psr\Http\Message\ResponseInterface;
27
use TYPO3\CMS\Backend\Routing\UriBuilder;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Routing\UriBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Template\Components\ButtonBar was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use TYPO3\CMS\Backend\Template\ModuleTemplate;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Template\ModuleTemplate was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Template\ModuleTemplateFactory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use TYPO3\CMS\Backend\Utility\BackendUtility;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Utility\BackendUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
33
use TYPO3\CMS\Core\Imaging\Icon;
34
use TYPO3\CMS\Core\Imaging\IconFactory;
35
use TYPO3\CMS\Core\Localization\LanguageService;
36
use TYPO3\CMS\Core\Page\PageRenderer;
37
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
40
class AdministrationController extends AbstractController
41
{
42
    private const LANG_FILE = 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang_be.xlf:';
43
44
    protected ModuleTemplateFactory $moduleTemplateFactory;
45
    protected CustomNotificationLogRepository $customNotificationLogRepository;
46
    protected ExportService $exportService;
47
    protected SettingsService $settingsService;
48
    protected BeUserSessionService $beUserSessionService;
49
    protected MaintenanceService $maintenanceService;
50
    protected IconFactory $iconFactory;
51
    protected PageRenderer $pageRenderer;
52
    protected int $pid = 0;
53
54
    public function injectCustomNotificationLogRepository(
55
        CustomNotificationLogRepository $customNotificationLogRepository
56
    ): void {
57
        $this->customNotificationLogRepository = $customNotificationLogRepository;
58
    }
59
60
    public function injectExportService(ExportService $exportService): void
61
    {
62
        $this->exportService = $exportService;
63
    }
64
65
    public function injectSettingsService(SettingsService $settingsService): void
66
    {
67
        $this->settingsService = $settingsService;
68
    }
69
70
    public function injectBeUserSessionService(BeUserSessionService $beUserSessionService): void
71
    {
72
        $this->beUserSessionService = $beUserSessionService;
73
    }
74
75
    public function injectIconFactory(IconFactory $iconFactory): void
76
    {
77
        $this->iconFactory = $iconFactory;
78
    }
79
80
    public function injectMaintenanceService(MaintenanceService $maintenanceService): void
81
    {
82
        $this->maintenanceService = $maintenanceService;
83
    }
84
85
    public function injectModuleTemplateFactory(ModuleTemplateFactory $moduleTemplateFactory): void
86
    {
87
        $this->moduleTemplateFactory = $moduleTemplateFactory;
88
    }
89
90
    public function injectPageRenderer(PageRenderer $pageRenderer): void
91
    {
92
        $this->pageRenderer = $pageRenderer;
93
    }
94
95
    /**
96
     * Register docHeaderButtons
97
     */
98
    protected function registerDocHeaderButtons(ModuleTemplate $moduleTemplate): void
99
    {
100
        $buttonBar = $moduleTemplate->getDocHeaderComponent()->getButtonBar();
101
102
        if ($this->request->getControllerActionName() === 'list') {
103
            $buttons = [
104
                [
105
                    'label' => 'administration.newEvent',
106
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_event'),
107
                    'icon' => 'ext-sfeventmgt-event',
108
                    'group' => 1,
109
                ],
110
                [
111
                    'label' => 'administration.newLocation',
112
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_location'),
113
                    'icon' => 'ext-sfeventmgt-location',
114
                    'group' => 1,
115
                ],
116
                [
117
                    'label' => 'administration.newOrganisator',
118
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_organisator'),
119
                    'icon' => 'ext-sfeventmgt-organisator',
120
                    'group' => 1,
121
                ],
122
                [
123
                    'label' => 'administration.newSpeaker',
124
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_speaker'),
125
                    'icon' => 'ext-sfeventmgt-speaker',
126
                    'group' => 1,
127
                ],
128
                [
129
                    'label' => 'administration.handleExpiredRegistrations',
130
                    'link' => $this->uriBuilder->reset()->setRequest($this->request)
131
                        ->uriFor('handleExpiredRegistrations', [], 'Administration'),
132
                    'icon' => 'ext-sfeventmgt-action-handle-expired',
133
                    'group' => 2,
134
                ],
135
            ];
136
            foreach ($buttons as $tableConfiguration) {
137
                $title = $this->getLanguageService()->sL(self::LANG_FILE . $tableConfiguration['label']);
138
                $icon = $this->iconFactory->getIcon($tableConfiguration['icon'], Icon::SIZE_SMALL);
139
                $viewButton = $buttonBar->makeLinkButton()
140
                    ->setHref($tableConfiguration['link'])
141
                    ->setDataAttributes([
142
                        'toggle' => 'tooltip',
143
                        'placement' => 'bottom',
144
                        'title' => $title,
145
                        ])
146
                    ->setTitle($title)
147
                    ->setIcon($icon);
148
                $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, $tableConfiguration['group']);
149
            }
150
        }
151
    }
152
153
    /**
154
     * Returns the create new record URL for the given table
155
     */
156
    private function getCreateNewRecordUri(string $table): string
157
    {
158
        $pid = $this->pid;
159
        $tsConfig = BackendUtility::getPagesTSconfig(0);
160
        if ($pid === 0 && isset($tsConfig['defaultPid.'])
161
            && is_array($tsConfig['defaultPid.'])
162
            && isset($tsConfig['defaultPid.'][$table])
163
        ) {
164
            $pid = (int)$tsConfig['defaultPid.'][$table];
165
        }
166
167
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
168
169
        return (string)$uriBuilder->buildUriFromRoute('record_edit', [
170
            'edit[' . $table . '][' . $pid . ']' => 'new',
171
            'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'),
172
        ]);
173
    }
174
175
    /**
176
     * Initializes module template and returns a response which must be used as response for any extbase action
177
     * that should render a view.
178
     */
179
    protected function initModuleTemplateAndReturnResponse(string $templateFileName, array $variables = []): ResponseInterface
180
    {
181
        $moduleTemplate = $this->moduleTemplateFactory->create($this->request);
182
        $this->pageRenderer->addCssFile('EXT:sf_event_mgt/Resources/Public/Css/administration.css');
183
184
        $this->pageRenderer->loadJavaScriptModule('@derhansen/sf_event_mgt/administration-module.js');
185
186
        $this->registerDocHeaderButtons($moduleTemplate);
187
188
        $moduleTemplate->setFlashMessageQueue($this->getFlashMessageQueue());
189
190
        $initAdministrationModuleTemplateEvent = new InitAdministrationModuleTemplateEvent(
191
            $moduleTemplate,
192
            $this->uriBuilder,
193
            $this
194
        );
195
        $this->eventDispatcher->dispatch($initAdministrationModuleTemplateEvent);
196
197
        $variables['settings'] = $this->settings;
198
        $moduleTemplate->assignMultiple($variables);
199
200
        return $moduleTemplate->renderResponse($templateFileName);
201
    }
202
203
    public function initializeAction(): void
204
    {
205
        $this->pid = (int)($this->request->getQueryParams()['id'] ?? 0);
206
    }
207
208
    /**
209
     * Set date format for fields startDate and endDate
210
     */
211
    public function initializeListAction(): void
212
    {
213
        // Static format needed for date picker (flatpickr), see BackendController::generateJavascript() and #91606
214
        if (!empty($this->settings)) {
215
            $this->settings['search']['dateFormat'] = 'H:i d-m-Y';
0 ignored issues
show
Bug Best Practice introduced by
The property settings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
216
        }
217
    }
218
219
    /**
220
     * List action for backend module
221
     */
222
    public function listAction(?SearchDemand $searchDemand = null, array $overwriteDemand = []): ResponseInterface
223
    {
224
        if (empty($this->settings)) {
225
            return $this->redirect('settingsError');
226
        }
227
228
        if ($searchDemand !== null) {
229
            $searchDemand->setFields($this->settings['search']['fields'] ?? 'title');
230
231
            $sessionData = [];
232
            $sessionData['searchDemand'] = $searchDemand->toArray();
233
            $sessionData['overwriteDemand'] = $overwriteDemand;
234
            $this->beUserSessionService->saveSessionData($sessionData);
235
        } else {
236
            // Try to restore search demand from Session
237
            $sessionSearchDemand = $this->beUserSessionService->getSessionDataByKey('searchDemand') ?? [];
238
            $searchDemand = SearchDemand::fromArray($sessionSearchDemand);
239
            $overwriteDemand = $this->beUserSessionService->getSessionDataByKey('overwriteDemand');
240
        }
241
242
        if ($this->isResetFilter()) {
243
            $searchDemand = GeneralUtility::makeInstance(SearchDemand::class);
244
            $overwriteDemand = [];
245
246
            $sessionData = [];
247
            $sessionData['searchDemand'] = $searchDemand->toArray();
248
            $sessionData['overwriteDemand'] = $overwriteDemand;
249
            $this->beUserSessionService->saveSessionData($sessionData);
250
        }
251
252
        // Initialize default ordering when no overwriteDemand is available
253
        if (empty($overwriteDemand)) {
254
            $overwriteDemand = [
255
                'orderField' => $this->settings['defaultSorting']['orderField'] ?? 'title',
256
                'orderDirection' => $this->settings['defaultSorting']['orderDirection'] ?? 'asc',
257
            ];
258
        }
259
260
        $eventDemand = GeneralUtility::makeInstance(EventDemand::class);
261
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
0 ignored issues
show
Bug introduced by
It seems like $overwriteDemand can also be of type null; however, parameter $overwriteDemand of DERHANSEN\SfEventMgt\Con...riteEventDemandObject() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

261
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, /** @scrutinizer ignore-type */ $overwriteDemand);
Loading history...
262
        $eventDemand->setOrderFieldAllowed($this->settings['orderFieldAllowed'] ?? '');
263
        $eventDemand->setSearchDemand($searchDemand);
264
        $eventDemand->setStoragePage((string)$this->pid);
265
        $eventDemand->setIgnoreEnableFields(true);
266
267
        $events = [];
268
        $pagination = null;
269
        if ($this->getBackendUser()->isInWebMount($this->pid) &&
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getBackendUser()->isInWebMount($this->pid) of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
270
            $this->getBackendUser()->check('tables_select', 'tx_sfeventmgt_domain_model_event')
271
        ) {
272
            $events = $this->eventRepository->findDemanded($eventDemand);
273
            $pagination = $this->getPagination($events, $this->settings['pagination'] ?? []);
274
        }
275
276
        $modifyAdministrationListViewVariablesEvent = new ModifyAdministrationListViewVariablesEvent(
277
            [
278
                'pid' => $this->pid,
279
                'events' => $events,
280
                'searchDemand' => $searchDemand,
281
                'orderByFields' => $this->getOrderByFields(),
282
                'orderDirections' => $this->getOrderDirections(),
283
                'overwriteDemand' => $overwriteDemand,
284
                'pagination' => $pagination,
285
            ],
286
            $this
287
        );
288
        $this->eventDispatcher->dispatch($modifyAdministrationListViewVariablesEvent);
289
        $variables = $modifyAdministrationListViewVariablesEvent->getVariables();
290
291
        return $this->initModuleTemplateAndReturnResponse('Administration/List', $variables);
292
    }
293
294
    /**
295
     * Returns, if reset filter operation has been used
296
     */
297
    private function isResetFilter(): bool
298
    {
299
        $resetFilter = false;
300
        if ($this->request->hasArgument('operation')) {
301
            $resetFilter = $this->request->getArgument('operation') === 'reset-filters';
302
        }
303
304
        return $resetFilter;
305
    }
306
307
    /**
308
     * Export registrations for a given event
309
     */
310
    public function exportAction(int $eventUid): void
311
    {
312
        /** @var Event $event */
313
        $event = $this->eventRepository->findByUidIncludeHidden($eventUid);
314
        if ($event !== null) {
315
            $this->checkEventAccess($event);
316
            $this->exportService->downloadRegistrationsCsv($eventUid, $this->settings['csvExport'] ?? []);
317
        }
318
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
319
    }
320
321
    /**
322
     * Handles expired registrations
323
     */
324
    public function handleExpiredRegistrationsAction(): ResponseInterface
325
    {
326
        $delete = (bool)($this->settings['registration']['deleteExpiredRegistrations'] ?? false);
327
        $this->maintenanceService->handleExpiredRegistrations($delete);
328
329
        $this->addFlashMessage(
330
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.content'),
331
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.title')
332
        );
333
334
        return $this->redirect('list');
335
    }
336
337
    /**
338
     * The index notify action
339
     */
340
    public function indexNotifyAction(Event $event): ResponseInterface
341
    {
342
        $this->checkEventAccess($event);
343
        $customNotification = GeneralUtility::makeInstance(CustomNotification::class);
344
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
345
        $logEntries = $this->customNotificationLogRepository->findByEvent($event);
346
347
        $modifyAdministrationIndexNotifyViewVariablesEvent = new ModifyAdministrationIndexNotifyViewVariablesEvent(
348
            [
349
                'event' => $event,
350
                'recipients' => $this->getNotificationRecipients(),
351
                'customNotification' => $customNotification,
352
                'customNotifications' => $customNotifications,
353
                'logEntries' => $logEntries,
354
            ],
355
            $this
356
        );
357
        $this->eventDispatcher->dispatch($modifyAdministrationIndexNotifyViewVariablesEvent);
358
        $variables = $modifyAdministrationIndexNotifyViewVariablesEvent->getVariables();
359
360
        return $this->initModuleTemplateAndReturnResponse('Administration/IndexNotify', $variables);
361
    }
362
363
    /**
364
     * Returns an array of recipient option for the indexNotify action
365
     */
366
    public function getNotificationRecipients(): array
367
    {
368
        return [
369
            [
370
                'value' => CustomNotification::RECIPIENTS_ALL,
371
                'label' => $this->getLanguageService()->sL(
372
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_ALL
373
                ),
374
            ],
375
            [
376
                'value' => CustomNotification::RECIPIENTS_CONFIRMED,
377
                'label' => $this->getLanguageService()->sL(
378
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_CONFIRMED
379
                ),
380
            ],
381
            [
382
                'value' => CustomNotification::RECIPIENTS_UNCONFIRMED,
383
                'label' => $this->getLanguageService()->sL(
384
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_UNCONFIRMED
385
                ),
386
            ],
387
        ];
388
    }
389
390
    /**
391
     * Notify action
392
     */
393
    public function notifyAction(Event $event, CustomNotification $customNotification): ResponseInterface
394
    {
395
        $this->checkEventAccess($event);
396
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
397
        $result = $this->notificationService->sendCustomNotification($event, $customNotification, $this->settings);
398
        $this->notificationService->createCustomNotificationLogentry(
399
            $event,
400
            $customNotifications[$customNotification->getTemplate()],
401
            $result,
402
            $customNotification
403
        );
404
        $this->addFlashMessage(
405
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.content'),
406
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.title')
407
        );
408
        return $this->redirect('list');
409
    }
410
411
    /**
412
     * Checks if the current backend user has access to the PID of the event and if not, enqueue an
413
     * access denied flash message and redirect to list view
414
     */
415
    public function checkEventAccess(Event $event): void
416
    {
417
        if ($this->getBackendUser()->isInWebMount($event->getPid()) === null) {
418
            $this->addFlashMessage(
419
                $this->getLanguageService()->sL(self::LANG_FILE . 'administration.accessdenied.content'),
420
                $this->getLanguageService()->sL(self::LANG_FILE . 'administration.accessdenied.title'),
421
                ContextualFeedbackSeverity::ERROR
422
            );
423
424
            $this->redirect('list');
425
        }
426
    }
427
428
    /**
429
     * Shows the settings error view
430
     */
431
    public function settingsErrorAction(): ResponseInterface
432
    {
433
        return $this->initModuleTemplateAndReturnResponse('Administration/SettingsError');
434
    }
435
436
    /**
437
     * Suppress default validation messages
438
     */
439
    protected function getErrorFlashMessage(): bool
440
    {
441
        return false;
442
    }
443
444
    /**
445
     * Returns an array with possible order directions
446
     */
447
    public function getOrderDirections(): array
448
    {
449
        return [
450
            'asc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.asc'),
451
            'desc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.desc'),
452
        ];
453
    }
454
455
    /**
456
     * Returns an array with possible orderBy fields
457
     */
458
    public function getOrderByFields(): array
459
    {
460
        return [
461
            'title' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.title'),
462
            'startdate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.startdate'),
463
            'enddate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.enddate'),
464
        ];
465
    }
466
467
    protected function getLanguageService(): LanguageService
468
    {
469
        return $GLOBALS['LANG'];
470
    }
471
472
    protected function getBackendUser(): BackendUserAuthentication
473
    {
474
        return $GLOBALS['BE_USER'];
475
    }
476
}
477