Passed
Push — master ( 2eb814...039015 )
by Josh
06:20
created

AbstractXSLSupportCheck   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 16
eloc 32
c 1
b 0
f 1
dl 0
loc 105
ccs 33
cts 33
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A check() 0 4 1
A getXPathExpressions() 0 24 5
A checkXPathExpressions() 0 5 2
A checkXslElements() 0 15 4
A checkXPathExpression() 0 9 4
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2020 The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Configurator\TemplateChecks;
9
10
use DOMElement;
11
use DOMXPath;
12
use RuntimeException;
13
use s9e\TextFormatter\Configurator\Helpers\AVTHelper;
14
use s9e\TextFormatter\Configurator\Items\Tag;
15
use s9e\TextFormatter\Configurator\TemplateCheck;
16
17
abstract class AbstractXSLSupportCheck extends TemplateCheck
18
{
19
	/**
20
	* @var string[] List of supported XSL elements (local name only)
21
	*/
22
	protected $supportedElements = [];
23
24
	/**
25
	* @var string[] List of supported XPath functions
26
	*/
27
	protected $supportedFunctions = [];
28
29
	/**
30
	* @var string[] List of supported XPath operators
31
	*/
32
	protected $supportedOperators = ['and', 'div', 'mod', 'or'];
33
34
	/**
35
	* Check for elements not supported by the PHP renderer
36
	*
37
	* @param DOMElement $template <xsl:template/> node
38
	* @param Tag        $tag      Tag this template belongs to
39
	*/
40 10
	public function check(DOMElement $template, Tag $tag): void
41
	{
42 10
		$this->checkXslElements($template);
43 3
		$this->checkXPathExpressions($template);
44
	}
45
46
	/**
47
	* Check given XPath expression
48
	*/
49 3
	protected function checkXPathExpression(string $expr): void
50
	{
51 3
		preg_match_all('("[^"]*+"|\'[^\']*+\'|((?:[a-z]++-)*+[a-z]++)(?=\\s*\\())', $expr, $m);
52 3
		foreach (array_filter($m[1]) as $funcName)
53
		{
54 3
			if (!in_array($funcName, $this->supportedFunctions, true)
55 3
			 && !in_array($funcName, $this->supportedOperators, true))
56
			{
57 3
				throw new RuntimeException('XPath function ' . $funcName . '() is not supported');
58
			}
59
		}
60
	}
61
62
	/**
63
	* Check all XPath expressions in given template
64
	*/
65 3
	protected function checkXPathExpressions(DOMElement $template): void
66
	{
67 3
		foreach ($this->getXPathExpressions($template) as $expr)
68
		{
69 3
			$this->checkXPathExpression($expr);
70
		}
71
	}
72
73
	/**
74
	* Check all XSL elements in given template
75
	*/
76 10
	protected function checkXslElements(DOMElement $template): void
77
	{
78 10
		$xpath = new DOMXPath($template->ownerDocument);
79 10
		$nodes = $xpath->query('/xsl:template//xsl:*');
80 10
		foreach ($nodes as $node)
81
		{
82 9
			if (!in_array($node->localName, $this->supportedElements, true))
83
			{
84 1
				throw new RuntimeException('xsl:' . $node->localName . ' elements are not supported');
85
			}
86
87 8
			$methodName = 'checkXsl' . str_replace(' ', '', ucwords(str_replace('-', ' ', $node->localName))) . 'Element';
88 8
			if (method_exists($this, $methodName))
89
			{
90 7
				$this->$methodName($node);
91
			}
92
		}
93
	}
94
95
	/**
96
	* Return all XPath expressions in given template
97
	*/
98 3
	protected function getXPathExpressions(DOMElement $template): array
99
	{
100 3
		$exprs = [];
101 3
		$xpath = new DOMXPath($template->ownerDocument);
102
103 3
		$query = '//xsl:*/@name | //*[namespace-uri() != "' . self::XMLNS_XSL . '"]/@*[contains(., "{")]';
104 3
		foreach ($xpath->query($query) as $attribute)
105
		{
106 2
			foreach (AVTHelper::parse($attribute->value) as [$type, $content])
107
			{
108 2
				if ($type === 'expression')
109
				{
110 2
					$exprs[] = $content;
111
				}
112
			}
113
		}
114
115 3
		$query = '//xsl:*/@select | //xsl:*/@test';
116 3
		foreach ($xpath->query($query) as $attribute)
117
		{
118 1
			$exprs[] = $attribute->value;
119
		}
120
121 3
		return $exprs;
122
	}
123
}