Passed
Push — develop ( cd7fef...a71946 )
by Mikaël
01:37
created

getElementByNameAndAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
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 10
    public function __construct(DOMDocument $domDocument)
21
    {
22 10
        $this->domDocument = $domDocument;
23 10
        $this->initRootElement();
24 8
    }
25
26 80
    public function getHandler($node, int $index = -1): AbstractNodeHandler
27
    {
28 80
        if ($node instanceof DOMElement) {
29 62
            return $this->getElementHandler($node, $this, $index);
30
        }
31 60
        if ($node instanceof DOMAttr) {
32 46
            return $this->getAttributeHandler($node, $this, $index);
33
        }
34 14
        if ($node instanceof DOMNameSpaceNode) {
35 6
            return new NameSpaceHandler($node, $this, $index);
36
        }
37
38 8
        return $this->getNodeHandler($node, $this, $index);
39
    }
40
41 42
    public function getNodeByName(string $name): ?NodeHandler
42
    {
43 42
        return $this->domDocument->getElementsByTagName($name)->length > 0 ? $this->getNodeHandler($this->domDocument->getElementsByTagName($name)->item(0), $this) : null;
44
    }
45
46 26
    public function getElementByName(string $name): ?ElementHandler
47
    {
48 26
        $node = $this->getNodeByName($name);
49 26
        if ($node instanceof AbstractNodeHandler && $node->getNode() instanceof DOMElement) {
50 24
            return $this->getElementHandler($node->getNode(), $this);
51
        }
52
53 2
        return null;
54
    }
55
56 50
    public function getNodesByName(string $name, ?string $checkInstance = null): array
57
    {
58 50
        $nodes = [];
59 50
        if ($this->domDocument->getElementsByTagName($name)->length > 0) {
60 50
            foreach ($this->domDocument->getElementsByTagName($name) as $node) {
61 50
                if (is_null($checkInstance) || $node instanceof $checkInstance) {
62 50
                    $nodes[] = $this->getHandler($node, count($nodes));
63
                }
64
            }
65
        }
66
67 50
        return $nodes;
68
    }
69
70 48
    public function getElementsByName(string $name): array
71
    {
72 48
        return $this->getNodesByName($name, DOMElement::class);
73
    }
74
75 46
    public function getElementsByNameAndAttributes(string $name, array $attributes, ?DOMNode $node = null): array
76
    {
77 46
        $matchingElements = $this->getElementsByName($name);
78 46
        if ((!empty($attributes) || $node instanceof DOMNode) && !empty($matchingElements)) {
79 46
            $nodes = $this->searchTagsByXpath($name, $attributes, $node);
80
81 46
            if (!empty($nodes)) {
82 46
                $matchingElements = $this->getElementsHandlers($nodes);
83
            }
84
        }
85
86 46
        return $matchingElements;
87
    }
88
89 48
    public function getElementsHandlers(DOMNodeList $nodeList): array
90
    {
91 48
        $nodes = [];
92 48
        if (!empty($nodeList)) {
93 48
            $index = 0;
94 48
            foreach ($nodeList as $node) {
95 48
                if ($node instanceof DOMElement) {
96 48
                    $nodes[] = $this->getElementHandler($node, $this, $index);
97 48
                    ++$index;
98
                }
99
            }
100
        }
101
102 48
        return $nodes;
103
    }
104
105 46
    public function searchTagsByXpath(string $name, array $attributes, ?DOMNode $node = null): DOMNodeList
106
    {
107 46
        $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 46
        $xQuery = sprintf("%s//*[local-name()='%s']", $node instanceof DOMNode ? '.' : '', $name);
109 46
        foreach ($attributes as $attributeName => $attributeValue) {
110 46
            if (false !== strpos($attributeValue, '*')) {
111 2
                $xQuery .= sprintf("[contains(@%s, '%s')]", $attributeName, str_replace('*', '', $attributeValue));
112
            } else {
113 46
                $xQuery .= sprintf("[@%s='%s']", $attributeName, $attributeValue);
114
            }
115
        }
116
117 46
        return $xpath->query($xQuery, $node);
118
    }
119
120 42
    public function getElementByNameAndAttributes(string $name, array $attributes): ?ElementHandler
121
    {
122 42
        $elements = $this->getElementsByNameAndAttributes($name, $attributes);
123
124 42
        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 10
    protected function initRootElement()
133
    {
134 10
        if ($this->domDocument->hasChildNodes()) {
135 8
            foreach ($this->domDocument->childNodes as $node) {
136 8
                if ($node instanceof DOMElement) {
137 8
                    $this->rootElement = $this->getElementHandler($node, $this);
138
139 8
                    break;
140
                }
141
            }
142
        } else {
143 2
            throw new InvalidArgumentException('Document seems to be invalid', __LINE__);
144
        }
145 8
    }
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