Completed
Push — master ( 0803f0...703d5c )
by Esteban De La Fuente
01:58
created

Dte::agregarReferencia()   C

Complexity

Conditions 8
Paths 34

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 18
nc 34
nop 3
1
<?php
2
3
/**
4
 * LibreDTE
5
 * Copyright (C) SASCO SpA (https://sasco.cl)
6
 *
7
 * Este programa es software libre: usted puede redistribuirlo y/o
8
 * modificarlo bajo los términos de la Licencia Pública General Affero de GNU
9
 * publicada por la Fundación para el Software Libre, ya sea la versión
10
 * 3 de la Licencia, o (a su elección) cualquier versión posterior de la
11
 * misma.
12
 *
13
 * Este programa se distribuye con la esperanza de que sea útil, pero
14
 * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita
15
 * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO.
16
 * Consulte los detalles de la Licencia Pública General Affero de GNU para
17
 * obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
22
 */
23
24
namespace sasco\LibreDTE\Sii\PDF;
25
26
/**
27
 * Clase para generar el PDF de un documento tributario electrónico (DTE)
28
 * chileno.
29
 * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
30
 * @version 2017-07-13
31
 */
32
class Dte extends \sasco\LibreDTE\PDF
33
{
34
35
    private $dte; ///< Tipo de DTE que se está generando
36
    private $logo; ///< Datos del logo que se ubicará en el PDF (ruta, datos y/o posición)
37
    private $resolucion; ///< Arreglo con los datos de la resolución (índices: NroResol y FchResol)
38
    private $cedible = false; ///< Por defecto DTEs no son cedibles
39
    protected $papelContinuo = false; ///< Indica si se usa papel continuo o no
40
    private $sinAcuseRecibo = [39, 41, 56, 61, 110, 111, 112]; ///< Boletas, notas de crédito y notas de débito no tienen acuse de recibo
41
    private $web_verificacion = 'www.sii.cl'; ///< Página web para verificar el documento
42
    private $ecl = 5; ///< error correction level para PHP >= 7.0.0
43
44
    private $tipos = [
45
        // códigos oficiales SII
46
        29 => 'FACTURA DE INICIO',
47
        30 => 'FACTURA',
48
        32 => 'FACTURA DE VENTA BIENES Y SERVICIOS NO AFECTOS O EXENTOS DE IVA',
49
        33 => 'FACTURA ELECTRÓNICA',
50
        34 => 'FACTURA NO AFECTA O EXENTA ELECTRÓNICA',
51
        35 => 'BOLETA',
52
        38 => 'BOLETA EXENTA',
53
        39 => 'BOLETA ELECTRÓNICA',
54
        40 => 'LIQUIDACION FACTURA',
55
        41 => 'BOLETA NO AFECTA O EXENTA ELECTRÓNICA',
56
        43 => 'LIQUIDACIÓN FACTURA ELECTRÓNICA',
57
        45 => 'FACTURA DE COMPRA',
58
        46 => 'FACTURA DE COMPRA ELECTRÓNICA',
59
        48 => 'COMPROBANTE DE PAGO ELECTRÓNICO',
60
        50 => 'GUÍA DE DESPACHO',
61
        52 => 'GUÍA DE DESPACHO ELECTRÓNICA',
62
        55 => 'NOTA DE DÉBITO',
63
        56 => 'NOTA DE DÉBITO ELECTRÓNICA',
64
        60 => 'NOTA DE CRÉDITO',
65
        61 => 'NOTA DE CRÉDITO ELECTRÓNICA',
66
        101 => 'FACTURA DE EXPORTACIÓN',
67
        102 => 'FACTURA DE VENTA EXENTA A ZONA FRANCA PRIMARIA',
68
        103 => 'LIQUIDACIÓN',
69
        104 => 'NOTA DE DÉBITO DE EXPORTACIÓN',
70
        105 => 'BOLETA LIQUIDACIÓN',
71
        106 => 'NOTA DE CRÉDITO DE EXPORTACIÓN',
72
        108 => 'SOLICITUD REGISTRO DE FACTURA (SRF)',
73
        109 => 'FACTURA TURISTA',
74
        110 => 'FACTURA DE EXPORTACIÓN ELECTRÓNICA',
75
        111 => 'NOTA DE DÉBITO DE EXPORTACIÓN ELECTRÓNICA',
76
        112 => 'NOTA DE CRÉDITO DE EXPORTACIÓN ELECTRÓNICA',
77
        801 => 'ORDEN DE COMPRA',
78
        802 => 'NOTA DE PEDIDO',
79
        803 => 'CONTRATO',
80
        804 => 'RESOLUCIÓN',
81
        805 => 'PROCEDO CHILECOMPRA',
82
        806 => 'FICHA CHILECOMPRA',
83
        807 => 'DUS',
84
        808 => 'B/L (CONOCIMIENTO DE EMBARQUE)',
85
        809 => 'AWB',
86
        810 => 'MIC (MANIFIESTO INTERNACIONAL)',
87
        811 => 'CARTA DE PORTE',
88
        812 => 'RESOLUCION SNA',
89
        813 => 'PASAPORTE',
90
        814 => 'CERTIFICADO DE DEPÓSITO BOLSA PROD. CHILE',
91
        815 => 'VALE DE PRENDA BOLSA PROD. CHILE',
92
        901 => 'FACTURA DE VENTAS A EMPRESAS DEL TERRITORIO PREFERENCIAL',
93
        902 => 'CONOCIMIENTO DE EMBARQUE',
94
        903 => 'DOCUMENTO ÚNICO DE SALIDA (DUS)',
95
        904 => 'FACTURA DE TRASPASO',
96
        905 => 'FACTURA DE REEXPEDICIÓN',
97
        906 => 'BOLETAS VENTA MÓDULOS ZF (TODAS)',
98
        907 => 'FACTURAS VENTA MÓDULO ZF (TODAS)',
99
        909 => 'FACTURAS VENTA MÓDULO ZF',
100
        910 => 'SOLICITUD TRASLADO ZONA FRANCA (Z)',
101
        911 => 'DECLARACIÓN DE INGRESO A ZONA FRANCA PRIMARIA',
102
        914 => 'DECLARACIÓN DE INGRESO (DIN)',
103
        919 => 'RESUMEN VENTAS DE NACIONALES PASAJES SIN FACTURA',
104
        920 => 'OTROS REGISTROS NO DOCUMENTADOS (AUMENTA DÉBITO)',
105
        922 => 'OTROS REGISTROS (DISMINUYE DÉBITO)',
106
        924 => 'RESUMEN VENTAS DE INTERNACIONALES PASAJES SIN FACTURA',
107
        // códigos de LibreDTE
108
        0 => 'COTIZACIÓN',
109
        'HES' => 'HOJA DE ENTRADA DE SERVICIOS (HES)',
110
    ]; ///< Glosas para los tipos de documentos (DTE y otros)
111
112
    private $formas_pago = [
113
        1 => 'Contado',
114
        2 => 'Crédito',
115
        3 => 'Sin costo',
116
    ]; ///< Glosas de las formas de pago
117
118
    private $formas_pago_exportacion = [
119
        1 => 'Cobranza hasta 1 año',
120
        2 => 'Cobranza más de 1 año',
121
        11 => 'Acreditivo hasta 1 año',
122
        12 => 'Acreditivo más de 1 año',
123
        21 => 'Sin pago',
124
        32 => 'Pago anticipado a la fecha de embarque',
125
    ]; ///< Códigos de forma de pago (básicos) de la aduana para exportaciones
126
127
    private $detalle_cols = [
128
        'CdgItem' => ['title'=>'Código', 'align'=>'left', 'width'=>20],
129
        'NmbItem' => ['title'=>'Item', 'align'=>'left', 'width'=>0],
130
        'IndExe' => ['title'=>'IE', 'align'=>'left', 'width'=>'7'],
131
        'QtyItem' => ['title'=>'Cant.', 'align'=>'right', 'width'=>15],
132
        'UnmdItem' => ['title'=>'Unidad', 'align'=>'left', 'width'=>22],
133
        'PrcItem' => ['title'=>'P. unitario', 'align'=>'right', 'width'=>22],
134
        'DescuentoMonto' => ['title'=>'Descuento', 'align'=>'right', 'width'=>22],
135
        'RecargoMonto' => ['title'=>'Recargo', 'align'=>'right', 'width'=>22],
136
        'MontoItem' => ['title'=>'Total item', 'align'=>'right', 'width'=>22],
137
    ]; ///< Nombres de columnas detalle, alineación y ancho
138
139
    private $item_detalle_posicion = 0; ///< Posición del detalle del item respecto al nombre
140
    private $detalle_fuente = 10; ///< Tamaño de la fuente para el detalle en hoja carta
141
142
    private $traslados = [
143
        1 => 'Operación constituye venta',
144
        2 => 'Ventas por efectuar',
145
        3 => 'Consignaciones',
146
        4 => 'Entrega gratuita',
147
        5 => 'Traslados internos',
148
        6 => 'Otros traslados no venta',
149
        7 => 'Guía de devolución',
150
        8 => 'Traslado para exportación (no venta)',
151
        9 => 'Venta para exportación',
152
    ]; ///< Tipos de traslado para guías de despacho
153
154
    public static $papel = [
155
        0  => 'Hoja carta',
156
        57 => 'Papel contínuo 57mm',
157
        75 => 'Papel contínuo 75mm',
158
        80 => 'Papel contínuo 80mm',
159
    ]; ///< Tamaño de papel que es soportado
160
161
    /**
162
     * Constructor de la clase
163
     * @param papelContinuo =true indica que el PDF se generará en formato papel continuo (si se pasa un número será el ancho del PDF en mm)
164
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
165
     * @version 2016-10-06
166
     */
167
    public function __construct($papelContinuo = false)
168
    {
169
        parent::__construct();
170
        $this->SetTitle('Documento Tributario Electrónico (DTE) de Chile by LibreDTE');
171
        $this->papelContinuo = $papelContinuo === true ? 80 : $papelContinuo;
0 ignored issues
show
Documentation Bug introduced by
It seems like $papelContinuo === true ? 80 : $papelContinuo can also be of type integer. However, the property $papelContinuo is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
172
    }
173
174
    /**
175
     * Método que asigna la ubicación del logo de la empresa
176
     * @param logo URI del logo (puede ser local o en una URL)
177
     * @param posicion Posición respecto a datos del emisor (=0 izq, =1 arriba)
178
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
179
     * @version 2016-08-04
180
     */
181
    public function setLogo($logo, $posicion = 0)
182
    {
183
        $this->logo = [
184
            'uri' => $logo,
185
            'posicion' => (int)$posicion,
186
        ];
187
    }
188
189
    /**
190
     * Método que asigna los datos de la resolución del SII que autoriza al
191
     * emisor a emitir DTEs
192
     * @param resolucion Arreglo con índices NroResol y FchResol
193
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
194
     * @version 2015-09-08
195
     */
196
    public function setResolucion(array $resolucion)
197
    {
198
        $this->resolucion = $resolucion;
199
    }
200
201
    /**
202
     * Método que asigna la página web que se debe utilizar para indicar donde
203
     * se puede verificar el DTE
204
     * @param web Página web donde se puede verificar el documento
205
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
206
     * @version 2015-12-11
207
     */
208
    public function setWebVerificacion($web)
209
    {
210
        $this->web_verificacion = $web;
0 ignored issues
show
Documentation Bug introduced by
It seems like $web of type object<sasco\LibreDTE\Sii\PDF\Página> is incompatible with the declared type string of property $web_verificacion.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
211
    }
212
213
    /**
214
     * Método que indica si el documento será o no cedible
215
     * @param cedible =true se incorporará leyenda de destino
216
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
217
     * @version 2015-09-09
218
     */
219
    public function setCedible($cedible = true)
220
    {
221
        $this->cedible = $cedible;
222
    }
223
224
    /**
225
     * Método que asigna la posición del detalle del Item respecto al nombre
226
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
227
     * @version 2016-08-05
228
     */
229
    public function setPosicionDetalleItem($posicion)
230
    {
231
        $this->item_detalle_posicion = (int)$posicion;
232
    }
233
234
    /**
235
     * Método que asigna el tamaño de la fuente para el detalle
236
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
237
     * @version 2016-08-03
238
     */
239
    public function setFuenteDetalle($fuente)
240
    {
241
        $this->detalle_fuente = (int)$fuente;
242
    }
243
244
    /**
245
     * Método que asigna el ancho e las columnas del detalle desde un arreglo
246
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
247
     * @version 2016-08-03
248
     */
249
    public function setAnchoColumnasDetalle(array $anchos)
250
    {
251
        foreach ($anchos as $col => $ancho) {
252
            if (isset($this->detalle_cols[$col]) and $ancho) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
253
                $this->detalle_cols[$col]['width'] = (int)$ancho;
254
            }
255
        }
256
    }
