Issues (4)

src/AbstractDomDocumentHandler.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace WsdlToPhp\DomHandler;
4
5
use DOMElement;
6
7
abstract class AbstractDomDocumentHandler
8
{
9
    protected \DOMDocument $domDocument;
10
11
    protected ?ElementHandler $rootElement;
12
13 10
    public function __construct(\DOMDocument $domDocument)
14
    {
15 10
        $this->domDocument = $domDocument;
16 10
        $this->initRootElement();
17
    }
18
19
    /**
20
     * @param \DOMAttr|\DOMElement|\DOMNameSpaceNode|\DOMNode $node
21
     */
22 80
    public function getHandler($node, int $index = -1): AbstractNodeHandler
23
    {
24 80
        if ($node instanceof \DOMElement) {
25 62
            return $this->getElementHandler($node, $this, $index);
26
        }
27 60
        if ($node instanceof \DOMAttr) {
28 46
            return $this->getAttributeHandler($node, $this, $index);
29
        }
30 14
        if ($node instanceof \DOMNameSpaceNode) {
31 6
            return new NameSpaceHandler($node, $this, $index);
32
        }
33
34 8
        return $this->getNodeHandler($node, $this, $index);
35
    }
36
37 42
    public function getNodeByName(string $name): ?NodeHandler
38
    {
39 42
        return $this->domDocument->getElementsByTagName($name)->length > 0 ? $this->getNodeHandler($this->domDocument->getElementsByTagName($name)->item(0), $this) : null;
40
    }
41
42 26
    public function getElementByName(string $name): ?ElementHandler
43
    {
44 26
        $node = $this->getNodeByName($name);
45 26
        if ($node instanceof AbstractNodeHandler && $node->getNode() instanceof \DOMElement) {
46 24
            return $this->getElementHandler($node->getNode(), $this);
47
        }
48
49 2
        return null;
50
    }
51
52
    /**
53
     * @return AbstractAttributeHandler[]|AbstractElementHandler[]|AbstractNodeHandler[]
54
     */
55 50
    public function getNodesByName(string $name, ?string $checkInstance = null): array
56
    {
57 50
        $nodes = [];
58 50
        if ($this->domDocument->getElementsByTagName($name)->length > 0) {
59 50
            foreach ($this->domDocument->getElementsByTagName($name) as $node) {
60 50
                if (is_null($checkInstance) || $node instanceof $checkInstance) {
61 50
                    $nodes[] = $this->getHandler($node, count($nodes));
62
                }
63
            }
64
        }
65
66 50
        return $nodes;
67
    }
68
69
    /**
70
     * @return AbstractAttributeHandler[]|AbstractElementHandler[]|AbstractNodeHandler[]
71
     */
72 48
    public function getElementsByName(string $name): array
73
    {
74 48
        return $this->getNodesByName($name, \DOMElement::class);
75
    }
76
77
    /**
78
     * @param string[] $attributes
79
     *
80
     * @return AbstractAttributeHandler[]|AbstractElementHandler[]|AbstractNodeHandler[]
81
     */
82 46
    public function getElementsByNameAndAttributes(string $name, array $attributes, ?\DOMNode $node = null): array
83
    {
84 46
        $matchingElements = $this->getElementsByName($name);
85 46
        if ((!empty($attributes) || $node instanceof \DOMNode) && !empty($matchingElements)) {
86 46
            $nodes = $this->searchTagsByXpath($name, $attributes, $node);
87
88 46
            if (false !== $nodes) {
89 46
                $matchingElements = $this->getElementsHandlers($nodes);
90
            }
91
        }
92
93 46
        return $matchingElements;
94
    }
95
96
    /**
97
     * @param \DOMNodeList<\DOMAttr|\DOMElement|\DOMNode> $nodeList
98
     *
99
     * @return AbstractElementHandler[]
100
     */
101 48
    public function getElementsHandlers(\DOMNodeList $nodeList): array
102
    {
103 48
        $nodes = [];
104 48
        if (0 === $nodeList->count()) {
105
            return $nodes;
106
        }
107
108 48
        $index = 0;
109 48
        foreach ($nodeList as $node) {
110 48
            if (!$node instanceof \DOMElement) {
111 2
                continue;
112
            }
113
114 48
            $nodes[] = $this->getElementHandler($node, $this, $index);
115 48
            ++$index;
116
        }
117
118 48
        return $nodes;
119
    }
120
121
    /**
122
     * @param string[] $attributes
123
     *
124
     * @return \DOMNodeList<\DOMAttr|\DOMElement|\DOMNode>|false
125
     */
126 46
    public function searchTagsByXpath(string $name, array $attributes, ?\DOMNode $node = null)
127
    {
128 46
        $xpath = new \DOMXPath($node ? $node->ownerDocument : $this->domDocument);
0 ignored issues
show
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

128
        $xpath = new \DOMXPath(/** @scrutinizer ignore-type */ $node ? $node->ownerDocument : $this->domDocument);
Loading history...
129 46
        $xQuery = sprintf("%s//*[local-name()='%s']", $node instanceof \DOMNode ? '.' : '', $name);
130 46
        foreach ($attributes as $attributeName => $attributeValue) {
131 46
            if (false !== strpos($attributeValue, '*')) {
132 2
                $xQuery .= sprintf("[contains(@%s, '%s')]", $attributeName, str_replace('*', '', $attributeValue));
133
            } else {
134 46
                $xQuery .= sprintf("[@%s='%s']", $attributeName, $attributeValue);
135
            }
136
        }
137
138 46
        return $xpath->query($xQuery, $node);
139
    }
140
141
    /**
142
     * @param string[] $attributes
143
     */
144 42
    public function getElementByNameAndAttributes(string $name, array $attributes): ?ElementHandler
145
    {
146 42
        $elements = $this->getElementsByNameAndAttributes($name, $attributes);
147
148 42
        $element = array_shift($elements);
149
150 42
        return $element instanceof ElementHandler ? $element : null;
151
    }
152
153
    /**
154
     * Find valid root node (not a comment, at least a DOMElement node).
155
     *
156
     * @throws \InvalidArgumentException
157
     */
158 10
    protected function initRootElement(): void
159
    {
160 10
        if ($this->domDocument->hasChildNodes()) {
161 8
            foreach ($this->domDocument->childNodes as $node) {
162 8
                if ($node instanceof \DOMElement) {
163 8
                    $this->rootElement = $this->getElementHandler($node, $this);
164
165 8
                    break;
166
                }
167
            }
168
        } else {
169 2
            throw new \InvalidArgumentException('Document seems to be invalid', __LINE__);
170
        }
171
    }
172
173
    abstract protected function getNodeHandler(\DOMNode $node, AbstractDomDocumentHandler $domDocument, int $index = -1): NodeHandler;
174
175
    abstract protected function getElementHandler(\DOMElement $element, AbstractDomDocumentHandler $domDocument, int $index = -1): ElementHandler;
176
177
    abstract protected function getAttributeHandler(\DOMAttr $attribute, AbstractDomDocumentHandler $domDocument, int $index = -1): AttributeHandler;
178
}
179