Test Failed
Push — master ( 59e870...659f9a )
by Esteban De La Fuente
04:33
created

DocumentEnvelope::getXmlDocument()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * LibreDTE: Biblioteca PHP (Núcleo).
7
 * Copyright (C) LibreDTE <https://www.libredte.cl>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de
20
 * GNU junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace libredte\lib\Core\Package\Billing\Component\Document\Support;
26
27
use Derafu\Lib\Core\Package\Prime\Component\Certificate\Contract\CertificateInterface;
28
use Derafu\Lib\Core\Package\Prime\Component\Xml\Contract\XmlInterface;
29
use Derafu\Lib\Core\Support\Store\Contract\DataContainerInterface;
30
use Derafu\Lib\Core\Support\Store\DataContainer;
31
use libredte\lib\Core\Package\Billing\Component\Document\Contract\DocumentBagInterface;
32
use libredte\lib\Core\Package\Billing\Component\Document\Contract\DocumentEnvelopeInterface;
33
use libredte\lib\Core\Package\Billing\Component\Document\Contract\SobreEnvioInterface;
34
use libredte\lib\Core\Package\Billing\Component\Document\Entity\TipoSobre;
35
use libredte\lib\Core\Package\Billing\Component\Document\Exception\DispatcherException;
36
use libredte\lib\Core\Package\Billing\Component\TradingParties\Contract\EmisorInterface;
37
use libredte\lib\Core\Package\Billing\Component\TradingParties\Contract\MandatarioInterface;
38
use libredte\lib\Core\Package\Billing\Component\TradingParties\Contract\ReceptorInterface;
39
40
/**
41
 * Contenedor de datos del sobre de documentos tributarios electrónicos.
42
 *
43
 * Permite "mover" un sobre con varios documentos, junto a otros datos
44
 * asociados, por métodos de manera sencilla y, sobre todo, extensible.
45
 */
