Passed
Push — master ( 052cde...5b58f4 )
by Josh
12:04
created

Document   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
eloc 35
c 1
b 0
f 0
dl 0
loc 97
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A createTagElement() 0 28 3
A normalizeAttributeMap() 0 12 2
A __toString() 0 9 2
A __construct() 0 5 1
A normalizeDocument() 0 13 3
1
<?php declare(strict_types=1);
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) The s9e authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Utils\ParsedDOM;
9
10
use const LIBXML_NSCLEAN, SORT_STRING, false;
11
use function ksort, substr, strpos;
12
use s9e\SweetDOM\Document as SweetDocument;
13
use s9e\TextFormatter\Configurator\Validators\TagName;
14
use s9e\TextFormatter\Configurator\Validators\AttributeName;
15
use s9e\TextFormatter\Utils;
16
17
class Document extends SweetDocument
18
{
19
	/**
20
	* @link https://www.php.net/manual/domdocument.construct.php
21
	*
22
	* @param string $version  Version number of the document
23
	* @param string $encoding Encoding of the document
24
	*/
25
	public function __construct(string $version = '1.0', string $encoding = 'utf-8')
26
	{
27
		parent::__construct($version, $encoding);
28
29
		$this->registerNodeClass('DOMElement', Element::class);
30
	}
31
32
	public function __toString(): string
33
	{
34
		$this->formatOutput = false;
35
		$this->normalizeDocument();
36
37
		$xml = $this->saveXML($this->documentElement, LIBXML_NSCLEAN);
38
		$xml = Utils::encodeUnicodeSupplementaryCharacters($xml);
39
40
		return ($xml === '<t/>') ? '<t></t>' : $xml;
41
	}
42
43
	/**
44
	* @link https://www.php.net/manual/en/domdocument.normalizedocument.php
45
	*/
46
	public function normalizeDocument(): void
47
	{
48
		parent::normalizeDocument();
49
		$this->documentElement->normalize();
50
51
		$nodeName = $this->documentElement->firstOf('.//*[name() != "br"][name() != "p"]') ? 'r' : 't';
1 ignored issue
show
introduced by
The method firstOf() does not exist on DOMElement. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
		$nodeName = $this->documentElement->/** @scrutinizer ignore-call */ firstOf('.//*[name() != "br"][name() != "p"]') ? 'r' : 't';
Loading history...
52
53
		$root = $this->createElement($nodeName);
54
		while (isset($this->documentElement->firstChild))
55
		{
56
			$root->appendChild($this->documentElement->firstChild);
1 ignored issue
show
Bug introduced by
It seems like $this->documentElement->firstChild can also be of type null; however, parameter $node of DOMNode::appendChild() does only seem to accept DOMNode, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

56
			$root->appendChild(/** @scrutinizer ignore-type */ $this->documentElement->firstChild);
Loading history...
57
		}
58
		$this->documentElement->replaceWith($root);
59
	}
60
61
	/**
62
	* Create an element that represents a tag
63
	*
64
	* @param  string                $tagName
65
	* @param  array<string, string> $attributes
66
	* @return Element
67
	*/
68
	public function createTagElement(string $tagName, array $attributes = []): Element
69
	{
70
		$tagName = TagName::normalize($tagName);
71
		$pos     = strpos($tagName, ':');
72
73
		if ($pos === false)
74
		{
75
			$element = $this->createElement($tagName);
76
		}
77
		else
78
		{
79
			$prefix       = substr($tagName, 0, $pos);
80
			$namespaceURI = 'urn:s9e:TextFormatter:' . $prefix;
81
			$this->documentElement->setAttributeNS(
82
				'http://www.w3.org/2000/xmlns/',
83
				'xmlns:' . $prefix,
84
				$namespaceURI
85
			);
86
87
			$element = $this->createElementNS($namespaceURI, $tagName);
88
		}
89
90
		foreach ($this->normalizeAttributeMap($attributes) as $attrName => $attrValue)
91
		{
92
			$element->setAttribute($attrName, $attrValue);
93
		}
94
95
		return $element;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $element returns the type DOMElement which includes types incompatible with the type-hinted return s9e\TextFormatter\Utils\ParsedDOM\Element.
Loading history...
96
	}
97
98
	/**
99
	* @param  array<string, string> $attributes
100
	* @return array<string, string> $attributes
101
	*/
102
	protected function normalizeAttributeMap(array $attributes): array
103
	{
104
		$map = [];
105
		foreach ($attributes as $attrName => $attrValue)
106
		{
107
			$attrName       = AttributeName::normalize($attrName);
108
			$map[$attrName] = (string) $attrValue;
109
110
		}
111
		ksort($map, SORT_STRING);
112
113
		return $map;
114
	}
115
}