Completed
Push — master ( 0ecd6b...9f36b3 )
by Tim
03:56
created

TimeTableService::selectTimesBy()   C

Complexity

Conditions 11
Paths 22

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 21
nc 22
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Time table builder service.
4
 */
5
namespace HDNET\Calendarize\Service;
6
7
use Exception;
8
use HDNET\Calendarize\Domain\Model\Configuration;
9
use HDNET\Calendarize\Domain\Model\ConfigurationInterface;
10
use HDNET\Calendarize\Domain\Repository\ConfigurationRepository;
11
use HDNET\Calendarize\Service\TimeTable\AbstractTimeTable;
12
use HDNET\Calendarize\Utility\DateTimeUtility;
13
use HDNET\Calendarize\Utility\HelperUtility;
14
use TYPO3\CMS\Core\Messaging\FlashMessage;
15
16
/**
17
 * Time table builder service.
18
 */
19
class TimeTableService extends AbstractService
20
{
21
    /**
22
     * Build the timetable for the given configuration matrix (sorted).
23
     *
24
     * @param array $ids
25
     *
26
     * @return array
27
     */
28
    public function getTimeTablesByConfigurationIds(array $ids)
29
    {
30
        $timeTable = [];
31
        if (!$ids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
32
            return $timeTable;
33
        }
34
35
        $configRepository = HelperUtility::create(ConfigurationRepository::class);
36
        foreach ($ids as $configurationUid) {
37
            $configuration = $configRepository->findByUid($configurationUid);
38
            if (!($configuration instanceof Configuration)) {
39
                continue;
40
            }
41
42
            $handler = $this->buildConfigurationHandler($configuration);
43
            if (!$handler) {
44
                HelperUtility::createFlashMessage(
45
                    'There is no TimeTable handler for the given configuration type: ' . $configuration->getType(),
46
                    'Index invalid',
47
                    FlashMessage::ERROR
48
                );
49
                continue;
50
            }
51
52
            if ($configuration->getHandling() === ConfigurationInterface::HANDLING_INCLUDE) {
53
                $handler->handleConfiguration($timeTable, $configuration);
54
            } elseif ($configuration->getHandling() === ConfigurationInterface::HANDLING_EXCLUDE) {
55
                $timesToExclude = [];
56
                $handler->handleConfiguration($timesToExclude, $configuration);
57
                $timeTable = $this->checkAndRemoveTimes($timeTable, $timesToExclude);
58
            } elseif ($configuration->getHandling() === ConfigurationInterface::HANDLING_OVERRIDE) {
59
                // first remove overridden times
60
                $timesToOverride = [];
61
                $handler->handleConfiguration($timesToOverride, $configuration);
62
                $timeTable = $this->checkAndRemoveTimes($timeTable, $timesToOverride);
63
                // then add new times
64
                $handler->handleConfiguration($timeTable, $configuration);
65
            } elseif ($configuration->getHandling() === ConfigurationInterface::HANDLING_CUTOUT) {
66
                $timesToSelectBy = [];
67
                $handler->handleConfiguration($timesToSelectBy, $configuration);
68
                $timeTable = $this->selectTimesBy($timeTable, $timesToSelectBy);
69
            }
70
        }
71
72
        return $timeTable;
73
    }
74
75
    /**
76
     * Selects events by given times.
77
     *
78
     * @param array $base
79
     * @param array $selectBy
80
     *
81
     * @return array
82
     */
83
    public function selectTimesBy($base, $selectBy)
84
    {
85
        $timeTableSelection = [];
86
87
        foreach ($base as $baseValue) {
88
            try {
89
                $eventStart = $this->getCompleteDate($baseValue, 'start');
90
                $eventEnd = $this->getCompleteDate($baseValue, 'end');
91
            } catch (Exception $ex) {
92
                continue;
93
            }
94
95
            foreach ($selectBy as $selectByValue) {
96
                try {
97
                    $selectionStart = $this->getCompleteDate($selectByValue, 'start');
98
                    $selectionEnd = $this->getCompleteDate($selectByValue, 'end');
99
                } catch (Exception $ex) {
100
                    continue;
101
                }
102
103
                $startIn = ($eventStart >= $selectionStart && $eventStart < $selectionEnd);
104
                $endIn = ($eventEnd > $selectionStart && $eventEnd <= $selectionEnd);
105
                $envelope = ($eventStart < $selectionStart && $eventEnd > $selectionEnd);
106
107
                if ($startIn && $endIn || $envelope) {
108
                    $timeTableSelection[] = $baseValue;
109
                    break;
110
                }
111
            }
112
        }
113
114
        return $timeTableSelection;
115
    }
116
117
    /**
118
     * Remove excluded events.
119
     *
120
     * @param array $base
121
     * @param $remove
122
     *
123
     * @return array
124
     */
125
    public function checkAndRemoveTimes($base, $remove)
126
    {
127
        foreach ($base as $key => $value) {
128
            try {
129
                $eventStart = $this->getCompleteDate($value, 'start');
130
                $eventEnd = $this->getCompleteDate($value, 'end');
131
            } catch (Exception $ex) {
132
                continue;
133
            }
134
135
            foreach ($remove as $removeValue) {
136
                try {
137
                    $removeStart = $this->getCompleteDate($removeValue, 'start');
138
                    $removeEnd = $this->getCompleteDate($removeValue, 'end');
139
                } catch (Exception $ex) {
140
                    continue;
141
                }
142
143
                $startIn = ($eventStart >= $removeStart && $eventStart < $removeEnd);
144
                $endIn = ($eventEnd > $removeStart && $eventEnd <= $removeEnd);
145
                $envelope = ($eventStart < $removeStart && $eventEnd > $removeEnd);
146
147
                if ($startIn || $endIn || $envelope) {
148
                    unset($base[$key]);
149
                    continue;
150
                }
151
            }
152
        }
153
154
        return $base;
155
    }
156
157
    /**
158
     * Get the complete day.
159
     *
160
     * @param array  $record
161
     * @param string $position
162
     *
163
     * @return \DateTime
164
     *
165
     * @throws Exception
166
     */
167
    protected function getCompleteDate(array $record, $position)
168
    {
169
        if (!($record[$position . '_date'] instanceof \DateTimeInterface)) {
170
            throw new Exception('no valid record', 1236781);
171
        }
172
        /** @var \DateTime $base */
173
        $base = clone $record[$position . '_date'];
174
        if (is_int($record[$position . '_time']) && (int) $record[$position . '_time'] > 0) {
175
            // Fix handling, if the time field contains a complete timestamp
176
            $seconds = $record[$position . '_time'] % DateTimeUtility::SECONDS_DAY;
177
            $base->setTime(0, 0, 0);
178
            $base->modify('+ ' . $seconds . ' seconds');
179
        }
180
181
        return $base;
182
    }
183
184
    /**
185
     * Build the configuration handler.
186
     *
187
     * @param Configuration $configuration
188
     *
189
     * @return bool|AbstractTimeTable
190
     */
191
    protected function buildConfigurationHandler(Configuration $configuration)
192
    {
193
        $handler = 'HDNET\\Calendarize\\Service\\TimeTable\\' . ucfirst($configuration->getType()) . 'TimeTable';
194
        if (!class_exists($handler)) {
195
            return false;
196
        }
197
198
        return HelperUtility::create($handler);
199
    }
200
}
201