Completed
Push — master ( 4499a5...96cd65 )
by Tim
02:15
created

TimeTimeTable   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 6
dl 0
loc 241
rs 8.8798
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
B handleConfiguration() 0 20 6
B validateBaseEntry() 0 47 9
B addFrequencyItems() 0 21 7
A createNextLoopEntry() 0 14 1
B getFrequencyIncrement() 0 28 8
B addRecurrenceItems() 0 46 11
A getFrequencyLimitPerItem() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like TimeTimeTable 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 TimeTimeTable, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Time service.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Service\TimeTable;
9
10
use HDNET\Calendarize\Domain\Model\Configuration;
11
use HDNET\Calendarize\Service\RecurrenceService;
12
use HDNET\Calendarize\Utility\ConfigurationUtility;
13
use HDNET\Calendarize\Utility\DateTimeUtility;
14
use HDNET\Calendarize\Utility\HelperUtility;
15
use TYPO3\CMS\Core\Messaging\FlashMessage;
16
use TYPO3\CMS\Core\Messaging\FlashMessageService;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
19
20
/**
21
 * Time service.
22
 */
23
class TimeTimeTable extends AbstractTimeTable
24
{
25
    /**
26
     * Modify the given times via the configuration.
27
     *
28
     * @param array         $times
29
     * @param Configuration $configuration
30
     */
31
    public function handleConfiguration(array &$times, Configuration $configuration)
32
    {
33
        $startTime = $configuration->isAllDay() ? null : $configuration->getStartTime();
34
        $endTime = $configuration->isAllDay() ? null : $configuration->getEndTime();
35
        $baseEntry = [
36
            'pid' => $configuration->getPid(),
37
            'start_date' => $configuration->getStartDate(),
38
            'end_date' => $configuration->getEndDate() ?: $configuration->getStartDate(),
39
            'start_time' => $startTime,
40
            'end_time' => 0 === $endTime ? self::DAY_END : $endTime,
41
            'all_day' => $configuration->isAllDay(),
42
            'state' => $configuration->getState(),
43
        ];
44
        if (!$this->validateBaseEntry($baseEntry)) {
45
            return;
46
        }
47
        $times[$this->calculateEntryKey($baseEntry)] = $baseEntry;
48
        $this->addFrequencyItems($times, $configuration, $baseEntry);
49
        $this->addRecurrenceItems($times, $configuration, $baseEntry);
50
    }
51
52
    /**
53
     * Validate the base entry, if there are logica mistakes.
54
     *
55
     * @param array $baseEntry
56
     *
57
     * @return bool
58
     */
59
    protected function validateBaseEntry(array $baseEntry): bool
60
    {
61
        $message = null;
62
        if (!($baseEntry['start_date'] instanceof \DateTimeInterface)) {
63
            $message = GeneralUtility::makeInstance(
64
                FlashMessage::class,
65
                'There is no usage for a event configuration without start date?!',
66
                'No start date?',
67
                FlashMessage::ERROR
68
            );
69
        } elseif ($baseEntry['end_date'] instanceof \DateTimeInterface && $baseEntry['start_date'] > $baseEntry['end_date']) {
70
            $message = GeneralUtility::makeInstance(
71
                FlashMessage::class,
72
                LocalizationUtility::translate(
73
                    'LLL:EXT:calendarize/Resources/Private/Language/locallang.xlf:wrong.date.message',
74
                    'calendarize'
75
                ),
76
                LocalizationUtility::translate(
77
                    'LLL:EXT:calendarize/Resources/Private/Language/locallang.xlf:wrong.date',
78
                    'calendarize'
79
                ),
80
                FlashMessage::ERROR
81
            );
82
        } elseif ($baseEntry['end_date'] instanceof \DateTimeInterface && !$baseEntry['all_day'] && $baseEntry['start_date']->format('d.m.Y') === $baseEntry['end_date']->format('d.m.Y') && $baseEntry['start_time'] % DateTimeUtility::SECONDS_DAY > $baseEntry['end_time'] % DateTimeUtility::SECONDS_DAY) {
83
            $message = GeneralUtility::makeInstance(
84
                FlashMessage::class,
85
                LocalizationUtility::translate(
86
                    'LLL:EXT:calendarize/Resources/Private/Language/locallang.xlf:wrong.time.message',
87
                    'calendarize'
88
                ),
89
                LocalizationUtility::translate(
90
                    'LLL:EXT:calendarize/Resources/Private/Language/locallang.xlf:wrong.time',
91
                    'calendarize'
92
                ),
93
                FlashMessage::ERROR
94
            );
95
        }
96
        if ($message) {
97
            $flashMessageService = HelperUtility::create(FlashMessageService::class);
98
            $messageQueue = $flashMessageService->getMessageQueueByIdentifier();
99
            $messageQueue->addMessage($message);
100
101
            return false;
102
        }
103
104
        return true;
105
    }
106
107
    /**
108
     * Add frequency items.
109
     *
110
     * @param array         $times
111
     * @param Configuration $configuration
112
     * @param array         $baseEntry
113
     */
114
    protected function addFrequencyItems(array &$times, Configuration $configuration, array $baseEntry)
115
    {
116
        $frequencyIncrement = $this->getFrequencyIncrement($configuration);
117
        if (!$frequencyIncrement) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $frequencyIncrement of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
118
            return;
119
        }
120
        $amountCounter = $configuration->getCounterAmount();
121
        $tillDate = $configuration->getTillDate();
122
        $maxLimit = $this->getFrequencyLimitPerItem();
123
        $lastLoop = $baseEntry;
124
        for ($i = 0; $i < $maxLimit && (0 === $amountCounter || $i < $amountCounter); ++$i) {
125
            $loopEntry = $this->createNextLoopEntry($lastLoop, $frequencyIncrement);
126
127
            if ($tillDate instanceof \DateTimeInterface && $loopEntry['start_date'] > $tillDate) {
128
                break;
129
            }
130
131
            $lastLoop = $loopEntry;
132
            $times[$this->calculateEntryKey($loopEntry)] = $loopEntry;
133
        }
134
    }
