Completed
Branch Scrutinizer (3da711)
by Josh
03:32
created

NodeLocator::getNodes()   A

Complexity

Conditions 6
Paths 24

Size

Total Lines 28
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
dl 0
loc 28
ccs 12
cts 12
cp 1
rs 9.2222
c 1
b 0
f 0
cc 6
nc 24
nop 2
crap 6
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2019 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Configurator\Helpers;
9
10
use DOMDocument;
11
use DOMXPath;
12
13
abstract class NodeLocator
14
{
15
	/**
16
	* Return all attributes (literal or generated) that match given regexp
17
	*
18
	* @param  DOMDocument $dom    Document
19
	* @param  string      $regexp Regexp
20
	* @return DOMNode[]           List of DOMNode instances
21
	*/
22 51
	public static function getAttributesByRegexp(DOMDocument $dom, $regexp)
23
	{
24 51
		return self::getNodesByRegexp($dom, $regexp, 'attribute');
25
	}
26
27
	/**
28
	* Return all DOMNodes whose content is CSS
29
	*
30
	* @param  DOMDocument $dom Document
31
	* @return DOMNode[]        List of DOMNode instances
32
	*/
33 10
	public static function getCSSNodes(DOMDocument $dom)
34
	{
35 10
		$regexp = '/^style$/i';
36 10
		$nodes  = array_merge(
37 10
			self::getAttributesByRegexp($dom, $regexp),
38 10
			self::getElementsByRegexp($dom, '/^style$/i')
39
		);
40
41 10
		return $nodes;
42
	}
43
44
	/**
45
	* Return all elements (literal or generated) that match given regexp
46
	*
47
	* @param  DOMDocument $dom    Document
48
	* @param  string      $regexp Regexp
49
	* @return DOMNode[]           List of DOMNode instances
50
	*/
51 22
	public static function getElementsByRegexp(DOMDocument $dom, $regexp)
52
	{
53 22
		return self::getNodesByRegexp($dom, $regexp, 'element');
54
	}
55
56
	/**
57
	* Return all DOMNodes whose content is JavaScript
58
	*
59
	* @param  DOMDocument $dom Document
60
	* @return DOMNode[]        List of DOMNode instances
61
	*/
62 11
	public static function getJSNodes(DOMDocument $dom)
63
	{
64 11
		$regexp = '/^(?:data-s9e-livepreview-postprocess$|on)/i';
65 11
		$nodes  = array_merge(
66 11
			self::getAttributesByRegexp($dom, $regexp),
67 11
			self::getElementsByRegexp($dom, '/^script$/i')
68
		);
69
70 11
		return $nodes;
71
	}
72
73
	/**
74
	* Return all elements (literal or generated) that match given regexp
75
	*
76
	* Will return all <param/> descendants of <object/> and all attributes of <embed/> whose name
77
	* matches given regexp. This method will NOT catch <param/> elements whose 'name' attribute is
78
	* set via an <xsl:attribute/>
79
	*
80
	* @param  DOMDocument $dom    Document
81
	* @param  string      $regexp
82
	* @return DOMNode[]           List of DOMNode instances
83
	*/
84 30
	public static function getObjectParamsByRegexp(DOMDocument $dom, $regexp)
85
	{
86 30
		$xpath = new DOMXPath($dom);
87 30
		$nodes = [];
88
89
		// Collect attributes from <embed/> elements
90 30
		foreach (self::getAttributesByRegexp($dom, $regexp) as $attribute)
91
		{
92 5
			if ($attribute->nodeType === XML_ATTRIBUTE_NODE)
93
			{
94 2
				if (strtolower($attribute->parentNode->localName) === 'embed')
95
				{
96 2
					$nodes[] = $attribute;
97
				}
98
			}
99 3
			elseif ($xpath->evaluate('count(ancestor::embed)', $attribute))
100
			{
101
				// Assuming <xsl:attribute/> or <xsl:copy-of/>
102 3
				$nodes[] = $attribute;
103
			}
104
		}
105
106
		// Collect <param/> descendants of <object/> elements
107 30
		foreach ($xpath->query('//object//param') as $param)
108
		{
109 4
			if (preg_match($regexp, $param->getAttribute('name')))
110
			{
111 4
				$nodes[] = $param;
112
			}
113
		}
114
115 30
		return $nodes;
116
	}
117
118
	/**
119
	* Return all DOMNodes whose content is an URL
120
	*
121
	* NOTE: it will also return HTML4 nodes whose content is an URI
122
	*
123
	* @param  DOMDocument $dom Document
124
	* @return DOMNode[]        List of DOMNode instances
125
	*/
126 22
	public static function getURLNodes(DOMDocument $dom)
127
	{
128 22
		$regexp = '/(?:^(?:action|background|c(?:ite|lassid|odebase)|data|formaction|href|icon|longdesc|manifest|p(?:ing|luginspage|oster|rofile)|usemap)|src)$/i';
129 22
		$nodes  = self::getAttributesByRegexp($dom, $regexp);
130
131
		/**
132
		* @link http://helpx.adobe.com/flash/kb/object-tag-syntax-flash-professional.html
133
		* @link http://www.sitepoint.com/control-internet-explorer/
134
		*/
135 22
		foreach (self::getObjectParamsByRegexp($dom, '/^(?:dataurl|movie)$/i') as $param)
136
		{
137 2
			$node = $param->getAttributeNode('value');
138 2
			if ($node)
139
			{
140 2
				$nodes[] = $node;
141
			}
142
		}
143
144 22
		return $nodes;
145
	}
146
147
	/**
148
	* Return all nodes of given type
149
	*
150
	* @param  DOMDocument $dom  Owner document
151
	* @param  string      $type Node type ('element' or 'attribute')
152
	* @return DOMNode[]         List of DOMNode instances
153
	*/
154 52
	protected static function getNodes(DOMDocument $dom, $type)
155
	{
156 52
		$nodes  = [];
157 52
		$prefix = ($type === 'attribute') ? '@' : '';
158 52
		$xpath  = new DOMXPath($dom);
159
160
		// Get natural nodes
161 52
		foreach ($xpath->query('//' . $prefix . '*') as $node)
162
		{
163 49
			$nodes[] = [$node, $node->nodeName];
164
		}
165
166
		// Get XSL-generated nodes
167 52
		foreach ($xpath->query('//xsl:' . $type) as $node)
168
		{
169 10
			$nodes[] = [$node, $node->getAttribute('name')];
170
		}
171
172
		// Get xsl:copy-of nodes
173 52
		foreach ($xpath->query('//xsl:copy-of') as $node)
174
		{
175 4
			if (preg_match('/^' . $prefix . '(\\w+)$/', $node->getAttribute('select'), $m))
176
			{
177 4
				$nodes[] = [$node, $m[1]];
178
			}
179
		}
180
181 52
		return $nodes;
182
	}
183
184
	/**
185
	* Return all nodes (literal or generated) that match given regexp
186
	*
187
	* @param  DOMDocument $dom    Owner document
188
	* @param  string      $regexp Regexp
189
	* @param  string      $type   Node type ('element' or 'attribute')
190
	* @return DOMNode[]           List of DOMNode instances
191
	*/
192 52
	protected static function getNodesByRegexp(DOMDocument $dom, $regexp, $type)
193
	{
194 52
		$nodes = [];
195 52
		foreach (self::getNodes($dom, $type) as list($node, $name))
196
		{
197 49
			if (preg_match($regexp, $name))
198
			{
199 42
				$nodes[] = $node;
200
			}
201
		}
202
203 52
		return $nodes;
204
	}
205
}