HolidayIteratorFactory   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 14
eloc 43
c 3
b 0
f 0
dl 0
loc 106
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A decorateElement() 0 7 2
A __construct() 0 13 1
A getElement() 0 10 3
A createIteratorFromISO3166() 0 13 2
A createIteratorFromXmlFile() 0 29 6
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Copyright (c) Andreas Heigl<[email protected]>
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 *
26
 * @author    Andreas Heigl<[email protected]>
27
 * @copyright Andreas Heigl
28
 * @license   http://www.opensource.org/licenses/mit-license.php MIT-License
29
 * @since     09.03.2017
30
 * @link      http://github.com/heiglandreas/org.heigl.Holidaychecker
31
 */
32
33
namespace Org_Heigl\Holidaychecker;
34
35
use DOMDocument;
36
use DOMElement;
37
use Exception;
38
use Org_Heigl\Holidaychecker\Factory\DateFactory;
39
use Org_Heigl\Holidaychecker\Factory\DateFollowupFactory;
40
use Org_Heigl\Holidaychecker\Factory\DecorateFromDomElement;
41
use Org_Heigl\Holidaychecker\Factory\EasterFactory;
42
use Org_Heigl\Holidaychecker\Factory\EasterOrthodoxFactory;
43
use Org_Heigl\Holidaychecker\Factory\ItemFromDomElementCreator;
44
use Org_Heigl\Holidaychecker\Factory\ObservanceDecoratorFactory;
45
use Org_Heigl\Holidaychecker\Factory\RelativeFactory;
46
use Org_Heigl\Holidaychecker\Factory\SwapDecoratorFactory;
47
use RuntimeException;
48
use Throwable;
49
use UnexpectedValueException;
50
use function is_readable;
51
use function sprintf;
52
53
class HolidayIteratorFactory
54
{
55
	/** @var ItemFromDomElementCreator[] */
56
	private $factories;
57
58
	/** @var DecorateFromDomElement[] */
59
	private $decorators;
60
61
	public function __construct()
62
	{
63
		$this->factories = [
64
			new EasterFactory(),
65
			new EasterOrthodoxFactory(),
66
			new DateFactory(),
67
			new DateFollowupFactory(),
68
			new RelativeFactory(),
69
		];
70
71
		$this->decorators = [
72
			new ObservanceDecoratorFactory(),
73
			new SwapDecoratorFactory(),
74
		];
75
	}
76
77
	/**
78
	 * Create a HolidayIterator from an ISO 3166-code.
79
	 *
80
	 * @param string $isoCode
81
	 *
82
	 * @return HolidayIterator
83
	 */
84
	public function createIteratorFromISO3166(string $isoCode): HolidayIterator
85
	{
86
		$file = __DIR__ . '/../share/%s.xml';
87
		$file1 = sprintf($file, $isoCode);
88
89
		if (!is_readable($file1)) {
90
			throw new UnexpectedValueException(sprintf(
91
				'There is no holiday-file for %s',
92
				$isoCode
93
			));
94
		}
95
96
		return $this->createIteratorFromXmlFile($file1);
97
	}
98
99
	/**
100
	 * Create a HolidayIterator from an XML-File
101
	 *
102
	 * The provided XML-File has to validate against the holiday.xsd-file you
103
	 * can find in this projects "share" folder.
104
	 *
105
	 * @param string $file
106
	 *
107
	 * @return HolidayIterator
108
	 */
109
	public function createIteratorFromXmlFile(string $file): HolidayIterator
110
	{
111
		$iterator = new HolidayIterator();
112
113
		$dom = new DOMDocument('1.0', 'UTF-8');
114
		$dom->load($file);
115
		$dom->xinclude();
116
117
		if (!@$dom->schemaValidate(__DIR__ . '/../share/holidays.xsd')) {
118
			throw new Exception('XML-File does not validate agains schema');
119
		}
120
		foreach ($dom->documentElement->childNodes as $child) {
121
			if (!$child instanceof DOMElement) {
122
				continue;
123
			}
124
			if ($child->nodeName === 'resources') {
125
				continue;
126
			}
127
128
			try {
129
				$element = $this->getElement($child);
130
				$element = $this->decorateElement($element, $child);
131
				$iterator->append($element);
132
			} catch (Throwable $e) {
133
				// Do nothing on purpose
134
			}
135
		}
136
137
		return $iterator;
138
	}
139
140
	private function getElement(DOMElement $child): HolidayIteratorItemInterface
141
	{
142
		foreach ($this->factories as $factory) {
143
			$element = $factory->itemFromDomElement($child);
144
			if ($element instanceof HolidayIteratorItemInterface) {
145
				return $element;
146
			}
147
		}
148
149
		throw new RuntimeException('Unknown element encountered');
150
	}
151
152
	private function decorateElement(HolidayIteratorItemInterface $element, DOMElement $child): HolidayIteratorItemInterface
153
	{
154
		foreach ($this->decorators as $decorator) {
155
			$element = $decorator->decorate($element, $child);
156
		}
157
158
		return $element;
159
	}
160
}
161