Passed
Push — master ( da5c3a...138f6a )
by Torben
132:09 queued 128:49
created

getNotificationRecipients()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 0
dl 0
loc 19
ccs 0
cts 0
cp 0
crap 2
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.txt file that was distributed with this source code.
8
 */
9
10
namespace DERHANSEN\SfEventMgt\Controller;
11
12
use DERHANSEN\SfEventMgt\Domain\Model\Dto\CustomNotification;
13
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
14
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
15
use DERHANSEN\SfEventMgt\Domain\Model\Event;
16
use DERHANSEN\SfEventMgt\Service;
17
use TYPO3\CMS\Backend\Routing\UriBuilder;
18
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
19
use TYPO3\CMS\Backend\Utility\BackendUtility;
20
use TYPO3\CMS\Backend\View\BackendTemplateView;
21
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22
use TYPO3\CMS\Core\Imaging\Icon;
23
use TYPO3\CMS\Core\Imaging\IconFactory;
24
use TYPO3\CMS\Core\Localization\LanguageService;
25
use TYPO3\CMS\Core\Messaging\FlashMessage;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
28
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder as ExtbaseUriBuilder;
29
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
30
31
/**
32
 * AdministrationController
33
 *
34
 * Several parts are heavily inspired by ext:news from Georg Ringer
35
 */
