Completed
Push — master ( 226640...8edbcf )
by Tim
02:24
created

CalendarController   F

Complexity

Total Complexity 66

Size/Duplication

Total Lines 604
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
wmc 66
lcom 1
cbo 18
dl 0
loc 604
rs 3.116
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
B initializeAction() 0 54 9
A latestAction() 0 29 3
A resultAction() 0 29 3
A listAction() 0 31 3
B shortcutAction() 0 31 6
A pastAction() 0 11 1
A yearAction() 0 9 1
A monthAction() 0 9 1
A weekAction() 0 31 3
A dayAction() 0 18 1
B detailAction() 0 26 6
A searchAction() 0 18 3
B singleAction() 0 39 6
C determineSearch() 0 56 12
A getAllowedActions() 0 10 3
A getCurrentConfigurations() 0 12 3
A slottedRedirect() 0 30 2

How to fix   Complexity   

Complex Class

Complex classes like CalendarController 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 CalendarController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Calendar.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Controller;
9
10
use HDNET\Calendarize\Domain\Model\Index;
11
use HDNET\Calendarize\Register;
12
use HDNET\Calendarize\Utility\DateTimeUtility;
13
use HDNET\Calendarize\Utility\EventUtility;
14
use HDNET\Calendarize\Utility\ExtensionConfigurationUtility;
15
use HDNET\Calendarize\Utility\TranslateUtility;
16
use TYPO3\CMS\Backend\Utility\BackendUtility;
17
use TYPO3\CMS\Core\Utility\ClassNamingUtility;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Core\Utility\MathUtility;
20
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
21
use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
22
use TYPO3\CMS\Extbase\Object\ObjectManager;
23
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
24
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
25
use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
26
27
/**
28
 * Calendar.
29
 */
