AbstractProvider::getTimeZone()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Holiday Library.
5
 *
6
 * (c) Michał Mańko <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Michalmanko\Holiday\Provider;
13
14
use ArrayObject;
15
use DateTime;
16
use DateTimeZone;
17
use Michalmanko\Holiday\Holiday;
18
use Michalmanko\Holiday\Provider\Exception\InvalidArgumentException;
19
use Michalmanko\Holiday\Provider\Exception\UnexpectedValueException;
20
21
/**
22
 * Abstract provider class.
23
 *
24
 * @author Michał Mańko <[email protected]>
25
 */
26
abstract class AbstractProvider
27
{
28
    /**
29
     * Timezone.
30
     *
31
     * @var DateTimeZone
32
     */
33
    protected $timezone;
34
35
    /**
36
     * List of holidays by year.
37
     *
38
     * @var array
39
     */
40
    private $holidays = array();
41
42
    /**
43
     * @param null|DateTimeZone $timezone (optional) Timezone
44
     */
45 46
    public function __construct(DateTimeZone $timezone = null)
46
    {
47 46
        $this->timezone = $timezone;
48 46
    }
49
50
    /**
51
     * Prepare the holidays in given year.
52
     *
53
     * @param int $year The year to prepare the holidays for
54
     *
55
     * @return array An array of holidays
56
     */
57
    abstract protected function prepareHolidays($year);
58
59
    /**
60
     * Returns timezone.
61
     *
62
     * @return DateTimeZone
63
     */
64 30
    public function getTimeZone()
65
    {
66 30
        return $this->timezone;
67
    }
68
69
    /**
70
     * Creates a holiday object based on current timezone.
71
     *
72
     * @param string $name Name
73
     * @param mixed  $time Time
74
     * @param string $type Type
75
     *
76
     * @return Holiday
77
     */
78 28
    public function createHoliday($name, $time, $type = Holiday::TYPE_HOLIDAY)
79
    {
80 28
        return new Holiday($name, $time, $this->getTimeZone(), $type);
81
    }
82
83
    /**
84
     * Provides a DateTime object that represents easter sunday for this year.<br/>
85
     * The time is always set to 00:00:00.
86
     *
87
     * @param int $year The year for which to calculcate the easter sunday date
88
     *
89
     * @throws InvalidArgumentException
90
     *
91
     * @return DateTime
92
     */
93 26
    protected function getEaster($year)
94
    {
95 26
        $easter = new DateTime('now', $this->getTimeZone());
96 26
        $easter->setDate($year, 3, 21);
97 26
        $easter->setTime(0, 0, 0);
98 26
        $easter->modify('+' . easter_days($year) . 'days');
99
100 26
        return $easter;
101
    }
102
103
    /**
104
     * Prepare the holidays in given year based on {@see prepareHolidays()}.
105
     *
106
     * @param int $year
107
     *
108
     * @throws UnexpectedValueException
109
     */
110 34
    private function prepareHolidaysByYear($year)
111
    {
112 34
        if (!isset($this->holidays[$year])) {
113 34
            $preparedHolidays = $this->prepareHolidays($year);
114 34
            if (is_object($preparedHolidays) && $preparedHolidays instanceof ArrayObject) {
115 1
                $preparedHolidays = $preparedHolidays->getArrayCopy();
116 1
            }
117 34
            if (!is_array($preparedHolidays)) {
118 1
                throw new UnexpectedValueException(\sprintf(
119 1
                    'Method %s::prepareHolidays() must returns an array',
120 1
                    get_class($this)
121 1
                ));
122
            }
123
124 33
            $this->holidays[$year] = $preparedHolidays;
125 33
        }
126 33
    }
127
128
    /**
129
     * Returns the holidays in given year.
130
     *
131
     * @param int         $year The year to get the holidays for
132
     * @param null|string $type (optional) Holiday type
133
     *
134
     * @throws InvalidArgumentException
135
     *
136
     * @return array An array of Holidays
137
     */
138 34
    public function getHolidaysByYear($year, $type = null)
139
    {
140 34
        $this->prepareHolidaysByYear($year);
141
142 33
        if (null === $type) {
143 31
            return $this->holidays[$year];
144
        }
145
146
        // Note: array_filter preserves keys, so we use array_values to reset array keys
147 2
        return array_values(array_filter(
148 2
            $this->holidays[$year],
149
            function (Holiday $holiday) use ($type) {
150 2
                return $holiday->getType() === $type;
151
            }
152 2
        ));
153
    }
154
155
    /**
156
     * Returns all holidays in the given time period.
157
     *
158
     * @param DateTime $startDate     The start date
159
     * @param mixed    $endDateOrType (optional) The end date or holiday type
160
     * @param string   $type          (optional) Holiday type
161
     *
162
     * @return array
163
     */
164 31
    public function getHolidays(
165
        DateTime $startDate,
166
        $endDateOrType = null,
167
        $type = null
168
    ) {
169 31
        $startDate = clone $startDate;
170 31
        $startDate->setTime(0, 0, 0);
171
172 31
        if ($endDateOrType !== null && !($endDateOrType instanceof DateTime)) {
173 2
            if ($type !== null) {
174 1
                throw new InvalidArgumentException(
175
                    '$endDateOrType must be an instance of \DateTime'
176 1
                );
177
            }
178 1
            $type          = $endDateOrType;
179 1
            $endDateOrType = clone $startDate;
180 30
        } elseif ($endDateOrType === null) {
181 27
            $endDateOrType = clone $startDate;
182 27
        } else {
183 2
            $endDateOrType = clone $endDateOrType;
184
        }
185 30
        $endDateOrType->setTime(23, 59, 59);
186
187 30
        $startyear = (int) $startDate->format('Y');
188 30
        $endyear   = (int) $endDateOrType->format('Y');
189 30
        $holidays  = array();
190 30
        for ($y = $startyear; $y <= $endyear; $y++) {
191 30
            $holidays = array_merge($holidays, $this->getHolidaysByYear($y, $type));
192 30
        }
193
194
        // Note: array_filter preserves keys, so we use array_values to reset array keys
195 30
        return array_values(array_filter(
196 30
            $holidays,
197 30
            function (Holiday $holiday) use ($startDate, $endDateOrType) {
198 30
                return $holiday >= $startDate && $holiday <= $endDateOrType;
199
            }
200 30
        ));
201
    }
202
203
    /**
204
     * Returns true if any holiday exists in the given time period.
205
     *
206
     * @param DateTime      $startDate The start date
207
     * @param null|DateTime $endDate   (optional) The end date
208
     * @param null|string   $type      (optional) Holiday type
209
     *
210
     * @return bool
211
     */
212 1
    public function hasHolidays(
213
        DateTime $startDate,
214
        DateTime $endDate,
215
        $type = null
216
    ) {
217 1
        return count($this->getHolidays($startDate, $endDate, $type)) > 0;
218
    }
219
220
    /**
221
     * Returns true if $date is a holiday.
222
     *
223
     * @param DateTime    $date The date
224
     * @param null|string $type (optional) Holiday type
225
     *
226
     * @return bool
227
     */
228 1
    public function isHoliday(DateTime $date, $type = null)
229
    {
230 1
        return count($this->getHolidays($date, null, $type)) > 0;
231
    }
232
}
233