36
class AdministrationController extends AbstractController
37
{
38
    const LANG_FILE = 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang_be.xlf:';
39
40
    /**
41
     * Backend Template Container
42
     *
43
     * @var string
44
     */
45
    protected $defaultViewObjectName = \TYPO3\CMS\Backend\View\BackendTemplateView::class;
46
47
    /**
48
     * CustomNotificationLogRepository
49
     *
50
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository
51
     */
52
    protected $customNotificationLogRepository;
53
54
    /**
55
     * ExportService
56
     *
57
     * @var \DERHANSEN\SfEventMgt\Service\ExportService
58
     */
59
    protected $exportService;
60
61
    /**
62
     * SettingsService
63
     *
64
     * @var \DERHANSEN\SfEventMgt\Service\SettingsService
65
     */
66
    protected $settingsService;
67
68
    /**
69
     * Backend User Session Service
70
     *
71
     * @var \DERHANSEN\SfEventMgt\Service\BeUserSessionService
72
     */
73
    protected $beUserSessionService;
74
75
    /**
76
     * @var \DERHANSEN\SfEventMgt\Service\MaintenanceService
77
     */
78
    protected $maintenanceService;
79
80
    /**
81
     * The current page uid
82
     *
83
     * @var int
84
     */
85
    protected $pid = 0;
86
87
    /**
88
     * BackendTemplateContainer
89
     *
90
     * @var BackendTemplateView
91 2
     */
92
    protected $view;
93 2
94 2
    /**
95
     * @var IconFactory
96
     */
97
    protected $iconFactory;
98
99
    /**
100
     * DI for $customNotificationLogRepository
101 4
     *
102
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
103 4
     */
104 2
    public function injectCustomNotificationLogRepository(
105 2
        \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
106 4
    ) {
107 4
        $this->customNotificationLogRepository = $customNotificationLogRepository;
108 4
    }
109 4
110 4
    /**
111 4
     * DI for $exportService
112 4
     *
113 4
     * @param Service\ExportService $exportService
114 4
     */
115 4
    public function injectExportService(\DERHANSEN\SfEventMgt\Service\ExportService $exportService)
116 4
    {
117 4
        $this->exportService = $exportService;
118 4
    }
119 4
120 4
    /**
121
     * DI for $settingsService
122
     *
123
     * @param Service\SettingsService $settingsService
124
     */
125
    public function injectSettingsService(\DERHANSEN\SfEventMgt\Service\SettingsService $settingsService)
126
    {
127
        $this->settingsService = $settingsService;
128
    }
129
130 8
    /**
131
     * DI for $beUserSessionService
132
     *
133 8
     * @param Service\BeUserSessionService $beUserSessionService
134
     */
135 8
    public function injectBeUserSessionService(\DERHANSEN\SfEventMgt\Service\BeUserSessionService $beUserSessionService)
136 6
    {
137 6
        $this->beUserSessionService = $beUserSessionService;
138 8
    }
139
140 8
    /**
141 4
     * DI for $iconFactory
142 4
     *
143
     * @param IconFactory $iconFactory
144 8
     */
145 2
    public function injectIconFactory(IconFactory $iconFactory)
146 2
    {
147 2
        $this->iconFactory = $iconFactory;
148 2
    }
149
150 8
    /**
151 8
     * @param Service\MaintenanceService $maintenanceService
152 8
     */
153 8
    public function injectMaintenanceService(\DERHANSEN\SfEventMgt\Service\MaintenanceService $maintenanceService)
154
    {
155
        $this->maintenanceService = $maintenanceService;
156
    }
157
158
    /**
159
     * Set up the doc header properly here
160
     *
161
     * @param ViewInterface $view
162 2
     */
163
    protected function initializeView(ViewInterface $view)
164 2
    {
165 2
        /** @var BackendTemplateView $view */
166
        parent::initializeView($view);
167
        if ($this->actionMethodName === 'listAction'
168
            || $this->actionMethodName === 'indexNotifyAction'
169
            || $this->actionMethodName === 'settingsErrorAction'
170
        ) {
171
            $this->registerDocHeaderButtons();
172
173 2
            $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
174
            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DateTimePicker');
175 2
176 2
            $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ?
177 2
                ['MM-DD-YYYY', 'HH:mm MM-DD-YYYY'] :
178
                ['DD-MM-YYYY', 'HH:mm DD-MM-YYYY'];
179
            $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
180
181
            $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
182
            if ($view instanceof BackendTemplateView) {
0 ignored issues
show
introduced by
$view is always a sub-type of TYPO3\CMS\Backend\View\BackendTemplateView.
Loading history...
183
                $view->getModuleTemplate()->getPageRenderer()->addCssFile(
184
                    'EXT:sf_event_mgt/Resources/Public/Css/administration.css'
185
                );
186 2
            }
187
        }
188 2
    }
189 2
190 2
    /**
191 2
     * Register docHeaderButtons
192 2
     */
193 2
    protected function registerDocHeaderButtons()
194 2
    {
195 2
        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
196
197
        $uriBuilder = $this->objectManager->get(ExtbaseUriBuilder::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

197
        $uriBuilder = /** @scrutinizer ignore-deprecated */ $this->objectManager->get(ExtbaseUriBuilder::class);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
198
        $uriBuilder->setRequest($this->request);
199
200
        if ($this->request->getControllerActionName() === 'list') {
201
            $buttons = [
202
                [
203
                    'label' => 'administration.newEvent',
204
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_event'),
205 2
                    'icon' => 'ext-sfeventmgt-event',
206
                    'group' => 1
207 2
                ],
208 2
                [
209 2
                    'label' => 'administration.newLocation',
210 2
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_location'),
211 2
                    'icon' => 'ext-sfeventmgt-location',
212
                    'group' => 1
213 2
                ],
214 2
                [
215 2
                    'label' => 'administration.newOrganisator',
216
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_organisator'),
217
                    'icon' => 'ext-sfeventmgt-organisator',
218
                    'group' => 1
219
                ],
220
                [
221
                    'label' => 'administration.newSpeaker',
222
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_speaker'),
223
                    'icon' => 'ext-sfeventmgt-speaker',
224
                    'group' => 1
225
                ],
226
                [
227
                    'label' => 'administration.handleExpiredRegistrations',
228
                    'link' => $uriBuilder->reset()->setRequest($this->request)
229
                        ->uriFor('handleExpiredRegistrations', [], 'Administration'),
230
                    'icon' => 'ext-sfeventmgt-action-handle-expired',
231
                    'group' => 2,
232
                ]
233
            ];
234
            foreach ($buttons as $key => $tableConfiguration) {
235
                $title = $this->getLanguageService()->sL(self::LANG_FILE . $tableConfiguration['label']);
236
                $icon = $this->iconFactory->getIcon($tableConfiguration['icon'], Icon::SIZE_SMALL);
237
                $viewButton = $buttonBar->makeLinkButton()
238
                    ->setHref($tableConfiguration['link'])
239
                    ->setDataAttributes([
240
                        'toggle' => 'tooltip',
241
                        'placement' => 'bottom',
242
                        'title' => $title
243
                        ])
244
                    ->setTitle($title)
245
                    ->setIcon($icon);
246
                $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, $tableConfiguration['group']);
247
            }
248
        }
249
    }
250
251
    /**
252
     * Returns the create new record URL for the given table
253
     *
254
     * @param string $table
255
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
256
     * @return string
257
     */
258
    private function getCreateNewRecordUri($table): string
259
    {
260
        $pid = $this->pid;
261
        $tsConfig = BackendUtility::getPagesTSconfig(0);
262
        if ($pid === 0 && isset($tsConfig['defaultPid.'])
263
            && is_array($tsConfig['defaultPid.'])
264
            && isset($tsConfig['defaultPid.'][$table])
265
        ) {
266
            $pid = (int)$tsConfig['defaultPid.'][$table];
267
        }
268
269
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
270
271
        return $uriBuilder->buildUriFromRoute('record_edit', [
272
            'edit[' . $table . '][' . $pid . ']' => 'new',
273
            'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
274
        ]);
275
    }
276
277
    /**
278
     * Initialize action
279
     */
280
    public function initializeAction()
281
    {
282
        $this->pid = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('id');
283
    }
284
285
    /**
286
     * Set date format for fields startDate and endDate
287
     */
288
    public function initializeListAction()
289
    {
290
        if ($this->settings === null || empty($this->settings)) {
291
            $this->redirect('settingsError');
292
        }
293
        $this->arguments->getArgument('searchDemand')
294
            ->getPropertyMappingConfiguration()->forProperty('startDate')
295
            ->setTypeConverterOption(
296
                DateTimeConverter::class,
297
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
298
                $this->settings['search']['dateFormat']
299
            );
300
        $this->arguments->getArgument('searchDemand')
301
            ->getPropertyMappingConfiguration()->forProperty('endDate')
302
            ->setTypeConverterOption(
303
                DateTimeConverter::class,
304
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
305
                $this->settings['search']['dateFormat']
306
            );
307
    }
308
309
    /**
310
     * List action for backend module
311
     *
312
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
313
     * @param array $overwriteDemand OverwriteDemand
314
     */
315
    public function listAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
316
    {
317
        if ($searchDemand !== null) {
318
            $searchDemand->setFields($this->settings['search']['fields']);
319
320
            $sessionData = [];
321
            $sessionData['searchDemand'] = $searchDemand;
322
            $sessionData['overwriteDemand'] = $overwriteDemand;
323
            $this->beUserSessionService->saveSessionData($sessionData);
324
        } else {
325
            // Try to restore search demand from Session
326
            $searchDemand = $this->beUserSessionService->getSessionDataByKey('searchDemand');
327
            $overwriteDemand = $this->beUserSessionService->getSessionDataByKey('overwriteDemand');
328
        }
329
330
        /** @var EventDemand $eventDemand */
331
        $eventDemand = $this->objectManager->get(EventDemand::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

331
        $eventDemand = /** @scrutinizer ignore-deprecated */ $this->objectManager->get(EventDemand::class);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
332
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand ?? []);
0 ignored issues
show
Bug introduced by
It seems like $overwriteDemand ?? array() 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

332
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, /** @scrutinizer ignore-type */ $overwriteDemand ?? []);
Loading history...
333
        $eventDemand->setOrderFieldAllowed($this->settings['orderFieldAllowed']);
334
        $eventDemand->setSearchDemand($searchDemand);
335
        $eventDemand->setStoragePage($this->pid);
336
        $eventDemand->setIgnoreEnableFields(true);
337
338
        $events = [];
339
        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...
340
            $events = $this->eventRepository->findDemanded($eventDemand);
341
        }
