Test Failed
Push — master ( 8dc6a9...a5e9ad )
by Esteban De La Fuente
06:42
created

TemplateDataHandler::createHandlers()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 96
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 4.5492

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 68
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 96
ccs 54
cts 80
cp 0.675
crap 4.5492
rs 8.6981

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Service;
26
27
use Closure;
28
use Derafu\Lib\Core\Helper\Rut;
29
use Derafu\Lib\Core\Package\Prime\Component\Entity\Contract\EntityComponentInterface;
30
use Derafu\Lib\Core\Package\Prime\Component\Template\Contract\DataHandlerInterface;
31
use Derafu\Lib\Core\Package\Prime\Component\Template\Service\DataHandler;
32
use Derafu\Lib\Core\Support\Store\Contract\RepositoryInterface;
33
use libredte\lib\Core\Package\Billing\Component\Document\Contract\TipoDocumentoInterface;
34
use libredte\lib\Core\Package\Billing\Component\Document\Entity\AduanaMoneda;
35
use libredte\lib\Core\Package\Billing\Component\Document\Entity\AduanaPais;
36
use libredte\lib\Core\Package\Billing\Component\Document\Entity\AduanaTransporte;
37
use libredte\lib\Core\Package\Billing\Component\Document\Entity\Comuna;
38
use libredte\lib\Core\Package\Billing\Component\Document\Entity\FormaPago;
39
use libredte\lib\Core\Package\Billing\Component\Document\Entity\Moneda;
40
use libredte\lib\Core\Package\Billing\Component\Document\Entity\TagXml;
41
use libredte\lib\Core\Package\Billing\Component\Document\Entity\Traslado;
42
use libredte\lib\Core\Package\Billing\Component\Document\Exception\RendererException;
43
use TCPDF2DBarcode;
44
45
/**
46
 * Servicio para traducir los datos de los documentos a su representación para
47
 * ser utilizada en la renderización del documento.
48
 */