257
258
    /**
259
     * Método que agrega un documento tributario, ya sea en formato de una
260
     * página o papel contínuo según se haya indicado en el constructor
261
     * @param dte Arreglo con los datos del XML (tag Documento)
262
     * @param timbre String XML con el tag TED del DTE
263
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
264
     * @version 2017-07-13
265
     */
266
    public function agregar(array $dte, $timbre = null)
267
    {
268
        $this->dte = $dte['Encabezado']['IdDoc']['TipoDTE'];
269
        // papel hoja carta
270
        if (!$this->papelContinuo) {
271
            $this->agregarNormal($dte, $timbre);
272
        }
273
        // papel contínuo 57mm
274
        else if ($this->papelContinuo==57) {
275
            $this->agregarContinuo57($dte, $timbre);
276
        }
277
        // papel contínuo 75 o 80mm
278
        else {
279
            $this->agregarContinuo($dte, $timbre, $this->papelContinuo);
280
        }
281
    }
282
283
    /**
284
     * Método que agrega una página con el documento tributario
285
     * @param dte Arreglo con los datos del XML (tag Documento)
286
     * @param timbre String XML con el tag TED del DTE
287
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
288
     * @version 2017-06-15
289
     */
290
    private function agregarNormal(array $dte, $timbre)
291
    {
292
        // agregar página para la factura
293
        $this->AddPage();
294
        // agregar cabecera del documento
295
        $y[] = $this->agregarEmisor($dte['Encabezado']['Emisor']);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$y was never initialized. Although not strictly required by PHP, it is generally a good practice to add $y = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
296
        $y[] = $this->agregarFolio(
297
            $dte['Encabezado']['Emisor']['RUTEmisor'],
298
            $dte['Encabezado']['IdDoc']['TipoDTE'],
299
            $dte['Encabezado']['IdDoc']['Folio'],
300
            $dte['Encabezado']['Emisor']['CmnaOrigen']
301
        );
302
        // datos del documento
303
        $this->setY(max($y));
304
        $this->Ln();
305
        $y = [];
306
        $y[] = $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null);
307
        $y[] = $this->agregarReceptor($dte['Encabezado']);
308
        $this->setY(max($y));
309
        $this->agregarTraslado(
310
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
311
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null
312
        );
313
        if (!empty($dte['Referencia']))
314
            $this->agregarReferencia($dte['Referencia']);
315
        $this->agregarDetalle($dte['Detalle']);
316
        if (!empty($dte['DscRcgGlobal'])) {
317
            $this->agregarSubTotal($dte['Detalle']);
318
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal']);
319
        }
320 View Code Duplication
        if (!empty($dte['Encabezado']['IdDoc']['MntPagos']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos']);
322
        $this->agregarTotales($dte['Encabezado']['Totales']);
323
        // agregar observaciones
324
        $this->agregarObservacion($dte['Encabezado']['IdDoc']);
325
        // agregar timbre
326
        $this->agregarTimbre($timbre);
327
        // agregar acuse de recibo y leyenda cedible
328
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
329
            $this->agregarAcuseRecibo();
330
            $this->agregarLeyendaDestino($dte['Encabezado']['IdDoc']['TipoDTE']);
331
        }
332
    }
