Completed
Pull Request — master (#243)
by Luc
05:30
created

createOpeningHoursFromWeekScheme()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.439
c 0
b 0
f 0
cc 6
eloc 18
nc 3
nop 1
1
<?php
2
3
namespace CultuurNet\UDB3;
4
5
use CultuurNet\UDB3\Cdb\DateTimeFactory;
6
use ValueObjects\DateTime\Time;
7
use ValueObjects\DateTime\WeekDay;
8
9
class CalendarFactory implements CalendarFactoryInterface
10
{
11
    /**
12
     * @inheritdoc
13
     */
14
    public function createFromCdbCalendar(\CultureFeed_Cdb_Data_Calendar $cdbCalendar)
15
    {
16
        //
17
        // Get the calendar type.
18
        //
19
        $calendarType = '';
20
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_Permanent) {
21
            $calendarType = 'permanent';
22
        } else if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
23
            $calendarType = 'periodic';
24
        } else if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_TimestampList) {
25
            $calendarType = 'single';
26
            if (iterator_count($cdbCalendar) > 1) {
27
                $calendarType = 'multiple';
28
            }
29
        }
30
31
        //
32
        // Get the start day.
33
        //
34
        $cdbCalendar->rewind();
35
        $startDateString = '';
36
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
37
            /** @var \CultureFeed_Cdb_Data_Calendar_Period $period */
38
            $period = $cdbCalendar->current();
39
            $startDateString = $period->getDateFrom() . 'T00:00:00';
40 View Code Duplication
        } else if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_TimestampList) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
41
            /** @var \CultureFeed_Cdb_Data_Calendar_Timestamp $timestamp */
42
            $timestamp = $cdbCalendar->current();
43
            if ($timestamp->getStartTime()) {
44
                $startDateString = $timestamp->getDate() . 'T' . $timestamp->getStartTime();
45
            } else {
46
                $startDateString = $timestamp->getDate() . 'T00:00:00';
47
            }
48
        }
49
        $startDate = !empty($startDateString) ? DateTimeFactory::dateTimeFromDateString($startDateString) : null;
50
51
        //
52
        // Get the end day.
53
        //
54
        $cdbCalendar->rewind();
55
        $endDateString = '';
56
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
57
            /** @var \CultureFeed_Cdb_Data_Calendar_Period $period */
58
            $period = $cdbCalendar->current();
59
            $endDateString = $period->getDateTo() . 'T00:00:00';
60
        } else if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_TimestampList) {
61
            $firstTimestamp = $cdbCalendar->current();
62
            /** @var \CultureFeed_Cdb_Data_Calendar_Timestamp $timestamp */
63
            $cdbCalendarAsArray = iterator_to_array($cdbCalendar);
64
            $timestamp = iterator_count($cdbCalendar) > 1 ? end($cdbCalendarAsArray) : $firstTimestamp;
65 View Code Duplication
            if ($timestamp->getEndTime()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
66
                $endDateString = $timestamp->getDate() . 'T' . $timestamp->getEndTime();
67
            } else {
68
                $endTime = $timestamp->getStartTime() ? $timestamp->getStartTime() : '00:00:00';
69
                $endDateString = $timestamp->getDate() . 'T' . $endTime;
70
            }
71
        }
72
        $endDate = !empty($endDateString) ? DateTimeFactory::dateTimeFromDateString($endDateString) : null;
73
74
        //
75
        // Get the time stamps.
76
        //
77
        $cdbCalendar->rewind();
78
        $timestamps = [];
79
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_TimestampList) {
80
            while ($cdbCalendar->valid()) {
81
                /** @var \CultureFeed_Cdb_Data_Calendar_Timestamp $timestamp */
82
                $timestamp = $cdbCalendar->current();
83
                $cdbCalendar->next();
84
85
                if ($timestamp->getStartTime()) {
86
                    $startDateString = $timestamp->getDate() . 'T' . $timestamp->getStartTime();
87
88 View Code Duplication
                    if ($timestamp->getEndTime()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
                        $endDateString = $timestamp->getDate() . 'T' . $timestamp->getEndTime();
90
                    } else {
91
                        $endTime = $timestamp->getStartTime() ? $timestamp->getStartTime() : '00:00:00';
92
                        $endDateString = $timestamp->getDate() . 'T' . $endTime;
93
                    }
94
                }
95
96
                $timestamps[] = new Timestamp(
97
                    DateTimeFactory::dateTimeFromDateString($startDateString),
98
                    DateTimeFactory::dateTimeFromDateString($endDateString)
99
                );
100
            }
101
        }
102
103
        //
104
        // Get the opening hours.
105
        //
106
        $cdbCalendar->rewind();
107
        $openingHoursAsArray = [];
108
109
        $weekSchema = null;
110
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
111
            $period = $cdbCalendar->current();
112
            $weekSchema = $period->getWeekScheme();
113
        } else if ($cdbCalendar instanceof  \CultureFeed_Cdb_Data_Calendar_Permanent) {
114
            $weekSchema = $cdbCalendar->getWeekScheme();
115
        }
