Passed
Branch develop (cd7fef)
by Mikaël
01:30
created

AbstractDomDocumentHandler   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 35
eloc 55
c 1
b 0
f 0
dl 0
loc 138
ccs 0
cts 63
cp 0
rs 9.6

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getElementsHandlers() 0 14 4
A initRootElement() 0 12 4
A __construct() 0 4 1
A getElementsByNameAndAttributes() 0 12 5
A searchTagsByXpath() 0 13 5
A getElementByNameAndAttributes() 0 5 1
A getHandler() 0 13 4
A getNodesByName() 0 12 5
A getElementsByName() 0 3 1
A getNodeByName() 0 3 2
A getElementByName() 0 8 3
1
<?php
2
3
namespace WsdlToPhp\DomHandler;
4
5
use DOMAttr;
6
use DOMDocument;
7
use DOMElement;
8
use DOMNameSpaceNode;
9
use DOMNode;
10
use DOMNodeList;
11
use DOMXPath;
12
use InvalidArgumentException;
13
14
abstract class AbstractDomDocumentHandler
15
{
16
    protected DOMDocument $domDocument;
17
18
    protected ?ElementHandler $rootElement;
19
20
    public function __construct(DOMDocument $domDocument)
21
    {
22
        $this->domDocument = $domDocument;
23
        $this->initRootElement();
24
    }
25
26
    public function getHandler($node, int $index = -1): AbstractNodeHandler
27
    {
28
        if ($node instanceof DOMElement) {
29
            return $this->getElementHandler($node, $this, $index);
30
        }
31
        if ($node instanceof DOMAttr) {
32
            return $this->getAttributeHandler($node, $this, $index);
33
        }
34
        if ($node instanceof DOMNameSpaceNode) {
35
            return new NameSpaceHandler($node, $this, $index);
36
        }
37
38
        return $this->getNodeHandler($node, $this, $index);
39
    }
40
41
    public function getNodeByName(string $name): ?NodeHandler
42
    {
43
        return $this->domDocument->getElementsByTagName($name)->length > 0 ? $this->getNodeHandler($this->domDocument->getElementsByTagName($name)->item(0), $this) : null;
44
    }
45
46
    public function getElementByName(string $name): ?ElementHandler
47
    {
48
        $node = $this->getNodeByName($name);
49
        if ($node instanceof AbstractNodeHandler && $node->getNode() instanceof DOMElement) {
50
            return $this->getElementHandler($node->getNode(), $this);
51
        }
52
53
        return null;
54
    }
55
56
    public function getNodesByName(string $name, ?string $checkInstance = null): array
57
    {
58
        $nodes = [];
59
        if ($this->domDocument->getElementsByTagName($name)->length > 0) {
60
            foreach ($this->domDocument->getElementsByTagName($name) as $node) {
61
                if (is_null($checkInstance) || $node instanceof $checkInstance) {
62
                    $nodes[] = $this->getHandler($node, count($nodes));
63
                }
64
            }
65
        }
66
67
        return $nodes;
68
    }
69
70
    public function getElementsByName(string $name): array
71
    {
72
        return $this->getNodesByName($name, DOMElement::class);
73
    }
74
75
    public function getElementsByNameAndAttributes(string $name, array $attributes, ?DOMNode $node = null): array
76
    {
77
        $matchingElements = $this->getElementsByName($name);
78
        if ((!empty($attributes) || $node instanceof DOMNode) && !empty($matchingElements)) {
79
            $nodes = $this->searchTagsByXpath($name, $attributes, $node);
80
81
            if (!empty($nodes)) {
82
                $matchingElements = $this->getElementsHandlers($nodes);
83
            }
84
        }
85
86
        return $matchingElements;
87
    }
88
89
    public function getElementsHandlers(DOMNodeList $nodeList): array
90
    {
91
        $nodes = [];
92
        if (!empty($nodeList)) {
93
            $index = 0;
94
            foreach ($nodeList as $node) {
95
                if ($node instanceof DOMElement) {
96
                    $nodes[] = $this->getElementHandler($node, $this, $index);
97
                    ++$index;
98
                }
99
            }
100
        }
101
102
        return $nodes;
103
    }
104
105
    public function searchTagsByXpath(string $name, array $attributes, ?DOMNode $node = null): DOMNodeList
106
    {
107
        $xpath = new DOMXPath($node ? $node->ownerDocument : $this->domDocument);
0 ignored issues
show
Bug introduced by
It seems like $node ? $node->ownerDocument : $this->domDocument can also be of type null; however, parameter $document of DOMXPath::__construct() does only seem to accept DOMDocument, 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

107
        $xpath = new DOMXPath(/** @scrutinizer ignore-type */ $node ? $node->ownerDocument : $this->domDocument);
Loading history...
108
        $xQuery = sprintf("%s//*[local-name()='%s']", $node instanceof DOMNode ? '.' : '', $name);
109
        foreach ($attributes as $attributeName => $attributeValue) {
110
            if (false !== strpos($attributeValue, '*')) {
111
                $xQuery .= sprintf("[contains(@%s, '%s')]", $attributeName, str_replace('*', '', $attributeValue));
112
            } else {
113
                $xQuery .= sprintf("[@%s='%s']", $attributeName, $attributeValue);
114
            }
115
        }
116
117
        return $xpath->query($xQuery, $node);
118
    }
119
120
    public function getElementByNameAndAttributes(string $name, array $attributes): ?ElementHandler
121
    {
122
        $elements = $this->getElementsByNameAndAttributes($name, $attributes);
123
124
        return array_shift($elements);
125
    }
126
127
    /**
128
     * Find valid root node (not a comment, at least a DOMElement node).
129
     *
130
     * @throws InvalidArgumentException
131
     */
132
    protected function initRootElement()
133
    {
134
        if ($this->domDocument->hasChildNodes()) {
135
            foreach ($this->domDocument->childNodes as $node) {
136
                if ($node instanceof DOMElement) {
137
                    $this->rootElement = $this->getElementHandler($node, $this);
138
139
                    break;
140
                }
141
            }
142
        } else {
143
            throw new InvalidArgumentException('Document seems to be invalid', __LINE__);
144
        }
145
    }
146
147
    abstract protected function getNodeHandler(DOMNode $node, AbstractDomDocumentHandler $domDocument, int $index = -1): NodeHandler;
148
149
    abstract protected function getElementHandler(DOMElement $element, AbstractDomDocumentHandler $domDocument, int $index = -1): ElementHandler;
150
151
    abstract protected function getAttributeHandler(DOMAttr $attribute, AbstractDomDocumentHandler $domDocument, int $index = -1): AttributeHandler;
152
}
153