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

src/CfdiUtils/Retenciones/RetencionesCreator10.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace CfdiUtils\Retenciones;
4
5
use CfdiUtils\CadenaOrigen\DOMBuilder;
6
use CfdiUtils\CadenaOrigen\XsltBuilderInterface;
7
use CfdiUtils\CadenaOrigen\XsltBuilderPropertyInterface;
8
use CfdiUtils\CadenaOrigen\XsltBuilderPropertyTrait;
9
use CfdiUtils\Certificado\Certificado;
10
use CfdiUtils\Certificado\CertificadoPropertyInterface;
11
use CfdiUtils\Certificado\CertificadoPropertyTrait;
12
use CfdiUtils\Elements\Retenciones10\Retenciones;
0 ignored issues
show
This use statement conflicts with another class in this namespace, CfdiUtils\Retenciones\Retenciones. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use CfdiUtils\Nodes\XmlNodeUtils;
14
use CfdiUtils\PemPrivateKey\PemPrivateKey;
15
use CfdiUtils\Validate\Asserts;
16
use CfdiUtils\Validate\Cfdi33\Xml\XmlFollowSchema;
17
use CfdiUtils\XmlResolver\XmlResolver;
18
use CfdiUtils\XmlResolver\XmlResolverPropertyInterface;
19
use CfdiUtils\XmlResolver\XmlResolverPropertyTrait;
20
21
class RetencionesCreator10 implements
22
    CertificadoPropertyInterface,
23
    XmlResolverPropertyInterface,
24
    XsltBuilderPropertyInterface
25
{
26
    use CertificadoPropertyTrait;
27
    use XmlResolverPropertyTrait;
28
    use XsltBuilderPropertyTrait;
29
30
    /** @var Retenciones */
31
    private $retenciones;
32
33 4
    public function __construct(
34
        array $comprobanteAttributes = [],
35
        XmlResolver $xmlResolver = null,
36
        XsltBuilderInterface $xsltBuilder = null
37
    ) {
38 4
        $this->retenciones = new Retenciones($comprobanteAttributes);
39 4
        $this->setXmlResolver($xmlResolver ? : new XmlResolver());
40 4
        $this->setXsltBuilder($xsltBuilder ? : new DOMBuilder());
41 4
    }
42
43 1
    public function retenciones(): Retenciones
44
    {
45 1
        return $this->retenciones;
46
    }
47
48 2
    public function putCertificado(Certificado $certificado)
49
    {
50 2
        $this->setCertificado($certificado);
51 2
        $this->retenciones['NumCert'] = $certificado->getSerial();
52 2
        $pemContents = implode('', preg_grep('/^((?!-).)*$/', explode(PHP_EOL, $certificado->getPemContents())));
53 2
        $this->retenciones['Cert'] = $pemContents;
54 2
    }
55
56 1
    public function buildCadenaDeOrigen(): string
57
    {
58 1
        if (! $this->hasXmlResolver()) {
59
            throw new \LogicException('Cannot build the cadena de origen since there is no xml resolver');
60
        }
61 1
        $xmlResolver = $this->getXmlResolver();
62 1
        $xsltLocation = $xmlResolver->resolve(
63 1
            'http://www.sat.gob.mx/esquemas/retencionpago/1/retenciones.xslt',
64 1
            $xmlResolver::TYPE_XSLT
65
        );
66 1
        return $this->getXsltBuilder()->build($this->asXml(), $xsltLocation);
67
    }
68
69 3
    public function addSello(string $key, string $passPhrase = '')
70
    {
71
        // create private key
72 3
        $privateKey = new PemPrivateKey($key);
73 3
        if (! $privateKey->open($passPhrase)) {
74 1
            throw new \RuntimeException('Cannot open the private key');
75
        }
76
77
        // check privatekey belongs to certificado
78 2
        if ($this->hasCertificado()) {
79 2
            if (! $privateKey->belongsTo($this->getCertificado()->getPemContents())) {
80 1
                throw new \RuntimeException('The private key does not belong to the current certificate');
81
            }
82
        }
83
84
        // create sign and set into Sello attribute
85 1
        $this->retenciones['Sello'] = base64_encode(
86 1
            $privateKey->sign($this->buildCadenaDeOrigen(), OPENSSL_ALGO_SHA1)
87
        );
88 1
    }
89
90 2
    public function validate(): Asserts
91
    {
92 2
        $validator = new XmlFollowSchema();
93 2
        $validator->setXmlResolver($this->getXmlResolver());
94 2
        $asserts = new Asserts();
95 2
        $validator->validate($this->retenciones, $asserts);
96 2
        return $asserts;
97
    }
98
99 1
    public function asXml(): string
100
    {
101 1
        return XmlNodeUtils::nodeToXmlString($this->retenciones, true);
102
    }
103
}
104