|
2 | 2 |
|
3 | 3 | namespace CfdiUtils;
|
4 | 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; |
| 5 | +use CfdiUtils\Internals\XmlReaderTrait; |
10 | 6 | use DOMDocument;
|
11 |
| -use DOMElement; |
12 | 7 |
|
13 | 8 | /**
|
14 | 9 | * This class contains minimum helpers to read CFDI based on DOMDocument
|
|
27 | 22 | */
|
28 | 23 | class Cfdi
|
29 | 24 | {
|
30 |
| - /** @var DOMDocument */ |
31 |
| - private $document; |
32 |
| - |
33 |
| - /** @var string */ |
34 |
| - private $version; |
35 |
| - |
36 |
| - /** @var string|null */ |
37 |
| - private $source; |
38 |
| - |
39 |
| - /** @var NodeInterface|null */ |
40 |
| - private $node; |
41 |
| - |
42 |
| - /** @var QuickReader|null */ |
43 |
| - private $quickReader; |
| 25 | + use XmlReaderTrait; |
44 | 26 |
|
45 | 27 | const CFDI_NAMESPACE = 'http://www.sat.gob.mx/cfd/3';
|
46 | 28 |
|
47 | 29 | public function __construct(DOMDocument $document)
|
48 | 30 | {
|
49 |
| - $rootElement = $this->extractValidRootElement($document, static::CFDI_NAMESPACE, 'cfdi', 'Comprobante'); |
50 |
| - |
51 |
| - $this->version = (new CfdiVersion())->getFromDOMElement($rootElement); |
| 31 | + $rootElement = self::checkRootElement($document, static::CFDI_NAMESPACE, 'cfdi', 'Comprobante'); |
52 | 32 | $this->document = clone $document;
|
53 |
| - } |
54 |
| - |
55 |
| - |
56 |
| - private function extractValidRootElement( |
57 |
| - DOMDocument $document, |
58 |
| - string $expectedNamespace, |
59 |
| - string $expectedNsPrefix, |
60 |
| - string $expectedRootBaseNodeName |
61 |
| - ): DOMElement { |
62 |
| - $rootElement = Xml::documentElement($document); |
63 |
| - |
64 |
| - // is not docummented: lookupPrefix returns NULL instead of string when not found |
65 |
| - // this is why we are casting the value to string |
66 |
| - $nsPrefix = (string) $document->lookupPrefix($expectedNamespace); |
67 |
| - if ('' === $nsPrefix) { |
68 |
| - throw new \UnexpectedValueException( |
69 |
| - sprintf('Document does not implement namespace %s', $expectedNamespace) |
70 |
| - ); |
71 |
| - } |
72 |
| - if ($expectedNsPrefix !== $nsPrefix) { |
73 |
| - throw new \UnexpectedValueException( |
74 |
| - sprintf('Prefix for namespace %s is not "%s"', $expectedNamespace, $expectedNsPrefix) |
75 |
| - ); |
76 |
| - } |
77 |
| - |
78 |
| - $expectedRootNodeName = $expectedNsPrefix . ':' . $expectedRootBaseNodeName; |
79 |
| - if ($rootElement->tagName !== $expectedRootNodeName) { |
80 |
| - throw new \UnexpectedValueException(sprintf('Root element is not %s', $expectedRootNodeName)); |
81 |
| - } |
82 |
| - |
83 |
| - return $rootElement; |
84 |
| - } |
85 |
| - |
86 |
| - /** |
87 |
| - * Create a CFDI object from a xml string |
88 |
| - * |
89 |
| - * @param string $content |
90 |
| - * @return static |
91 |
| - */ |
92 |
| - public static function newFromString(string $content): self |
93 |
| - { |
94 |
| - $document = Xml::newDocumentContent($content); |
95 |
| - // populate source since it is already available |
96 |
| - // in this way we avoid the conversion from document to string |
97 |
| - $cfdi = new self($document); |
98 |
| - $cfdi->source = $content; |
99 |
| - return $cfdi; |
100 |
| - } |
101 |
| - |
102 |
| - /** |
103 |
| - * Obtain the version from the CFDI, it is compatible with 3.2 and 3.3 |
104 |
| - */ |
105 |
| - public function getVersion(): string |
106 |
| - { |
107 |
| - return $this->version; |
108 |
| - } |
109 |
| - |
110 |
| - /** |
111 |
| - * Get a clone of the local DOM document |
112 |
| - */ |
113 |
| - public function getDocument(): DOMDocument |
114 |
| - { |
115 |
| - return clone $this->document; |
116 |
| - } |
117 |
| - |
118 |
| - /** |
119 |
| - * Get the xml string source |
120 |
| - */ |
121 |
| - public function getSource(): string |
122 |
| - { |
123 |
| - if (null === $this->source) { |
124 |
| - // pass the document element to avoid xml header |
125 |
| - $this->source = $this->document->saveXML(Xml::documentElement($this->document)); |
126 |
| - } |
127 |
| - |
128 |
| - return $this->source; |
129 |
| - } |
130 |
| - |
131 |
| - /** |
132 |
| - * Get the node object to iterate through the CFDI |
133 |
| - */ |
134 |
| - public function getNode(): NodeInterface |
135 |
| - { |
136 |
| - if (null === $this->node) { |
137 |
| - $this->node = XmlNodeUtils::nodeFromXmlElement(Xml::documentElement($this->document)); |
138 |
| - } |
139 |
| - |
140 |
| - return $this->node; |
141 |
| - } |
142 |
| - |
143 |
| - /** |
144 |
| - * Get the quick reader object to iterate through the CFDI |
145 |
| - */ |
146 |
| - public function getQuickReader(): QuickReader |
147 |
| - { |
148 |
| - if (null === $this->quickReader) { |
149 |
| - $this->quickReader = (new QuickReaderImporter())->importDocument($this->document); |
150 |
| - } |
151 |
| - |
152 |
| - return $this->quickReader; |
| 33 | + $this->version = (new CfdiVersion())->getFromDOMElement($rootElement); |
153 | 34 | }
|
154 | 35 | }
|
0 commit comments