342
343
        $this->view->assignMultiple([
344
            'pid' => $this->pid,
345
            'events' => $events,
346
            'searchDemand' => $searchDemand,
347
            'orderByFields' => $this->getOrderByFields(),
348
            'orderDirections' => $this->getOrderDirections(),
349
            'overwriteDemand' => $overwriteDemand,
350
        ]);
351
    }
352
353
    /**
354
     * Export registrations for a given event
355
     *
356
     * @param int $eventUid Event UID
357
     */
358
    public function exportAction($eventUid)
359
    {
360
        /** @var Event $event */
361
        $event = $this->eventRepository->findByUidIncludeHidden($eventUid);
362
        if ($event) {
0 ignored issues
show
introduced by
$event is of type DERHANSEN\SfEventMgt\Domain\Model\Event, thus it always evaluated to true.
Loading history...
363
            $this->checkEventAccess($event);
364
            $this->exportService->downloadRegistrationsCsv($eventUid, $this->settings['csvExport']);
365
        }
366
        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...
367
    }
368
369
    /**
370
     * Handles expired registrations
371
     */
372
    public function handleExpiredRegistrationsAction()
373
    {
374
        $delete = (bool)$this->settings['registration']['deleteExpiredRegistrations'];
375
        $this->maintenanceService->handleExpiredRegistrations($delete);
376
377
        $this->addFlashMessage(
378
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.content'),
379
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.title'),
380
            FlashMessage::OK
381
        );
382
383
        $this->redirect('list');
384
    }
385
386
    /**
387
     * The index notify action
388
     *
389
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
390
     */
