GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#68)
by
unknown
01:21
created

OpeningHours::nextClose()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 20
Ratio 100 %

Importance

Changes 0
Metric Value
dl 20
loc 20
rs 9.6
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Spatie\OpeningHours;
4
5
use DateTime;
6
use DateTimeZone;
7
use DateTimeInterface;
8
use Spatie\OpeningHours\Helpers\Arr;
9
use Spatie\OpeningHours\Exceptions\Exception;
10
use Spatie\OpeningHours\Exceptions\InvalidDate;
11
use Spatie\OpeningHours\Exceptions\InvalidDayName;
12
13
class OpeningHours
14
{
15
    /** @var \Spatie\OpeningHours\Day[] */
16
    protected $openingHours = [];
17
18
    /** @var array */
19
    protected $exceptions = [];
20
21
    /** @var DateTimeZone|null */
22
    protected $timezone = null;
23
24
    public function __construct($timezone = null)
25
    {
26
        $this->timezone = $timezone ? new DateTimeZone($timezone) : null;
27
28
        $this->openingHours = Day::mapDays(function () {
29
            return new OpeningHoursForDay();
30
        });
31
    }
32
33
    /**
34
     * @param array $data
35
     *
36
     * @return static
37
     */
38
    public static function create(array $data)
39
    {
40
        return (new static())->fill($data);
41
    }
42
43
    /**
44
     * @param array $data
45
     *
46
     * @return bool
47
     */
48
    public static function isValid(array $data): bool
49
    {
50
        try {
51
            static::create($data);
52
53
            return true;
54
        } catch (Exception $exception) {
55
            return false;
56
        }
57
    }
58
59
    public function fill(array $data)
60
    {
61
        list($openingHours, $exceptions) = $this->parseOpeningHoursAndExceptions($data);
62
63
        foreach ($openingHours as $day => $openingHoursForThisDay) {
64
            $this->setOpeningHoursFromStrings($day, $openingHoursForThisDay);
65
        }
66
67
        $this->setExceptionsFromStrings($exceptions);
68
69
        return $this;
70
    }
71
72
    public function forWeek(): array
73
    {
74
        return $this->openingHours;
75
    }
76
77
    public function forWeekCombined(): array
78
    {
79
        $equalDays = [];
80
        $allOpeningHours = $this->openingHours;
81
        $uniqueOpeningHours = array_unique($allOpeningHours);
82
        $nonUniqueOpeningHours = $allOpeningHours;
83
84
        foreach ($uniqueOpeningHours as $day => $value) {
85
            $equalDays[$day] = ['days' => [$day], 'opening_hours' => $value];
86
            unset($nonUniqueOpeningHours[$day]);
87
        }
88
89
        foreach ($uniqueOpeningHours as $uniqueDay => $uniqueValue) {
90
            foreach ($nonUniqueOpeningHours as $nonUniqueDay => $nonUniqueValue) {
91
                if ((string) $uniqueValue === (string) $nonUniqueValue) {
92
                    $equalDays[$uniqueDay]['days'][] = $nonUniqueDay;
93
                }
94
            }
95
        }
96
97
        return $equalDays;
98
    }
99
100
    public function forDay(string $day): OpeningHoursForDay
101
    {
102
        $day = $this->normalizeDayName($day);
103
104
        return $this->openingHours[$day];
105
    }
106
107
    public function forDate(DateTimeInterface $date): OpeningHoursForDay
108
    {
109
        $date = $this->applyTimezone($date);
110
111
        return $this->exceptions[$date->format('Y-m-d')] ?? ($this->exceptions[$date->format('m-d')] ?? $this->forDay(Day::onDateTime($date)));
112
    }
113
114
    public function exceptions(): array
115
    {
116
        return $this->exceptions;
117
    }
118
119
    public function isOpenOn(string $day): bool
120
    {
121
        return count($this->forDay($day)) > 0;
122
    }
123
124
    public function isClosedOn(string $day): bool
125
    {
126
        return ! $this->isOpenOn($day);
127
    }
128
129
    public function isOpenAt(DateTimeInterface $dateTime): bool
130
    {
131
        $dateTime = $this->applyTimezone($dateTime);
132
133
        $openingHoursForDay = $this->forDate($dateTime);
134
135
        return $openingHoursForDay->isOpenAt(Time::fromDateTime($dateTime));
136
    }
137
138
    public function isClosedAt(DateTimeInterface $dateTime): bool
139
    {
140
        return ! $this->isOpenAt($dateTime);
141
    }
142
143
    public function isOpen(): bool
144
    {
145
        return $this->isOpenAt(new DateTime());
146
    }
147
148
    public function isClosed(): bool
149
    {
150
        return $this->isClosedAt(new DateTime());
151
    }
152
153 View Code Duplication
    public function nextOpen(DateTimeInterface $dateTime): DateTime
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
154
    {
155
        $openingHoursForDay = $this->forDate($dateTime);
156
        $nextOpen = $openingHoursForDay->nextOpen(Time::fromDateTime($dateTime));
157
158
        while ($nextOpen == false) {
159
            $dateTime
160
                ->modify('+1 day')
161
                ->setTime(0, 0, 0);
162
163
            $openingHoursForDay = $this->forDate($dateTime);
164
165
            $nextOpen = $openingHoursForDay->nextOpen(Time::fromDateTime($dateTime));
166
        }
167
168
        $nextDateTime = $nextOpen->toDateTime();
169
        $dateTime->setTime($nextDateTime->format('G'), $nextDateTime->format('i'), 0);
170
171
        return $dateTime;
172
    }
173
174 View Code Duplication
    public function nextClose(DateTimeInterface $dateTime): DateTime
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
175
    {
176
        $openingHoursForDay = $this->forDate($dateTime);
177
        $nextClose = $openingHoursForDay->nextClose(Time::fromDateTime($dateTime));
178
179
        while ($nextClose == false) {
180
            $dateTime
181
                ->modify('+1 day')
182
                ->setTime(0, 0, 0);
183
184
            $openingHoursForDay = $this->forDate($dateTime);
185
186
            $nextClose = $openingHoursForDay->nextClose(Time::fromDateTime($dateTime));
187
        }
188
189
        $nextDateTime = $nextClose->toDateTime();
190
        $dateTime->setTime($nextDateTime->format('G'), $nextDateTime->format('i'), 0);
191
192
        return $dateTime;
193
    }
194
195
    public function regularClosingDays(): array
196
    {
197
        return array_keys($this->filter(function (OpeningHoursForDay $openingHoursForDay) {
198
            return $openingHoursForDay->isEmpty();
199
        }));
200
    }
201
202
    public function regularClosingDaysISO(): array
203
    {
204
        return Arr::map($this->regularClosingDays(), [Day::class, 'toISO']);
205
    }
206
207
    public function exceptionalClosingDates(): array
208
    {
209
        $dates = array_keys($this->filterExceptions(function (OpeningHoursForDay $openingHoursForDay, $date) {
0 ignored issues
show
Unused Code introduced by
The parameter $date 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...
210
            return $openingHoursForDay->isEmpty();
211
        }));
212
213
        return Arr::map($dates, function ($date) {
214
            return DateTime::createFromFormat('Y-m-d', $date);
215
        });
216
    }
217
218
    public function setTimezone($timezone)
219
    {
220
        $this->timezone = new DateTimeZone($timezone);
221
    }
222
223
    protected function parseOpeningHoursAndExceptions(array $data): array
224
    {
225
        $exceptions = Arr::pull($data, 'exceptions', []);
226
        $openingHours = [];
227
228
        foreach ($data as $day => $openingHoursData) {
229
            $openingHours[$this->normalizeDayName($day)] = $openingHoursData;
230
        }
231
232
        return [$openingHours, $exceptions];
233
    }
234
235
    protected function setOpeningHoursFromStrings(string $day, array $openingHours)
236
    {
237
        $day = $this->normalizeDayName($day);
238
239
        $this->openingHours[$day] = OpeningHoursForDay::fromStrings($openingHours);
240
    }
241
242
    protected function setExceptionsFromStrings(array $exceptions)
243
    {
244
        $this->exceptions = Arr::map($exceptions, function (array $openingHours, string $date) {
245
            $recurring = DateTime::createFromFormat('m-d', $date);
246
247
            if ($recurring === false || $recurring->format('m-d') !== $date) {
248
                $dateTime = DateTime::createFromFormat('Y-m-d', $date);
249
250
                if ($dateTime === false || $dateTime->format('Y-m-d') !== $date) {
251
                    throw InvalidDate::invalidDate($date);
252
                }
253
            }
254
255
            return OpeningHoursForDay::fromStrings($openingHours);
256
        });
257
    }
258
259
    protected function normalizeDayName(string $day)
260
    {
261
        $day = strtolower($day);
262
263
        if (! Day::isValid($day)) {
264
            throw new InvalidDayName();
265
        }
266
267
        return $day;
268
    }
269
270
    protected function applyTimezone(DateTimeInterface $date)
271
    {
272
        if ($this->timezone) {
273
            $date = $date->setTimezone($this->timezone);
274
        }
275
276
        return $date;
277
    }
278
279
    public function filter(callable $callback): array
280
    {
281
        return Arr::filter($this->openingHours, $callback);
282
    }
283
284
    public function map(callable $callback): array
285
    {
286
        return Arr::map($this->openingHours, $callback);
287
    }
288
289
    public function flatMap(callable $callback): array
290
    {
291
        return Arr::flatMap($this->openingHours, $callback);
292
    }
293
294
    public function filterExceptions(callable $callback): array
295
    {
296
        return Arr::filter($this->exceptions, $callback);
297
    }
298
299
    public function mapExceptions(callable $callback): array
300
    {
301
        return Arr::map($this->exceptions, $callback);
302
    }
303
304
    public function flatMapExceptions(callable $callback): array
305
    {
306
        return Arr::flatMap($this->exceptions, $callback);
307
    }
308
309
    public function asStructuredData(): array
310
    {
311 View Code Duplication
        $regularHours = $this->flatMap(function (OpeningHoursForDay $openingHoursForDay, string $day) {
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...
312
            return $openingHoursForDay->map(function (TimeRange $timeRange) use ($day) {
313
                return [
314
                    '@type' => 'OpeningHoursSpecification',
315
                    'dayOfWeek' => ucfirst($day),
316
                    'opens' => (string) $timeRange->start(),
317
                    'closes' => (string) $timeRange->end(),
318
                ];
319
            });
320
        });
321
322
        $exceptions = $this->flatMapExceptions(function (OpeningHoursForDay $openingHoursForDay, string $date) {
323
            if ($openingHoursForDay->isEmpty()) {
324
                return [[
325
                    '@type' => 'OpeningHoursSpecification',
326
                    'opens' => '00:00',
327
                    'closes' => '00:00',
328
                    'validFrom' => $date,
329
                    'validThrough' => $date,
330
                ]];
331
            }
332
333 View Code Duplication
            return $openingHoursForDay->map(function (TimeRange $timeRange) use ($date) {
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...
334
                return [
335
                    '@type' => 'OpeningHoursSpecification',
336
                    'opens' => (string) $timeRange->start(),
337
                    'closes' => (string) $timeRange->end(),
338
                    'validFrom' => $date,
339
                    'validThrough' => $date,
340
                ];
341
            });
342
        });
343
344
        return array_merge($regularHours, $exceptions);
345
    }
346
}
347