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 (#57)
by Deniss
01:36 queued 14s
created

OpeningHours::forWeekCombined()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 13
nc 8
nop 0
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
    public function nextOpen(DateTimeInterface $dateTime): DateTime
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
    public function regularClosingDays(): array
175
    {
176
        return array_keys($this->filter(function (OpeningHoursForDay $openingHoursForDay) {
177
            return $openingHoursForDay->isEmpty();
178
        }));
179
    }
180
181
    public function regularClosingDaysISO(): array
182
    {
183
        return Arr::map($this->regularClosingDays(), [Day::class, 'toISO']);
184
    }
185
186
    public function exceptionalClosingDates(): array
187
    {
188
        $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...
189
            return $openingHoursForDay->isEmpty();
190
        }));
191
192
        return Arr::map($dates, function ($date) {
193
            return DateTime::createFromFormat('Y-m-d', $date);
194
        });
195
    }
196
197
    public function setTimezone($timezone)
198
    {
199
        $this->timezone = new DateTimeZone($timezone);
200
    }
201
202
    protected function parseOpeningHoursAndExceptions(array $data): array
203
    {
204
        $exceptions = Arr::pull($data, 'exceptions', []);
205
        $openingHours = [];
206
207
        foreach ($data as $day => $openingHoursData) {
208
            $openingHours[$this->normalizeDayName($day)] = $openingHoursData;
209
        }
210
211
        return [$openingHours, $exceptions];
212
    }
213
214
    protected function setOpeningHoursFromStrings(string $day, array $openingHours)
215
    {
216
        $day = $this->normalizeDayName($day);
217
218
        $this->openingHours[$day] = OpeningHoursForDay::fromStrings($openingHours);
219
    }
220
221
    protected function setExceptionsFromStrings(array $exceptions)
222
    {
223
        $this->exceptions = Arr::map($exceptions, function (array $openingHours, string $date) {
224
            $recurring = DateTime::createFromFormat('m-d', $date);
225
226
            if ($recurring === false || $recurring->format('m-d') !== $date) {
227
                $dateTime = DateTime::createFromFormat('Y-m-d', $date);
228
229
                if ($dateTime === false || $dateTime->format('Y-m-d') !== $date) {
230
                    throw InvalidDate::invalidDate($date);
231
                }
232
            }
233
234
            return OpeningHoursForDay::fromStrings($openingHours);
235
        });
236
    }
237
238
    protected function normalizeDayName(string $day)
239
    {
240
        $day = strtolower($day);
241
242
        if (! Day::isValid($day)) {
243
            throw new InvalidDayName();
244
        }
245
246
        return $day;
247
    }
248
249
    protected function applyTimezone(DateTimeInterface $date)
250
    {
251
        if ($this->timezone) {
252
            $date = $date->setTimezone($this->timezone);
253
        }
254
255
        return $date;
256
    }
257
258
    public function filter(callable $callback): array
259
    {
260
        return Arr::filter($this->openingHours, $callback);
261
    }
262
263
    public function map(callable $callback): array
264
    {
265
        return Arr::map($this->openingHours, $callback);
266
    }
267
268
    public function flatMap(callable $callback): array
269
    {
270
        return Arr::flatMap($this->openingHours, $callback);
271
    }
272
273
    public function filterExceptions(callable $callback): array
274
    {
275
        return Arr::filter($this->exceptions, $callback);
276
    }
277
278
    public function mapExceptions(callable $callback): array
279
    {
280
        return Arr::map($this->exceptions, $callback);
281
    }
282
283
    public function flatMapExceptions(callable $callback): array
284
    {
285
        return Arr::flatMap($this->exceptions, $callback);
286
    }
287
288
    public function asStructuredData(): array
289
    {
290 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...
291
            return $openingHoursForDay->map(function (TimeRange $timeRange) use ($day) {
292
                return [
293
                    '@type' => 'OpeningHoursSpecification',
294
                    'dayOfWeek' => ucfirst($day),
295
                    'opens' => (string) $timeRange->start(),
296
                    'closes' => (string) $timeRange->end(),
297
                ];
298
            });
299
        });
300
301
        $exceptions = $this->flatMapExceptions(function (OpeningHoursForDay $openingHoursForDay, string $date) {
302
            if ($openingHoursForDay->isEmpty()) {
303
                return [[
304
                    '@type' => 'OpeningHoursSpecification',
305
                    'opens' => '00:00',
306
                    'closes' => '00:00',
307
                    'validFrom' => $date,
308
                    'validThrough' => $date,
309
                ]];
310
            }
311
312 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...
313
                return [
314
                    '@type' => 'OpeningHoursSpecification',
315
                    'opens' => $timeRange->start(),
316
                    'closes' => $timeRange->end(),
317
                    'validFrom' => $date,
318
                    'validThrough' => $date,
319
                ];
320
            });
321
        });
322
323
        return array_merge($regularHours, $exceptions);
324
    }
325
}
326