NodeCreator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
c 1
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\SweetDOM
5
* @copyright Copyright (c) The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\SweetDOM;
9
10
use DOMException;
11
use const DOM_NAMESPACE_ERR, DOM_SYNTAX_ERR, ENT_XML1;
12
use function htmlspecialchars, str_contains, strpos, substr;
13
14
class NodeCreator
15
{
16
	public function __construct(protected Document $ownerDocument)
17
	{
18
	}
19
20
	public function createComment(string $data): Comment
21
	{
22
		if (str_contains($data, '--'))
23
		{
24
			throw new DOMException('Double hyphen within comment: ' . $data, DOM_SYNTAX_ERR);
25
		}
26
27
		return $this->ownerDocument->createComment($data);
28
	}
29
30
	/**
31
	* Create a DocumentFragment and execute given callback on it before returning it
32
	*/
33
	public function createDocumentFragment(?callable $callback = null): DocumentFragment
34
	{
35
		$fragment = $this->ownerDocument->createDocumentFragment();
36
		if (isset($callback))
37
		{
38
			$callback($fragment);
39
		}
40
41
		return $fragment;
42
	}
43
44
	/**
45
	* Create and return an element
46
	*
47
	* @param  string $nodeName    Full qualified name for the node
48
	* @param  string $textContent Text content, will be automatically escaped
49
	* @return Element
50
	*/
51
	public function createElement(string $nodeName, string $textContent = ''): Element
52
	{
53
		$pos = strpos($nodeName, ':');
54
		if ($pos === false)
55
		{
56
			$namespace = null;
57
		}
58
		else
59
		{
60
			$prefix    = substr($nodeName, 0, $pos);
61
			$namespace = $this->ownerDocument->lookupNamespaceURI($prefix);
62
			if ($namespace === null)
63
			{
64
				throw new DOMException('Undefined namespace prefix', DOM_NAMESPACE_ERR);
65
			}
66
		}
67
68
		return $this->createElementNS($namespace, $nodeName, $textContent);
69
	}
70
71
	public function createElementNS(?string $namespace, string $nodeName, string $textContent = ''): Element
72
	{
73
		$value   = htmlspecialchars($textContent, ENT_XML1);
74
		$element = $this->ownerDocument->createElementNS($namespace, $nodeName, $value);
75
		if ($element instanceof Element)
76
		{
77
			return $element;
78
		}
79
80
		throw new DOMException;
81
	}
82
83
	/**
84
	* Create and return an xsl:apply-templates element
85
	*/
86
	public function createXslApplyTemplates(?string $select = null, ?string $mode = null): Element
87
	{
88
		return $this->createXslElementByName('apply-templates', '', ['mode' => $mode, 'select' => $select]);
89
	}
90
91
	/**
92
	* Create and return an xsl:attribute element
93
	*/
94
	public function createXslAttribute(string $name, string $textContent = '', ?string $namespace = null): Element
95
	{
96
		return $this->createXslElementByName('attribute', $textContent, ['name' => $name, 'namespace' => $namespace]);
97
	}
98
99
	/**
100
	* Create and return an xsl:choose element
101
	*/
102
	public function createXslChoose(): Element
103
	{
104
		return $this->createXslElementByName('choose');
105
	}
106
107
	/**
108
	* Create and return an xsl:comment element
109
	*/
110
	public function createXslComment(string $textContent = ''): Element
111
	{
112
		return $this->createXslElementByName('comment', $textContent);
113
	}
114
115
	/**
116
	* Create and return an xsl:copy-of element
117
	*/
118
	public function createXslCopyOf(string $select): Element
119
	{
120
		return $this->createXslElementByName('copy-of', '', ['select' => $select]);
121
	}
122
123
	/**
124
	* Create and return an xsl:element element
125
	*/
126
	public function createXslElement(string $name, ?string $namespace = null, ?string $useAttributeSets = null): Element
127
	{
128
		return $this->createXslElementByName('element', '', ['name' => $name, 'namespace' => $namespace, 'use-attribute-sets' => $useAttributeSets]);
129
	}
130
131
	/**
132
	* Create and return an XSL element
133
	*/
134
	protected function createXslElementByName(string $localName, string $textContent = '', array $attributes = []): Element
135
	{
136
		$element = $this->createElementNS(
137
			'http://www.w3.org/1999/XSL/Transform',
138
			'xsl:' . $localName,
139
			$textContent
140
		);
141
		foreach ($attributes as $attrName => $attrValue)
142
		{
143
			// Skip attributes with a NULL value
144
			if (isset($attrValue))
145
			{
146
				$element->setAttribute($attrName, $attrValue);
147
			}
148
		}
149
150
		return $element;
151
	}
152
153
	/**
154
	* Create and return an xsl:if element
155
	*/
156
	public function createXslIf(string $test, string $textContent = ''): Element
157
	{
158
		return $this->createXslElementByName('if', $textContent, ['test' => $test]);
159
	}
160
161
	/**
162
	* Create and return an xsl:otherwise element
163
	*/
164
	public function createXslOtherwise(string $textContent = ''): Element
165
	{
166
		return $this->createXslElementByName('otherwise', $textContent);
167
	}
168
169
	/**
170
	* Create and return an xsl:text element
171
	*/
172
	public function createXslText(string $textContent = '', ?string $disableOutputEscaping = null): Element
173
	{
174
		return $this->createXslElementByName('text', $textContent, ['disable-output-escaping' => $disableOutputEscaping]);
175
	}
176
177
	/**
178
	* Create and return an xsl:value-of element
179
	*/
180
	public function createXslValueOf(string $select, ?string $disableOutputEscaping = null): Element
181
	{
182
		return $this->createXslElementByName('value-of', '', ['disable-output-escaping' => $disableOutputEscaping, 'select' => $select]);
183
	}
184
185
	/**
186
	* Create and return an xsl:variable element
187
	*/
188
	public function createXslVariable(string $name, ?string $select = null): Element
189
	{
190
		return $this->createXslElementByName('variable', '', ['name' => $name, 'select' => $select]);
191
	}
192
193
	/**
194
	* Create and return an xsl:when element
195
	*/
196
	public function createXslWhen(string $test, string $textContent = ''): Element
197
	{
198
		return $this->createXslElementByName('when', $textContent, ['test' => $test]);
199
	}
200
}