30
class CalendarController extends AbstractController
31
{
32
    /**
33
     * Init all actions.
34
     */
35
    public function initializeAction()
36
    {
37
        parent::initializeAction();
38
        $this->indexRepository->setIndexTypes(GeneralUtility::trimExplode(',', $this->settings['configuration'], true));
39
        $additionalSlotArguments = [
40
            'contentRecord' => $this->configurationManager->getContentObject()->data,
41
            'settings' => $this->settings,
42
        ];
43
        $this->indexRepository->setAdditionalSlotArguments($additionalSlotArguments);
44
45
        if (isset($this->settings['sorting'])) {
46
            if (isset($this->settings['sortBy'])) {
47
                $this->indexRepository->setDefaultSortingDirection($this->settings['sorting'], $this->settings['sortBy']);
48
            } else {
49
                $this->indexRepository->setDefaultSortingDirection($this->settings['sorting']);
50
            }
51
        }
52
53
        if (isset($this->arguments['startDate'])) {
54
            $this->arguments['startDate']->getPropertyMappingConfiguration()
55
                ->setTypeConverterOption(
56
                    DateTimeConverter::class,
57
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
58
                    $this->settings['dateFormat']
59
                );
60
        }
61
        if (isset($this->arguments['endDate'])) {
62
            $this->arguments['endDate']->getPropertyMappingConfiguration()
63
                ->setTypeConverterOption(
64
                    DateTimeConverter::class,
65
                    DateTimeConverter::CONFIGURATION_DATE_FORMAT,
66
                    $this->settings['dateFormat']
67
                );
68
        }
69
        if ($this->request->hasArgument('event') && 'detailAction' === $this->actionMethodName) {
70
            // default configuration
71
            $configurationName = $this->settings['configuration'];
72
            // configuration overwritten by argument?
73
            if ($this->request->hasArgument('extensionConfiguration')) {
74
                $configurationName = $this->request->getArgument('extensionConfiguration');
75
            }
76
            // get the configuration
77
            $configuration = ExtensionConfigurationUtility::get($configurationName);
78
79
            // get Event by Configuration and Uid
80
            $event = EventUtility::getOriginalRecordByConfiguration($configuration, (int) $this->request->getArgument('event'));
81
            $index = $this->indexRepository->findByEventTraversing($event, true, false, 1)->getFirst();
82
83
            // if there is a valid index in the event
84
            if ($index) {
85
                $this->redirect('detail', null, null, ['index' => $index]);
86
            }
87
        }
88
    }
89
90
    /**
91
     * Latest action.
92
     *
93
     * @param \HDNET\Calendarize\Domain\Model\Index $index
94
     * @param \DateTime                             $startDate
95
     * @param \DateTime                             $endDate
96
     * @param array                                 $customSearch *
97
     * @param int                                   $year
98
     * @param int                                   $month
99
     * @param int                                   $week
100
     *
101
     * @ignorevalidation $startDate
102
     * @ignorevalidation $endDate
103
     * @ignorevalidation $customSearch
104
     *
105
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
106
     */
107
    public function latestAction(
108
        Index $index = null,
109
        \DateTime $startDate = null,
110
        \DateTime $endDate = null,
111
        array $customSearch = [],
112
        $year = null,
113
        $month = null,
114
        $week = null
115
    ) {
116
        $this->checkStaticTemplateIsIncluded();
117
        if (($index instanceof Index) && \in_array('detail', $this->getAllowedActions(), true)) {
118
            $this->forward('detail');
119
        }
120
121
        $search = $this->determineSearch($startDate, $endDate, $customSearch, $year, $month, null, $week);
122
123
        $this->slotExtendedAssignMultiple([
124
            'indices' => $search['indices'],
125
            'searchMode' => $search['searchMode'],
126
            'searchParameter' => [
127
                'startDate' => $startDate,
128
                'endDate' => $endDate,
129
                'customSearch' => $customSearch,
130
                'year' => $year,
131
                'month' => $month,
132
                'week' => $week,
133
            ],
134
        ], __CLASS__, __FUNCTION__);
135
    }
136
137
    /**
138
     * Result action.
139
     *
140
     * @param \HDNET\Calendarize\Domain\Model\Index $index
141
     * @param \DateTime                             $startDate
142
     * @param \DateTime                             $endDate
143
     * @param array                                 $customSearch
144
     * @param int                                   $year
145
     * @param int                                   $month
146
     * @param int                                   $week
147
     *
148
     * @ignorevalidation $startDate
149
     * @ignorevalidation $endDate
150
     * @ignorevalidation $customSearch
151
     *
152
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
153
     */
154
    public function resultAction(
155
        Index $index = null,
156
        \DateTime $startDate = null,
157
        \DateTime $endDate = null,
158
        array $customSearch = [],
159
        $year = null,
160
        $month = null,
161
        $week = null
162
    ) {
163
        $this->checkStaticTemplateIsIncluded();
164
        if (($index instanceof Index) && \in_array('detail', $this->getAllowedActions(), true)) {
165
            $this->forward('detail');
166
        }
167
168
        $search = $this->determineSearch($startDate, $endDate, $customSearch, $year, $month, null, $week);
169
170
        $this->slotExtendedAssignMultiple([
171
            'indices' => $search['indices'],
172
            'searchMode' => $search['searchMode'],
173
            'searchParameter' => [
174
                'startDate' => $startDate,
175
                'endDate' => $endDate,
176
                'customSearch' => $customSearch,
177
                'year' => $year,
178
                'month' => $month,
179
                'week' => $week,
180
            ],
181
        ], __CLASS__, __FUNCTION__);
182
    }
183
184
    /**
185
     * List action.
186
     *
187
     * @param \HDNET\Calendarize\Domain\Model\Index $index
188
     * @param \DateTime                             $startDate
189
     * @param \DateTime                             $endDate
190
     * @param array                                 $customSearch *
191
     * @param int                                   $year
192
     * @param int                                   $month
193
     * @param int                                   $day
194
     * @param int                                   $week
195
     *
196
     * @ignorevalidation $startDate
197
     * @ignorevalidation $endDate
198
     * @ignorevalidation $customSearch
199
     *
200
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
201
     */
202
    public function listAction(
203
        Index $index = null,
204
        \DateTime $startDate = null,
205
        \DateTime $endDate = null,
206
        array $customSearch = [],
207
        $year = null,
208
        $month = null,
209
        $day = null,
210
        $week = null
211
    ) {
212
        $this->checkStaticTemplateIsIncluded();
213
        if (($index instanceof Index) && \in_array('detail', $this->getAllowedActions(), true)) {
214
            $this->forward('detail');
215
        }
216
217
        $search = $this->determineSearch($startDate, $endDate, $customSearch, $year, $month, $day, $week);
218
219
        $this->slotExtendedAssignMultiple([
220
            'indices' => $search['indices'],
221
            'searchMode' => $search['searchMode'],
222
            'searchParameter' => [
223
                'startDate' => $startDate,
224
                'endDate' => $endDate,
225
                'customSearch' => $customSearch,
226
                'year' => $year,
227
                'month' => $month,
228
                'day' => $day,
229
                'week' => $week,
230
            ],
231
        ], __CLASS__, __FUNCTION__);
232
    }
233
234
    /**
235
     * Shortcut.
236
     */
237
    public function shortcutAction()
238
    {
239
        list($table, $uid) = explode(':', $GLOBALS['TSFE']->currentRecord);
240
        $register = Register::getRegister();
241
242
        $event = null;
243
        foreach ($register as $key => $value) {
244
            if ($value['tableName'] === $table) {
245
                $repositoryName = ClassNamingUtility::translateModelNameToRepositoryName($value['modelName']);
246
                if (class_exists($repositoryName)) {
247
                    $objectManager = new ObjectManager();
248
                    $repository = $objectManager->get($repositoryName);
249
                    $event = $repository->findByUid($uid);
250
                }
251
            }
252
        }
253
254
        if (!($event instanceof DomainObjectInterface)) {
255
            return 'Invalid object';
256
        }
257
258
        $fetchEvent = $this->indexRepository->findByEventTraversing($event, true, false, 1);
259
        if (count($fetchEvent) <= 0) {
260
            $fetchEvent = $this->indexRepository->findByEventTraversing($event, false, true, 1, QueryInterface::ORDER_DESCENDING);
261
        }
262
263
264
        $this->view->assignMultiple([
265
            'indices' => $fetchEvent,
266
        ]);
267
    }
268
269
    /**
270
     * Past action.
271
     *
272
     * @param int    $limit
273
     * @param string $sort
274
     *
275
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
276
     */
277
    public function pastAction(
278
        $limit = 100,
0 ignored issues
show
Unused Code introduced by
The parameter $limit is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
279
        $sort = 'ASC'
0 ignored issues
show
Unused Code introduced by
The parameter $sort is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
280
    ) {
281
        $limit = (int) ($this->settings['limit']);
282
        $sort = $this->settings['sorting'];
283
        $this->checkStaticTemplateIsIncluded();
284
        $this->slotExtendedAssignMultiple([
285
           'indices' => $this->indexRepository->findByPast($limit, $sort),
286
        ], __CLASS__, __FUNCTION__);
287
    }
288
289
    /**
290
     * Year action.
291
     *
292
     * @param int $year
293
     */
294
    public function yearAction($year = null)
295
    {
296
        $date = DateTimeUtility::normalizeDateTime(1, 1, $year);
297
298
        $this->slotExtendedAssignMultiple([
299
            'indices' => $this->indexRepository->findYear((int) $date->format('Y')),
300
            'date' => $date,
301
        ], __CLASS__, __FUNCTION__);
302
    }
303
304
    /**
305
     * Month action.
306
     *
307
     * @param int $year
308
     * @param int $month
309
     * @param int $day
310
     */
311
    public function monthAction($year = null, $month = null, $day = null)
312
    {
313
        $date = DateTimeUtility::normalizeDateTime($day, $month, $year);
314
315
        $this->slotExtendedAssignMultiple([
316
            'date' => $date,
317
            'indices' => $this->indexRepository->findMonth((int) $date->format('Y'), (int) $date->format('n')),
318
        ], __CLASS__, __FUNCTION__);
319
    }
320
321
    /**
322
     * Week action.
323
     *
324
     * @param int $year
325
     * @param int $week
326
     */
327
    public function weekAction($year = null, $week = null)
328
    {
329
        $now = DateTimeUtility::getNow();
330
        if (null === $year) {
331
            $year = $now->format('o'); // 'o' instead of 'Y': http://php.net/manual/en/function.date.php#106974
332
        }
333
        if (null === $week) {
334
            $week = $now->format('W');
335
        }
336
        $weekStart = (int) $this->settings['weekStart'];
337
        $firstDay = DateTimeUtility::convertWeekYear2DayMonthYear((int) $week, $year, $weekStart);
338
        $timezone = DateTimeUtility::getTimeZone();
339
        $firstDay->setTimezone($timezone);
340
        $firstDay->setTime(0, 0, 0);
341
342
        $weekConfiguration = [
343
            '+0 day' => 2,
344
            '+1 days' => 2,
345
            '+2 days' => 2,
346
            '+3 days' => 2,
347
            '+4 days' => 2,
348
            '+5 days' => 1,
349
            '+6 days' => 1,
350
        ];
351
352
        $this->slotExtendedAssignMultiple([
353
            'firstDay' => $firstDay,
354
            'indices' => $this->indexRepository->findWeek($year, $week, $this->settings['weekStart']),
355
            'weekConfiguration' => $weekConfiguration,
356
        ], __CLASS__, __FUNCTION__);
357
    }
358
359
    /**
360
     * Day action.
361
     *
362
     * @param int $year
363
     * @param int $month
364
     * @param int $day
365
     */
366
    public function dayAction($year = null, $month = null, $day = null)
367
    {
368
        $date = DateTimeUtility::normalizeDateTime($day, $month, $year);
369
        $date->modify('+12 hours');
370
371
        $previous = clone $date;
372
        $previous->modify('-1 day');
373
374
        $next = clone $date;
375
        $next->modify('+1 day');
376
377
        $this->slotExtendedAssignMultiple([
378
            'indices' => $this->indexRepository->findDay((int) $date->format('Y'), (int) $date->format('n'), (int) $date->format('j')),
379
            'today' => $date,
380
            'previous' => $previous,
381
            'next' => $next,
382
        ], __CLASS__, __FUNCTION__);
383
    }
384
385
    /**
386
     * Detail action.
387
     *
388
     * @param \HDNET\Calendarize\Domain\Model\Index $index
389
     *
390
     * @return string
391
     */
392
    public function detailAction(Index $index = null)
393
    {
394
        if (null === $index) {
395
            // handle fallback for "strange language settings"
396
            if ($this->request->hasArgument('index')) {
397
                $indexId = (int) $this->request->getArgument('index');
398
                if ($indexId > 0) {
399
                    $index = $this->indexRepository->findByUid($indexId);
400
                }
401
            }
402
403
            if (null === $index) {
404
                if (!MathUtility::canBeInterpretedAsInteger($this->settings['listPid'])) {
405
                    return (string) TranslateUtility::get('noEventDetailView');
406
                }
407
                $this->slottedRedirect(__CLASS__, __FUNCTION__ . 'noEvent');
408
            }
409
        }
410
411
        $this->slotExtendedAssignMultiple([
412
            'index' => $index,
413
            'domain' => GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'),
414
        ], __CLASS__, __FUNCTION__);
415
416
        return $this->view->render();
417
    }
418
419
    /**
420
     * Render the search view.
421
     *
422
     * @param \DateTime $startDate
423
     * @param \DateTime $endDate
424
     * @param array     $customSearch
425
     *
426
     * @ignorevalidation $startDate
427
     * @ignorevalidation $endDate
428
     * @ignorevalidation $customSearch
429
     */
430
    public function searchAction(\DateTime $startDate = null, \DateTime $endDate = null, array $customSearch = [])
431
    {
432
        $baseDate = DateTimeUtility::getNow();
433
        if (!($startDate instanceof \DateTimeInterface)) {
434
            $startDate = clone $baseDate;
435
        }
436
        if (!($endDate instanceof \DateTimeInterface)) {
437
            $baseDate->modify($this->settings['searchEndModifier']);
438
            $endDate = $baseDate;
439
        }
440
441
        $this->slotExtendedAssignMultiple([
442
            'startDate' => $startDate,
443
            'endDate' => $endDate,
444
            'customSearch' => $customSearch,
445
            'configurations' => $this->getCurrentConfigurations(),
446
        ], __CLASS__, __FUNCTION__);
447
    }
448
449
    /**
450
     * Render single items.
451
     */
452
    public function singleAction()
453
    {
454
        $indicies = [];
455
456
        // prepare selection
457
        $selections = [];
458
        $configurations = $this->getCurrentConfigurations();
459
        foreach (GeneralUtility::trimExplode(',', $this->settings['singleItems']) as $item) {
460
            list($table, $uid) = BackendUtility::splitTable_Uid($item);
461
            foreach ($configurations as $configuration) {
462
                if ($configuration['tableName'] === $table) {
463
                    $selections[] = [
464
                        'configuration' => $configuration,
465
                        'uid' => $uid,
466
                    ];
467
                    break;
468
                }
469
            }
470
        }
471
472
        // fetch index
473
        foreach ($selections as $selection) {
474
            $this->indexRepository->setIndexTypes([$selection['configuration']['uniqueRegisterKey']]);
475
            $dummyIndex = new Index();
476
            $dummyIndex->setForeignTable($selection['configuration']['tableName']);
477
            $dummyIndex->setForeignUid($selection['uid']);
478
479
            $result = $this->indexRepository->findByTraversing($dummyIndex);
480
            $index = $result->getQuery()->setLimit(1)->execute()->getFirst();
481
            if (\is_object($index)) {
482
                $indicies[] = $index;
483
            }
484
        }
485
486
        $this->slotExtendedAssignMultiple([
487
            'indicies' => $indicies,
488
            'configurations' => $configurations,
489
        ], __CLASS__, __FUNCTION__);
490
    }
491
492
    /**
493
     * Build the search structure.
494
     *
495
     * @param \DateTime|null $startDate
496
     * @param \DateTime|null $endDate
497
     * @param array          $customSearch
498
     * @param int            $year
499
     * @param int            $month
500
     * @param int            $day
501
     * @param int            $week
502
     *
503
     * @return array
504
     */
505
    protected function determineSearch(
506
        \DateTime $startDate = null,
507
        \DateTime $endDate = null,
508
        array $customSearch = [],
509
        $year = null,
510
        $month = null,
511
        $day = null,
512
        $week = null
513
    ) {
514
        $searchMode = false;
515
        if ($startDate || $endDate || !empty($customSearch)) {
516
            $searchMode = true;
517
            $indices = $this->indexRepository->findBySearch($startDate, $endDate, $customSearch);
518
        } elseif (MathUtility::canBeInterpretedAsInteger($year) && MathUtility::canBeInterpretedAsInteger($month) && MathUtility::canBeInterpretedAsInteger($day)) {
519
            $indices = $this->indexRepository->findDay((int) $year, (int) $month, (int) $day);
520
        } elseif (MathUtility::canBeInterpretedAsInteger($year) && MathUtility::canBeInterpretedAsInteger($month)) {
521
            $indices = $this->indexRepository->findMonth((int) $year, (int) $month);
522
        } elseif (MathUtility::canBeInterpretedAsInteger($year) && MathUtility::canBeInterpretedAsInteger($week)) {
523
            $indices = $this->indexRepository->findWeek($year, $week, $this->settings['weekStart']);
524
        } elseif (MathUtility::canBeInterpretedAsInteger($year)) {
525
            $indices = $this->indexRepository->findYear((int) $year);
526
        } else {
527
            $overrideStartDate = (int) $this->settings['overrideStartdate'];
528
            $overrideEndDate = (int) $this->settings['overrideEnddate'];
529
            $indices = $this->indexRepository->findList(
530
                (int) $this->settings['limit'],
531
                $this->settings['listStartTime'],
532
                (int) $this->settings['listStartTimeOffsetHours'],
533
                $overrideStartDate,
534
                $overrideEndDate
535
            );
536
        }
537
538
        // use this variable in your extension to add more custom variables
539
        $variables = [
540
            'extended' => [
541
                'indices' => $indices,
542
                'searchMode' => $searchMode,
543
                'parameters' => [
544
                    'startDate' => $startDate,
545
                    'endDate' => $endDate,
546
                    'customSearch' => $customSearch,
547
                    'year' => $year,
548
                    'month' => $month,
549
                    'day' => $day,
550
                    'week' => $week,
551
                ],
552
            ],
553
        ];
554
        $variables['settings'] = $this->settings;
555
556
        $dispatcher = $this->objectManager->get(Dispatcher::class);
557
        $variables = $dispatcher->dispatch(__CLASS__, __FUNCTION__, $variables);
558
559
        return $variables['extended'];
560
    }
561
562
    /**
563
     * Get the allowed actions.
564
     *
565
     * @return array
566
     */
567
    protected function getAllowedActions(): array
568
    {
569
        $configuration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
570
        $allowedActions = [];
571
        foreach ($configuration['controllerConfiguration'] as $controllerName => $controllerActions) {
572
            $allowedActions[$controllerName] = $controllerActions['actions'];
573
        }
574
575
        return \is_array($allowedActions['Calendar']) ? $allowedActions['Calendar'] : [];
576
    }
577
578
    /**
579
     * Get the current configurations.
580
     *
581
     * @return array
582
     */
583
    protected function getCurrentConfigurations()
584
    {
585
        $configurations = GeneralUtility::trimExplode(',', $this->settings['configuration'], true);
586
        $return = [];
587
        foreach (Register::getRegister() as $key => $configuration) {
588
            if (\in_array($key, $configurations, true)) {
589
                $return[] = $configuration;
590
            }
591
        }
592
593
        return $return;
594
    }
595
596
    /**
597
     * A redirect that have a slot included.
598
     *
599
     * @param string $signalClassName name of the signal class: __CLASS__
600
     * @param string $signalName      name of the signal: __FUNCTION__
601
     * @param array  $variables       optional: if not set use the defaults
602
     */
603
    protected function slottedRedirect($signalClassName, $signalName, $variables = null)
604
    {
605
        // set default variables for the redirect
606
        if (null === $variables) {
607
            $variables['extended'] = [
608
                'actionName' => 'list',
609
                'controllerName' => null,
610
                'extensionName' => null,
611
                'arguments' => [],
612
                'pageUid' => $this->settings['listPid'],
613
                'delay' => 0,
614
                'statusCode' => 301,
615
            ];
616
            $variables['extended']['pluginHmac'] = $this->calculatePluginHmac();
617
            $variables['settings'] = $this->settings;
618
        }
619
620
        $dispatcher = $this->objectManager->get(Dispatcher::class);
621
        $variables = $dispatcher->dispatch($signalClassName, $signalName, $variables);
622
623
        $this->redirect(
624
            $variables['extended']['actionName'],
625
            $variables['extended']['controllerName'],
626
            $variables['extended']['extensionName'],
627
            $variables['extended']['arguments'],
628
            $variables['extended']['pageUid'],
629
            $variables['extended']['delay'],
630
            $variables['extended']['statusCode']
631
        );
632
    }
633
}
634