46
class DocumentEnvelope implements DocumentEnvelopeInterface
47
{
48
    /**
49
     * Tipo del sobre de documentos.
50
     *
51
     * @var TipoSobre|null
52
     */
53
    private ?TipoSobre $tipo_sobre = null;
54
55
    /**
56
     * Entidad del sobre del envío de documentos.
57
     *
58
     * @var SobreEnvioInterface|null
59
     */
60
    private ?SobreEnvioInterface $sobre_envio = null;
61
62
    /**
63
     * Instancia del documento XML asociado al sobre de documentos tributarios.
64
     *
65
     * @var XmlInterface|null
66
     */
67
    private ?XmlInterface $xmlDocument = null;
68
69
    /**
70
     * Lista de bolsas de documentos tributarios que este sobre contendrá.
71
     *
72
     * @var DocumentBagInterface[]|null
73
     */
74
    private ?array $documents = null;
75
76
    /**
77
     * Opciones para los workers asociados al documento.
78
     *
79
     * Se definen los siguientes índices para las opciones:
80
     *
81
     *   - `dispatcher`: Opciones para el despachador del sobre.
82
     *
83
     * Se usarán las opciones por defecto en cada worker si no se indican los
84
     * índices en el arreglo $options.
85
     *
86
     * @param DataContainerInterface|null
87
     */
88
    private ?DataContainerInterface $options = null;
89
90
    /**
91
     * Reglas de esquema de las opciones del documento.
92
     *
93
     * El formato del esquema es el utilizado por
94
     * Symfony\Component\OptionsResolver\OptionsResolver.
95
     *
96
     * Acá solo se indicarán los índices que deben pueden existir en las
97
     * opciones. No se define el esquema de cada opción pues cada clase que
98
     * utilice estas opciones deberá resolver y validar sus propias opciones.
99
     *
100
     * @var array
101
     */
102
    protected array $optionsSchema = [
103
        'dispatcher' => [
104
            'types' => 'array',
105
            'default' => [],
106
        ],
107
    ];
108
109
    /**
110
     * Emisor del sobre de documentos.
111
     *
112
     * @var EmisorInterface|null
113
     */
114
    private ?EmisorInterface $emisor = null;
115
116
    /**
117
     * Mandatario del sobre de documentos.
118
     *
119
     * @var MandatarioInterface|null
120
     */
121
    private ?MandatarioInterface $mandatario = null;
122
123
    /**
124
     * Receptor del sobre de documentos.
125
     *
126
     * @var ReceptorInterface|null
127
     */
128
    private ?ReceptorInterface $receptor = null;
129
130
    /**
131
     * Certificado digital (firma electrónica) para la firma del sobre.
132
     *
133
     * @var CertificateInterface|null
134
     */
135
    private ?CertificateInterface $certificate = null;
136
137
    /**
138
     * Datos de la carátula del sobre.
139
     *
140
     * @var array|null
141
     */
142
    private ?array $caratula = null;
143
144
    /**
145
     * {@inheritdoc}
146
     */
147
    public function getId(): string
148
    {
149
        return 'LibreDTE_SetDoc';
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 5
    public function getTipoSobre(): TipoSobre
156
    {
157 5
        return $this->tipo_sobre;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->tipo_sobre could return the type null which is incompatible with the type-hinted return libredte\lib\Core\Packag...cument\Entity\TipoSobre. Consider adding an additional type-check to rule them out.
Loading history...
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 5
    public function setSobreEnvio(SobreEnvioInterface $sobre_envio): static
164
    {
165 5
        $this->sobre_envio = $sobre_envio;
166
167 5
        return $this;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 5
    public function getSobreEnvio(): ?SobreEnvioInterface
174
    {
175 5
        return $this->sobre_envio;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181 5
    public function setXmlDocument(?XmlInterface $xmlDocument): static
182
    {
183 5
        $this->xmlDocument = $xmlDocument;
184
185 5
        return $this;
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191 5
    public function getXmlDocument(): ?XmlInterface
192
    {
193 5
        return $this->xmlDocument;
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     */
199
    public function setDocuments(array $documents): static
200
    {
201
        foreach ($documents as $document) {
202
            $this->addDocument($document);
203
        }
204
205
        return $this;
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211 5
    public function getDocuments(): ?array
212
    {
213 5
        return $this->documents;
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219 5
    public function addDocument(?DocumentBagInterface $document): static
220
    {
221
        // Si ya se agregó la carátula no se permite agregar nuevos documentos.
222 5
        if (isset($this->caratula)) {
223
            throw new DispatcherException(
224
                'No es posible agregar documentos al sobre cuando la carátula ya fue generada.'
225
            );
226
        }
227
228
        // Si no hay documentos previamente se inicializa un arreglo vacío.
229 5
        if ($this->documents === null) {
230 5
            $this->documents = [];
231
        }
232
233
        // Si no está definido el tipo de sobre el primer documento que se
234
        // agregue lo definirá.
235 5
        if (!isset($this->tipo_sobre)) {
236 5
            $this->tipo_sobre = $document->getTipoDocumento()->getTipoSobre();
0 ignored issues
show
Bug introduced by
The method getTipoDocumento() does not exist on null. ( Ignorable by Annotation )

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

236
            $this->tipo_sobre = $document->/** @scrutinizer ignore-call */ getTipoDocumento()->getTipoSobre();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
237
        }
238
239
        // Validar que el tipo de documento se pueda agregar al sobre.
240 5
        if ($document->getTipoDocumento()->getTipoSobre() !== $this->tipo_sobre) {
241
            throw new DispatcherException(sprintf(
242
                'El tipo de documento %s no se puede agregar a un sobre de tipo %s.',
243
                $document->getTipoDocumento()->getNombre(),
244
                $this->getTipoSobre()->getNombre()
245
            ));
246
        }
247
248
        // Validar que no se haya llenado la lista de documentos permitida.
249 5
        $maximoDocumentos = $this->getTipoSobre()->getMaximoDocumentos();
250 5
        if (isset($this->documentos[$maximoDocumentos - 1])) {
0 ignored issues
show
Bug introduced by
The property documentos does not exist on libredte\lib\Core\Packag...upport\DocumentEnvelope. Did you mean documents?
Loading history...
251
            throw new DispatcherException(sprintf(
252
                'No es posible agregar nuevos documentos al sobre %s, el límite es de %d documentos por sobre.',
253
                $this->getTipoSobre()->getNombre(),
254
                $maximoDocumentos
255
            ));
256
        }
257
258
        // Agregar el documento al sobre.
259 5
        $this->documents[] = $document;
260
261
        // Entregar la misma instancia para encadenamiento.
262 5
        return $this;
263
    }
264
265
    /**
266
     * {@inheritdoc}
267
     */
268
    public function setOptions(array|DataContainerInterface|null $options): static
269
    {
270
        if ($options === null) {
0 ignored issues
show
introduced by
The condition $options === null is always false.
Loading history...
271
            $options = [];
272
        }
273
274
        if (is_array($options)) {
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
275
            $options = new DataContainer($options, $this->optionsSchema);
276
        }
277
278
        $this->options = $options;
279
280
        return $this;
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    public function getOptions(): ?DataContainerInterface
287
    {
288
        return $this->options;
289
    }
290
291
    /**
292
     * {@inheritdoc}
293
     */
294
    public function getDispatcherOptions(): array
295
    {
296
        return (array) $this->options?->get('dispatcher');
297
    }
298
299
    /**
300
     * {@inheritdoc}
301
     */
302 5
    public function setEmisor(?EmisorInterface $emisor): static
303
    {
304 5
        $this->emisor = $emisor;
305
306 5
        return $this;
307
    }
308
309
    /**
310
     * {@inheritdoc}
311
     */
312 5
    public function getEmisor(): ?EmisorInterface
313
    {
314 5
        return $this->emisor;
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320
    public function setMandatario(?MandatarioInterface $mandatario): static
321
    {
322
        $this->mandatario = $mandatario;
323
324
        return $this;
325
    }
326
327
    /**
328
     * {@inheritdoc}
329
     */
330 5
    public function getMandatario(): ?MandatarioInterface
331
    {
332 5
        return $this->mandatario;
333
    }
334
335
    /**
336
     * {@inheritdoc}
337
     */
338 5
    public function setReceptor(?ReceptorInterface $receptor): static
339
    {
340 5
        $this->receptor = $receptor;
341
342 5
        return $this;
343
    }
344
345
    /**
346
     * {@inheritdoc}
347
     */
348 5
    public function getReceptor(): ?ReceptorInterface
349
    {
350 5
        return $this->receptor;
351
    }
352
353
    /**
354
     * {@inheritdoc}
355
     */
356
    public function setCertificate(?CertificateInterface $certificate): static
357
    {
358
        $this->certificate = $certificate;
359
360
        return $this;
361
    }
362
363
    /**
364
     * {@inheritdoc}
365
     */
366 5
    public function getCertificate(): ?CertificateInterface
367
    {
368 5
        return $this->certificate;
369
    }
370
371
    /**
372
     * {@inheritdoc}
373
     */
374
    public function setCaratula(array $caratula): static
375
    {
376
        $this->caratula = $caratula;
377
378
        return $this;
379
    }
380
381
    /**
382
     * {@inheritdoc}
383
     */
384 5
    public function getCaratula(): ?array
385
    {
386 5
        return $this->caratula;
387
    }
388
389
    /**
390
     * {@inheritdoc}
391
     */
392
    public function withCertificate(
393
        CertificateInterface $certificate
394
    ): DocumentEnvelopeInterface {
395
        $envelope = new static();
396
        $envelope->setXmlDocument($this->getXmlDocument());
397
        $envelope->setDocuments($this->getDocuments());
0 ignored issues
show
Bug introduced by
It seems like $this->getDocuments() can also be of type null; however, parameter $documents of libredte\lib\Core\Packag...nvelope::setDocuments() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

397
        $envelope->setDocuments(/** @scrutinizer ignore-type */ $this->getDocuments());
Loading history...
398
        $envelope->setOptions($this->getOptions());
399
        $envelope->setEmisor($this->getEmisor());
400
        $envelope->setMandatario($this->getMandatario());
401
        $envelope->setReceptor($this->getReceptor());
402
        $envelope->setCertificate($this->getCertificate());
403
404
        return $envelope;
405
    }
406
}
407