Completed
Push — master ( 85652f...24268e )
by Torben
06:29
created

getNotificationRecipients()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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

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

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

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

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

Loading history...
320
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
321
        $eventDemand->setOrderFieldAllowed($this->settings['orderFieldAllowed']);
322
323
        if ($searchDemand !== null) {
324
            $searchDemand->setFields($this->settings['search']['fields']);
325
326
            $sessionData = [];
327
            $sessionData['searchDemand'] = $searchDemand;
328
            $sessionData['overwriteDemand'] = $overwriteDemand;
329
            $this->beUserSessionService->saveSessionData($sessionData);
330
        } else {
331
            // Try to restore search demand from Session
332
            $searchDemand = $this->beUserSessionService->getSessionDataByKey('searchDemand');
333
            $overwriteDemand = $this->beUserSessionService->getSessionDataByKey('overwriteDemand');
334
        }
335
336
        $eventDemand->setSearchDemand($searchDemand);
337
        $eventDemand->setStoragePage($this->pid);
338
339
        $this->view->assignMultiple([
340
            'pid' => $this->pid,
341
            'events' => $this->eventRepository->findDemanded($eventDemand),
342
            'searchDemand' => $searchDemand,
343
            'orderByFields' => $this->getOrderByFields(),
344
            'orderDirections' => $this->getOrderDirections(),
345
            'overwriteDemand' => $overwriteDemand,
346
        ]);
347
    }
348
349
    /**
350
     * Export registrations for a given event
351
     *
352
     * @param int $eventUid Event UID
353
     */
354
    public function exportAction($eventUid)
355
    {
356
        $this->exportService->downloadRegistrationsCsv($eventUid, $this->settings['csvExport']);
357
        exit();
358
    }
359
360
    /**
361
     * Handles expired registrations
362
     */
363
    public function handleExpiredRegistrationsAction()
364
    {
365
        $delete = (bool)$this->settings['registration']['deleteExpiredRegistrations'];
366
        $this->maintenanceService->handleExpiredRegistrations($delete);
367
368
        $this->addFlashMessage(
369
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.content'),
370
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.title'),
371
            FlashMessage::OK
372
        );
373
374
        $this->redirect('list');
375
    }
376
377
    /**
378
     * The index notify action
379
     *
380
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
381
     */
382
    public function indexNotifyAction(Event $event)
383
    {
384
        $customNotification = GeneralUtility::makeInstance(CustomNotification::class);
385
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
386
        $logEntries = $this->customNotificationLogRepository->findByEvent($event);
0 ignored issues
show
Documentation Bug introduced by
The method findByEvent does not exist on object<DERHANSEN\SfEvent...ificationLogRepository>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
387
        $this->view->assignMultiple([
388
            'event' => $event,
389
            'recipients' => $this->getNotificationRecipients(),
390
            'customNotification' => $customNotification,
391
            'customNotifications' => $customNotifications,
392
            'logEntries' => $logEntries,
393
        ]);
394
    }
395
396
    /**
397
     * Returns an array of recipient option for the indexNotify action
398
     *
399
     * @return array|array[]
400
     */
401
    public function getNotificationRecipients(): array
402
    {
403
        return [
404
            [
405
                'value' => CustomNotification::RECIPIENTS_ALL,
406
                'label' => $this->getLanguageService()->sL(
407
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_ALL
408
                )
409
            ],
410
            [
411
                'value' => CustomNotification::RECIPIENTS_CONFIRMED,
412
                'label' => $this->getLanguageService()->sL(
413
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_CONFIRMED
414
                )
415
            ],
416
            [
417
                'value' => CustomNotification::RECIPIENTS_UNCONFIRMED,
418
                'label' => $this->getLanguageService()->sL(
419
                    self::LANG_FILE . 'administration.notify.recipients.' . CustomNotification::RECIPIENTS_UNCONFIRMED
420
                )
421
            ],
422
        ];
423
    }
424
425
    /**
426
     * Notify action
427
     *
428
     * @param Event $event Event
429
     * @param CustomNotification $customNotification
430
     */
431
    public function notifyAction(Event $event, CustomNotification $customNotification)
432
    {
433
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
434
        $result = $this->notificationService->sendCustomNotification($event, $customNotification, $this->settings);
435
        $this->notificationService->createCustomNotificationLogentry(
436
            $event,
437
            $customNotifications[$customNotification->getTemplate()],
438
            $result
439
        );
440
        $this->addFlashMessage(
441
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.content'),
442
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.title'),
443
            FlashMessage::OK
444
        );
445
        $this->redirect('list');
446
    }
447
448
    /**
449
     * Shows the settings error view
450
     */
451
    public function settingsErrorAction()
452
    {
453
    }
454
455
    /**
456
     * Suppress default validation messages
457
     *
458
     * @return bool
459
     */
460
    protected function getErrorFlashMessage()
461
    {
462
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method TYPO3\CMS\Extbase\Mvc\Co...r::getErrorFlashMessage of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
463
    }
464
465
    /**
466
     * Returns the LanguageService
467
     *
468
     * @return LanguageService
469
     */
470
    protected function getLanguageService(): LanguageService
471
    {
472
        return $GLOBALS['LANG'];
473
    }
474
475
    /**
476
     * Returns an array with possible order directions
477
     *
478
     * @return array
479
     */
480
    public function getOrderDirections()
481
    {
482
        return [
483
            'asc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.asc'),
484
            'desc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.desc')
485
        ];
486
    }
487
488
    /**
489
     * Returns an array with possible orderBy fields
490
     *
491
     * @return array
492
     */
493
    public function getOrderByFields()
494
    {
495
        return [
496
            'title' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.title'),
497
            'startdate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.startdate'),
498
            'enddate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.enddate')
499
        ];
500
    }
501
}
502