391
    public function indexNotifyAction(Event $event)
392
    {
393
        $this->checkEventAccess($event);
394
        $customNotification = GeneralUtility::makeInstance(CustomNotification::class);
395
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
396
        $logEntries = $this->customNotificationLogRepository->findByEvent($event);
0 ignored issues
show
Bug introduced by
The method findByEvent() does not exist on DERHANSEN\SfEventMgt\Dom...tificationLogRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

396
        /** @scrutinizer ignore-call */ 
397
        $logEntries = $this->customNotificationLogRepository->findByEvent($event);
Loading history...
397
        $this->view->assignMultiple([
398
            'event' => $event,
399
            'recipients' => $this->getNotificationRecipients(),
400
            'customNotification' => $customNotification,
401
            'customNotifications' => $customNotifications,
402
            'logEntries' => $logEntries,
403
        ]);
404
    }
405
406
    /**
407
     * Returns an array of recipient option for the indexNotify action
408
     *
409
     * @return array|array[]
410
     */
411
    public function getNotificationRecipients(): array
412
    {
413
        return [
414
            [
415
                'value' => CustomNotification::RECIPIENTS_ALL,
416
                'label' => $this->getLanguageService()->sL(
417
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_ALL
418
                )
419
            ],
420
            [
421
                'value' => CustomNotification::RECIPIENTS_CONFIRMED,
422
                'label' => $this->getLanguageService()->sL(
423
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_CONFIRMED
424
                )
425
            ],
426
            [
427
                'value' => CustomNotification::RECIPIENTS_UNCONFIRMED,
428
                'label' => $this->getLanguageService()->sL(
429
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_UNCONFIRMED
430
                )
431
            ],
432
        ];
433
    }
434
435
    /**
436
     * Notify action
437
     *
438
     * @param Event $event Event
439
     * @param CustomNotification $customNotification
440
     */
441
    public function notifyAction(Event $event, CustomNotification $customNotification)
442
    {
443
        $this->checkEventAccess($event);
444
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
445
        $result = $this->notificationService->sendCustomNotification($event, $customNotification, $this->settings);
446
        $this->notificationService->createCustomNotificationLogentry(
447
            $event,
448
            $customNotifications[$customNotification->getTemplate()],
449
            $result
450
        );
451
        $this->addFlashMessage(
452
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.content'),
453
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.title'),
454
            FlashMessage::OK
455
        );
456
        $this->redirect('list');
457
    }
458
459
    /**
460
     * Checks if the current backend user has access to the PID of the event and if not, enqueue an
461
     * access denied flash message and redirect to list view
462
     *
463
     * @param Event $event
464
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
465
     */
466
    public function checkEventAccess(Event $event)
467
    {
468
        if ($this->getBackendUser()->isInWebMount($event->getPid()) === null) {
469
            $this->addFlashMessage(
470
                $this->getLanguageService()->sL(self::LANG_FILE . 'administration.accessdenied.content'),
471
                $this->getLanguageService()->sL(self::LANG_FILE . 'administration.accessdenied.title'),
472
                FlashMessage::ERROR
473
            );
474
475
            $this->redirect('list');
476
        }
477
    }
478
479
    /**
480
     * Shows the settings error view
481
     */
482
    public function settingsErrorAction()
483
    {
484
    }
485
486
    /**
487
     * Suppress default validation messages
488
     *
489
     * @return bool
490
     */
491
    protected function getErrorFlashMessage()
492
    {
493
        return false;
494
    }
495
496
    /**
497
     * Returns the LanguageService
498
     *
499
     * @return LanguageService
500
     */
501
    protected function getLanguageService(): LanguageService
502
    {
503
        return $GLOBALS['LANG'];
504
    }
505
506
    /**
507
     * Returns an array with possible order directions
508
     *
509
     * @return array
510
     */
511
    public function getOrderDirections()
512
    {
513
        return [
514
            'asc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.asc'),
515
            'desc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.desc')
516
        ];
517
    }
518
519
    /**
520
     * Returns an array with possible orderBy fields
521
     *
522
     * @return array
523
     */
524
    public function getOrderByFields()
525
    {
526
        return [
527
            'title' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.title'),
528
            'startdate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.startdate'),
529
            'enddate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.enddate')
530
        ];
531
    }
532
533
    /**
534
     * Returns the Backend User
535
     * @return BackendUserAuthentication
536
     */
537
    protected function getBackendUser(): BackendUserAuthentication
538
    {
539
        return $GLOBALS['BE_USER'];
540
    }
541
}
542