Completed
Push — typo3-10-compatibility ( 46cd8f...7e5223 )
by Torben
47:10 queued 02:11
created

AdministrationController::initializeAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace DERHANSEN\SfEventMgt\Controller;
3
4
/*
5
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use DERHANSEN\SfEventMgt\Domain\Model\Dto\EventDemand;
12
use DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand;
13
use DERHANSEN\SfEventMgt\Domain\Model\Event;
14
use DERHANSEN\SfEventMgt\Service;
15
use TYPO3\CMS\Backend\Routing\UriBuilder;
16
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
17
use TYPO3\CMS\Backend\Utility\BackendUtility;
18
use TYPO3\CMS\Backend\View\BackendTemplateView;
19
use TYPO3\CMS\Core\Imaging\Icon;
20
use TYPO3\CMS\Core\Imaging\IconFactory;
21
use TYPO3\CMS\Core\Localization\LanguageService;
22
use TYPO3\CMS\Core\Messaging\FlashMessage;
23
use TYPO3\CMS\Core\Utility\GeneralUtility;
24
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
25
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder as ExtbaseUriBuilder;
26
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
27
28
/**
29
 * AdministrationController
30
 *
31
 * Several parts are heavily inspired by ext:news from Georg Ringer
32
 *
33
 * @author Torben Hansen <[email protected]>
34
 */
35
class AdministrationController extends AbstractController
36
{
37
    const LANG_FILE = 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang_be.xlf:';
38
39
    /**
40
     * Backend Template Container
41
     *
42
     * @var string
43
     */
44
    protected $defaultViewObjectName = \TYPO3\CMS\Backend\View\BackendTemplateView::class;
45
46
    /**
47
     * CustomNotificationLogRepository
48
     *
49
     * @var \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository
50
     */
51
    protected $customNotificationLogRepository = null;
52
53
    /**
54
     * ExportService
55
     *
56
     * @var \DERHANSEN\SfEventMgt\Service\ExportService
57
     */
58
    protected $exportService = null;
59
60
    /**
61
     * SettingsService
62
     *
63
     * @var \DERHANSEN\SfEventMgt\Service\SettingsService
64
     */
65
    protected $settingsService = null;
66
67
    /**
68
     * Backend User Session Service
69
     *
70
     * @var \DERHANSEN\SfEventMgt\Service\BeUserSessionService
71
     */
72
    protected $beUserSessionService = null;
73
74
    /**
75
     * @var \DERHANSEN\SfEventMgt\Service\MaintenanceService
76
     */
77
    protected $maintenanceService = null;
78
79
    /**
80
     * The current page uid
81
     *
82
     * @var int
83
     */
84
    protected $pid = 0;
85
86
    /**
87
     * BackendTemplateContainer
88
     *
89
     * @var BackendTemplateView
90
     */
91
    protected $view;
92
93
    /**
94
     * @var IconFactory
95
     */
96
    protected $iconFactory = null;
97
98
    /**
99
     * DI for $customNotificationLogRepository
100
     *
101
     * @param \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
102
     */
103
    public function injectCustomNotificationLogRepository(
104
        \DERHANSEN\SfEventMgt\Domain\Repository\CustomNotificationLogRepository $customNotificationLogRepository
105
    ) {
106
        $this->customNotificationLogRepository = $customNotificationLogRepository;
107
    }
108
109
    /**
110
     * DI for $exportService
111
     *
112
     * @param Service\ExportService $exportService
113
     */
114
    public function injectExportService(\DERHANSEN\SfEventMgt\Service\ExportService $exportService)
115
    {
116
        $this->exportService = $exportService;
117
    }
118
119
    /**
120
     * DI for $settingsService
121
     *
122
     * @param Service\SettingsService $settingsService
123
     */
124
    public function injectSettingsService(\DERHANSEN\SfEventMgt\Service\SettingsService $settingsService)
125
    {
126
        $this->settingsService = $settingsService;
127
    }
128
129
    /**
130
     * DI for $beUserSessionService
131
     *
132
     * @param Service\BeUserSessionService $beUserSessionService
133
     */
134
    public function injectBeUserSessionService(\DERHANSEN\SfEventMgt\Service\BeUserSessionService $beUserSessionService)
135
    {
136
        $this->beUserSessionService = $beUserSessionService;
137
    }
138
139
    /**
140
     * DI for $iconFactory
141
     *
142
     * @param IconFactory $iconFactory
143
     */
144
    public function injectIconFactory(IconFactory $iconFactory)
145
    {
146
        $this->iconFactory = $iconFactory;
147
    }
148
149
    /**
150
     * @param Service\MaintenanceService $maintenanceService
151
     */
152
    public function injectMaintenanceService(\DERHANSEN\SfEventMgt\Service\MaintenanceService $maintenanceService)
153
    {
154
        $this->maintenanceService = $maintenanceService;
155
    }
156
157
    /**
158
     * Set up the doc header properly here
159
     *
160
     * @param ViewInterface $view
161
     *
162
     * @return void
163
     */
164
    protected function initializeView(ViewInterface $view)
165
    {
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
174
            $pageRenderer = $this->view->getModuleTemplate()->getPageRenderer();
175
            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DateTimePicker');
176
177
            $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
                );
187
            }