333
334
    /**
335
     * Método que agrega una página con el documento tributario en papel
336
     * contínuo
337
     * @param dte Arreglo con los datos del XML (tag Documento)
338
     * @param timbre String XML con el tag TED del DTE
339
     * @param width Ancho del papel contínuo en mm
340
     * @author Pablo Reyes (https://github.com/pabloxp)
341
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
342
     * @version 2017-06-15
343
     */
344
    private function agregarContinuo(array $dte, $timbre, $width)
345
    {
346
        $this->logo = null;
347
        $x_start = 1;
348
        $y_start = 1;
349
        $offset = 14;
350
        // determinar alto de la página y agregarla
351
        $height = 145;
352
        $n_detalle = count($dte['Detalle']);
353
        if ($n_detalle>1) $height += $n_detalle*20;
354
        if ($this->cedible) $height += 50;
355
        $this->AddPage('P', [$height, $width]);
356
        // agregar cabecera del documento
357
        $y = $this->agregarFolio(
358
            $dte['Encabezado']['Emisor']['RUTEmisor'],
359
            $dte['Encabezado']['IdDoc']['TipoDTE'],
360
            $dte['Encabezado']['IdDoc']['Folio'],
361
            $dte['Encabezado']['Emisor']['CmnaOrigen'],
362
            $x_start, $y_start, $width-($x_start*4), 10,
363
            [0,0,0]
364
        );
365
        $y = $this->agregarEmisor($dte['Encabezado']['Emisor'], $x_start, $y+2, 40, 8, 9, [0,0,0]);
366
        // datos del documento
367
        $this->SetY($y);
368
        $this->Ln();
369
        $this->setFont('', '', 8);
370
        $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null, $x_start, $offset, false);
371
        $this->agregarReceptor($dte['Encabezado'], $x_start, $offset);
372
        $this->agregarTraslado(
373
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
374
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null,
375
            $x_start, $offset
376
        );
377
        if (!empty($dte['Referencia'])) {
378
            $this->agregarReferencia($dte['Referencia'], $x_start, $offset);
379
        }
380
        $this->Ln();
381
        $this->agregarDetalleContinuo($dte['Detalle']);
382
        if (!empty($dte['DscRcgGlobal'])) {
383
            $this->Ln();
384
            $this->Ln();
385
            $this->agregarSubTotal($dte['Detalle'], $x_start);
386
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal'], $x_start);
387
        }
388 View Code Duplication
        if (!empty($dte['Encabezado']['IdDoc']['MntPagos'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
389
            $this->Ln();
390
            $this->Ln();
391
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos'], $x_start);
392
        }
393
        $this->agregarTotales($dte['Encabezado']['Totales'], $this->y+6, 23, 17);
394
        // agregar acuse de recibo y leyenda cedible
395 View Code Duplication
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
396
            $this->agregarAcuseReciboContinuo(3, $this->y+6, 68, 34);
397
            $this->agregarLeyendaDestino($dte['Encabezado']['IdDoc']['TipoDTE'], $this->y+6, 8);
398
        }
399
        // agregar timbre
400
        $y = $this->agregarObservacion($dte['Encabezado']['IdDoc'], $x_start, $this->y+6);
401
        $this->agregarTimbre($timbre, 0, $x_start, $y+6, 70, 6);
402
    }
403
404
    /**
405
     * Método que agrega una página con el documento tributario
406
     * @param dte Arreglo con los datos del XML (tag Documento)
407
     * @param timbre String XML con el tag TED del DTE
408
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
409
     * @version 2017-07-13
410
     */
411
    private function agregarContinuo57(array $dte, $timbre, $width = 57)
