Completed
Push — master ( ac2353...ba76dd )
by Josh
24:41
created

XmlFileDefinitionCollection::convertValueTypes()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 1
crap 3
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2017 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Plugins\MediaEmbed\Configurator\Collections;
9
10
use DOMDocument;
11
use DOMElement;
12
use InvalidArgumentException;
13
14
class XmlFileDefinitionCollection extends SiteDefinitionCollection
15
{
16
	/**
17
	* @var array Known config types [<name regexp>, <value regexp>, <type>]
18
	*/
19
	protected $configTypes = [
20
		['(^defaultValue$)', '(^[1-9][0-9]*$)D',     'castToInt'],
21
		['(height$|width$)', '(^[1-9][0-9]*$)D',     'castToInt'],
22
		['(^required$)',     '(^(?:true|false)$)iD', 'castToBool']
23
	];
24
25
	/**
26
	* Constructor
27
	*
28
	* @param  string $path Path to site definitions' dir
29
	*/
30 15
	public function __construct($path)
31
	{
32 15
		if (!file_exists($path) || !is_dir($path))
33 15
		{
34 1
			throw new InvalidArgumentException('Invalid site directory');
35
		}
36 14
		foreach (glob($path . '/*.xml') as $filepath)
37
		{
38 14
			$siteId = basename($filepath, '.xml');
39 14
			$this->items[$siteId] = $this->getConfigFromXmlFile($filepath);
40 14
		}
41 14
	}
42
43
	/**
44
	* Cast given config value to the appropriate type
45
	*
46
	* @param  string $name  Name of the config value
47
	* @param  string $value Config value in string form
48
	* @return mixed         Config value in appropriate type
49
	*/
50 14
	protected function castConfigValue($name, $value)
51
	{
52 14
		foreach ($this->configTypes as list($nameRegexp, $valueRegexp, $methodName))
53
		{
54 14
			if (preg_match($nameRegexp, $name) && preg_match($valueRegexp, $value))
55 14
			{
56 14
				return $this->$methodName($value);
57
			}
58 14
		}
59
60 14
		return $value;
61
	}
62
63
	/**
64
	* Cast given config value to a boolean
65
	*
66
	* @param  string $value
67
	* @return bool
68
	*/
69 14
	protected function castToBool($value)
70
	{
71 14
		return (strtolower($value) === 'true');
72
	}
73
74
	/**
75
	* Cast given config value to an integer
76
	*
77
	* @param  string  $value
78
	* @return integer
79
	*/
80 14
	protected function castToInt($value)
81
	{
82 14
		return (int) $value;
83
	}
84
85
	/**
86
	* Convert known config values to the appropriate type
87
	*
88
	* Will cast properties whose name is "defaultValue" or ends in "height" or "width" to integers
89
	*
90
	* @param  array $config Original config
91
	* @return array         Converted config
92
	*/
93 14
	protected function convertValueTypes(array $config)
94
	{
95 14
		foreach ($config as $k => $v)
96
		{
97 14
			if (is_array($v))
98 14
			{
99 14
				$config[$k] = $this->convertValueTypes($v);
100 14
			}
101
			else
102
			{
103 14
				$config[$k] = $this->castConfigValue($k, $v);
104
			}
105 14
		}
106
107 14
		return $config;
108
	}
109
110
	/**
111
	* Replace arrays that contain a single element with the element itself
112
	*
113
	* @param  array $config
114
	* @return array
115
	*/
116 14
	protected function flattenConfig(array $config)
117
	{
118 14
		foreach ($config as $k => $v)
119
		{
120 14
			if (is_array($v) && count($v) === 1)
121 14
			{
122 14
				$config[$k] = end($v);
123 14
			}
124 14
		}
125
126 14
		return $config;
127
	}
128
129
	/**
130
	* Extract a site's config from its XML file
131
	*
132
	* @param  string $filepath Path to the XML file
133
	* @return mixed
134
	*/
135 14
	protected function getConfigFromXmlFile($filepath)
136
	{
137 14
		$dom = new DOMDocument;
138 14
		$dom->load($filepath, LIBXML_NOCDATA);
139
140 14
		return $this->getElementConfig($dom->documentElement);
141
	}
142
143
	/**
144
	* Extract a site's config from its XML representation
145
	*
146
	* @param  DOMElement $element Current node
147
	* @return mixed
148
	*/
149 14
	protected function getElementConfig(DOMElement $element)
150
	{
151 14
		$config = [];
152 14
		foreach ($element->attributes as $attribute)
153
		{
154 14
			$config[$attribute->name][] = $attribute->value;
155 14
		}
156 14
		foreach ($element->childNodes as $childNode)
157
		{
158 14
			if ($childNode instanceof DOMElement)
159 14
			{
160 14
				$config[$childNode->nodeName][] = $this->getValueFromElement($childNode);
161 14
			}
162 14
		}
163
164 14
		return $this->flattenConfig($this->convertValueTypes($config));
165
	}
166
167
	/**
168
	* Extract a value from given element
169
	*
170
	* @param  DOMElement $element
171
	* @return mixed
172
	*/
173 14
	protected function getValueFromElement(DOMElement $element)
174
	{
175 14
		return (!$element->attributes->length && $element->childNodes->length === 1 && $element->firstChild->nodeType === XML_TEXT_NODE)
176 14
		     ? $element->nodeValue
177 14
		     : $this->getElementConfig($element);
178
	}
179
}