116
117
        if ($weekSchema) {
118
            $openingHours = $this->createOpeningHoursFromWeekScheme($weekSchema);
119
            $openingHoursAsArray = $this->openingHoursToArray($openingHours);
120
        }
121
122
        //
123
        // Create the calendar value object.
124
        //
125
        return new Calendar(
126
            CalendarType::fromNative($calendarType),
127
            $startDate,
128
            $endDate,
129
            $timestamps,
130
            $openingHoursAsArray
131
        );
132
    }
133
134
    /**
135
     * @param \CultureFeed_Cdb_Data_Calendar_Weekscheme|null $weekScheme
136
     * @return Calendar
137
     */
138
    public function createFromWeekScheme(
139
        \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme = null
140
    ) {
141
        $openingHoursAsArray = [];
142
143
        if ($weekScheme) {
144
            $openingHours = $this->createOpeningHoursFromWeekScheme($weekScheme);
145
            $openingHoursAsArray = $this->openingHoursToArray($openingHours);
146
        }
147
148
        return new Calendar(
149
            CalendarType::PERMANENT(),
150
            null,
151
            null,
152
            [],
153
            $openingHoursAsArray
154
        );
155
    }
156
157
    /**
158
     * @param \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme
159
     * @return OpeningHours
160
     */
161
    private function createOpeningHoursFromWeekScheme(
162
        \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme
163
    ) {
164
        $openingHours = new OpeningHours();
165
166
        foreach ($weekScheme->getDays() as $day) {
167
            if ($day->isOpen()) {
168
                /** @var \CultureFeed_Cdb_Data_Calendar_OpeningTime[] $openingTimes */
169
                $openingTimes = $day->getOpeningTimes();
170
171
                $opens = \DateTime::createFromFormat(
172
                    'H:i:s',
173
                    $openingTimes ? $openingTimes[0]->getOpenFrom() : '00:00:00'
174
                );
175
                $closes = \DateTime::createFromFormat(
176
                    'H:i:s',
177
                    $openingTimes ? $openingTimes[0]->getOpenTill() : '00:00:00'
178
                );
179
180
                $openingHour = new OpeningHour(
181
                    WeekDay::fromNative(ucfirst($day->getDayName())),
182
                    Time::fromNativeDateTime($opens),
0 ignored issues
show
Security Bug introduced by
It seems like $opens defined by \DateTime::createFromFor...penFrom() : '00:00:00') on line 171 can also be of type false; however, ValueObjects\DateTime\Time::fromNativeDateTime() does only seem to accept object<DateTime>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
183
                    $closes ? Time::fromNativeDateTime($closes) : Time::fromNativeDateTime($opens)
0 ignored issues
show
Security Bug introduced by
It seems like $opens defined by \DateTime::createFromFor...penFrom() : '00:00:00') on line 171 can also be of type false; however, ValueObjects\DateTime\Time::fromNativeDateTime() does only seem to accept object<DateTime>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
184
                );
185
186
                $openingHours->addOpeningHour($openingHour);
187
            }
188
        }
189
190
        return $openingHours;
191
    }
192
193
    /**
194
     * @param OpeningHours $openingHours
195
     * @return array
196
     */
197
    private function openingHoursToArray(OpeningHours $openingHours)
198
    {
199
        $openingHoursAsArray = [];
200
201
        $mergedOpeningHours = $this->createMergedOpeningHours($openingHours);
202
203
        foreach ($mergedOpeningHours as $mergedOpeningHour) {
204
            $openingHour = $mergedOpeningHour->getOpeningHours()[0];
205
            $openingHoursAsArray[] = [
206
                'dayOfWeek' => array_map(
207
                    function (WeekDay $weekDay) {
208
                        return strtolower($weekDay->toNative());
209
                    },
210
                    $mergedOpeningHour->getWeekDays()
211
                ),
212
                'opens' => $openingHour->getOpens()->toNativeDateTime()->format('H:i'),
213
                'closes' => $openingHour->getCloses()->toNativeDateTime()->format('H:i'),
214
            ];
215
        }
216
217
        return $openingHoursAsArray;
218
    }
219
220
    /**
221
     * @param OpeningHours $openingHours
222
     * @return OpeningHours[]
223
     */
224
    private function createMergedOpeningHours(OpeningHours $openingHours)
225
    {
226
        /** @var OpeningHours[] $mergedOpeningHours */
227
        $mergedOpeningHours = [];
228
229
        foreach ($openingHours->getOpeningHours() as $openingHour) {
230
            $merged = false;
231
            foreach ($mergedOpeningHours as $mergedOpeningHour) {
232
                if ($mergedOpeningHour->equalOpeningHour($openingHour)) {
233
                    $mergedOpeningHour->addOpeningHour($openingHour);
234
                    $merged = true;
235
                    break;
236
                }
237
            }
238
239
            if (!$merged) {
240
                $mergedOpeningHours[] = new OpeningHours([$openingHour]);
241
            }
242
        }
243
244
        return $mergedOpeningHours;
245
    }
246
}
247