412
    {
413
        // determinar alto de la página y agregarla
414
        $height = 100;
415
        if ($this->cedible) $height += 50;
416
        if ($dte['Encabezado']['Receptor']['RUTRecep']!='66666666-6') $height += 40;
417
        $this->AddPage('P', [$height, $width]);
418
        $x = 1;
419
        $y = 5;
420
        $this->SetXY($x,$y);
421
        // agregar datos del documento
422
        $this->setFont('', '', 8);
423
        $this->MultiTexto(!empty($dte['Encabezado']['Emisor']['RznSoc']) ? $dte['Encabezado']['Emisor']['RznSoc'] : $dte['Encabezado']['Emisor']['RznSocEmisor'], $x, null, '', $width-2);
424
        $this->MultiTexto($dte['Encabezado']['Emisor']['RUTEmisor'], $x, null, '', $width-2);
425
        $this->MultiTexto('Giro: '.(!empty($dte['Encabezado']['Emisor']['GiroEmis']) ? $dte['Encabezado']['Emisor']['GiroEmis'] : $dte['Encabezado']['Emisor']['GiroEmisor']), $x, null, '', $width-2);
426
        $this->MultiTexto($dte['Encabezado']['Emisor']['DirOrigen'].', '.$dte['Encabezado']['Emisor']['CmnaOrigen'], $x, null, '', $width-2);
427
        $this->MultiTexto($this->getTipo($dte['Encabezado']['IdDoc']['TipoDTE']).' N° '.$dte['Encabezado']['IdDoc']['Folio'], $x, null, '', $width-2);
428
        $this->MultiTexto('Fecha: '.date('d/m/Y', strtotime($dte['Encabezado']['IdDoc']['FchEmis'])), $x, null, '', $width-2);
429
        // si no es boleta no nominativa se agregan datos receptor
430
        if ($dte['Encabezado']['Receptor']['RUTRecep']!='66666666-6') {
431
            $this->Ln();
432
            $this->MultiTexto('Receptor: '.$dte['Encabezado']['Receptor']['RUTRecep'], $x, null, '', $width-2);
433
            $this->MultiTexto($dte['Encabezado']['Receptor']['RznSocRecep'], $x, null, '', $width-2);
434
            if (!empty($dte['Encabezado']['Receptor']['GiroRecep'])) {
435
                $this->MultiTexto('Giro: '.$dte['Encabezado']['Receptor']['GiroRecep'], $x, null, '', $width-2);
436
            }
437
            if (!empty($dte['Encabezado']['Receptor']['DirRecep'])) {
438
                $this->MultiTexto($dte['Encabezado']['Receptor']['DirRecep'].', '.$dte['Encabezado']['Receptor']['CmnaRecep'], $x, null, '', $width-2);
439
            }
440
            $this->Ln();
441
        }
442
        // hay un sólo detalle
443
        if (!isset($dte['Detalle'][0])) {
444
            $this->MultiTexto($dte['Detalle']['NmbItem'].': $'.$this->num($dte['Detalle']['MontoItem']), $x, null, '', $width-2);
445
        }
446
        // hay más de un detalle
447
        else {
448
            foreach ($dte['Detalle'] as $d) {
449
                $this->MultiTexto($d['NmbItem'].': $'.$this->num($d['MontoItem']), $x, null, '', $width-2);
450
            }
451
            if (in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
452
                $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
453
            }
454
        }
455
        // si no es boleta se coloca EXENTO, NETO, IVA y TOTAL si corresponde
456
        if (!in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
457 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['MntExe'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
458
                $this->MultiTexto('EXENTO: $'.$this->num($dte['Encabezado']['Totales']['MntExe']), $x, null, '', $width-2);
459
            }
460 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['MntNeto'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
461
                $this->MultiTexto('NETO: $'.$this->num($dte['Encabezado']['Totales']['MntNeto']), $x, null, '', $width-2);
462
            }
463 View Code Duplication
            if (!empty($dte['Encabezado']['Totales']['IVA'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
464
                $this->MultiTexto('IVA: $'.$this->num($dte['Encabezado']['Totales']['IVA']), $x, null, '', $width-2);
465
            }
466
            $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
467
        }
468
        // agregar acuse de recibo y leyenda cedible
469 View Code Duplication
        if ($this->cedible and !in_array($dte['Encabezado']['IdDoc']['TipoDTE'], $this->sinAcuseRecibo)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
470
            $this->agregarAcuseReciboContinuo(-1, $this->y+6, $width+2, 34);
471
            $this->agregarLeyendaDestino($dte['Encabezado']['IdDoc']['TipoDTE'], $this->y+6, 8);
472
        }
473
        // agregar timbre
474
        $this->agregarTimbre($timbre, 0, $x, $this->GetY()+6, 55, 6);
475
    }
476
477
    /**
478
     * Método que agrega los datos de la empresa
479
     * Orden de los datos:
480
     *  - Razón social del emisor
481
     *  - Giro del emisor (sin abreviar)
482
     *  - Dirección casa central del emisor
483
     *  - Dirección sucursales
484
     * @param emisor Arreglo con los datos del emisor (tag Emisor del XML)
485
     * @param x Posición horizontal de inicio en el PDF
486
     * @param y Posición vertical de inicio en el PDF
487
     * @param w Ancho de la información del emisor
488
     * @param w_img Ancho máximo de la imagen
489
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
490
     * @version 2016-12-02
491
     */
492
    private function agregarEmisor(array $emisor, $x = 10, $y = 15, $w = 75, $w_img = 30, $font_size = null, array $color = null)
493
    {
494
        // logo del documento
495
        if (isset($this->logo)) {
496
            $this->Image(
497
                $this->logo['uri'],
498
                $x,
499
                $y,
500
                !$this->logo['posicion']?$w_img:null, $this->logo['posicion']?($w_img/2):null,
501
                'PNG',
502
                (isset($emisor['url'])?$emisor['url']:''),
503
                'T'
504
            );
505
            if ($this->logo['posicion']) {
506
                $this->SetY($this->y + ($w_img/2));
507
                $w += 40;
508
            } else {
509
                $x = $this->x+3;
510
            }
511
        } else {
512
            $this->y = $y-2;
513
            $w += 40;
514
        }
515
        // agregar datos del emisor
516
        $this->setFont('', 'B', $font_size ? $font_size : 14);
517
        $this->SetTextColorArray($color===null?[32, 92, 144]:$color);
518
        $this->MultiTexto(!empty($emisor['RznSoc']) ? $emisor['RznSoc'] : $emisor['RznSocEmisor'], $x, $this->y+2, 'L', $w);
519
        $this->setFont('', 'B', $font_size ? $font_size : 9);
520
        $this->SetTextColorArray([0,0,0]);
521
        $this->MultiTexto(!empty($emisor['GiroEmis']) ? $emisor['GiroEmis'] : $emisor['GiroEmisor'], $x, $this->y, 'L', $w);
522
        $ciudad = !empty($emisor['CiudadOrigen']) ? $emisor['CiudadOrigen'] : \sasco\LibreDTE\Chile::getCiudad($emisor['CmnaOrigen']);
523
        $this->MultiTexto($emisor['DirOrigen'].', '.$emisor['CmnaOrigen'].($ciudad?(', '.$ciudad):''), $x, $this->y, 'L', $w);
524
        if (!empty($emisor['Sucursal'])) {
525
            $this->MultiTexto('Sucursal: '.$emisor['Sucursal'], $x, $this->y, 'L', $w);
526
        }
527
        $contacto = [];
528
        if (!empty($emisor['Telefono'])) {
529
            if (!is_array($emisor['Telefono']))
530
                $emisor['Telefono'] = [$emisor['Telefono']];
531
            foreach ($emisor['Telefono'] as $t)
532
                $contacto[] = $t;
533
        }
534
        if (!empty($emisor['CorreoEmisor'])) {
535
            $contacto[] = $emisor['CorreoEmisor'];
536
        }
537
        if ($contacto) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contacto of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
538
            $this->MultiTexto(implode(' / ', $contacto), $x, $this->y, 'L', $w);
539
        }
540
        return $this->y;
541
    }
542
543
    /**
544
     * Método que agrega el recuadro con el folio
545
     * Recuadro:
546
     *  - Tamaño mínimo 1.5x5.5 cms
547
     *  - En lado derecho (negro o rojo)
548
     *  - Enmarcado por una línea de entre 0.5 y 1 mm de espesor
549
     *  - Tamaño máximo 4x8 cms
550
     *  - Letras tamaño 10 o superior en mayúsculas y negritas
551
     *  - Datos del recuadro: RUT emisor, nombre de documento en 2 líneas,
552
     *    folio.
553
     *  - Bajo el recuadro indicar la Dirección regional o Unidad del SII a la
554
     *    que pertenece el emisor
555
     * @param rut RUT del emisor
556
     * @param tipo Código o glosa del tipo de documento
557
     * @param sucursal_sii Código o glosa de la sucursal del SII del Emisor
558
     * @param x Posición horizontal de inicio en el PDF
559
     * @param y Posición vertical de inicio en el PDF
560
     * @param w Ancho de la información del emisor
561
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
562
     * @version 2016-12-02
563
     */
564
    private function agregarFolio($rut, $tipo, $folio, $sucursal_sii = null, $x = 130, $y = 15, $w = 70, $font_size = null, array $color = null)
565
    {
566
        if ($color===null) {
567
            $color = $tipo ? ($tipo==52 ? [0,172,140] : [255,0,0]) : [0,0,0];
568
        }
569
        $this->SetTextColorArray($color);
570
        // colocar rut emisor, glosa documento y folio
571
        list($rut, $dv) = explode('-', $rut);
572
        $this->setFont ('', 'B', $font_size ? $font_size : 15);
573
        $this->MultiTexto('R.U.T.: '.$this->num($rut).'-'.$dv, $x, $y+4, 'C', $w);
574
        $this->setFont('', 'B', $font_size ? $font_size : 12);
575
        $this->MultiTexto($this->getTipo($tipo), $x, null, 'C', $w);
576
        $this->setFont('', 'B', $font_size ? $font_size : 15);
577
        $this->MultiTexto('N° '.$folio, $x, null, 'C', $w);
578
        // dibujar rectángulo rojo
579
        $this->Rect($x, $y, $w, round($this->getY()-$y+3), 'D', ['all' => ['width' => 0.5, 'color' => $color]]);
580
        // colocar unidad del SII
581
        $this->setFont('', 'B', $font_size ? $font_size : 10);
582
        if ($tipo) {
583
            $this->Texto('S.I.I. - '.\sasco\LibreDTE\Sii::getDireccionRegional($sucursal_sii), $x, $this->getY()+4, 'C', $w);
0 ignored issues
show
Bug introduced by
It seems like $sucursal_sii defined by parameter $sucursal_sii on line 564 can also be of type null; however, sasco\LibreDTE\Sii::getDireccionRegional() does only seem to accept object<sasco\LibreDTE\de>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
584
        }
585
        $this->SetTextColorArray([0,0,0]);
586
        $this->Ln();
587
        return $this->y;
588
    }
589
590
    /**
591
     * Método que entrega la glosa del tipo de documento
592
     * @param tipo Código del tipo de documento
593
     * @return Glosa del tipo de documento
594
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
595
     * @version 2016-11-18
596
     */
597
    private function getTipo($tipo)
598
    {
599
        if (!is_numeric($tipo) and !isset($this->tipos[$tipo]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
600
            return $tipo;
601
        return isset($this->tipos[$tipo]) ? strtoupper($this->tipos[$tipo]) : 'Documento '.$tipo;
602
    }
603
604
    /**
605
     * Método que agrega los datos de la emisión del DTE que no son los dato del
606
     * receptor
607
     * @param IdDoc Información general del documento
608
     * @param x Posición horizontal de inicio en el PDF
609
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
610
     * @version 2017-06-15
611
     */
612
    private function agregarDatosEmision($IdDoc, $CdgVendedor, $x = 10, $offset = 22, $mostrar_dia = true)
613
    {
614
        // si es hoja carta
615
        if ($x==10) {
616
            $y = $this->GetY();
617
            // fecha emisión
618
            $this->setFont('', 'B', null);
619
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x, null, 'R');
620
            $this->setFont('', '', null);
621
            // período facturación
622
            if (!empty($IdDoc['PeriodoDesde']) and !empty($IdDoc['PeriodoHasta'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
623
                $this->MultiTexto('Período del '.date('d/m/y', strtotime($IdDoc['PeriodoDesde'])).' al '.date('d/m/y', strtotime($IdDoc['PeriodoHasta'])), $x, null, 'R');
624
            }
625
            // pago anticicado
626 View Code Duplication
            if (!empty($IdDoc['FchCancel'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
627
                $this->MultiTexto('Pagado el '.$this->date($IdDoc['FchCancel'], false), $x, null, 'R');
628
            }
629
            // fecha vencimiento
630 View Code Duplication
            if (!empty($IdDoc['FchVenc'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
                $this->MultiTexto('Vence el '.$this->date($IdDoc['FchVenc'], false), $x, null, 'R');
632
            }
633
            // forma de pago nacional
634 View Code Duplication
            if (!empty($IdDoc['FmaPago'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
635
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago[$IdDoc['FmaPago']]), $x, null, 'R');
636
            }
637
            // forma de pago exportación
638 View Code Duplication
            if (!empty($IdDoc['FmaPagExp'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
639
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago_exportacion[$IdDoc['FmaPagExp']]), $x, null, 'R');
640
            }
641
            // vendedor
642
            if (!empty($CdgVendedor)) {
643
                $this->MultiTexto('Vendedor: '.$CdgVendedor, $x, null, 'R');
644
            }
645
            $y_end = $this->GetY();
646
            $this->SetY($y);
647
        }
648
        // papel contínuo
649
        else {
650
            // fecha de emisión
651
            $this->setFont('', 'B', null);
652
            $this->Texto('Emisión', $x);
653
            $this->Texto(':', $x+$offset);
654
            $this->setFont('', '', null);
655
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x+$offset+2);
656
            // forma de pago nacional
657
            if (!empty($IdDoc['FmaPago'])) {
658
                $this->setFont('', 'B', null);
659
                $this->Texto('Venta', $x);
660
                $this->Texto(':', $x+$offset);
661
                $this->setFont('', '', null);
662
                $this->MultiTexto($this->formas_pago[$IdDoc['FmaPago']], $x+$offset+2);
663
            }
664
            // forma de pago exportación
665
            if (!empty($IdDoc['FmaPagExp'])) {
666
                $this->setFont('', 'B', null);
667
                $this->Texto('Venta', $x);
668
                $this->Texto(':', $x+$offset);
669
                $this->setFont('', '', null);
670
                $this->MultiTexto($this->formas_pago_exportacion[$IdDoc['FmaPagExp']], $x+$offset+2);
671
            }
672
            // pago anticicado
673
            if (!empty($IdDoc['FchCancel'])) {
674
                $this->setFont('', 'B', null);
675
                $this->Texto('Pagado el', $x);
676
                $this->Texto(':', $x+$offset);
677
                $this->setFont('', '', null);
678
                $this->MultiTexto($this->date($IdDoc['FchCancel'], $mostrar_dia), $x+$offset+2);
679
            }
680
            // fecha vencimiento
681
            if (!empty($IdDoc['FchVenc'])) {
682
                $this->setFont('', 'B', null);
683
                $this->Texto('Vence el', $x);
684
                $this->Texto(':', $x+$offset);
685
                $this->setFont('', '', null);
686
                $this->MultiTexto($this->date($IdDoc['FchVenc'], $mostrar_dia), $x+$offset+2);
687
            }
688
            $y_end = $this->GetY();
689
        }
690
        return $y_end;
691
    }
692
693
    /**
694
     * Método que agrega los datos del receptor
695
     * @param receptor Arreglo con los datos del receptor (tag Receptor del XML)
696
     * @param x Posición horizontal de inicio en el PDF
697
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
698
     * @version 2017-06-15
699
     */
700
    private function agregarReceptor(array $Encabezado, $x = 10, $offset = 22)
701
    {
702
        $receptor = $Encabezado['Receptor'];
703 View Code Duplication
        if (!empty($receptor['RUTRecep']) and $receptor['RUTRecep']!='66666666-6') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
704
            list($rut, $dv) = explode('-', $receptor['RUTRecep']);
705
            $this->setFont('', 'B', null);
706
            $this->Texto('R.U.T.', $x);
707
            $this->Texto(':', $x+$offset);
708
            $this->setFont('', '', null);
709
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
710
        }
711 View Code Duplication
        if (!empty($receptor['RznSocRecep'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
712
            $this->setFont('', 'B', null);
713
            $this->Texto('Señor(es)', $x);
714
            $this->Texto(':', $x+$offset);
715
            $this->setFont('', '', null);
716
            $this->MultiTexto($receptor['RznSocRecep'], $x+$offset+2, null, '', $x==10?105:0);
717
        }
718 View Code Duplication
        if (!empty($receptor['GiroRecep'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
719
            $this->setFont('', 'B', null);
720
            $this->Texto('Giro', $x);
721
            $this->Texto(':', $x+$offset);
722
            $this->setFont('', '', null);
723
            $this->MultiTexto($receptor['GiroRecep'], $x+$offset+2);
724
        }
725
        if (!empty($receptor['DirRecep'])) {
726
            $this->setFont('', 'B', null);
727
            $this->Texto('Dirección', $x);
728
            $this->Texto(':', $x+$offset);
729
            $this->setFont('', '', null);
730
            $ciudad = !empty($receptor['CiudadRecep']) ? $receptor['CiudadRecep'] : (
731
                !empty($receptor['CmnaRecep']) ? \sasco\LibreDTE\Chile::getCiudad($receptor['CmnaRecep']) : ''
732
            );
733
            $this->MultiTexto($receptor['DirRecep'].(!empty($receptor['CmnaRecep'])?(', '.$receptor['CmnaRecep']):'').($ciudad?(', '.$ciudad):''), $x+$offset+2);
734
        }
735
        if (!empty($receptor['Extranjero']['Nacionalidad'])) {
736
            $this->setFont('', 'B', null);
737
            $this->Texto('Nacionalidad', $x);
738
            $this->Texto(':', $x+$offset);
739
            $this->setFont('', '', null);
740
            $this->MultiTexto(\sasco\LibreDTE\Sii\Aduana::getNacionalidad($receptor['Extranjero']['Nacionalidad']), $x+$offset+2);
741
        }
742 View Code Duplication
        if (!empty($receptor['Extranjero']['NumId'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
743
            $this->setFont('', 'B', null);
744
            $this->Texto('N° ID extranj.', $x);
745
            $this->Texto(':', $x+$offset);
746
            $this->setFont('', '', null);
747
            $this->MultiTexto($receptor['Extranjero']['NumId'], $x+$offset+2);
748
        }
749
        $contacto = [];
750
        if (!empty($receptor['Contacto']))
751
            $contacto[] = $receptor['Contacto'];
752
        if (!empty($receptor['CorreoRecep']))
753
            $contacto[] = $receptor['CorreoRecep'];
754 View Code Duplication
        if (!empty($contacto)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
755
            $this->setFont('', 'B', null);
756
            $this->Texto('Contacto', $x);
757
            $this->Texto(':', $x+$offset);
758
            $this->setFont('', '', null);
759
            $this->MultiTexto(implode(' / ', $contacto), $x+$offset+2);
760
        }
761 View Code Duplication
        if (!empty($Encabezado['RUTSolicita'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
762
            list($rut, $dv) = explode('-', $Encabezado['RUTSolicita']);
763
            $this->setFont('', 'B', null);
764
            $this->Texto('RUT solicita', $x);
765
            $this->Texto(':', $x+$offset);
766
            $this->setFont('', '', null);
767
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
768
        }
769 View Code Duplication
        if (!empty($receptor['CdgIntRecep'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
770
            $this->setFont('', 'B', null);
771
            $this->Texto('Cód. recep.', $x);
772
            $this->Texto(':', $x+$offset);
773
            $this->setFont('', '', null);
774
            $this->MultiTexto($receptor['CdgIntRecep'], $x+$offset+2, null, '', $x==10?105:0);
775
        }
776
        return $this->GetY();
777
    }
778
779
    /**
780
     * Método que agrega los datos del traslado
781
     * @param IndTraslado
782
     * @param Transporte
783
     * @param x Posición horizontal de inicio en el PDF
784
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
785
     * @version 2016-08-03
786
     */
787
    private function agregarTraslado($IndTraslado, array $Transporte = null, $x = 10, $offset = 22)
788
    {
789
        // agregar tipo de traslado
790 View Code Duplication
        if ($IndTraslado) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
791
            $this->setFont('', 'B', null);
792
            $this->Texto('Tipo oper.', $x);
793
            $this->Texto(':', $x+$offset);
794
            $this->setFont('', '', null);
795
            $this->MultiTexto($this->traslados[$IndTraslado], $x+$offset+2);
796
        }
797
        // agregar información de transporte
798
        if ($Transporte) {
799
            $transporte = '';
800
            if (!empty($Transporte['DirDest']) and !empty($Transporte['CmnaDest'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
801
                $transporte .= 'a '.$Transporte['DirDest'].', '.$Transporte['CmnaDest'];
802
            }
803
            if (!empty($Transporte['RUTTrans']))
804
                $transporte .= ' por '.$Transporte['RUTTrans'];
805
            if (!empty($Transporte['Patente']))
806
                $transporte .= ' en vehículo '.$Transporte['Patente'];
807
            if (isset($Transporte['Chofer']) and is_array($Transporte['Chofer'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
808 View Code Duplication
                if (!empty($Transporte['Chofer']['NombreChofer']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
809
                    $transporte .= ' con chofer '.$Transporte['Chofer']['NombreChofer'];
810 View Code Duplication
                if (!empty($Transporte['Chofer']['RUTChofer']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
811
                    $transporte .= ' ('.$Transporte['Chofer']['RUTChofer'].')';
812
            }
813 View Code Duplication
            if ($transporte) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
814
                $this->setFont('', 'B', null);
815
                $this->Texto('Traslado', $x);
816
                $this->Texto(':', $x+$offset);
817
                $this->setFont('', '', null);
818
                $this->MultiTexto(ucfirst(trim($transporte)), $x+$offset+2);
819
            }
820
        }
821
        // agregar información de aduana
822
        if (!empty($Transporte['Aduana']) and is_array($Transporte['Aduana'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
823
            $col = 0;
824
            foreach ($Transporte['Aduana'] as $tag => $codigo) {
825
                if ($codigo===false)
826
                    continue;
827
                $glosa = \sasco\LibreDTE\Sii\Aduana::getGlosa($tag);
828
                $valor = \sasco\LibreDTE\Sii\Aduana::getValor($tag, $codigo);
829
                if ($glosa!==false and $valor!==false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
830
                    if ($tag=='TipoBultos' and $col) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
831
                        $col = abs($col-110);
832
                        $this->Ln();
833
                    }
834
                    $this->setFont('', 'B', null);
835
                    $this->Texto($glosa, $x+$col);
836
                    $this->Texto(':', $x+$offset+$col);
837
                    $this->setFont('', '', null);
838
                    $this->Texto($valor, $x+$offset+2+$col);
839
                    if ($tag=='TipoBultos')
840
                        $col = abs($col-110);
841
                    if ($col)
842
                        $this->Ln();
843
                    $col = abs($col-110);
844
                }
845
            }
846
            if ($col)
847
                $this->Ln();
848
        }
849
    }
850
851
    /**
852
     * Método que agrega las referencias del documento
853
     * @param referencias Arreglo con las referencias del documento (tag Referencia del XML)
854
     * @param x Posición horizontal de inicio en el PDF
855
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
856
     * @version 2017-08-17
857
     */
858
    private function agregarReferencia($referencias, $x = 10, $offset = 22)
859
    {
860
        if (!isset($referencias[0]))
861
            $referencias = [$referencias];
862
        foreach($referencias as $r) {
863
            $texto = $r['NroLinRef'].' - ';
864
            if (!empty($r['TpoDocRef'])) {
865
                $texto .= $this->getTipo($r['TpoDocRef']).' ';
866
            }
867
            if (!empty($r['FolioRef'])) {
868
                $texto .= ' N° '.$r['FolioRef'].' ';
869
            }
870
            if (!empty($r['FchRef'])) {
871
                $texto .= 'del '.$r['FchRef'];
872
            }
873
            if (isset($r['RazonRef']) and $r['RazonRef']!==false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
874
                $texto = $texto.': '.$r['RazonRef'];
875
            }
876
            $this->setFont('', 'B', null);
877
            $this->Texto('Referencia', $x);
878
            $this->Texto(':', $x+$offset);
879
            $this->setFont('', '', null);
880
            $this->MultiTexto($texto, $x+$offset+2);
881
        }
882
    }
883
884
    /**
885
     * Método que agrega el detalle del documento
886
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
887
     * @param x Posición horizontal de inicio en el PDF
888
     * @param y Posición vertical de inicio en el PDF
889
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
890
     * @version 2016-08-05
891
     */
892
    private function agregarDetalle($detalle, $x = 10)
893
    {
894
        if (!isset($detalle[0]))
895
            $detalle = [$detalle];
896
        $this->setFont('', '', $this->detalle_fuente);
897
        // titulos
898
        $titulos = [];
899
        $titulos_keys = array_keys($this->detalle_cols);
900
        foreach ($this->detalle_cols as $key => $info) {
901
            $titulos[$key] = $info['title'];
902
        }
903
        // normalizar cada detalle
904
        $dte_exento = in_array($this->dte, [34, 110, 111, 112]);
905
        foreach ($detalle as &$item) {
906
            // quitar columnas
907
            foreach ($item as $col => $valor) {
908
                if ($col=='DscItem' and !empty($item['DscItem'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
909
                    $item['NmbItem'] .= !$this->item_detalle_posicion ? '<br/>' : ': ';
910
                    $item['NmbItem'] .= '<span style="font-size:0.7em">'.$item['DscItem'].'</span>';
911
                }
912
                if (!in_array($col, $titulos_keys) or ($dte_exento and $col=='IndExe'))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
913
                    unset($item[$col]);
914
            }
915
            // ajustes a IndExe
916
            if (isset($item['IndExe'])) {
917
                if ($item['IndExe']==1)
918
                    $item['IndExe'] = 'EX';
919
                else if ($item['IndExe']==2)
920
                    $item['IndExe'] = 'NF';
921
            }
922
            // agregar todas las columnas que se podrían imprimir en la tabla
923
            $item_default = [];
924
            foreach ($this->detalle_cols as $key => $info)
925
                $item_default[$key] = false;
926
            $item = array_merge($item_default, $item);
927
            // si hay código de item se extrae su valor
928
            if ($item['CdgItem'])
929
                $item['CdgItem'] = $item['CdgItem']['VlrCodigo'];
930
            // dar formato a números
931
            foreach (['QtyItem', 'PrcItem', 'DescuentoMonto', 'RecargoMonto', 'MontoItem'] as $col) {
932
                if ($item[$col])
933
                    $item[$col] = $this->num($item[$col]);
934
            }
935
        }
936
        // opciones
937
        $options = ['align'=>[]];
938
        $i = 0;
939
        foreach ($this->detalle_cols as $info) {
940
            if (isset($info['width']))
941
                $options['width'][$i] = $info['width'];
942
            $options['align'][$i] = $info['align'];
943
            $i++;
944
        }
945
        // agregar tabla de detalle
946
        $this->Ln();
947
        $this->SetX($x);
948
        $this->addTableWithoutEmptyCols($titulos, $detalle, $options);
949
    }
950
951
    /**
952
     * Método que agrega el detalle del documento
953
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
954
     * @param x Posición horizontal de inicio en el PDF
955
     * @param y Posición vertical de inicio en el PDF
956
     * @author Pablo Reyes (https://github.com/pabloxp)
957
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
958
     * @version 2016-12-13
959
     */
960
    private function agregarDetalleContinuo($detalle, $x = 3)
961
    {
962
        $this->SetY($this->getY()+1);
963
        $p1x = $x;
964
        $p1y = $this->y;
965
        $p2x = $this->getPageWidth() - 2;
966
        $p2y = $p1y;  // Use same y for a straight line
967
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
968
        $this->Line($p1x, $p1y, $p2x, $p2y, $style);
969
        $this->Texto($this->detalle_cols['NmbItem']['title'], $x+1, $this->y, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
970
        $this->Texto($this->detalle_cols['PrcItem']['title'], $x+15, $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
971
        $this->Texto($this->detalle_cols['QtyItem']['title'], $x+35, $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
972
        $this->Texto($this->detalle_cols['MontoItem']['title'], $x+45, $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
973
        $this->Line($p1x, $p1y+4, $p2x, $p2y+4, $style);
974
        if (!isset($detalle[0]))
975
            $detalle = [$detalle];
976
        $this->SetY($this->getY()+2);
977
        foreach($detalle as  &$d) {
978
            $this->MultiTexto($d['NmbItem'], $x+1, $this->y+4, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
979
            $this->Texto(number_format($d['PrcItem'],0,',','.'), $x+15, $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
980
            $this->Texto($this->num($d['QtyItem']), $x+35, $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
981
            $this->Texto($this->num($d['MontoItem']), $x+45, $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
982
        }
983
        $this->Line($p1x, $this->y+4, $p2x, $this->y+4, $style);
984
    }
985
986
    /**
987
     * Método que agrega el subtotal del DTE
988
     * @param detalle Arreglo con los detalles del documentos para poder
989
     * calcular subtotal
990
     * @param x Posición horizontal de inicio en el PDF
991
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
992
     * @version 2016-08-17
993
     */
994
    private function agregarSubTotal(array $detalle, $x = 10) {
995
        $subtotal = 0;
996
        if (!isset($detalle[0])) {
997
            $detalle = [$detalle];
998
        }
999
        foreach($detalle as  &$d) {
1000
            if (!empty($d['MontoItem'])) {
1001
                $subtotal += $d['MontoItem'];
1002
            }
1003
        }
1004
        if ($this->papelContinuo) {
1005
            $this->Texto('Subtotal: '.$this->num($subtotal), $x);
1006
        } else {
1007
            $this->Texto('Subtotal:', 77, null, 'R', 100);
1008
            $this->Texto($this->num($subtotal), 177, null, 'R', 22);
1009
        }
1010
        $this->Ln();
1011
    }
1012
1013
    /**
1014
     * Método que agrega los descuentos y/o recargos globales del documento
1015
     * @param descuentosRecargos Arreglo con los descuentos y/o recargos del documento (tag DscRcgGlobal del XML)
1016
     * @param x Posición horizontal de inicio en el PDF
1017
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1018
     * @version 2016-08-17
1019
     */
1020
    private function agregarDescuentosRecargos(array $descuentosRecargos, $x = 10)
1021
    {
1022
        if (!isset($descuentosRecargos[0]))
1023
            $descuentosRecargos = [$descuentosRecargos];
1024
        foreach($descuentosRecargos as $dr) {
1025
            $tipo = $dr['TpoMov']=='D' ? 'Descuento' : 'Recargo';
1026
            $valor = $dr['TpoValor']=='%' ? $dr['ValorDR'].'%' : $this->num($dr['ValorDR']);
1027
            if ($this->papelContinuo) {
1028
                $this->Texto($tipo.' global: '.$valor.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):''), $x);
1029
            } else {
1030
                $this->Texto($tipo.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):'').':', 77, null, 'R', 100);
1031
                $this->Texto($valor, 177, null, 'R', 22);
1032
            }
1033
            $this->Ln();
1034
        }
1035
    }
1036
1037
    /**
1038
     * Método que agrega los pagos del documento
1039
     * @param pagos Arreglo con los pagos del documento
1040
     * @param x Posición horizontal de inicio en el PDF
1041
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1042
     * @version 2016-07-24
1043
     */
1044
    private function agregarPagos(array $pagos, $x = 10)
1045
    {
1046
        if (!isset($pagos[0]))
1047
            $pagos = [$pagos];
1048
        $this->Texto('Pago(s) programado(s):', $x);
1049
        $this->Ln();
1050
        foreach($pagos as $p) {
1051
            $this->Texto('  - '.$this->date($p['FchPago'], false).': $'.$this->num($p['MntPago']).'.-'.(!empty($p['GlosaPagos'])?(' ('.$p['GlosaPagos'].')'):''), $x);
1052
            $this->Ln();
1053
        }
1054
    }
1055
1056
    /**
1057
     * Método que agrega los totales del documento
1058
     * @param totales Arreglo con los totales (tag Totales del XML)
1059
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1060
     * @version 2017-04-17
1061
     */
1062
    private function agregarTotales(array $totales, $y = 190, $x = 145, $offset = 25)
1063
    {
1064
        // normalizar totales
1065
        $totales = array_merge([
1066
            'TpoMoneda' => false,
1067
            'MntNeto' => false,
1068
            'MntExe' => false,
1069
            'TasaIVA' => false,
1070
            'IVA' => false,
1071
            'IVANoRet' => false,
1072
            'CredEC' => false,
1073
            'MntTotal' => false,
1074
            'MontoNF' => false,
1075
            'MontoPeriodo' => false,
1076
            'SaldoAnterior' => false,
1077
            'VlrPagar' => false,
1078
        ], $totales);
1079
        // glosas
1080
        $glosas = [
1081
            'TpoMoneda' => 'Moneda',
1082
            'MntNeto' => 'Neto $',
1083
            'MntExe' => 'Exento $',
1084
            'IVA' => 'IVA ('.$totales['TasaIVA'].'%) $',
1085
            'IVANoRet' => 'IVA no retenido $',
1086
            'CredEC' => 'Desc. 65% IVA $',
1087
            'MntTotal' => 'Total $',
1088
            'MontoNF' => 'Monto no facturable $',
1089
            'MontoPeriodo' => 'Monto período $',
1090
            'SaldoAnterior' => 'Saldo anterior $',
1091
            'VlrPagar' => 'Valor a pagar $',
1092
        ];
1093
        // agregar impuestos adicionales y retenciones
1094
        if (!empty($totales['ImptoReten'])) {
1095
            $ImptoReten = $totales['ImptoReten'];
1096
            $MntTotal = $totales['MntTotal'];
1097
            unset($totales['ImptoReten'], $totales['MntTotal']);
1098
            if (!isset($ImptoReten[0])) {
1099
                $ImptoReten = [$ImptoReten];
1100
            }
1101
            foreach($ImptoReten as $i) {
1102
                $totales['ImptoReten_'.$i['TipoImp']] = $i['MontoImp'];
1103
                if (!empty($i['TasaImp'])) {
1104
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' ('.$i['TasaImp'].'%) $';
1105
                } else {
1106
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' $';
1107
                }
1108
            }
1109
            $totales['MntTotal'] = $MntTotal;
1110
        }
1111
        // agregar cada uno de los totales
1112
        $this->setY($y);
1113
        $this->setFont('', 'B', null);
1114
        foreach ($totales as $key => $total) {
1115
            if ($total!==false and isset($glosas[$key])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1116
                $y = $this->GetY();
1117
                if (!$this->cedible or $this->papelContinuo) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1118
                    $this->Texto($glosas[$key].' :', $x, null, 'R', 30);
1119
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1120
                    $this->Ln();
1121
                } else {
1122
                    $this->MultiTexto($glosas[$key].' :', $x, null, 'R', 30);
1123
                    $y_new = $this->GetY();
1124
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1125
                    $this->SetY($y_new);
1126
                }
1127
            }
1128
        }
1129
    }
1130
1131
    /**
1132
     * Método que coloca las diferentes observaciones que puede tener el documnto
1133
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1134
     * @version 2016-04-11
1135
     */
1136
    private function agregarObservacion($IdDoc, $x = 10, $y = 175)
1137
    {
1138
        $this->SetXY($x, $y);
1139
        if (!empty($IdDoc['TermPagoGlosa'])) {
1140
            $this->MultiTexto('Observación: '.$IdDoc['TermPagoGlosa']);
1141
        }
1142
        return $this->GetY();
1143
    }
1144
1145
    /**
1146
     * Método que agrega el timbre de la factura
1147
     *  - Se imprime en el tamaño mínimo: 2x5 cms
1148
     *  - En el lado de abajo con margen izquierdo mínimo de 2 cms
1149
     * @param timbre String con los datos del timbre
1150
     * @param x Posición horizontal de inicio en el PDF
1151
     * @param y Posición vertical de inicio en el PDF
1152
     * @param w Ancho del timbre
1153
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1154
     * @version 2017-07-13
1155
     */
1156
    private function agregarTimbre($timbre, $x_timbre = 20, $x = 20, $y = 190, $w = 70, $font_size = 8)
1157
    {
1158
        if ($timbre!==null) {
1159
            $style = [
1160
                'border' => false,
1161
                'padding' => 0,
1162
                'hpadding' => 0,
1163
                'vpadding' => 0,
1164
                'module_width' => 1, // width of a single module in points
1165
                'module_height' => 1, // height of a single module in points
1166
                'fgcolor' => [0,0,0],
1167
                'bgcolor' => false, // [255,255,255]
0 ignored issues
show
Unused Code Comprehensibility introduced by
88% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1168
                'position' => $this->papelContinuo ? 'C' : 'S',
1169
            ];
1170
            $ecl = version_compare(phpversion(), '7.0.0', '<') ? -1 : $this->ecl;
1171
            $this->write2DBarcode($timbre, 'PDF417,,'.$ecl, $x_timbre, $y, $w, 0, $style, 'B');
1172
            $this->setFont('', 'B', $font_size);
1173
            $this->Texto('Timbre Electrónico SII', $x, null, 'C', $w);
1174
            $this->Ln();
1175
            $this->Texto('Resolución '.$this->resolucion['NroResol'].' de '.explode('-', $this->resolucion['FchResol'])[0], $x, null, 'C', $w);
1176
            $this->Ln();
1177
            if ($w>=60) {
1178
                $this->Texto('Verifique documento: '.$this->web_verificacion, $x, null, 'C', $w);
1179
            } else {
1180
                $this->Texto('Verifique documento:', $x, null, 'C', $w);
1181
                $this->Ln();
1182
                $this->Texto($this->web_verificacion, $x, null, 'C', $w);
1183
            }
1184
        }
1185
    }
1186
1187
    /**
1188
     * Método que agrega el acuse de rebido
1189
     * @param x Posición horizontal de inicio en el PDF
1190
     * @param y Posición vertical de inicio en el PDF
1191
     * @param w Ancho del acuse de recibo
1192
     * @param h Alto del acuse de recibo
1193
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1194
     * @version 2015-09-08
1195
     */
1196
    private function agregarAcuseRecibo($x = 93, $y = 190, $w = 50, $h = 40)
1197
    {
1198
        $this->SetTextColorArray([0,0,0]);
1199
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1200
        $this->setFont('', 'B', 10);
1201
        $this->Texto('Acuse de recibo', $x, $y+1, 'C', $w);
1202
        $this->setFont('', 'B', 8);
1203
        $this->Texto('Nombre', $x+2, $this->y+8);
1204
        $this->Texto('________________', $x+18);
1205
        $this->Texto('R.U.T.', $x+2, $this->y+6);
1206
        $this->Texto('________________', $x+18);
1207
        $this->Texto('Fecha', $x+2, $this->y+6);
1208
        $this->Texto('________________', $x+18);
1209
        $this->Texto('Recinto', $x+2, $this->y+6);
1210
        $this->Texto('________________', $x+18);
1211
        $this->Texto('Firma', $x+2, $this->y+8);
1212
        $this->Texto('________________', $x+18);
1213
        $this->setFont('', 'B', 7);
1214
        $this->MultiTexto('El acuse de recibo que se declara en este acto, de acuerdo a lo dispuesto en la letra b) del Art. 4°, y la letra c) del Art. 5° de la Ley 19.983, acredita que la entrega de mercaderías o servicio (s) prestado (s) ha (n) sido recibido (s).'."\n", $x, $this->y+6, 'J', $w);
1215
    }
1216
1217
    /**
1218
     * Método que agrega el acuse de rebido
1219
     * @param x Posición horizontal de inicio en el PDF
1220
     * @param y Posición vertical de inicio en el PDF
1221
     * @param w Ancho del acuse de recibo
1222
     * @param h Alto del acuse de recibo
1223
     * @author Pablo Reyes (https://github.com/pabloxp)
1224
     * @version 2015-11-17
1225
     */
1226
    private function agregarAcuseReciboContinuo($x = 3, $y = null, $w = 68, $h = 40)
1227
    {
1228
        $this->SetTextColorArray([0,0,0]);
1229
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1230
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
1231
        $this->Line($x, $y+22, $w+3, $y+22, $style);
1232
        //$this->setFont('', 'B', 10);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1233
        //$this->Texto('Acuse de recibo', $x, $y+1, 'C', $w);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1234
        $this->setFont('', 'B', 6);
1235
        $this->Texto('Nombre:', $x+2, $this->y+8);
1236
        $this->Texto('_____________________________________________', $x+12);
1237
        $this->Texto('R.U.T.:', $x+2, $this->y+6);
1238
        $this->Texto('________________', $x+12);
1239
        $this->Texto('Firma:', $x+32, $this->y+0.5);
1240
        $this->Texto('___________________', $x+42.5);
1241
        $this->Texto('Fecha:', $x+2, $this->y+6);
1242
        $this->Texto('________________', $x+12);
1243
        $this->Texto('Recinto:', $x+32, $this->y+0.5);
1244
        $this->Texto('___________________', $x+42.5);
1245
1246
        $this->setFont('', 'B', 5);
1247
        $this->MultiTexto('El acuse de recibo que se declara en este acto, de acuerdo a lo dispuesto en la letra b) del Art. 4°, y la letra c) del Art. 5° de la Ley 19.983, acredita que la entrega de mercaderías o servicio (s) prestado (s) ha (n) sido recibido (s).'."\n", $x+2, $this->y+8, 'J', $w-3);
1248
    }
1249
1250
    /**
1251
     * Método que agrega la leyenda de destino
1252
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1253
     * @version 2016-08-04
1254
     */
1255
    private function agregarLeyendaDestino($tipo, $y = 254, $font_size = 10)
1256
    {
1257
        $this->setFont('', 'B', $font_size);
1258
        $this->Texto('CEDIBLE'.($tipo==52?' CON SU FACTURA':''), null, $y, 'R');
1259
    }
1260
1261
    /**
1262
     * Método que formatea un número con separador de miles y decimales (si
1263
     * corresponden)
1264
     * @param n Número que se desea formatear
1265
     * @return Número formateado
1266
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1267
     * @version 2016-04-05
1268
     */
1269
    private function num($n)
1270
    {
1271
        if (!is_numeric($n))
1272
            return $n;
1273
        $broken_number = explode('.', (string)$n);
1274
        if (isset($broken_number[1]))
1275
            return number_format($broken_number[0], 0, ',', '.').','.$broken_number[1];
0 ignored issues
show
Bug Best Practice introduced by
The return type of return number_format($br...,' . $broken_number[1]; (string) is incompatible with the return type documented by sasco\LibreDTE\Sii\PDF\Dte::num of type sasco\LibreDTE\Sii\PDF\Número.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1276
        return number_format($broken_number[0], 0, ',', '.');
0 ignored issues
show
Bug Best Practice introduced by
The return type of return number_format($br...umber[0], 0, ',', '.'); (string) is incompatible with the return type documented by sasco\LibreDTE\Sii\PDF\Dte::num of type sasco\LibreDTE\Sii\PDF\Número.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1277
    }
1278
1279
    /**
1280
     * Método que formatea una fecha en formato YYYY-MM-DD a un string
1281
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1282
     * @version 2016-04-28
1283
     */
1284
    public function date($date, $mostrar_dia = true)
1285
    {
1286
        $dias = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];
1287
        $meses = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'];
1288
        $unixtime = strtotime($date);
1289
        $fecha = date(($mostrar_dia?'\D\I\A ':'').'j \d\e \M\E\S \d\e\l Y', $unixtime);
1290
        $dia = $dias[date('w', $unixtime)];
1291
        $mes = $meses[date('n', $unixtime)-1];
1292
        return str_replace(array('DIA', 'MES'), array($dia, $mes), $fecha);
1293
    }
1294
1295
}
1296