188
        }
189
    }
190
191
    /**
192
     * Register docHeaderButtons
193
     *
194
     * @return void
195
     */
196
    protected function registerDocHeaderButtons()
197
    {
198
        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
199
200
        $uriBuilder = $this->objectManager->get(ExtbaseUriBuilder::class);
201
        $uriBuilder->setRequest($this->request);
202
203
        if ($this->request->getControllerActionName() === 'list') {
204
            $buttons = [
205
                [
206
                    'label' => 'administration.newEvent',
207
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_event'),
208
                    'icon' => 'ext-sfeventmgt-event',
209
                    'group' => 1
210
                ],
211
                [
212
                    'label' => 'administration.newLocation',
213
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_location'),
214
                    'icon' => 'ext-sfeventmgt-location',
215
                    'group' => 1
216
                ],
217
                [
218
                    'label' => 'administration.newOrganisator',
219
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_organisator'),
220
                    'icon' => 'ext-sfeventmgt-organisator',
221
                    'group' => 1
222
                ],
223
                [
224
                    'label' => 'administration.newSpeaker',
225
                    'link' => $this->getCreateNewRecordUri('tx_sfeventmgt_domain_model_speaker'),
226
                    'icon' => 'ext-sfeventmgt-speaker',
227
                    'group' => 1
228
                ],
229
                [
230
                    'label' => 'administration.handleExpiredRegistrations',
231
                    'link' => $uriBuilder->reset()->setRequest($this->request)
232
                        ->uriFor('handleExpiredRegistrations', [], 'Administration'),
233
                    'icon' => 'ext-sfeventmgt-action-handle-expired',
234
                    'group' => 2,
235
                ]
236
            ];
237
            foreach ($buttons as $key => $tableConfiguration) {
238
                $title = $this->getLanguageService()->sL(self::LANG_FILE . $tableConfiguration['label']);
239
                $icon = $this->iconFactory->getIcon($tableConfiguration['icon'], Icon::SIZE_SMALL);
240
                $viewButton = $buttonBar->makeLinkButton()
241
                    ->setHref($tableConfiguration['link'])
242
                    ->setDataAttributes([
243
                        'toggle' => 'tooltip',
244
                        'placement' => 'bottom',
245
                        'title' => $title
246
                        ])
247
                    ->setTitle($title)
248
                    ->setIcon($icon);
249
                $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, $tableConfiguration['group']);
250
            }
251
        }
252
    }
253
254
    /**
255
     * Returns the create new record URL for the given table
256
     *
257
     * @param $table
258
     * @return string
259
     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
260
     */
261
    private function getCreateNewRecordUri($table): string
262
    {
263
        $pid = $this->pid;
264
        $tsConfig = BackendUtility::getPagesTSconfig(0);
265
        if ($pid === 0 && isset($tsConfig['defaultPid.'])
266
            && is_array($tsConfig['defaultPid.'])
267
            && isset($tsConfig['defaultPid.'][$table])
268
        ) {
269
            $pid = (int)$tsConfig['defaultPid.'][$table];
270
        }
271
272
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
273
        return $uriBuilder->buildUriFromRoute('record_edit', [
274
            'edit[' . $table . '][' . $pid . ']' => 'new',
275
            'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
276
        ]);
277
    }
278
279
    /**
280
     * Initialize action
281
     *
282
     * @return void
283
     */
284
    public function initializeAction()
285
    {
286
        $this->pid = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('id');
287
    }
288
289
    /**
290
     * Set date format for fields startDate and endDate
291
     *
292
     * @return void
293
     */
294
    public function initializeListAction()
295
    {
296
        if ($this->settings === null || empty($this->settings)) {
297
            $this->redirect('settingsError');
298
        }
299
        $this->arguments->getArgument('searchDemand')
300
            ->getPropertyMappingConfiguration()->forProperty('startDate')
301
            ->setTypeConverterOption(
302
                DateTimeConverter::class,
303
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
304
                $this->settings['search']['dateFormat']
305
            );
306
        $this->arguments->getArgument('searchDemand')
307
            ->getPropertyMappingConfiguration()->forProperty('endDate')
308
            ->setTypeConverterOption(
309
                DateTimeConverter::class,
310
                DateTimeConverter::CONFIGURATION_DATE_FORMAT,
311
                $this->settings['search']['dateFormat']
312
            );
313
    }
314
315
    /**
316
     * List action for backend module
317
     *
318
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Dto\SearchDemand $searchDemand SearchDemand
319
     * @param array $overwriteDemand OverwriteDemand
320
     *
321
     * @return void
322
     */
