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

Element   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 23
eloc 41
c 1
b 0
f 0
dl 0
loc 128
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setMarkupStart() 0 5 1
A normalize() 0 16 4
A unparse() 0 11 2
A unparseMarkupElement() 0 5 3
A setMarkupEnd() 0 5 1
A shouldBeRemoved() 0 8 4
A sortAttributes() 0 12 3
A attributesAreSorted() 0 13 3
A replaceTag() 0 10 2
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 DOMNode;
11
use const SORT_STRING;
12
use function count, ksort, preg_match;
13
use s9e\SweetDOM\Element as SweetElement;
14
15
class Element extends SweetElement
16
{
17
	/**
18
	* Normalize this element to match what the parser would produce
19
	*
20
	* @link https://www.php.net/manual/en/domnode.normalize.php
21
	*/
22
	public function normalize(): void
23
	{
24
		parent::normalize();
25
		foreach ($this->query('*') as $child)
26
		{
27
			$child->normalize();
28
		}
29
30
		if ($this->shouldBeRemoved())
31
		{
32
			// Remove elements with no content and no attributes
33
			$this->remove();
34
		}
35
		elseif (!$this->attributesAreSorted())
36
		{
37
			$this->sortAttributes();
38
		}
39
	}
40
41
	/**
42
	* Replace this element with a new tag
43
	*
44
	* @param  string $tagName    New tag's name
45
	* @param  array  $attributes Attributes for the new tag
46
	* @return static             Element that represents the new tag
47
	*/
48
	public function replaceTag(string $tagName, array $attributes = []): static
49
	{
50
		$element = $this->ownerDocument->createTagElement($tagName, $attributes);
1 ignored issue
show
Bug introduced by
The method createTagElement() does not exist on s9e\SweetDOM\Document. Did you maybe mean createElement()? ( Ignorable by Annotation )

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

50
		/** @scrutinizer ignore-call */ 
51
  $element = $this->ownerDocument->createTagElement($tagName, $attributes);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
51
		while (isset($this->firstChild))
52
		{
53
			$element->appendChild($this->firstChild);
54
		}
55
		$this->replaceWith($element);
56
57
		return $element;
58
	}
59
60
	/**
61
	* Set the markup at the end of this element's content
62
	*/
63
	public function setMarkupEnd(string $markup): void
64
	{
65
		$node = $this->firstOf('e') ?? $this->appendElement('e');
66
		$node->textContent = $markup;
67
		$node->normalize();
68
	}
69
70
	/**
71
	* Set the markup at the start of this element's content
72
	*/
73
	public function setMarkupStart(string $markup): void
74
	{
75
		$node = $this->firstOf('s') ?? $this->prependElement('s');
76
		$node->textContent = $markup;
77
		$node->normalize();
78
	}
79
80
	/**
81
	* Unparse this element without removing or unparsing its descendants
82
	*
83
	* Any markup associated with this element will become plain text.
84
	*/
85
	public function unparse(): void
86
	{
87
		$this->unparseMarkupElement('s', $this->firstChild);
88
		$this->unparseMarkupElement('e', $this->lastChild);
89
90
		$parent = $this->parentNode;
91
		while (isset($this->firstChild))
92
		{
93
			$parent->insertBefore($this->firstChild, $this);
1 ignored issue
show
Bug introduced by
It seems like $this->firstChild can also be of type null; however, parameter $node of DOMNode::insertBefore() 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

93
			$parent->insertBefore(/** @scrutinizer ignore-type */ $this->firstChild, $this);
Loading history...
94
		}
95
		$this->remove();
96
	}
97
98
	protected function unparseMarkupElement(string $nodeName, ?DOMNode $node): void
99
	{
100
		if ($node instanceof self && $node->nodeName === $nodeName)
101
		{
102
			$node->replaceWith($node->textContent);
103
		}
104
	}
105
106
	protected function attributesAreSorted(): bool
107
	{
108
		$lastName = '';
109
		foreach ($this->attributes as $name => $attribute)
110
		{
111
			if ($name < $lastName)
112
			{
113
				return false;
114
			}
115
			$lastName = $name;
116
		}
117
118
		return true;
119
	}
120
121
	protected function shouldBeRemoved(): bool
122
	{
123
		if (preg_match('/^[ies]$/', $this->nodeName) && count($this->childNodes) === 0 && count($this->attributes) === 0)
1 ignored issue
show
Bug introduced by
It seems like $this->attributes can also be of type null; however, parameter $value of count() does only seem to accept Countable|array, 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

123
		if (preg_match('/^[ies]$/', $this->nodeName) && count($this->childNodes) === 0 && count(/** @scrutinizer ignore-type */ $this->attributes) === 0)
Loading history...
124
		{
125
			return true;
126
		}
127
128
		return false;
129
	}
130
131
	protected function sortAttributes(): void
132
	{
133
		$attributes = [];
134
		foreach ($this->attributes as $name => $attribute)
135
		{
136
			$attributes[$name] = $this->removeAttributeNode($attribute);
137
		}
138
139
		ksort($attributes, SORT_STRING);
140
		foreach ($attributes as $attribute)
141
		{
142
			$this->setAttributeNode($attribute);
143
		}
144
	}
145
}