Completed
Push — master ( 245656...39df9a )
by Kristof
04:42
created

CalendarFactory::createTimestamp()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 2
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
                $startTime = $timestamp->getStartTime() ? $timestamp->getStartTime() : '00:00:00';
86
                $startDateString = $timestamp->getDate() . 'T' . $startTime;
87
88
                if ($timestamp->getEndTime()) {
89
                    $endDateString = $timestamp->getDate() . 'T' . $timestamp->getEndTime();
90
                } else {
91
                    $endDateString = $timestamp->getDate() . 'T' . $startTime;
92
                }
93
94
                $timestamps[] = $this->createTimestamp(
95
                    $startDateString,
96
                    $endDateString
97
                );
98
            }
99
        }
100
101
        //
102
        // Get the opening hours.
103
        //
104
        $cdbCalendar->rewind();
105
        $openingHoursAsArray = [];
106
107
        $weekSchema = null;
108
        if ($cdbCalendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
109
            $period = $cdbCalendar->current();
110
            $weekSchema = $period->getWeekScheme();
111
        } else if ($cdbCalendar instanceof  \CultureFeed_Cdb_Data_Calendar_Permanent) {
112
            $weekSchema = $cdbCalendar->getWeekScheme();
113
        }
114
115
        if ($weekSchema) {
116
            $openingHours = $this->createOpeningHoursFromWeekScheme($weekSchema);
117
            $openingHoursAsArray = $this->openingHoursToArray($openingHours);
118
        }
119
120
        // End date might be before start date in cdbxml when event takes place
121
        // between e.g. 9 PM and 3 AM (the next day). UDB3 does not support this
122
        // and gracefully ignores the end time.
123
        //
124
        // Example cdbxml:
125
        //
126
        // <timestamp>
127
        //   <date>2016-12-16</date>
128
        //   <timestart>21:00:00</timestart>
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
129
        //   <timeend>05:00:00</timeend>
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
130
        // </timestamp>
131
        //
132
        if ($endDate < $startDate) {
133
            $endDate = $startDate;
134
        }
135
136
        //
137
        // Create the calendar value object.
138
        //
139
        return new Calendar(
140
            CalendarType::fromNative($calendarType),
141
            $startDate,
142
            $endDate,
143
            $timestamps,
144
            $openingHoursAsArray
145
        );
146
    }
147
148
    /**
149
     * @param \CultureFeed_Cdb_Data_Calendar_Weekscheme|null $weekScheme
150
     * @return Calendar
151
     */
152
    public function createFromWeekScheme(
153
        \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme = null
154
    ) {
155
        $openingHoursAsArray = [];
156
157
        if ($weekScheme) {
158
            $openingHours = $this->createOpeningHoursFromWeekScheme($weekScheme);
159
            $openingHoursAsArray = $this->openingHoursToArray($openingHours);
160
        }
161
162
        return new Calendar(
163
            CalendarType::PERMANENT(),
164
            null,
165
            null,
166
            [],
167
            $openingHoursAsArray
168
        );
169
    }
170
171
    /**
172
     * @param \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme
173
     * @return OpeningHours
174
     */
175
    private function createOpeningHoursFromWeekScheme(
176
        \CultureFeed_Cdb_Data_Calendar_Weekscheme $weekScheme
177
    ) {
178
        $openingHours = new OpeningHours();
179
180
        foreach ($weekScheme->getDays() as $day) {
181
            if ($day->isOpen()) {
182
                /** @var \CultureFeed_Cdb_Data_Calendar_OpeningTime[] $openingTimes */
183
                $openingTimes = $day->getOpeningTimes();
184
185
                $opens = \DateTime::createFromFormat(
186
                    'H:i:s',
187
                    $openingTimes ? $openingTimes[0]->getOpenFrom() : '00:00:00'
188
                );
189
                $closes = \DateTime::createFromFormat(
190
                    'H:i:s',
191
                    $openingTimes ? $openingTimes[0]->getOpenTill() : '00:00:00'
192
                );
193
194
                $openingHour = new OpeningHour(
195
                    WeekDay::fromNative(ucfirst($day->getDayName())),
196
                    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 185 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...
197
                    $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 185 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...
198
                );
199
200
                $openingHours->addOpeningHour($openingHour);
201
            }
202
        }
203
204
        return $openingHours;
205
    }
206
207
    /**
208
     * @param OpeningHours $openingHours
209
     * @return array
210
     */
211
    private function openingHoursToArray(OpeningHours $openingHours)
212
    {
213
        $openingHoursAsArray = [];
214
215
        $mergedOpeningHours = $this->createMergedOpeningHours($openingHours);
216
217
        foreach ($mergedOpeningHours as $mergedOpeningHour) {
218
            $openingHour = $mergedOpeningHour->getOpeningHours()[0];
219
            $openingHoursAsArray[] = [
220
                'dayOfWeek' => array_map(
221
                    function (WeekDay $weekDay) {
222
                        return strtolower($weekDay->toNative());
223
                    },
224
                    $mergedOpeningHour->getWeekDays()
225
                ),
226
                'opens' => $openingHour->getOpens()->toNativeDateTime()->format('H:i'),
227
                'closes' => $openingHour->getCloses()->toNativeDateTime()->format('H:i'),
228
            ];
229
        }
230
231
        return $openingHoursAsArray;
232
    }
233
234
    /**
235
     * @param OpeningHours $openingHours
236
     * @return OpeningHours[]
237
     */
238
    private function createMergedOpeningHours(OpeningHours $openingHours)
239
    {
240
        /** @var OpeningHours[] $mergedOpeningHours */
241
        $mergedOpeningHours = [];
242
243
        foreach ($openingHours->getOpeningHours() as $openingHour) {
244
            $merged = false;
245
            foreach ($mergedOpeningHours as $mergedOpeningHour) {
246
                if ($mergedOpeningHour->equalOpeningHour($openingHour)) {
247
                    $mergedOpeningHour->addOpeningHour($openingHour);
248
                    $merged = true;
249
                    break;
250
                }
251
            }
252
253
            if (!$merged) {
254
                $mergedOpeningHours[] = new OpeningHours([$openingHour]);
255
            }
256
        }
257
258
        return $mergedOpeningHours;
259
    }
260
261
    /**
262
     * @param string $startDateString
263
     * @param string $endDateString
264
     * @return Timestamp
265
     */
266
    private function createTimestamp(
267
        $startDateString,
268
        $endDateString
269
    ) {
270
        $startDate = DateTimeFactory::dateTimeFromDateString($startDateString);
271
        $endDate = DateTimeFactory::dateTimeFromDateString($endDateString);
272
273
        // End date might be before start date in cdbxml when event takes place
274
        // between e.g. 9 PM and 3 AM (the next day). UDB3 does not support this
275
        // and gracefully ignores the end time.
276
        //
277
        // Example cdbxml:
278
        //
279
        // <timestamp>
280
        //   <date>2016-12-16</date>
281
        //   <timestart>21:00:00</timestart>
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
282
        //   <timeend>05:00:00</timeend>
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
283
        // </timestamp>
284
        //
285
        if ($endDate < $startDate) {
286
            $endDate = $startDate;
287
        }
288
289
        return new Timestamp($startDate, $endDate);
290
    }
291
}
292