323
    public function listAction(SearchDemand $searchDemand = null, array $overwriteDemand = [])
324
    {
325
        /** @var EventDemand $eventDemand */
326
        $eventDemand = $this->objectManager->get(EventDemand::class);
327
        $eventDemand = $this->overwriteEventDemandObject($eventDemand, $overwriteDemand);
328
        $eventDemand->setOrderFieldAllowed($this->settings['orderFieldAllowed']);
329
330
        if ($searchDemand !== null) {
331
            $searchDemand->setFields($this->settings['search']['fields']);
332
333
            $sessionData = [];
334
            $sessionData['searchDemand'] = $searchDemand;
335
            $sessionData['overwriteDemand'] = $overwriteDemand;
336
            $this->beUserSessionService->saveSessionData($sessionData);
337
        } else {
338
            // Try to restore search demand from Session
339
            $searchDemand = $this->beUserSessionService->getSessionDataByKey('searchDemand');
340
            $overwriteDemand = $this->beUserSessionService->getSessionDataByKey('overwriteDemand');
341
        }
342
343
        $eventDemand->setSearchDemand($searchDemand);
344
        $eventDemand->setStoragePage($this->pid);
345
346
        $this->view->assignMultiple([
347
            'pid' => $this->pid,
348
            'events' => $this->eventRepository->findDemanded($eventDemand),
349
            'searchDemand' => $searchDemand,
350
            'orderByFields' => $this->getOrderByFields(),
351
            'orderDirections' => $this->getOrderDirections(),
352
            'overwriteDemand' => $overwriteDemand,
353
        ]);
354
    }
355
356
    /**
357
     * Export registrations for a given event
358
     *
359
     * @param int $eventUid Event UID
360
     *
361
     * @return void
362
     */
363
    public function exportAction($eventUid)
364
    {
365
        $this->exportService->downloadRegistrationsCsv($eventUid, $this->settings['csvExport']);
366
        exit();
367
    }
368
369
    /**
370
     * Handles expired registrations
371
     *
372
     * @return void
373
     */
374
    public function handleExpiredRegistrationsAction()
375
    {
376
        $delete = (bool)$this->settings['registration']['deleteExpiredRegistrations'];
377
        $this->maintenanceService->handleExpiredRegistrations($delete);
378
379
        $this->addFlashMessage(
380
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.content'),
381
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-1.title'),
382
            FlashMessage::OK
383
        );
384
385
        $this->redirect('list');
386
    }
387
388
    /**
389
     * The index notify action
390
     *
391
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
392
     *
393
     * @return void
394
     */
395
    public function indexNotifyAction(Event $event)
396
    {
397
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
398
        $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...
399
        $this->view->assignMultiple([
400
            'event' => $event,
401
            'customNotifications' => $customNotifications,
402
            'logEntries' => $logEntries,
403
        ]);
404
    }
405
406
    /**
407
     * Notify action
408
     *
409
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Event $event Event
410
     * @param string $customNotification CustomNotification
411
     *
412
     * @return void
413
     */
414
    public function notifyAction(Event $event, $customNotification)
415
    {
416
        $customNotifications = $this->settingsService->getCustomNotifications($this->settings);
417
        $result = $this->notificationService->sendCustomNotification($event, $customNotification, $this->settings);
418
        $this->notificationService->createCustomNotificationLogentry(
419
            $event,
420
            $customNotifications[$customNotification],
421
            $result
422
        );
423
        $this->addFlashMessage(
424
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.content'),
425
            $this->getLanguageService()->sL(self::LANG_FILE . 'administration.message-2.title'),
426
            FlashMessage::OK
427
        );
428
        $this->redirect('list');
429
    }
430
431
    /**
432
     * Shows the settings error view
433
     *
434
     * @return void
435
     */
436
    public function settingsErrorAction()
437
    {
438
    }
439
440
    /**
441
     * Suppress default validation messages
442
     *
443
     * @return bool
444
     */
445
    protected function getErrorFlashMessage()
446
    {
447
        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...
448
    }
449
450
    /**
451
     * Returns the LanguageService
452
     *
453
     * @return LanguageService
454
     */
455
    protected function getLanguageService(): LanguageService
456
    {
457
        return $GLOBALS['LANG'];
458
    }
459
460
    /**
461
     * Returns an array with possible order directions
462
     *
463
     * @return array
464
     */
465
    public function getOrderDirections()
466
    {
467
        return [
468
            'asc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.asc'),
469
            'desc' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.sortOrder.desc')
470
        ];
471
    }
472
473
    /**
474
     * Returns an array with possible orderBy fields
475
     *
476
     * @return array
477
     */
478
    public function getOrderByFields()
479
    {
480
        return [
481
            'title' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.title'),
482
            'startdate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.startdate'),
483
            'enddate' => $this->getLanguageService()->sL(self::LANG_FILE . 'administration.orderBy.enddate')
484
        ];
485
    }
486
}
487