135
136
    /**
137
     * Create the next loop entry.
138
     *
139
     * @param array  $loopEntry
140
     * @param string $modification
141
     *
142
     * @return array
143
     */
144
    protected function createNextLoopEntry(array $loopEntry, string $modification): array
145
    {
146
        /** @var $startDate \DateTime */
147
        $startDate = clone $loopEntry['start_date'];
148
        $startDate->modify($modification);
149
        $loopEntry['start_date'] = $startDate;
150
151
        /** @var $endDate \DateTime */
152
        $endDate = clone $loopEntry['end_date'];
153
        $endDate->modify($modification);
154
        $loopEntry['end_date'] = $endDate;
155
156
        return $loopEntry;
157
    }
158
159
    /**
160
     * Get the frequency date increment.
161
     *
162
     * @param Configuration $configuration
163
     *
164
     * @return string
165
     */
166
    protected function getFrequencyIncrement(Configuration $configuration)
167
    {
168
        $interval = $configuration->getCounterInterval() <= 1 ? 1 : $configuration->getCounterInterval();
169
        switch ($configuration->getFrequency()) {
170
            case Configuration::FREQUENCY_DAILY:
171
                $intervalValue = '+' . $interval . ' days';
172
                break;
173
            case Configuration::FREQUENCY_WEEKLY:
174
                $intervalValue = '+' . $interval . ' weeks';
175
                break;
176
            case Configuration::FREQUENCY_MONTHLY:
177
                if (Configuration::RECURRENCE_NONE !== $configuration->getRecurrence()) {
178
                    return false;
179
                }
180
                $intervalValue = '+' . $interval . ' months';
181
                break;
182
            case Configuration::FREQUENCY_YEARLY:
183
                if (Configuration::RECURRENCE_NONE !== $configuration->getRecurrence()) {
184
                    return false;
185
                }
186
                $intervalValue = '+' . $interval . ' years';
187
                break;
188
            default:
189
                $intervalValue = false;
190
        }
191
192
        return $intervalValue;
193
    }
194
195
    /**
196
     * Add recurrence items.
197
     *
198
     * @param array         $times
199
     * @param Configuration $configuration
200
     * @param array         $baseEntry
201
     */
202
    protected function addRecurrenceItems(array &$times, Configuration $configuration, array $baseEntry)
203
    {
204
        if (Configuration::RECURRENCE_NONE === $configuration->getRecurrence() || Configuration::DAY_NONE === $configuration->getDay()) {
205
            return;
206
        }
207
208
        $recurrenceService = GeneralUtility::makeInstance(RecurrenceService::class);
209
        $amountCounter = $configuration->getCounterAmount();
210
        $tillDate = $configuration->getTillDate();
211
        $maxLimit = $this->getFrequencyLimitPerItem();
212
        $lastLoop = $baseEntry;
213
        for ($i = 0; $i < $maxLimit && (0 === $amountCounter || $i < $amountCounter); ++$i) {
214
            $loopEntry = $lastLoop;
215
216
            $dateTime = false;
217
            if (Configuration::FREQUENCY_MONTHLY === $configuration->getFrequency()) {
218
                $dateTime = $recurrenceService->getRecurrenceForNextMonth(
219
                    $loopEntry['start_date'],
220
                    $configuration->getRecurrence(),
221
                    $configuration->getDay()
222
                );
223
            } elseif (Configuration::FREQUENCY_YEARLY === $configuration->getFrequency()) {
224
                $dateTime = $recurrenceService->getRecurrenceForNextYear(
225
                    $loopEntry['start_date'],
226
                    $configuration->getRecurrence(),
227
                    $configuration->getDay()
228
                );
229
            }
230
            if (false === $dateTime) {
231
                break;
232
            }
233
234
            /** @var \DateInterval $interval */
235
            $interval = $loopEntry['start_date']->diff($dateTime);
236
            $frequencyIncrement = $interval->format('%R%a days');
237
238
            $loopEntry = $this->createNextLoopEntry($loopEntry, $frequencyIncrement);
239
240
            if ($tillDate instanceof \DateTimeInterface && $loopEntry['start_date'] > $tillDate) {
241
                break;
242
            }
243
244
            $lastLoop = $loopEntry;
245
            $times[$this->calculateEntryKey($loopEntry)] = $loopEntry;
246
        }
247
    }
248
249
    /**
250
     * Get the limit of the frequency.
251
     *
252
     * @return int
253
     */
254
    protected function getFrequencyLimitPerItem(): int
255
    {
256
        $maxLimit = (int) ConfigurationUtility::get('frequencyLimitPerItem');
257
        if ($maxLimit <= 0) {
258
            $maxLimit = 300;
259
        }
260
261
        return $maxLimit;
262
    }
263
}
264