Passed
Push — master ( 64b813...0fa737 )
by Carlos C
04:57
created

XmlReaderTrait::getNode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace CfdiUtils\Internals;
4
5
use CfdiUtils\Nodes\NodeInterface;
6
use CfdiUtils\Nodes\XmlNodeUtils;
7
use CfdiUtils\QuickReader\QuickReader;
8
use CfdiUtils\QuickReader\QuickReaderImporter;
9
use CfdiUtils\Utils\Xml;
10
use DOMDocument;
11
use DOMElement;
12
13
/** @internal */
14
trait XmlReaderTrait
15
{
16
    /** @var DOMDocument */
17
    private $document;
18
19
    /** @var string */
20
    private $version;
21
22
    /** @var string|null */
23
    private $source;
24
25
    /** @var NodeInterface|null */
26
    private $node;
27
28
    /** @var QuickReader|null */
29
    private $quickReader;
30
31 64
    private static function checkRootElement(
32
        DOMDocument $document,
33
        string $expectedNamespace,
34
        string $expectedNsPrefix,
35
        string $expectedRootBaseNodeName
36
    ): DOMElement {
37 64
        $rootElement = Xml::documentElement($document);
38
39
        // is not docummented: lookupPrefix returns NULL instead of string when not found
40
        // this is why we are casting the value to string
41 62
        $nsPrefix = (string) $document->lookupPrefix($expectedNamespace);
42 62
        if ('' === $nsPrefix) {
43 3
            throw new \UnexpectedValueException(
44 3
                sprintf('Document does not implement namespace %s', $expectedNamespace)
45
            );
46
        }
47 59
        if ($expectedNsPrefix !== $nsPrefix) {
48 1
            throw new \UnexpectedValueException(
49 1
                sprintf('Prefix for namespace %s is not "%s"', $expectedNamespace, $expectedNsPrefix)
50
            );
51
        }
52
53 58
        $expectedRootNodeName = $expectedNsPrefix . ':' . $expectedRootBaseNodeName;
54 58
        if ($rootElement->tagName !== $expectedRootNodeName) {
55 4
            throw new \UnexpectedValueException(sprintf('Root element is not %s', $expectedRootNodeName));
56
        }
57
58 54
        return $rootElement;
59
    }
60
61
    /**
62
     * Create a CFDI object from a xml string
63
     *
64
     * @param string $content
65
     * @return self
66
     */
67 67
    public static function newFromString(string $content): self
68
    {
69 67
        $document = Xml::newDocumentContent($content);
70
        // populate source since it is already available, in this way we avoid the conversion from document to string
71
        /** @noinspection PhpMethodParametersCountMismatchInspection */
72 61
        $cfdi = new self($document);
0 ignored issues
show
Unused Code introduced by
The call to CfdiUtils\Internals\XmlReaderTrait::__construct() has too many arguments starting with $document. ( Ignorable by Annotation )

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

72
        $cfdi = /** @scrutinizer ignore-call */ new self($document);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
73 53
        $cfdi->source = $content;
74 53
        return $cfdi;
75
    }
76
77
    /**
78
     * Obtain the version from the document, if the version was not detected returns an empty string
79
     */
80 22
    public function getVersion(): string
81
    {
82 22
        return $this->version;
83
    }
84
85
    /**
86
     * Get a clone of the local DOM Document
87
     */
88 10
    public function getDocument(): DOMDocument
89
    {
90 10
        return clone $this->document;
91
    }
92
93
    /**
94
     * Get the XML string source
95
     */
96 3
    public function getSource(): string
97
    {
98 3
        if (null === $this->source) {
99
            // pass the document element to avoid xml header
100
            $this->source = (string) $this->document->saveXML(Xml::documentElement($this->document));
101
        }
102
103 3
        return $this->source;
104
    }
105
106
    /**
107
     * Get the node object to iterate through the document
108
     */
109 25
    public function getNode(): NodeInterface
110
    {
111 25
        if (null === $this->node) {
112 25
            $this->node = XmlNodeUtils::nodeFromXmlElement(Xml::documentElement($this->document));
113
        }
114
115 25
        return $this->node;
116
    }
117
118
    /**
119
     * Get the quick reader object to iterate through the document
120
     */
121 9
    public function getQuickReader(): QuickReader
122
    {
123 9
        if (null === $this->quickReader) {
124 9
            $this->quickReader = (new QuickReaderImporter())->importDocument($this->document);
125
        }
126
127 9
        return $this->quickReader;
128
    }
129
}
130