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
Push — master ( 138d08...b4d67e )
by Dragos
14:16
created

BusinessHours::getDateBefore()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
1
<?php
2
3
namespace Speicher210\BusinessHours;
4
5
use Speicher210\BusinessHours\Day\DayInterface;
6
use Speicher210\BusinessHours\Day\Time\TimeBuilder;
7
use Speicher210\BusinessHours\Day\Time\TimeIntervalInterface;
8
9
/**
10
 * Default implementation of BusinessHoursInterface.
11
 */
12
class BusinessHours implements BusinessHoursInterface
13
{
14
    /**
15
     * The days.
16
     *
17
     * @var DayInterface[]
18
     */
19
    protected $days;
20
21
    /**
22
     * The time zone.
23
     *
24
     * @var \DateTimeZone
25
     */
26
    protected $timezone;
27
28
    /**
29
     * Constructor.
30
     *
31
     * @param DayInterface[] $days
32
     * @param \DateTimeZone|null $timezone
33
     */
34
    public function __construct(array $days, \DateTimeZone $timezone = null)
35
    {
36
        $this->setDays($days);
37
        $this->timezone = $timezone ?: new \DateTimeZone(date_default_timezone_get());
38
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43
    public function getTimezone()
44
    {
45
        return $this->timezone;
46
    }
47
48
    /**
49
     * Get the days.
50
     *
51
     * @return DayInterface[]
52
     */
53
    public function getDays()
54
    {
55
        return array_values($this->days);
56
    }
57
58
    /**
59
     * Add a set of days.
60
     *
61
     * @param DayInterface[] $days The days.
62
     * @throws \InvalidArgumentException If no days are passed.
63
     */
64
    protected function setDays(array $days)
65
    {
66
        if (empty($days)) {
67
            throw new \InvalidArgumentException('At least one day must be added.');
68
        }
69
70
        $this->days = [];
71
72
        foreach ($days as $day) {
73
            $this->addDay($day);
74
        }
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function within(\DateTime $date)
81
    {
82
        $tmpDate = clone $date;
83
        $tmpDate->setTimezone($this->timezone);
84
85
        if (null !== $day = $this->getDay((int)$tmpDate->format('N'))) {
86
            return $day->isWithinOpeningHours(TimeBuilder::fromDate($tmpDate));
87
        }
88
89
        return false;
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95 View Code Duplication
    public function getNextChangeDateTime(\DateTime $date)
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...
96
    {
97
        $tmpDate = clone $date;
98
        $tmpDate->setTimezone($this->timezone);
99
        $dateInterval = $this->getNextClosestInterval($tmpDate);
100
101
        if ($this->within($date)) {
102
            return ($date == $dateInterval->getStart()) ? $dateInterval->getStart() : $dateInterval->getEnd();
103
        } else {
104
            return $dateInterval->getStart();
105
        }
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111 View Code Duplication
    public function getPreviousChangeDateTime(\DateTime $date)
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...
112
    {
113
        $tmpDate = clone $date;
114
        $tmpDate->setTimezone($this->timezone);
115
        $dateInterval = $this->getPreviousClosestInterval($tmpDate);
116
117
        if ($this->within($date)) {
118
            return ($date == $dateInterval->getEnd()) ? $dateInterval->getEnd() : $dateInterval->getStart();
119
        } else {
120
            return $dateInterval->getEnd();
121
        }
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127
    public function jsonSerialize()
128
    {
129
        return array(
130
            'days' => $this->days,
131
            'timezone' => $this->timezone->getName(),
132
        );
133
    }
134
135
    /**
136
     * Get the closest business hours date interval before the given date.
137
     *
138
     * @param \DateTime $date The given date.
139
     * @return DateTimeInterval
140
     */
141 View Code Duplication
    private function getClosestDateIntervalBefore(\DateTime $date)
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...
142
    {
143
        $tmpDate = clone $date;
144
        $dayOfWeek = (int)$tmpDate->format('N');
145
        $time = TimeBuilder::fromDate($tmpDate);
146
147
        if (null !== $day = $this->getDay($dayOfWeek)) {
148
            if (null !== $closestTime = $day->getClosestPreviousOpeningHoursInterval($time)) {
149
                return $this->buildDateTimeInterval($tmpDate, $closestTime);
150
            }
151
        }
152
153
        $tmpDate = $this->getDateBefore($tmpDate);
154
155
        $closestDay = $this->getClosestDayBefore((int)$tmpDate->format('N'));
156
157
        $closingTime = $closestDay->getClosingTime();
158
        $closestTime = $closestDay->getClosestPreviousOpeningHoursInterval($closingTime);
159
160
        return $this->buildDateTimeInterval($tmpDate, $closestTime);
161
    }
162
163
    /**
164
     * Get the closest business hours date interval after the given date.
165
     *
166
     * @param \DateTime $date The given date.
167
     * @return DateTimeInterval
168
     */
169 View Code Duplication
    private function getClosestDateIntervalAfter(\DateTime $date)
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...
170
    {
171
        $tmpDate = clone $date;
172
        $dayOfWeek = (int)$tmpDate->format('N');
173
        $time = TimeBuilder::fromDate($tmpDate);
174
175
        if (null !== $day = $this->getDay($dayOfWeek)) {
176
            if (null !== $closestTime = $day->getClosestNextOpeningHoursInterval($time)) {
177
                return $this->buildDateTimeInterval($tmpDate, $closestTime);
178
            }
179
        }
180
181
        $tmpDate = $this->getDateAfter($tmpDate);
182
183
        $closestDay = $this->getClosestDayBefore((int)$tmpDate->format('N'));
184
185
        $openingTime = $closestDay->getOpeningTime();
186
        $closestTime = $closestDay->getClosestNextOpeningHoursInterval($openingTime);
187
188
        return $this->buildDateTimeInterval($tmpDate, $closestTime);
189
    }
190
191
    /**
192
     * Build a new date time interval for a date.
193
     *
194
     * @param \DateTime $date The date.
195
     * @param TimeIntervalInterface $timeInterval
196
     * @return DateTimeInterval
197
     */
198
    private function buildDateTimeInterval(\DateTime $date, TimeIntervalInterface $timeInterval)
199
    {
200
        $intervalStart = clone $date;
201
        $intervalEnd = clone $date;
202
203
        $intervalStart->setTime(
204
            $timeInterval->getStart()->getHours(),
205
            $timeInterval->getStart()->getMinutes(),
206
            $timeInterval->getStart()->getSeconds()
207
        );
208
        $intervalEnd->setTime(
209
            $timeInterval->getEnd()->getHours(),
210
            $timeInterval->getEnd()->getMinutes(),
211
            $timeInterval->getEnd()->getSeconds()
212
        );
213
214
        return new DateTimeInterval($intervalStart, $intervalEnd);
215
    }
216
217
    /**
218
     * Get the business hours date before the given date.
219
     *
220
     * @param \DateTime $date
221
     * @return \DateTime
222
     */
223
    private function getDateBefore(\DateTime $date)
224
    {
225
        $tmpDate = clone $date;
226
        $tmpDate->modify('-1 day');
227
228
        $dayOfWeek = (int)$tmpDate->format('N');
229
        $closestDay = $this->getClosestDayBefore($dayOfWeek);
230
        if ($closestDay->getDayOfWeek() !== $dayOfWeek) {
231
            $tmpDate->modify(sprintf('last %s', $closestDay->getDayOfWeekName()));
232
        }
233
        return $tmpDate;
234
    }
235
236
    /**
237
     * Get the business hours date after the given date.
238
     *
239
     * @param \DateTime $date
240
     * @return \DateTime
241
     */
242
    private function getDateAfter(\DateTime $date)
243
    {
244
        $tmpDate = clone $date;
245
        $tmpDate->modify('+1 day');
246
247
        $dayOfWeek = (int)$tmpDate->format('N');
248
        $closestDay = $this->getClosestDayAfter($dayOfWeek);
249
250
        if ($closestDay->getDayOfWeek() !== $dayOfWeek) {
251
            $tmpDate->modify(sprintf('next %s', $closestDay->getDayOfWeekName()));
252
        }
253
254
        return $tmpDate;
255
    }
256
257
    /**
258
     * Get the closest interval endpoint after the given date.
259
     *
260
     * @param \DateTime $date
261
     * @return DateTimeInterval
262
     */
263 View Code Duplication
    private function getPreviousClosestInterval(\DateTime $date)
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...
264
    {
265
        $tmpDate = clone $date;
266
        $dayOfWeek = (int)$tmpDate->format('N');
267
        $time = TimeBuilder::fromDate($tmpDate);
268
269
        if (null !== $day = $this->getDay($dayOfWeek)) {
270
            if (null !== $closestTime = $day->getClosestPreviousOpeningHoursInterval($time)) {
271
                return $this->buildDateTimeInterval($tmpDate, $closestTime);
272
            }
273
        }
274
275
        return $this->getClosestDateIntervalBefore($date);
276
    }
277
278
    /**
279
     * Get the closest interval endpoint after the given date.
280
     *
281
     * @param \DateTime $date
282
     * @return DateTimeInterval
283
     */
284 View Code Duplication
    private function getNextClosestInterval(\DateTime $date)
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...
285
    {
286
        $tmpDate = clone $date;
287
        $dayOfWeek = (int)$tmpDate->format('N');
288
        $time = TimeBuilder::fromDate($tmpDate);
289
290
        if (null !== $day = $this->getDay($dayOfWeek)) {
291
            if (null !== $closestTime = $day->getClosestNextOpeningHoursInterval($time)) {
292
                return $this->buildDateTimeInterval($tmpDate, $closestTime);
293
            }
294
        }
295
296
        return $this->getClosestDateIntervalAfter($date);
297
    }
298
299
    /**
300
     * Get the closest business hours day before a given day number (including it).
301
     *
302
     * @param integer $dayNumber
303
     * @return DayInterface|null
304
     */
305
    private function getClosestDayBefore($dayNumber)
306
    {
307
        if (null !== $day = $this->getDay($dayNumber)) {
308
            return $day;
309
        }
310
311
        return $this->getDayBefore($dayNumber);
312
    }
313
314
    /**
315
     * Get the closest business hours day after a given day number (including it).
316
     *
317
     * @param integer $dayNumber
318
     * @return DayInterface|null
319
     */
320
    private function getClosestDayAfter($dayNumber)
321
    {
322
        if (null !== $day = $this->getDay($dayNumber)) {
323
            return $day;
324
        }
325
326
        return $this->getDayAfter($dayNumber);
327
    }
328
329
    /**
330
     * Get the business hours day before the day number.
331
     *
332
     * @param integer $dayNumber
333
     * @return DayInterface|null
334
     */
335 View Code Duplication
    private function getDayBefore($dayNumber)
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...
336
    {
337
        $tmpDayNumber = $dayNumber;
338
339
        for ($i = 0; $i < 6; $i++) {
340
            $tmpDayNumber = (DayInterface::WEEK_DAY_MONDAY === $tmpDayNumber) ? DayInterface::WEEK_DAY_SUNDAY : --$tmpDayNumber;
341
342
            if (null !== $day = $this->getDay($tmpDayNumber)) {
343
                return $day;
344
            }
345
        }
346
347
        return $this->getDay($dayNumber);
348
    }
349
350
    /**
351
     * Get the business hours day after the day number.
352
     *
353
     * @param integer $dayNumber
354
     * @return DayInterface|null
355
     */
356 View Code Duplication
    private function getDayAfter($dayNumber)
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...
357
    {
358
        $tmpDayNumber = $dayNumber;
359
360
        for ($i = 0; $i < 6; $i++) {
361
            $tmpDayNumber = (DayInterface::WEEK_DAY_SUNDAY === $tmpDayNumber) ? DayInterface::WEEK_DAY_MONDAY : ++$tmpDayNumber;
362
363
            if (null !== $day = $this->getDay($tmpDayNumber)) {
364
                return $day;
365
            }
366
        }
367
368
        return $this->getDay($dayNumber);
369
    }
370
371
    /**
372
     * Get the day corresponding to the day of the week.
373
     *
374
     * @param integer $dayOfWeek The day of the week.
375
     * @return DayInterface|null
376
     */
377
    private function getDay($dayOfWeek)
378
    {
379
        return isset($this->days[$dayOfWeek]) ? $this->days[$dayOfWeek] : null;
380
    }
381
382
    /**
383
     * Add a day.
384
     *
385
     * @param DayInterface $day The day.
386
     */
387
    private function addDay(DayInterface $day)
388
    {
389
        $this->days[$day->getDayOfWeek()] = $day;
390
    }
391
392
    /**
393
     * Clone.
394
     */
395
    public function __clone()
396
    {
397
        $days = array();
398
        foreach ($this->days as $key => $day) {
399
            $days[$key] = clone $day;
400
        }
401
402
        $this->days = $days;
403
    }
404
}
405