SwapDecorator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 3
1
<?php
2
3
/**
4
 * Copyright Andreas Heigl <[email protected]>
5
 *
6
 * Licensed under the MIT-license. For details see the included file LICENSE.md
7
 */
8
9
declare(strict_types=1);
10
11
namespace Org_Heigl\Holidaychecker\IteratorItem;
12
13
use DateTimeInterface;
14
use IntlCalendar;
15
use Org_Heigl\Holidaychecker\CalendarDay;
16
use Org_Heigl\Holidaychecker\GregorianWeekday;
17
use Org_Heigl\Holidaychecker\HolidayIteratorItemInterface;
18
use Org_Heigl\Holidaychecker\SwapDirection;
19
use Org_Heigl\Holidaychecker\SwapRule;
20
use function in_array;
21
22
class SwapDecorator implements HolidayIteratorItemInterface
23
{
24
	/** @var HolidayIteratorItemInterface */
25
	private $rule;
26
27
	/** @var CalendarDay */
28
	private $day;
29
30
	/** @var SwapRule[] */
31
	private $swapRules;
32
33
	public function __construct(HolidayIteratorItemInterface $rule, CalendarDay $day, SwapRule ...$swapRules)
34
	{
35
		$this->rule = $rule;
36
		$this->day = $day;
37
		$this->swapRules = $swapRules;
38
	}
39
40
	public function dateMatches(DateTimeInterface $date): bool
41
	{
42
		$year = (int) $date->format('Y');
43
		$weekday = GregorianWeekday::fromIntlWeekday($this->day->getWeekdayForGregorianYear($year));
44
		foreach ($this->swapRules as $rule) {
45
			if ($this->ruleMatches($rule, $weekday)) {
46
				return $this->isModifiedDate($date, $rule->getSwapToDay(), $rule->getDirection());
47
			}
48
		}
49
50
		return $this->rule->dateMatches($date);
51
	}
52
53
	private function ruleMatches(SwapRule $rule, GregorianWeekday $weekday): bool
54
	{
55
		return in_array($weekday, $rule->getSwapWhenDays(), true);
56
	}
57
58
	private function isModifiedDate(DateTimeInterface $dateTime, GregorianWeekday $modifiedDay, SwapDirection $direction): bool
59
	{
60
		$cal = $this->day->getCalendar();
61
		$cal = CalendarDay::setGregorianYearForDate((int) $dateTime->format('Y'), $cal);
62
		$day = $cal->toDateTime();
63
		$day->modify($direction->getDateTimeDirection() . ' ' . $modifiedDay);
64
		$cal->setTime($day->getTimestamp() * 1000);
65
		$cal2 = $this->day->getCalendar();
66
		$cal2->setTime($dateTime->getTimestamp() * 1000);
67
68
		if ($this->day->hasYearSet() && $cal->get(IntlCalendar::FIELD_YEAR) !== $cal2->get(IntlCalendar::FIELD_YEAR)) {
69
			return false;
70
		}
71
72
		if ($cal->get(IntlCalendar::FIELD_MONTH) !== $cal2->get(IntlCalendar::FIELD_MONTH)) {
73
			return false;
74
		}
75
76
		return $cal->get(IntlCalendar::FIELD_DAY_OF_MONTH) === $cal2->get(IntlCalendar::FIELD_DAY_OF_MONTH);
77
	}
78
79
	public function getName(): string
80
	{
81
		return $this->rule->getName();
82
	}
83
84
	public function isHoliday(): bool
85
	{
86
		return $this->rule->isHoliday();
87
	}
88
}
89