Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace CfdiUtils;
4
5
use CfdiUtils\Internals\XmlReaderTrait;
6
use DOMDocument;
7
use UnexpectedValueException;
8
9
/**
10
 * This class contains minimum helpers to read CFDI based on DOMDocument
11
 *
12
 * When the object is instantiated it checks that:
13
 * implements the namespace static::CFDI_NAMESPACE using a prefix
14
 * the root node is prefix + Comprobante
15
 *
16
 * This class also provides version information through getVersion() method
17
 *
18
 * This class also provides conversion to Node for easy access and manipulation,
19
 * changes made in Node structure are not reflected into the DOMDocument,
20
 * changes made in DOMDocument three are not reflected into the Node,
21
 *
22
 * Use this class as your starting point to read documents
23
 */
24
class Cfdi
25
{
26
    use XmlReaderTrait;
27
28
    /**
29
     * @var string CFDI 3 namespace definition
30
     * @deprecated :3.0.0
31
     * @internal Preserve this constant to not break compatibility
32
     */
33
    public const CFDI_NAMESPACE = 'http://www.sat.gob.mx/cfd/3';
34
35
    /** @var array<string, string> Dictionary of versions and namespaces  */
36
    private const CFDI_SPECS = [
37
        '4.0' => 'http://www.sat.gob.mx/cfd/4',
38
        '3.3' => 'http://www.sat.gob.mx/cfd/3',
39
        '3.2' => 'http://www.sat.gob.mx/cfd/3',
40
    ];
41
42 78
    public function __construct(DOMDocument $document)
43
    {
44 78
        $cfdiVersion = new CfdiVersion();
45
        /** @var array<string, UnexpectedValueException> $exceptions */
46 78
        $exceptions = [];
47 78
        foreach (self::CFDI_SPECS as $version => $namespace) {
48
            try {
49 78
                $this->loadDocumentWithNamespace($cfdiVersion, $document, $namespace);
50 62
                return;
51 62
            } catch (UnexpectedValueException $exception) {
52 62
                $exceptions[$version] = $exception;
53
            }
54
        }
55
56 16
        throw CfdiCreateObjectException::withVersionExceptions($exceptions);
57
    }
58
59
    /** @throws UnexpectedValueException */
60 78
    private function loadDocumentWithNamespace(CfdiVersion $cfdiVersion, DOMDocument $document, string $namespace): void
61
    {
62 78
        $rootElement = self::checkRootElement($document, $namespace, 'cfdi', 'Comprobante');
63 62
        $this->version = $cfdiVersion->getFromDOMElement($rootElement);
64 62
        $this->document = clone $document;
65
    }
66
}
67