Node::getAttribute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 2
1
<?php
2
3
namespace Thruster\Component\XMLIterator;
4
5
use DOMNode;
6
use DOMDocument;
7
use SimpleXMLElement;
8
use BadMethodCallException;
9
10
/**
11
 * Class Node
12
 *
13
 * @package Thruster\Component\XMLIterator
14
 * @author  Aurimas Niekis <[email protected]>
15
 */
16
class Node
17
{
18
    /**
19
     * @var XMLReader
20
     */
21
    protected $reader;
22
23
    /**
24
     * @var int
25
     */
26
    private $nodeType;
27
28
    /**
29
     * @var string
30
     */
31
    private $name;
32
33
    /**
34
     * @var string
35
     */
36
    private $localName;
37
38
    /**
39
     * @var SimpleXMLElement
40
     */
41
    private $simpleXML;
42
43
    /**
44
     * @var AttributeIterator
45
     */
46
    private $attributes;
47
48
    /**
49
     * @var string
50
     */
51
    private $string;
52
53 26
    public function __construct(XMLReader $reader)
54
    {
55 26
        $this->reader   = $reader;
56 26
        $this->nodeType = $reader->nodeType;
57 26
        $this->name     = $reader->name;
58 26
    }
59
60
    /**
61
     * @inheritdoc
62
     */
63 1
    public function __toString()
64
    {
65 1
        if (null === $this->string) {
66 1
            $this->string = $this->readString();
67
        }
68
69 1
        return $this->string;
70
    }
71
72
    /**
73
     * @return SimpleXMLElement
74
     */
75 1
    public function getSimpleXMLElement()
76
    {
77 1
        if (null === $this->simpleXML) {
78 1
            if ($this->reader->nodeType !== XMLReader::ELEMENT) {
79 1
                return null;
80
            }
81
82 1
            $node            = $this->expand();
83 1
            $this->simpleXML = simplexml_import_dom($node);
84
        }
85
86 1
        return $this->simpleXML;
87
    }
88
89
    /**
90
     * @return AttributeIterator|array
91
     */
92 18
    public function getAttributes()
93
    {
94 18
        if (null === $this->attributes) {
95 18
            $this->attributes = new AttributeIterator($this->reader);
96
        }
97
98 18
        return $this->attributes;
99
    }
100
101
    /**
102
     * @param string $name
103
     * @param null   $default
104
     *
105
     * @return string
106
     */
107
    public function getAttribute(string $name, $default = null)
108
    {
109
        return $this->reader->getAttribute($name) ?? $default;
110
    }
111
112
    /**
113
     * @param null $name
114
     * @param bool $descendantAxis
115
     *
116
     * @return ChildElementIterator
117
     */
118 1
    public function getChildElements($name = null, bool $descendantAxis = false) : ChildElementIterator
119
    {
120 1
        return new ChildElementIterator($this->reader, $name, $descendantAxis);
121
    }
122
123
    /**
124
     * @return ChildIterator|Node[]
125
     */
126
    public function getChildren() : ChildIterator
127
    {
128
        return new ChildIterator($this->reader);
129
    }
130
131
    /**
132
     * @return string name
133
     */
134 5
    public function getName()
135
    {
136 5
        return $this->name;
137
    }
138
139
    /**
140
     * @return string local name
141
     */
142
    public function getLocalName()
143
    {
144
        return $this->localName;
145
    }
146
147
    public function getReader()
148
    {
149
        return $this->reader;
150
    }
151
152
    /**
153
     * @return string
154
     */
155
    public function readOuterXml()
156
    {
157
        return $this->reader->readOuterXml();
158
    }
159
160
    /**
161
     * XMLReader expand node and import it into a DOMNode with a DOMDocument
162
     *
163
     * This is for example useful for DOMDocument::saveXML() @see readOuterXml
164
     * or getting a SimpleXMLElement out of it @see getSimpleXMLElement
165
     *
166
     * @throws BadMethodCallException
167
     *
168
     * @param DOMNode $baseNode
169
     *
170
     * @return DOMNode
171
     */
172 2
    public function expand(DOMNode $baseNode = null)
173
    {
174 2
        if (null === $baseNode) {
175 2
            $baseNode = new DOMDocument();
176
        }
177
178 2
        if ($baseNode instanceof DOMDocument) {
179 2
            $doc = $baseNode;
180
        } else {
181
            $doc = $baseNode->ownerDocument;
182
        }
183
184 2
        if (false === $node = $this->reader->expand($baseNode)) {
185
            throw new BadMethodCallException('Unable to expand node.');
186
        }
187
188 2
        if ($node->ownerDocument !== $doc) {
189
            $node = $doc->importNode($node, true);
190
        }
191
192 2
        return $node;
193
    }
194
195
    /**
196
     * Decorated method
197
     *
198
     * @throws BadMethodCallException
199
     * @return string
200
     */
201 6
    public function readString()
202
    {
203 6
        return $this->reader->readString();
204
    }
205
206
    /**
207
     * Return node-type as human readable string (constant name)
208
     *
209
     * @param null $nodeType
210
     *
211
     * @return string
212
     */
213 15
    public function getNodeTypeName($nodeType = null)
214
    {
215
        $strings = [
216 15
            XMLReader::NONE                   => 'NONE',
217 15
            XMLReader::ELEMENT                => 'ELEMENT',
218 15
            XMLReader::ATTRIBUTE              => 'ATTRIBUTE',
219 15
            XMLREADER::TEXT                   => 'TEXT',
220 15
            XMLREADER::CDATA                  => 'CDATA',
221 15
            XMLReader::ENTITY_REF             => 'ENTITY_REF',
222 15
            XMLReader::ENTITY                 => 'ENTITY',
223 15
            XMLReader::PI                     => 'PI',
224 15
            XMLReader::COMMENT                => 'COMMENT',
225 15
            XMLReader::DOC                    => 'DOC',
226 15
            XMLReader::DOC_TYPE               => 'DOC_TYPE',
227 15
            XMLReader::DOC_FRAGMENT           => 'DOC_FRAGMENT',
228 15
            XMLReader::NOTATION               => 'NOTATION',
229 15
            XMLReader::WHITESPACE             => 'WHITESPACE',
230 15
            XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',
231 15
            XMLReader::END_ELEMENT            => 'END_ELEMENT',
232 15
            XMLReader::END_ENTITY             => 'END_ENTITY',
233 15
            XMLReader::XML_DECLARATION        => 'XML_DECLARATION',
234
        ];
235
236 15
        if (null === $nodeType) {
237 15
            $nodeType = $this->nodeType;
238
        }
239
240 15
        return $strings[$nodeType];
241
    }
242
243
    /**
244
     * decorate method calls
245
     *
246
     * @param string $name
247
     * @param array  $args
248
     *
249
     * @return mixed
250
     */
251
    public function __call($name, $args)
252
    {
253
        return call_user_func_array([$this->reader, $name], $args);
254
    }
255
256
    /**
257
     * decorate property get
258
     *
259
     * @param string $name
260
     *
261
     * @return string
262
     */
263 2
    public function __get($name)
264
    {
265 2
        return $this->reader->$name;
266
    }
267
268
    /**
269
     * debug utility method
270
     *
271
     * @param XMLReader $reader
272
     * @param bool      $return (optional) prints by default but can return string
273
     *
274
     * @return string|null
275
     */
276 14
    public static function dump(XMLReader $reader, bool $return = false)
277
    {
278 14
        $node     = new self($reader);
279 14
        $nodeType = $reader->nodeType;
280 14
        $nodeName = $node->getNodeTypeName();
281 14
        $extra    = '';
282
283 14
        if ($reader->nodeType === XMLReader::ELEMENT) {
284 14
            $extra = '<' . $reader->name . '> ';
285 14
            $extra .= sprintf("(isEmptyElement: %s) ", $reader->isEmptyElement ? 'Yes' : 'No');
286
        }
287
288 14
        if ($reader->nodeType === XMLReader::END_ELEMENT) {
289 7
            $extra = '</' . $reader->name . '> ';
290
        }
291
292 14
        if ($reader->nodeType === XMLReader::ATTRIBUTE) {
293
            $str = $reader->value;
294
            $len = strlen($str);
295
            if ($len > 20) {
296
                $str = substr($str, 0, 17) . '...';
297
            }
298
            $str   = strtr($str, ["\n" => '\n']);
299
            $extra = sprintf('%s = (%d) "%s" ', $reader->name, strlen($str), $str);
300
        }
301
302 14
        if ($reader->nodeType === XMLReader::TEXT || $reader->nodeType === XMLReader::WHITESPACE ||
303 14
            $reader->nodeType === XMLReader::SIGNIFICANT_WHITESPACE
304
        ) {
305 7
            $str = $reader->readString();
306 7
            $len = strlen($str);
307 7
            if ($len > 20) {
308 3
                $str = substr($str, 0, 17) . '...';
309
            }
310 7
            $str   = strtr($str, ["\n" => '\n']);
311 7
            $extra = sprintf('(%d) "%s" ', strlen($str), $str);
312
        }
313
314 14
        $label = sprintf("(#%d) %s %s", $nodeType, $nodeName, $extra);
315
316 14
        if ($return) {
317 14
            return $label;
318
        }
319
320
        printf("%s%s\n", str_repeat('  ', $reader->depth), $label);
321
322
        return null;
323
    }
324
}
325