49
class TemplateDataHandler implements DataHandlerInterface
50
{
51
    /**
52
     * Mapa de handlers.
53
     *
54
     * @var array
55
     */
56
    private array $handlers;
57
58
    /**
59
     * Handler por defecto para manejar los casos.
60
     *
61
     * @var DataHandlerInterface
62
     */
63
    private DataHandlerInterface $handler;
64
65
    /**
66
     * Constructor del handler.
67
     *
68
     * @param EntityComponentInterface $entityComponent
69
     * @param DataHandlerInterface|null $handler
70
     */
71 54
    public function __construct(
72
        private EntityComponentInterface $entityComponent,
73
        DataHandlerInterface $handler = null
74
    ) {
75 54
        $this->handler = $handler ?? new DataHandler();
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81 54
    public function handle(string $id, mixed $data): string
82
    {
83
        // Si no hay valor asignado en los datos se entrega un string vacio.
84 54
        if (!$data) {
85 18
            return '';
86
        }
87
88
        // Buscar el handler.
89 54
        $handler = $this->getHandler($id);
90
91
        // Ejecutar el handler sobre los datos para formatearlos.
92 54
        assert($this->handler instanceof DataHandler);
93 54
        return $this->handler->handle($id, $data, $handler);
0 ignored issues
show
Unused Code introduced by
The call to Derafu\Lib\Core\Package\...dlerInterface::handle() has too many arguments starting with $handler. ( Ignorable by Annotation )

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

93
        return $this->handler->/** @scrutinizer ignore-call */ handle($id, $data, $handler);

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...
94
    }
95
96
    /**
97
     * Obtiene el handler de un campo a partir de su ID.
98
     *
99
     * @param string $id
100
     * @return Closure|RepositoryInterface
101
     */
102 54
    private function getHandler(string $id): Closure|RepositoryInterface
103
    {
104 54
        if (!isset($this->handlers)) {
105 54
            $this->handlers = $this->createHandlers();
106
        }
107
108 54
        if (!isset($this->handlers[$id])) {
109
            throw new RendererException(sprintf(
110
                'El formato para %s no está definido. Los disponibles son: %s.',
111
                $id,
112
                implode(', ', array_keys($this->handlers))
113
            ));
114
        }
115
116 54
        if (is_string($this->handlers[$id]) && str_starts_with($this->handlers[$id], 'alias:')) {
117 50
            [$alias, $handler] = explode(':', $this->handlers[$id], 2);
118
119 50
            if (!isset($this->handlers[$handler])) {
120
                throw new RendererException(sprintf(
121
                    'El alias %s del formato para %s no está definido. Los disponibles son: %s.',
122
                    $handler,
123
                    $id,
124
                    implode(', ', array_keys($this->handlers))
125
                ));
126
            }
127
128 50
            return $this->handlers[$handler];
129
        }
130
131 54
        return $this->handlers[$id];
132
    }
133
134
    /**
135
     * Mapa de campos a handlers para los documentos tributarios electrónicos.
136
     *
137
     * @return array
138
     */
139 54
    private function createHandlers(): array
140
    {
141 54
        return [
142
            // Tipos de documento.
143 54
            'TipoDTE' => $this->entityComponent->getRepository(
144 54
                TipoDocumentoInterface::class
145 54
            ),
146 54
            'TpoDocRef' => 'alias:TipoDTE',
147
            // RUT.
148 54
            'RUTEmisor' => fn (string $rut) => Rut::formatFull($rut),
149 54
            'RUTRecep' => 'alias:RUTEmisor',
150 54
            'RUTSolicita' => 'alias:RUTEmisor',
151 54
            'RUTTrans' => 'alias:RUTEmisor',
152 54
            'RUTChofer' => 'alias:RUTEmisor',
153
            // Comuna.
154 54
            'CdgSIISucur' => fn (string $comuna) =>
155 53
                $this->entityComponent->getRepository(
156 53
                    Comuna::class
157 53
                )->find($comuna)->getDireccionRegional()
158 54
            ,
159 54
            'CiudadOrigen' => fn (string $comuna) =>
160
                $this->entityComponent->getRepository(
161
                    Comuna::class
162
                )->find($comuna)->getCiudad()
163 54
            ,
164 54
            'CiudadRecep' => 'alias:CiudadOrigen',
165
            // Fechas largas.
166 54
            'FchEmis' => function (string $fecha) {
167 54
                $timestamp = strtotime($fecha);
168 54
                return date('d/m/Y', $timestamp); // TODO: Formato largo.
169 54
            },
170 54
            'FchRef' => 'alias:FchEmis',
171 54
            'FchVenc' => 'alias:FchEmis',
172
            // Fechas cortas.
173 54
            'PeriodoDesde' => function (string $fecha) {
174 1
                $timestamp = strtotime($fecha);
175 1
                return date('d/m/Y', $timestamp);
176 54
            },
177 54
            'PeriodoHasta' => 'alias:PeriodoDesde',
178
            // Solo año de una fecha.
179 54
            'FchResol' => fn (string $fecha) => explode('-', $fecha, 2)[0],
180
            // Datos de Aduana.
181 54
            'Aduana' => function (string $tagXmlAndValue) {
182
                [$tagXml, $value] = explode(':', $tagXmlAndValue);
183
                $xmlTagEntity = $this->entityComponent->getRepository(
184
                    TagXml::class
185
                )->find($tagXml);
186
                $name = $xmlTagEntity->getGlosa();
187
                $entityClass = $xmlTagEntity->getEntity();
188
                if ($entityClass) {
189
                    $description = $this->entityComponent->getRepository(
190
                        $entityClass
191
                    )->find($value)->getGlosa();
192
                } else {
193
                    $description = $this->handle($tagXml, $value);
194
                }
195
                if ($name && !in_array($description, [false, null, ''], true)) {
196
                    return $name . ': ' . $description;
197
                }
198
                return '';
199 54
            },
200
            // Otros datos que se mapean de un código a su glosa usando un
201
            // repositorio.
202 54
            'FmaPago' => $this->entityComponent->getRepository(
203 54
                FormaPago::class
204 54
            ),
205 54
            'Nacionalidad' => $this->entityComponent->getRepository(
206 54
                AduanaPais::class
207 54
            ),
208 54
            'CodPaisRecep' => 'alias:Nacionalidad',
209 54
            'IndTraslado' => $this->entityComponent->getRepository(
210 54
                Traslado::class
211 54
            ),
212 54
            'CodViaTransp' => $this->entityComponent->getRepository(
213 54
                AduanaTransporte::class
214 54
            ),
215
            //  Timbre Electrónico del Documento (TED).
216 54
            'TED' => function (string $timbre) {
217 54
                $pdf417 = new TCPDF2DBarcode($timbre, 'PDF417,,5');
218 54
                $png = $pdf417->getBarcodePngData(1, 1, [0,0,0]);
219 54
                return 'data:image/png;base64,' . base64_encode($png);
220 54
            },
221
            // Montos sin decimales.
222 54
            'Number' => function (int|float|string $num) {
223
                $num = round((float) $num);
224
                return number_format($num, 0, ',', '.');
225 54
            },
226
            // Montos según moneda.
227 54
            'MontoMoneda' => function (string $value) {
228
                [$codigo, $num] = explode(':', $value);
229
                $result = $this->entityComponent->getRepository(
230
                    AduanaMoneda::class
231
                )->findBy(['glosa' => $codigo]);
232
                $moneda = ($result[0] ?? null)->getMoneda() ?? Moneda::XXX;
0 ignored issues
show
Bug introduced by
The method getMoneda() 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

232
                $moneda = ($result[0] ?? null)->/** @scrutinizer ignore-call */ getMoneda() ?? Moneda::XXX;

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...
233
                $num = round((float) $num, $moneda->getDecimales());
234
                return number_format($num, $moneda->getDecimales(), ',', '.');
235 54
            },
236 54
        ];
237
    }
238
}
239