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:26
created

OpeningHours::forWeekCombined()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.5906
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
            /** @var OpeningHoursForDay $nonUniqueValue */
91
            foreach ($nonUniqueOpeningHours as $nonUniqueDay => $nonUniqueValue) {
92
                if ((string) $uniqueValue === (string) $nonUniqueValue) {
93
                    $equalDays[$uniqueDay]['days'][] = $nonUniqueDay;
94
                }
95
            }
96
        }
97
98
        return $equalDays;
99
    }
100
101
    public function forDay(string $day): OpeningHoursForDay
102
    {
103
        $day = $this->normalizeDayName($day);
104
105
        return $this->openingHours[$day];
106
    }
107
108
    public function forDate(DateTimeInterface $date): OpeningHoursForDay
109
    {
110
        $date = $this->applyTimezone($date);
111
112
        return $this->exceptions[$date->format('Y-m-d')] ?? ($this->exceptions[$date->format('m-d')] ?? $this->forDay(Day::onDateTime($date)));
113
    }
114
115
    public function exceptions(): array
116
    {
117
        return $this->exceptions;
118
    }
119
120
    public function isOpenOn(string $day): bool
121
    {
122
        return count($this->forDay($day)) > 0;
123
    }
124
125
    public function isClosedOn(string $day): bool
126
    {
127
        return ! $this->isOpenOn($day);
128
    }
129
130
    public function isOpenAt(DateTimeInterface $dateTime): bool
131
    {
132
        $dateTime = $this->applyTimezone($dateTime);
133
134
        $openingHoursForDay = $this->forDate($dateTime);
135
136
        return $openingHoursForDay->isOpenAt(Time::fromDateTime($dateTime));
137
    }
138
139
    public function isClosedAt(DateTimeInterface $dateTime): bool
140
    {
141
        return ! $this->isOpenAt($dateTime);
142
    }
143
144
    public function isOpen(): bool
145
    {
146
        return $this->isOpenAt(new DateTime());
147
    }
148
149
    public function isClosed(): bool
150
    {
151
        return $this->isClosedAt(new DateTime());
152
    }
153
154
    public function nextOpen(DateTimeInterface $dateTime): DateTime
155
    {
156
        $openingHoursForDay = $this->forDate($dateTime);
157
        $nextOpen = $openingHoursForDay->nextOpen(Time::fromDateTime($dateTime));
158
159
        while ($nextOpen == false) {
160
            $dateTime
161
                ->modify('+1 day')
162
                ->setTime(0, 0, 0);
163
164
            $openingHoursForDay = $this->forDate($dateTime);
165
166
            $nextOpen = $openingHoursForDay->nextOpen(Time::fromDateTime($dateTime));
167
        }
168
169
        $nextDateTime = $nextOpen->toDateTime();
170
        $dateTime->setTime($nextDateTime->format('G'), $nextDateTime->format('i'), 0);
171
172
        return $dateTime;
173
    }
174
175
    public function regularClosingDays(): array
176
    {
177
        return array_keys($this->filter(function (OpeningHoursForDay $openingHoursForDay) {
178
            return $openingHoursForDay->isEmpty();
179
        }));
180
    }
181
182
    public function regularClosingDaysISO(): array
183
    {
184
        return Arr::map($this->regularClosingDays(), [Day::class, 'toISO']);
185
    }
186
187
    public function exceptionalClosingDates(): array
188
    {
189
        $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...
190
            return $openingHoursForDay->isEmpty();
191
        }));
192
193
        return Arr::map($dates, function ($date) {
194
            return DateTime::createFromFormat('Y-m-d', $date);
195
        });
196
    }
197
198
    public function setTimezone($timezone)
199
    {
200
        $this->timezone = new DateTimeZone($timezone);
201
    }
202
203
    protected function parseOpeningHoursAndExceptions(array $data): array
204
    {
205
        $exceptions = Arr::pull($data, 'exceptions', []);
206
        $openingHours = [];
207
208
        foreach ($data as $day => $openingHoursData) {
209
            $openingHours[$this->normalizeDayName($day)] = $openingHoursData;
210
        }
211
212
        return [$openingHours, $exceptions];
213
    }
214
215
    protected function setOpeningHoursFromStrings(string $day, array $openingHours)
216
    {
217
        $day = $this->normalizeDayName($day);
218
219
        $this->openingHours[$day] = OpeningHoursForDay::fromStrings($openingHours);
220
    }
221
222
    protected function setExceptionsFromStrings(array $exceptions)
223
    {
224
        $this->exceptions = Arr::map($exceptions, function (array $openingHours, string $date) {
225
            $recurring = DateTime::createFromFormat('m-d', $date);
226
227
            if ($recurring === false || $recurring->format('m-d') !== $date) {
228
                $dateTime = DateTime::createFromFormat('Y-m-d', $date);
229
230
                if ($dateTime === false || $dateTime->format('Y-m-d') !== $date) {
231
                    throw InvalidDate::invalidDate($date);
232
                }
233
            }
234
235
            return OpeningHoursForDay::fromStrings($openingHours);
236
        });
237
    }
238
239
    protected function normalizeDayName(string $day)
240
    {
241
        $day = strtolower($day);
242
243
        if (! Day::isValid($day)) {
244
            throw new InvalidDayName();
245
        }
246
247
        return $day;
248
    }
249
250
    protected function applyTimezone(DateTimeInterface $date)
251
    {
252
        if ($this->timezone) {
253
            $date = $date->setTimezone($this->timezone);
254
        }
255
256
        return $date;
257
    }
258
259
    public function filter(callable $callback): array
260
    {
261
        return Arr::filter($this->openingHours, $callback);
262
    }
263
264
    public function map(callable $callback): array
265
    {
266
        return Arr::map($this->openingHours, $callback);
267
    }
268
269
    public function flatMap(callable $callback): array
270
    {
271
        return Arr::flatMap($this->openingHours, $callback);
272
    }
273
274
    public function filterExceptions(callable $callback): array
275
    {
276
        return Arr::filter($this->exceptions, $callback);
277
    }
278
279
    public function mapExceptions(callable $callback): array
280
    {
281
        return Arr::map($this->exceptions, $callback);
282
    }
283
284
    public function flatMapExceptions(callable $callback): array
285
    {
286
        return Arr::flatMap($this->exceptions, $callback);
287
    }
288
289
    public function asStructuredData(): array
290
    {
291 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...
292
            return $openingHoursForDay->map(function (TimeRange $timeRange) use ($day) {
293
                return [
294
                    '@type' => 'OpeningHoursSpecification',
295
                    'dayOfWeek' => ucfirst($day),
296
                    'opens' => (string) $timeRange->start(),
297
                    'closes' => (string) $timeRange->end(),
298
                ];
299
            });
300
        });
301
302
        $exceptions = $this->flatMapExceptions(function (OpeningHoursForDay $openingHoursForDay, string $date) {
303
            if ($openingHoursForDay->isEmpty()) {
304
                return [[
305
                    '@type' => 'OpeningHoursSpecification',
306
                    'opens' => '00:00',
307
                    'closes' => '00:00',
308
                    'validFrom' => $date,
309
                    'validThrough' => $date,
310
                ]];
311
            }
312
313 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...
314
                return [
315
                    '@type' => 'OpeningHoursSpecification',
316
                    'opens' => $timeRange->start(),
317
                    'closes' => $timeRange->end(),
318
                    'validFrom' => $date,
319
                    'validThrough' => $date,
320
                ];
321
            });
322
        });
323
324
        return array_merge($regularHours, $exceptions);
325
    }
326
}
327