Completed
Push — master ( 9fc349...910333 )
by Esteban De La Fuente
05:10
created

Dte::agregarObservacion()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 8
nc 16
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-10-05
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
    private $papel_continuo_alto = 5000; ///< Alto exageradamente grande para autocálculo de alto en papel continuo
44
    private $timbre_pie = true; ///< Indica si el timbre va al pie o no (va pegado al detalle)
45
46
    private $tipos = [
47
        // códigos oficiales SII
48
        29 => 'FACTURA DE INICIO',
49
        30 => 'FACTURA',
50
        32 => 'FACTURA DE VENTA BIENES Y SERVICIOS NO AFECTOS O EXENTOS DE IVA',
51
        33 => 'FACTURA ELECTRÓNICA',
52
        34 => 'FACTURA NO AFECTA O EXENTA ELECTRÓNICA',
53
        35 => 'BOLETA',
54
        38 => 'BOLETA EXENTA',
55
        39 => 'BOLETA ELECTRÓNICA',
56
        40 => 'LIQUIDACION FACTURA',
57
        41 => 'BOLETA NO AFECTA O EXENTA ELECTRÓNICA',
58
        43 => 'LIQUIDACIÓN FACTURA ELECTRÓNICA',
59
        45 => 'FACTURA DE COMPRA',
60
        46 => 'FACTURA DE COMPRA ELECTRÓNICA',
61
        48 => 'COMPROBANTE DE PAGO ELECTRÓNICO',
62
        50 => 'GUÍA DE DESPACHO',
63
        52 => 'GUÍA DE DESPACHO ELECTRÓNICA',
64
        55 => 'NOTA DE DÉBITO',
65
        56 => 'NOTA DE DÉBITO ELECTRÓNICA',
66
        60 => 'NOTA DE CRÉDITO',
67
        61 => 'NOTA DE CRÉDITO ELECTRÓNICA',
68
        101 => 'FACTURA DE EXPORTACIÓN',
69
        102 => 'FACTURA DE VENTA EXENTA A ZONA FRANCA PRIMARIA',
70
        103 => 'LIQUIDACIÓN',
71
        104 => 'NOTA DE DÉBITO DE EXPORTACIÓN',
72
        105 => 'BOLETA LIQUIDACIÓN',
73
        106 => 'NOTA DE CRÉDITO DE EXPORTACIÓN',
74
        108 => 'SOLICITUD REGISTRO DE FACTURA (SRF)',
75
        109 => 'FACTURA TURISTA',
76
        110 => 'FACTURA DE EXPORTACIÓN ELECTRÓNICA',
77
        111 => 'NOTA DE DÉBITO DE EXPORTACIÓN ELECTRÓNICA',
78
        112 => 'NOTA DE CRÉDITO DE EXPORTACIÓN ELECTRÓNICA',
79
        801 => 'ORDEN DE COMPRA',
80
        802 => 'NOTA DE PEDIDO',
81
        803 => 'CONTRATO',
82
        804 => 'RESOLUCIÓN',
83
        805 => 'PROCEDO CHILECOMPRA',
84
        806 => 'FICHA CHILECOMPRA',
85
        807 => 'DUS',
86
        808 => 'B/L (CONOCIMIENTO DE EMBARQUE)',
87
        809 => 'AWB',
88
        810 => 'MIC (MANIFIESTO INTERNACIONAL)',
89
        811 => 'CARTA DE PORTE',
90
        812 => 'RESOLUCION SNA',
91
        813 => 'PASAPORTE',
92
        814 => 'CERTIFICADO DE DEPÓSITO BOLSA PROD. CHILE',
93
        815 => 'VALE DE PRENDA BOLSA PROD. CHILE',
94
        901 => 'FACTURA DE VENTAS A EMPRESAS DEL TERRITORIO PREFERENCIAL',
95
        902 => 'CONOCIMIENTO DE EMBARQUE',
96
        903 => 'DOCUMENTO ÚNICO DE SALIDA (DUS)',
97
        904 => 'FACTURA DE TRASPASO',
98
        905 => 'FACTURA DE REEXPEDICIÓN',
99
        906 => 'BOLETAS VENTA MÓDULOS ZF (TODAS)',
100
        907 => 'FACTURAS VENTA MÓDULO ZF (TODAS)',
101
        909 => 'FACTURAS VENTA MÓDULO ZF',
102
        910 => 'SOLICITUD TRASLADO ZONA FRANCA (Z)',
103
        911 => 'DECLARACIÓN DE INGRESO A ZONA FRANCA PRIMARIA',
104
        914 => 'DECLARACIÓN DE INGRESO (DIN)',
105
        919 => 'RESUMEN VENTAS DE NACIONALES PASAJES SIN FACTURA',
106
        920 => 'OTROS REGISTROS NO DOCUMENTADOS (AUMENTA DÉBITO)',
107
        922 => 'OTROS REGISTROS (DISMINUYE DÉBITO)',
108
        924 => 'RESUMEN VENTAS DE INTERNACIONALES PASAJES SIN FACTURA',
109
        // códigos de LibreDTE
110
        0 => 'COTIZACIÓN',
111
        'HES' => 'HOJA DE ENTRADA DE SERVICIOS (HES)',
112
    ]; ///< Glosas para los tipos de documentos (DTE y otros)
113
114
    private $formas_pago = [
115
        1 => 'Contado',
116
        2 => 'Crédito',
117
        3 => 'Sin costo',
118
    ]; ///< Glosas de las formas de pago
119
120
    private $formas_pago_exportacion = [
121
        1 => 'Cobranza hasta 1 año',
122
        2 => 'Cobranza más de 1 año',
123
        11 => 'Acreditivo hasta 1 año',
124
        12 => 'Acreditivo más de 1 año',
125
        21 => 'Sin pago',
126
        32 => 'Pago anticipado a la fecha de embarque',
127
    ]; ///< Códigos de forma de pago (básicos) de la aduana para exportaciones
128
129
    private $detalle_cols = [
130
        'CdgItem' => ['title'=>'Código', 'align'=>'left', 'width'=>20],
131
        'NmbItem' => ['title'=>'Item', 'align'=>'left', 'width'=>0],
132
        'IndExe' => ['title'=>'IE', 'align'=>'left', 'width'=>'7'],
133
        'QtyItem' => ['title'=>'Cant.', 'align'=>'right', 'width'=>15],
134
        'UnmdItem' => ['title'=>'Unidad', 'align'=>'left', 'width'=>22],
135
        'PrcItem' => ['title'=>'P. unitario', 'align'=>'right', 'width'=>22],
136
        'DescuentoMonto' => ['title'=>'Descuento', 'align'=>'right', 'width'=>22],
137
        'RecargoMonto' => ['title'=>'Recargo', 'align'=>'right', 'width'=>22],
138
        'MontoItem' => ['title'=>'Total item', 'align'=>'right', 'width'=>22],
139
    ]; ///< Nombres de columnas detalle, alineación y ancho
140
141
    private $item_detalle_posicion = 0; ///< Posición del detalle del item respecto al nombre
142
    private $detalle_fuente = 10; ///< Tamaño de la fuente para el detalle en hoja carta
143
144
    private $traslados = [
145
        1 => 'Operación constituye venta',
146
        2 => 'Ventas por efectuar',
147
        3 => 'Consignaciones',
148
        4 => 'Entrega gratuita',
149
        5 => 'Traslados internos',
150
        6 => 'Otros traslados no venta',
151
        7 => 'Guía de devolución',
152
        8 => 'Traslado para exportación (no venta)',
153
        9 => 'Venta para exportación',
154
    ]; ///< Tipos de traslado para guías de despacho
155
156
    public static $papel = [
157
        0  => 'Hoja carta',
158
        57 => 'Papel contínuo 57mm',
159
        75 => 'Papel contínuo 75mm',
160
        80 => 'Papel contínuo 80mm',
161
    ]; ///< Tamaño de papel que es soportado
162
163
    /**
164
     * Constructor de la clase
165
     * @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)
166
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
167
     * @version 2016-10-06
168
     */
169
    public function __construct($papelContinuo = false)
170
    {
171
        parent::__construct();
172
        $this->SetTitle('Documento Tributario Electrónico (DTE) de Chile by LibreDTE');
173
        $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...
174
    }
175
176
    /**
177
     * Método que asigna la ubicación del logo de la empresa
178
     * @param logo URI del logo (puede ser local o en una URL)
179
     * @param posicion Posición respecto a datos del emisor (=0 izq, =1 arriba)
180
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
181
     * @version 2016-08-04
182
     */
183
    public function setLogo($logo, $posicion = 0)
184
    {
185
        $this->logo = [
186
            'uri' => $logo,
187
            'posicion' => (int)$posicion,
188
        ];
189
    }
190
191
    /**
192
     * Método que asigna los datos de la resolución del SII que autoriza al
193
     * emisor a emitir DTEs
194
     * @param resolucion Arreglo con índices NroResol y FchResol
195
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
196
     * @version 2015-09-08
197
     */
198
    public function setResolucion(array $resolucion)
199
    {
200
        $this->resolucion = $resolucion;
201
    }
202
203
    /**
204
     * Método que asigna la página web que se debe utilizar para indicar donde
205
     * se puede verificar el DTE
206
     * @param web Página web donde se puede verificar el documento
207
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
208
     * @version 2015-12-11
209
     */
210
    public function setWebVerificacion($web)
211
    {
212
        $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...
213
    }
214
215
    /**
216
     * Método que indica si el documento será o no cedible
217
     * @param cedible =true se incorporará leyenda de destino
218
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
219
     * @version 2015-09-09
220
     */
221
    public function setCedible($cedible = true)
222
    {
223
        $this->cedible = $cedible;
224
    }
225
226
    /**
227
     * Método que asigna la posición del detalle del Item respecto al nombre
228
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
229
     * @version 2016-08-05
230
     */
231
    public function setPosicionDetalleItem($posicion)
232
    {
233
        $this->item_detalle_posicion = (int)$posicion;
234
    }
235
236
    /**
237
     * Método que asigna el tamaño de la fuente para el detalle
238
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
239
     * @version 2016-08-03
240
     */
241
    public function setFuenteDetalle($fuente)
242
    {
243
        $this->detalle_fuente = (int)$fuente;
244
    }
245
246
    /**
247
     * Método que asigna el ancho e las columnas del detalle desde un arreglo
248
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
249
     * @version 2016-08-03
250
     */
251
    public function setAnchoColumnasDetalle(array $anchos)
252
    {
253
        foreach ($anchos as $col => $ancho) {
254
            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...
255
                $this->detalle_cols[$col]['width'] = (int)$ancho;
256
            }
257
        }
258
    }
259
260
    /**
261
     * Método que asigna si el tumbre va al pie (por defecto) o va pegado al detalle
262
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
263
     * @version 2017-10-05
264
     */
265
    public function setTimbrePie($timbre_pie = true)
266
    {
267
        $this->timbre_pie = (bool)$timbre_pie;
268
    }
269
270
    /**
271
     * Método que agrega un documento tributario, ya sea en formato de una
272
     * página o papel contínuo según se haya indicado en el constructor
273
     * @param dte Arreglo con los datos del XML (tag Documento)
274
     * @param timbre String XML con el tag TED del DTE
275
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
276
     * @version 2017-07-13
277
     */
278
    public function agregar(array $dte, $timbre = null)
279
    {
280
        $this->dte = $dte['Encabezado']['IdDoc']['TipoDTE'];
281
        // papel hoja carta
282
        if (!$this->papelContinuo) {
283
            $this->agregarNormal($dte, $timbre);
284
        }
285
        // papel contínuo 57mm
286
        else if ($this->papelContinuo==57) {
287
            $this->agregarContinuo57($dte, $timbre);
288
        }
289
        // papel contínuo 75 o 80mm
290
        else {
291
            $this->agregarContinuo($dte, $timbre, $this->papelContinuo);
292
        }
293
    }
294
295
    /**
296
     * Método que agrega una página con el documento tributario
297
     * @param dte Arreglo con los datos del XML (tag Documento)
298
     * @param timbre String XML con el tag TED del DTE
299
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
300
     * @version 2017-10-05
301
     */
302
    private function agregarNormal(array $dte, $timbre)
303
    {
304
        // agregar página para la factura
305
        $this->AddPage();
306
        // agregar cabecera del documento
307
        $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...
308
        $y[] = $this->agregarFolio(
309
            $dte['Encabezado']['Emisor']['RUTEmisor'],
310
            $dte['Encabezado']['IdDoc']['TipoDTE'],
311
            $dte['Encabezado']['IdDoc']['Folio'],
312
            $dte['Encabezado']['Emisor']['CmnaOrigen']
313
        );
314
        // datos del documento
315
        $this->setY(max($y));
316
        $this->Ln();
317
        $y = [];
318
        $y[] = $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null);
319
        $y[] = $this->agregarReceptor($dte['Encabezado']);
320
        $this->setY(max($y));
321
        $this->agregarTraslado(
322
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
323
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null
324
        );
325
        if (!empty($dte['Referencia'])) {
326
            $this->agregarReferencia($dte['Referencia']);
327
        }
328
        $this->agregarDetalle($dte['Detalle']);
329
        if (!empty($dte['DscRcgGlobal'])) {
330
            $this->agregarSubTotal($dte['Detalle']);
331
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal']);
332
        }
333 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...
334
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos']);
335
        }
336
        // agregar observaciones
337
        $this->x_fin_datos = $this->getY();
338
        $this->agregarObservacion($dte['Encabezado']['IdDoc']);
339
        if (!$this->timbre_pie) {
340
            $this->Ln();
341
        }
342
        $this->x_fin_datos = $this->getY();
343
        $this->agregarTotales($dte['Encabezado']['Totales'], !empty($dte['Encabezado']['OtraMoneda']) ? $dte['Encabezado']['OtraMoneda'] : null);
344
        // agregar timbre
345
        $this->agregarTimbre($timbre);
346
        // agregar acuse de recibo y leyenda cedible
347
        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...
348
            $this->agregarAcuseRecibo();
349
            $this->agregarLeyendaDestino($dte['Encabezado']['IdDoc']['TipoDTE']);
350
        }
351
    }
352
353
    /**
354
     * Método que agrega una página con el documento tributario en papel
355
     * contínuo
356
     * @param dte Arreglo con los datos del XML (tag Documento)
357
     * @param timbre String XML con el tag TED del DTE
358
     * @param width Ancho del papel contínuo en mm
359
     * @author Pablo Reyes (https://github.com/pabloxp)
360
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
361
     * @version 2017-10-05
362
     */
363
    private function agregarContinuo(array $dte, $timbre, $width, $height = 0)
364
    {
365
        // determinar alto de la página y agregarla
366
        $this->logo = null;
367
        $x_start = 1;
368
        $y_start = 1;
369
        $offset = 14;
370
        // determinar alto de la página y agregarla
371
        $this->AddPage('P', [$height ? $height : $this->papel_continuo_alto, $width]);
372
        // agregar cabecera del documento
373
        $y = $this->agregarFolio(
374
            $dte['Encabezado']['Emisor']['RUTEmisor'],
375
            $dte['Encabezado']['IdDoc']['TipoDTE'],
376
            $dte['Encabezado']['IdDoc']['Folio'],
377
            $dte['Encabezado']['Emisor']['CmnaOrigen'],
378
            $x_start, $y_start, $width-($x_start*4), 10,
379
            [0,0,0]
380
        );
381
        $y = $this->agregarEmisor($dte['Encabezado']['Emisor'], $x_start, $y+2, 40, 8, 9, [0,0,0]);
382
        // datos del documento
383
        $this->SetY($y);
384
        $this->Ln();
385
        $this->setFont('', '', 8);
386
        $this->agregarDatosEmision($dte['Encabezado']['IdDoc'], !empty($dte['Encabezado']['Emisor']['CdgVendedor'])?$dte['Encabezado']['Emisor']['CdgVendedor']:null, $x_start, $offset, false);
387
        $this->agregarReceptor($dte['Encabezado'], $x_start, $offset);
388
        $this->agregarTraslado(
389
            !empty($dte['Encabezado']['IdDoc']['IndTraslado']) ? $dte['Encabezado']['IdDoc']['IndTraslado'] : null,
390
            !empty($dte['Encabezado']['Transporte']) ? $dte['Encabezado']['Transporte'] : null,
391
            $x_start, $offset
392
        );
393
        if (!empty($dte['Referencia'])) {
394
            $this->agregarReferencia($dte['Referencia'], $x_start, $offset);
395
        }
396
        $this->Ln();
397
        $this->agregarDetalleContinuo($dte['Detalle']);
398
        if (!empty($dte['DscRcgGlobal'])) {
399
            $this->Ln();
400
            $this->Ln();
401
            $this->agregarSubTotal($dte['Detalle'], $x_start);
402
            $this->agregarDescuentosRecargos($dte['DscRcgGlobal'], $x_start);
403
        }
404 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...
405
            $this->Ln();
406
            $this->Ln();
407
            $this->agregarPagos($dte['Encabezado']['IdDoc']['MntPagos'], $x_start);
408
        }
409
        $this->agregarTotales($dte['Encabezado']['Totales'], !empty($dte['Encabezado']['OtraMoneda']) ? $dte['Encabezado']['OtraMoneda'] : null, $this->y+6, 23, 17);
410
        // agregar acuse de recibo y leyenda cedible
411 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...
412
            $this->agregarAcuseReciboContinuo(3, $this->y+6, 68, 34);
413
            $this->agregarLeyendaDestinoContinuo($dte['Encabezado']['IdDoc']['TipoDTE']);
414
        }
415
        // agregar timbre
416
        $y = $this->agregarObservacion($dte['Encabezado']['IdDoc'], $x_start, $this->y+6);
417
        $this->agregarTimbre($timbre, 0, $x_start, $y+6, 70, 6);
418
        // si el alto no se pasó, entonces es con autocálculo, se elimina esta página y se pasa el alto
419
        // que se logró determinar para crear la página con el alto correcto
420 View Code Duplication
        if (!$height) {
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...
421
            $this->deletePage($this->PageNo());
422
            $this->agregarContinuo($dte, $timbre, $width, $this->getY()+30);
423
        }
424
    }
425
426
    /**
427
     * Método que agrega una página con el documento tributario
428
     * @param dte Arreglo con los datos del XML (tag Documento)
429
     * @param timbre String XML con el tag TED del DTE
430
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
431
     * @version 2017-10-05
432
     */
433
    private function agregarContinuo57(array $dte, $timbre, $width = 57, $height = 0)
434
    {
435
        // determinar alto de la página y agregarla
436
        $this->AddPage('P', [$height ? $height : $this->papel_continuo_alto, $width]);
437
        $x = 1;
438
        $y = 5;
439
        $this->SetXY($x,$y);
440
        // agregar datos del documento
441
        $this->setFont('', '', 8);
442
        $this->MultiTexto(!empty($dte['Encabezado']['Emisor']['RznSoc']) ? $dte['Encabezado']['Emisor']['RznSoc'] : $dte['Encabezado']['Emisor']['RznSocEmisor'], $x, null, '', $width-2);
443
        $this->MultiTexto($dte['Encabezado']['Emisor']['RUTEmisor'], $x, null, '', $width-2);
444
        $this->MultiTexto('Giro: '.(!empty($dte['Encabezado']['Emisor']['GiroEmis']) ? $dte['Encabezado']['Emisor']['GiroEmis'] : $dte['Encabezado']['Emisor']['GiroEmisor']), $x, null, '', $width-2);
445
        $this->MultiTexto($dte['Encabezado']['Emisor']['DirOrigen'].', '.$dte['Encabezado']['Emisor']['CmnaOrigen'], $x, null, '', $width-2);
446
        $this->MultiTexto($this->getTipo($dte['Encabezado']['IdDoc']['TipoDTE']).' N° '.$dte['Encabezado']['IdDoc']['Folio'], $x, null, '', $width-2);
447
        $this->MultiTexto('Fecha: '.date('d/m/Y', strtotime($dte['Encabezado']['IdDoc']['FchEmis'])), $x, null, '', $width-2);
448
        // si no es boleta no nominativa se agregan datos receptor
449
        if ($dte['Encabezado']['Receptor']['RUTRecep']!='66666666-6') {
450
            $this->Ln();
451
            $this->MultiTexto('Receptor: '.$dte['Encabezado']['Receptor']['RUTRecep'], $x, null, '', $width-2);
452
            $this->MultiTexto($dte['Encabezado']['Receptor']['RznSocRecep'], $x, null, '', $width-2);
453
            if (!empty($dte['Encabezado']['Receptor']['GiroRecep'])) {
454
                $this->MultiTexto('Giro: '.$dte['Encabezado']['Receptor']['GiroRecep'], $x, null, '', $width-2);
455
            }
456
            if (!empty($dte['Encabezado']['Receptor']['DirRecep'])) {
457
                $this->MultiTexto($dte['Encabezado']['Receptor']['DirRecep'].', '.$dte['Encabezado']['Receptor']['CmnaRecep'], $x, null, '', $width-2);
458
            }
459
        }
460
        $this->Ln();
461
        // hay un sólo detalle
462
        if (!isset($dte['Detalle'][0])) {
463
            $this->MultiTexto($dte['Detalle']['NmbItem'].': $'.$this->num($dte['Detalle']['MontoItem']), $x, null, '', $width-2);
464
        }
465
        // hay más de un detalle
466
        else {
467
            foreach ($dte['Detalle'] as $d) {
468
                $this->MultiTexto($d['NmbItem'].': $'.$this->num($d['MontoItem']), $x, null, '', $width-2);
469
            }
470
            if (in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
471
                $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
472
            }
473
        }
474
        // si no es boleta se coloca EXENTO, NETO, IVA y TOTAL si corresponde
475
        if (!in_array($dte['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
476 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...
477
                $this->MultiTexto('EXENTO: $'.$this->num($dte['Encabezado']['Totales']['MntExe']), $x, null, '', $width-2);
478
            }
479 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...
480
                $this->MultiTexto('NETO: $'.$this->num($dte['Encabezado']['Totales']['MntNeto']), $x, null, '', $width-2);
481
            }
482 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...
483
                $this->MultiTexto('IVA: $'.$this->num($dte['Encabezado']['Totales']['IVA']), $x, null, '', $width-2);
484
            }
485
            $this->MultiTexto('TOTAL: $'.$this->num($dte['Encabezado']['Totales']['MntTotal']), $x, null, '', $width-2);
486
        }
487
        // agregar acuse de recibo y leyenda cedible
488 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...
489
            $this->agregarAcuseReciboContinuo(-1, $this->y+6, $width+2, 34);
490
            $this->agregarLeyendaDestinoContinuo($dte['Encabezado']['IdDoc']['TipoDTE']);
491
        }
492
        // agregar timbre
493
        if (!empty($dte['Encabezado']['IdDoc']['TermPagoGlosa'])) {
494
            $this->Ln();
495
            $this->MultiTexto('Observación: '.$dte['Encabezado']['IdDoc']['TermPagoGlosa']."\n\n", $x);
496
        }
497
        $this->agregarTimbre($timbre, 0, $x, $this->GetY()+6, 55, 6);
498
        // si el alto no se pasó, entonces es con autocálculo, se elimina esta página y se pasa el alto
499
        // que se logró determinar para crear la página con el alto correcto
500 View Code Duplication
        if (!$height) {
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...
501
            $this->deletePage($this->PageNo());
502
            $this->agregarContinuo57($dte, $timbre, $width, $this->getY()+30);
503
        }
504
    }
505
506
    /**
507
     * Método que agrega los datos de la empresa
508
     * Orden de los datos:
509
     *  - Razón social del emisor
510
     *  - Giro del emisor (sin abreviar)
511
     *  - Dirección casa central del emisor
512
     *  - Dirección sucursales
513
     * @param emisor Arreglo con los datos del emisor (tag Emisor del XML)
514
     * @param x Posición horizontal de inicio en el PDF
515
     * @param y Posición vertical de inicio en el PDF
516
     * @param w Ancho de la información del emisor
517
     * @param w_img Ancho máximo de la imagen
518
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
519
     * @version 2016-12-02
520
     */
521
    private function agregarEmisor(array $emisor, $x = 10, $y = 15, $w = 75, $w_img = 30, $font_size = null, array $color = null)
522
    {
523
        // logo del documento
524
        if (isset($this->logo)) {
525
            $this->Image(
526
                $this->logo['uri'],
527
                $x,
528
                $y,
529
                !$this->logo['posicion']?$w_img:null, $this->logo['posicion']?($w_img/2):null,
530
                'PNG',
531
                (isset($emisor['url'])?$emisor['url']:''),
532
                'T'
533
            );
534
            if ($this->logo['posicion']) {
535
                $this->SetY($this->y + ($w_img/2));
536
                $w += 40;
537
            } else {
538
                $x = $this->x+3;
539
            }
540
        } else {
541
            $this->y = $y-2;
542
            $w += 40;
543
        }
544
        // agregar datos del emisor
545
        $this->setFont('', 'B', $font_size ? $font_size : 14);
546
        $this->SetTextColorArray($color===null?[32, 92, 144]:$color);
547
        $this->MultiTexto(!empty($emisor['RznSoc']) ? $emisor['RznSoc'] : $emisor['RznSocEmisor'], $x, $this->y+2, 'L', $w);
548
        $this->setFont('', 'B', $font_size ? $font_size : 9);
549
        $this->SetTextColorArray([0,0,0]);
550
        $this->MultiTexto(!empty($emisor['GiroEmis']) ? $emisor['GiroEmis'] : $emisor['GiroEmisor'], $x, $this->y, 'L', $w);
551
        $ciudad = !empty($emisor['CiudadOrigen']) ? $emisor['CiudadOrigen'] : \sasco\LibreDTE\Chile::getCiudad($emisor['CmnaOrigen']);
552
        $this->MultiTexto($emisor['DirOrigen'].', '.$emisor['CmnaOrigen'].($ciudad?(', '.$ciudad):''), $x, $this->y, 'L', $w);
553
        if (!empty($emisor['Sucursal'])) {
554
            $this->MultiTexto('Sucursal: '.$emisor['Sucursal'], $x, $this->y, 'L', $w);
555
        }
556
        $contacto = [];
557
        if (!empty($emisor['Telefono'])) {
558
            if (!is_array($emisor['Telefono']))
559
                $emisor['Telefono'] = [$emisor['Telefono']];
560
            foreach ($emisor['Telefono'] as $t)
561
                $contacto[] = $t;
562
        }
563
        if (!empty($emisor['CorreoEmisor'])) {
564
            $contacto[] = $emisor['CorreoEmisor'];
565
        }
566
        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...
567
            $this->MultiTexto(implode(' / ', $contacto), $x, $this->y, 'L', $w);
568
        }
569
        return $this->y;
570
    }
571
572
    /**
573
     * Método que agrega el recuadro con el folio
574
     * Recuadro:
575
     *  - Tamaño mínimo 1.5x5.5 cms
576
     *  - En lado derecho (negro o rojo)
577
     *  - Enmarcado por una línea de entre 0.5 y 1 mm de espesor
578
     *  - Tamaño máximo 4x8 cms
579
     *  - Letras tamaño 10 o superior en mayúsculas y negritas
580
     *  - Datos del recuadro: RUT emisor, nombre de documento en 2 líneas,
581
     *    folio.
582
     *  - Bajo el recuadro indicar la Dirección regional o Unidad del SII a la
583
     *    que pertenece el emisor
584
     * @param rut RUT del emisor
585
     * @param tipo Código o glosa del tipo de documento
586
     * @param sucursal_sii Código o glosa de la sucursal del SII del Emisor
587
     * @param x Posición horizontal de inicio en el PDF
588
     * @param y Posición vertical de inicio en el PDF
589
     * @param w Ancho de la información del emisor
590
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
591
     * @version 2016-12-02
592
     */
593
    private function agregarFolio($rut, $tipo, $folio, $sucursal_sii = null, $x = 130, $y = 15, $w = 70, $font_size = null, array $color = null)
594
    {
595
        if ($color===null) {
596
            $color = $tipo ? ($tipo==52 ? [0,172,140] : [255,0,0]) : [0,0,0];
597
        }
598
        $this->SetTextColorArray($color);
599
        // colocar rut emisor, glosa documento y folio
600
        list($rut, $dv) = explode('-', $rut);
601
        $this->setFont ('', 'B', $font_size ? $font_size : 15);
602
        $this->MultiTexto('R.U.T.: '.$this->num($rut).'-'.$dv, $x, $y+4, 'C', $w);
603
        $this->setFont('', 'B', $font_size ? $font_size : 12);
604
        $this->MultiTexto($this->getTipo($tipo), $x, null, 'C', $w);
605
        $this->setFont('', 'B', $font_size ? $font_size : 15);
606
        $this->MultiTexto('N° '.$folio, $x, null, 'C', $w);
607
        // dibujar rectángulo rojo
608
        $this->Rect($x, $y, $w, round($this->getY()-$y+3), 'D', ['all' => ['width' => 0.5, 'color' => $color]]);
609
        // colocar unidad del SII
610
        $this->setFont('', 'B', $font_size ? $font_size : 10);
611
        if ($tipo) {
612
            $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 593 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...
613
        }
614
        $this->SetTextColorArray([0,0,0]);
615
        $this->Ln();
616
        return $this->y;
617
    }
618
619
    /**
620
     * Método que entrega la glosa del tipo de documento
621
     * @param tipo Código del tipo de documento
622
     * @return Glosa del tipo de documento
623
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
624
     * @version 2016-11-18
625
     */
626
    private function getTipo($tipo)
627
    {
628
        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...
629
            return $tipo;
630
        return isset($this->tipos[$tipo]) ? strtoupper($this->tipos[$tipo]) : 'Documento '.$tipo;
631
    }
632
633
    /**
634
     * Método que agrega los datos de la emisión del DTE que no son los dato del
635
     * receptor
636
     * @param IdDoc Información general del documento
637
     * @param x Posición horizontal de inicio en el PDF
638
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
639
     * @version 2017-06-15
640
     */
641
    private function agregarDatosEmision($IdDoc, $CdgVendedor, $x = 10, $offset = 22, $mostrar_dia = true)
642
    {
643
        // si es hoja carta
644
        if ($x==10) {
645
            $y = $this->GetY();
646
            // fecha emisión
647
            $this->setFont('', 'B', null);
648
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x, null, 'R');
649
            $this->setFont('', '', null);
650
            // período facturación
651
            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...
652
                $this->MultiTexto('Período del '.date('d/m/y', strtotime($IdDoc['PeriodoDesde'])).' al '.date('d/m/y', strtotime($IdDoc['PeriodoHasta'])), $x, null, 'R');
653
            }
654
            // pago anticicado
655 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...
656
                $this->MultiTexto('Pagado el '.$this->date($IdDoc['FchCancel'], false), $x, null, 'R');
657
            }
658
            // fecha vencimiento
659 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...
660
                $this->MultiTexto('Vence el '.$this->date($IdDoc['FchVenc'], false), $x, null, 'R');
661
            }
662
            // forma de pago nacional
663 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...
664
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago[$IdDoc['FmaPago']]), $x, null, 'R');
665
            }
666
            // forma de pago exportación
667 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...
668
                $this->MultiTexto('Venta: '.strtolower($this->formas_pago_exportacion[$IdDoc['FmaPagExp']]), $x, null, 'R');
669
            }
670
            // vendedor
671
            if (!empty($CdgVendedor)) {
672
                $this->MultiTexto('Vendedor: '.$CdgVendedor, $x, null, 'R');
673
            }
674
            $y_end = $this->GetY();
675
            $this->SetY($y);
676
        }
677
        // papel contínuo
678
        else {
679
            // fecha de emisión
680
            $this->setFont('', 'B', null);
681
            $this->Texto('Emisión', $x);
682
            $this->Texto(':', $x+$offset);
683
            $this->setFont('', '', null);
684
            $this->MultiTexto($this->date($IdDoc['FchEmis'], $mostrar_dia), $x+$offset+2);
685
            // forma de pago nacional
686
            if (!empty($IdDoc['FmaPago'])) {
687
                $this->setFont('', 'B', null);
688
                $this->Texto('Venta', $x);
689
                $this->Texto(':', $x+$offset);
690
                $this->setFont('', '', null);
691
                $this->MultiTexto($this->formas_pago[$IdDoc['FmaPago']], $x+$offset+2);
692
            }
693
            // forma de pago exportación
694
            if (!empty($IdDoc['FmaPagExp'])) {
695
                $this->setFont('', 'B', null);
696
                $this->Texto('Venta', $x);
697
                $this->Texto(':', $x+$offset);
698
                $this->setFont('', '', null);
699
                $this->MultiTexto($this->formas_pago_exportacion[$IdDoc['FmaPagExp']], $x+$offset+2);
700
            }
701
            // pago anticicado
702
            if (!empty($IdDoc['FchCancel'])) {
703
                $this->setFont('', 'B', null);
704
                $this->Texto('Pagado el', $x);
705
                $this->Texto(':', $x+$offset);
706
                $this->setFont('', '', null);
707
                $this->MultiTexto($this->date($IdDoc['FchCancel'], $mostrar_dia), $x+$offset+2);
708
            }
709
            // fecha vencimiento
710
            if (!empty($IdDoc['FchVenc'])) {
711
                $this->setFont('', 'B', null);
712
                $this->Texto('Vence el', $x);
713
                $this->Texto(':', $x+$offset);
714
                $this->setFont('', '', null);
715
                $this->MultiTexto($this->date($IdDoc['FchVenc'], $mostrar_dia), $x+$offset+2);
716
            }
717
            $y_end = $this->GetY();
718
        }
719
        return $y_end;
720
    }
721
722
    /**
723
     * Método que agrega los datos del receptor
724
     * @param receptor Arreglo con los datos del receptor (tag Receptor del XML)
725
     * @param x Posición horizontal de inicio en el PDF
726
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
727
     * @version 2017-06-15
728
     */
729
    private function agregarReceptor(array $Encabezado, $x = 10, $offset = 22)
730
    {
731
        $receptor = $Encabezado['Receptor'];
732 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...
733
            list($rut, $dv) = explode('-', $receptor['RUTRecep']);
734
            $this->setFont('', 'B', null);
735
            $this->Texto('R.U.T.', $x);
736
            $this->Texto(':', $x+$offset);
737
            $this->setFont('', '', null);
738
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
739
        }
740 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...
741
            $this->setFont('', 'B', null);
742
            $this->Texto('Señor(es)', $x);
743
            $this->Texto(':', $x+$offset);
744
            $this->setFont('', '', null);
745
            $this->MultiTexto($receptor['RznSocRecep'], $x+$offset+2, null, '', $x==10?105:0);
746
        }
747 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...
748
            $this->setFont('', 'B', null);
749
            $this->Texto('Giro', $x);
750
            $this->Texto(':', $x+$offset);
751
            $this->setFont('', '', null);
752
            $this->MultiTexto($receptor['GiroRecep'], $x+$offset+2);
753
        }
754
        if (!empty($receptor['DirRecep'])) {
755
            $this->setFont('', 'B', null);
756
            $this->Texto('Dirección', $x);
757
            $this->Texto(':', $x+$offset);
758
            $this->setFont('', '', null);
759
            $ciudad = !empty($receptor['CiudadRecep']) ? $receptor['CiudadRecep'] : (
760
                !empty($receptor['CmnaRecep']) ? \sasco\LibreDTE\Chile::getCiudad($receptor['CmnaRecep']) : ''
761
            );
762
            $this->MultiTexto($receptor['DirRecep'].(!empty($receptor['CmnaRecep'])?(', '.$receptor['CmnaRecep']):'').($ciudad?(', '.$ciudad):''), $x+$offset+2);
763
        }
764
        if (!empty($receptor['Extranjero']['Nacionalidad'])) {
765
            $this->setFont('', 'B', null);
766
            $this->Texto('Nacionalidad', $x);
767
            $this->Texto(':', $x+$offset);
768
            $this->setFont('', '', null);
769
            $this->MultiTexto(\sasco\LibreDTE\Sii\Aduana::getNacionalidad($receptor['Extranjero']['Nacionalidad']), $x+$offset+2);
770
        }
771 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...
772
            $this->setFont('', 'B', null);
773
            $this->Texto('N° ID extranj.', $x);
774
            $this->Texto(':', $x+$offset);
775
            $this->setFont('', '', null);
776
            $this->MultiTexto($receptor['Extranjero']['NumId'], $x+$offset+2);
777
        }
778
        $contacto = [];
779
        if (!empty($receptor['Contacto']))
780
            $contacto[] = $receptor['Contacto'];
781
        if (!empty($receptor['CorreoRecep']))
782
            $contacto[] = $receptor['CorreoRecep'];
783 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...
784
            $this->setFont('', 'B', null);
785
            $this->Texto('Contacto', $x);
786
            $this->Texto(':', $x+$offset);
787
            $this->setFont('', '', null);
788
            $this->MultiTexto(implode(' / ', $contacto), $x+$offset+2);
789
        }
790 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...
791
            list($rut, $dv) = explode('-', $Encabezado['RUTSolicita']);
792
            $this->setFont('', 'B', null);
793
            $this->Texto('RUT solicita', $x);
794
            $this->Texto(':', $x+$offset);
795
            $this->setFont('', '', null);
796
            $this->MultiTexto($this->num($rut).'-'.$dv, $x+$offset+2);
797
        }
798 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...
799
            $this->setFont('', 'B', null);
800
            $this->Texto('Cód. recep.', $x);
801
            $this->Texto(':', $x+$offset);
802
            $this->setFont('', '', null);
803
            $this->MultiTexto($receptor['CdgIntRecep'], $x+$offset+2, null, '', $x==10?105:0);
804
        }
805
        return $this->GetY();
806
    }
807
808
    /**
809
     * Método que agrega los datos del traslado
810
     * @param IndTraslado
811
     * @param Transporte
812
     * @param x Posición horizontal de inicio en el PDF
813
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
814
     * @version 2016-08-03
815
     */
816
    private function agregarTraslado($IndTraslado, array $Transporte = null, $x = 10, $offset = 22)
817
    {
818
        // agregar tipo de traslado
819 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...
820
            $this->setFont('', 'B', null);
821
            $this->Texto('Tipo oper.', $x);
822
            $this->Texto(':', $x+$offset);
823
            $this->setFont('', '', null);
824
            $this->MultiTexto($this->traslados[$IndTraslado], $x+$offset+2);
825
        }
826
        // agregar información de transporte
827
        if ($Transporte) {
828
            $transporte = '';
829
            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...
830
                $transporte .= 'a '.$Transporte['DirDest'].', '.$Transporte['CmnaDest'];
831
            }
832
            if (!empty($Transporte['RUTTrans']))
833
                $transporte .= ' por '.$Transporte['RUTTrans'];
834
            if (!empty($Transporte['Patente']))
835
                $transporte .= ' en vehículo '.$Transporte['Patente'];
836
            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...
837 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...
838
                    $transporte .= ' con chofer '.$Transporte['Chofer']['NombreChofer'];
839 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...
840
                    $transporte .= ' ('.$Transporte['Chofer']['RUTChofer'].')';
841
            }
842 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...
843
                $this->setFont('', 'B', null);
844
                $this->Texto('Traslado', $x);
845
                $this->Texto(':', $x+$offset);
846
                $this->setFont('', '', null);
847
                $this->MultiTexto(ucfirst(trim($transporte)), $x+$offset+2);
848
            }
849
        }
850
        // agregar información de aduana
851
        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...
852
            $col = 0;
853
            foreach ($Transporte['Aduana'] as $tag => $codigo) {
854
                if ($codigo===false)
855
                    continue;
856
                $glosa = \sasco\LibreDTE\Sii\Aduana::getGlosa($tag);
857
                $valor = \sasco\LibreDTE\Sii\Aduana::getValor($tag, $codigo);
858
                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...
859
                    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...
860
                        $col = abs($col-110);
861
                        $this->Ln();
862
                    }
863
                    $this->setFont('', 'B', null);
864
                    $this->Texto($glosa, $x+$col);
865
                    $this->Texto(':', $x+$offset+$col);
866
                    $this->setFont('', '', null);
867
                    $this->Texto($valor, $x+$offset+2+$col);
868
                    if ($tag=='TipoBultos')
869
                        $col = abs($col-110);
870
                    if ($col)
871
                        $this->Ln();
872
                    $col = abs($col-110);
873
                }
874
            }
875
            if ($col)
876
                $this->Ln();
877
        }
878
    }
879
880
    /**
881
     * Método que agrega las referencias del documento
882
     * @param referencias Arreglo con las referencias del documento (tag Referencia del XML)
883
     * @param x Posición horizontal de inicio en el PDF
884
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
885
     * @version 2017-09-25
886
     */
887
    private function agregarReferencia($referencias, $x = 10, $offset = 22)
888
    {
889
        if (!isset($referencias[0]))
890
            $referencias = [$referencias];
891
        foreach($referencias as $r) {
892
            $texto = $r['NroLinRef'].' - ';
893
            if (!empty($r['TpoDocRef'])) {
894
                $texto .= $this->getTipo($r['TpoDocRef']).' ';
895
            }
896
            if (!empty($r['FolioRef'])) {
897
                if (is_numeric($r['FolioRef'])) {
898
                    $texto .= ' N° '.$r['FolioRef'].' ';
899
                } else {
900
                    $texto .= ' '.$r['FolioRef'].' ';
901
                }
902
            }
903
            if (!empty($r['FchRef'])) {
904
                $texto .= 'del '.date('d/m/Y', strtotime($r['FchRef']));
905
            }
906
            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...
907
                $texto = $texto.': '.$r['RazonRef'];
908
            }
909
            $this->setFont('', 'B', null);
910
            $this->Texto('Referencia', $x);
911
            $this->Texto(':', $x+$offset);
912
            $this->setFont('', '', null);
913
            $this->MultiTexto($texto, $x+$offset+2);
914
        }
915
    }
916
917
    /**
918
     * Método que agrega el detalle del documento
919
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
920
     * @param x Posición horizontal de inicio en el PDF
921
     * @param y Posición vertical de inicio en el PDF
922
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
923
     * @version 2016-08-05
924
     */
925
    private function agregarDetalle($detalle, $x = 10)
926
    {
927
        if (!isset($detalle[0]))
928
            $detalle = [$detalle];
929
        $this->setFont('', '', $this->detalle_fuente);
930
        // titulos
931
        $titulos = [];
932
        $titulos_keys = array_keys($this->detalle_cols);
933
        foreach ($this->detalle_cols as $key => $info) {
934
            $titulos[$key] = $info['title'];
935
        }
936
        // normalizar cada detalle
937
        $dte_exento = in_array($this->dte, [34, 110, 111, 112]);
938
        foreach ($detalle as &$item) {
939
            // quitar columnas
940
            foreach ($item as $col => $valor) {
941
                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...
942
                    $item['NmbItem'] .= !$this->item_detalle_posicion ? '<br/>' : ': ';
943
                    $item['NmbItem'] .= '<span style="font-size:0.7em">'.$item['DscItem'].'</span>';
944
                }
945
                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...
946
                    unset($item[$col]);
947
            }
948
            // ajustes a IndExe
949
            if (isset($item['IndExe'])) {
950
                if ($item['IndExe']==1)
951
                    $item['IndExe'] = 'EX';
952
                else if ($item['IndExe']==2)
953
                    $item['IndExe'] = 'NF';
954
            }
955
            // agregar todas las columnas que se podrían imprimir en la tabla
956
            $item_default = [];
957
            foreach ($this->detalle_cols as $key => $info)
958
                $item_default[$key] = false;
959
            $item = array_merge($item_default, $item);
960
            // si hay código de item se extrae su valor
961
            if ($item['CdgItem'])
962
                $item['CdgItem'] = $item['CdgItem']['VlrCodigo'];
963
            // dar formato a números
964
            foreach (['QtyItem', 'PrcItem', 'DescuentoMonto', 'RecargoMonto', 'MontoItem'] as $col) {
965
                if ($item[$col])
966
                    $item[$col] = $this->num($item[$col]);
967
            }
968
        }
969
        // opciones
970
        $options = ['align'=>[]];
971
        $i = 0;
972
        foreach ($this->detalle_cols as $info) {
973
            if (isset($info['width']))
974
                $options['width'][$i] = $info['width'];
975
            $options['align'][$i] = $info['align'];
976
            $i++;
977
        }
978
        // agregar tabla de detalle
979
        $this->Ln();
980
        $this->SetX($x);
981
        $this->addTableWithoutEmptyCols($titulos, $detalle, $options);
982
    }
983
984
    /**
985
     * Método que agrega el detalle del documento
986
     * @param detalle Arreglo con el detalle del documento (tag Detalle del XML)
987
     * @param x Posición horizontal de inicio en el PDF
988
     * @param y Posición vertical de inicio en el PDF
989
     * @author Pablo Reyes (https://github.com/pabloxp)
990
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
991
     * @version 2016-12-13
992
     */
993
    private function agregarDetalleContinuo($detalle, $x = 3)
994
    {
995
        $this->SetY($this->getY()+1);
996
        $p1x = $x;
997
        $p1y = $this->y;
998
        $p2x = $this->getPageWidth() - 2;
999
        $p2y = $p1y;  // Use same y for a straight line
1000
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
1001
        $this->Line($p1x, $p1y, $p2x, $p2y, $style);
1002
        $this->Texto($this->detalle_cols['NmbItem']['title'], $x+1, $this->y, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
1003
        $this->Texto($this->detalle_cols['PrcItem']['title'], $x+15, $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
1004
        $this->Texto($this->detalle_cols['QtyItem']['title'], $x+35, $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
1005
        $this->Texto($this->detalle_cols['MontoItem']['title'], $x+45, $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
1006
        $this->Line($p1x, $p1y+4, $p2x, $p2y+4, $style);
1007
        if (!isset($detalle[0]))
1008
            $detalle = [$detalle];
1009
        $this->SetY($this->getY()+2);
1010
        foreach($detalle as  &$d) {
1011
            $this->MultiTexto($d['NmbItem'], $x+1, $this->y+4, ucfirst($this->detalle_cols['NmbItem']['align'][0]), $this->detalle_cols['NmbItem']['width']);
1012
            $this->Texto(number_format($d['PrcItem'],0,',','.'), $x+15, $this->y, ucfirst($this->detalle_cols['PrcItem']['align'][0]), $this->detalle_cols['PrcItem']['width']);
1013
            $this->Texto($this->num($d['QtyItem']), $x+35, $this->y, ucfirst($this->detalle_cols['QtyItem']['align'][0]), $this->detalle_cols['QtyItem']['width']);
1014
            $this->Texto($this->num($d['MontoItem']), $x+45, $this->y, ucfirst($this->detalle_cols['MontoItem']['align'][0]), $this->detalle_cols['MontoItem']['width']);
1015
        }
1016
        $this->Line($p1x, $this->y+4, $p2x, $this->y+4, $style);
1017
    }
1018
1019
    /**
1020
     * Método que agrega el subtotal del DTE
1021
     * @param detalle Arreglo con los detalles del documentos para poder
1022
     * calcular subtotal
1023
     * @param x Posición horizontal de inicio en el PDF
1024
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1025
     * @version 2016-08-17
1026
     */
1027
    private function agregarSubTotal(array $detalle, $x = 10) {
1028
        $subtotal = 0;
1029
        if (!isset($detalle[0])) {
1030
            $detalle = [$detalle];
1031
        }
1032
        foreach($detalle as  &$d) {
1033
            if (!empty($d['MontoItem'])) {
1034
                $subtotal += $d['MontoItem'];
1035
            }
1036
        }
1037
        if ($this->papelContinuo) {
1038
            $this->Texto('Subtotal: '.$this->num($subtotal), $x);
1039
        } else {
1040
            $this->Texto('Subtotal:', 77, null, 'R', 100);
1041
            $this->Texto($this->num($subtotal), 177, null, 'R', 22);
1042
        }
1043
        $this->Ln();
1044
    }
1045
1046
    /**
1047
     * Método que agrega los descuentos y/o recargos globales del documento
1048
     * @param descuentosRecargos Arreglo con los descuentos y/o recargos del documento (tag DscRcgGlobal del XML)
1049
     * @param x Posición horizontal de inicio en el PDF
1050
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1051
     * @version 2016-08-17
1052
     */
1053
    private function agregarDescuentosRecargos(array $descuentosRecargos, $x = 10)
1054
    {
1055
        if (!isset($descuentosRecargos[0]))
1056
            $descuentosRecargos = [$descuentosRecargos];
1057
        foreach($descuentosRecargos as $dr) {
1058
            $tipo = $dr['TpoMov']=='D' ? 'Descuento' : 'Recargo';
1059
            $valor = $dr['TpoValor']=='%' ? $dr['ValorDR'].'%' : $this->num($dr['ValorDR']);
1060
            if ($this->papelContinuo) {
1061
                $this->Texto($tipo.' global: '.$valor.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):''), $x);
1062
            } else {
1063
                $this->Texto($tipo.(!empty($dr['GlosaDR'])?(' ('.$dr['GlosaDR'].')'):'').':', 77, null, 'R', 100);
1064
                $this->Texto($valor, 177, null, 'R', 22);
1065
            }
1066
            $this->Ln();
1067
        }
1068
    }
1069
1070
    /**
1071
     * Método que agrega los pagos del documento
1072
     * @param pagos Arreglo con los pagos del documento
1073
     * @param x Posición horizontal de inicio en el PDF
1074
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1075
     * @version 2016-07-24
1076
     */
1077
    private function agregarPagos(array $pagos, $x = 10)
1078
    {
1079
        if (!isset($pagos[0]))
1080
            $pagos = [$pagos];
1081
        $this->Texto('Pago(s) programado(s):', $x);
1082
        $this->Ln();
1083
        foreach($pagos as $p) {
1084
            $this->Texto('  - '.$this->date($p['FchPago'], false).': $'.$this->num($p['MntPago']).'.-'.(!empty($p['GlosaPagos'])?(' ('.$p['GlosaPagos'].')'):''), $x);
1085
            $this->Ln();
1086
        }
1087
    }
1088
1089
    /**
1090
     * Método que agrega los totales del documento
1091
     * @param totales Arreglo con los totales (tag Totales del XML)
1092
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1093
     * @version 2017-10-05
1094
     */
1095
    private function agregarTotales(array $totales, $otra_moneda, $y = 190, $x = 145, $offset = 25)
1096
    {
1097
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
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...
1098
        // normalizar totales
1099
        $totales = array_merge([
1100
            'TpoMoneda' => false,
1101
            'MntNeto' => false,
1102
            'MntExe' => false,
1103
            'TasaIVA' => false,
1104
            'IVA' => false,
1105
            'IVANoRet' => false,
1106
            'CredEC' => false,
1107
            'MntTotal' => false,
1108
            'MontoNF' => false,
1109
            'MontoPeriodo' => false,
1110
            'SaldoAnterior' => false,
1111
            'VlrPagar' => false,
1112
        ], $totales);
1113
        // glosas
1114
        $glosas = [
1115
            'TpoMoneda' => 'Moneda',
1116
            'MntNeto' => 'Neto $',
1117
            'MntExe' => 'Exento $',
1118
            'IVA' => 'IVA ('.$totales['TasaIVA'].'%) $',
1119
            'IVANoRet' => 'IVA no retenido $',
1120
            'CredEC' => 'Desc. 65% IVA $',
1121
            'MntTotal' => 'Total $',
1122
            'MontoNF' => 'Monto no facturable $',
1123
            'MontoPeriodo' => 'Monto período $',
1124
            'SaldoAnterior' => 'Saldo anterior $',
1125
            'VlrPagar' => 'Valor a pagar $',
1126
        ];
1127
        // agregar impuestos adicionales y retenciones
1128
        if (!empty($totales['ImptoReten'])) {
1129
            $ImptoReten = $totales['ImptoReten'];
1130
            $MntTotal = $totales['MntTotal'];
1131
            unset($totales['ImptoReten'], $totales['MntTotal']);
1132
            if (!isset($ImptoReten[0])) {
1133
                $ImptoReten = [$ImptoReten];
1134
            }
1135
            foreach($ImptoReten as $i) {
1136
                $totales['ImptoReten_'.$i['TipoImp']] = $i['MontoImp'];
1137
                if (!empty($i['TasaImp'])) {
1138
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' ('.$i['TasaImp'].'%) $';
1139
                } else {
1140
                    $glosas['ImptoReten_'.$i['TipoImp']] = \sasco\LibreDTE\Sii\ImpuestosAdicionales::getGlosa($i['TipoImp']).' $';
1141
                }
1142
            }
1143
            $totales['MntTotal'] = $MntTotal;
1144
        }
1145
        // agregar cada uno de los totales
1146
        $this->setY($y);
1147
        $this->setFont('', 'B', null);
1148
        foreach ($totales as $key => $total) {
1149
            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...
1150
                $y = $this->GetY();
1151
                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...
1152
                    $this->Texto($glosas[$key].' :', $x, null, 'R', 30);
1153
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1154
                    $this->Ln();
1155
                } else {
1156
                    $this->MultiTexto($glosas[$key].' :', $x, null, 'R', 30);
1157
                    $y_new = $this->GetY();
1158
                    $this->Texto($this->num($total), $x+$offset, $y, 'R', 30);
1159
                    $this->SetY($y_new);
1160
                }
1161
            }
1162
        }
1163
        // agregar totales en otra moneda
1164
        if (!empty($otra_moneda)) {
1165
            if (!isset($otra_moneda[0])) {
1166
                $otra_moneda = [$otra_moneda];
1167
            }
1168
            $this->setFont('', '', null);
1169
            $this->Ln();
1170
            foreach ($otra_moneda as $om) {
1171
                $y = $this->GetY();
1172
                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...
1173
                    $this->Texto('Total '.$om['TpoMoneda'].' :', $x, null, 'R', 30);
1174
                    $this->Texto($this->num($om['MntTotOtrMnda']), $x+$offset, $y, 'R', 30);
1175
                    $this->Ln();
1176
                } else {
1177
                    $this->MultiTexto('Total '.$om['TpoMoneda'].' :', $x, null, 'R', 30);
1178
                    $y_new = $this->GetY();
1179
                    $this->Texto($this->num($om['MntTotOtrMnda']), $x+$offset, $y, 'R', 30);
1180
                    $this->SetY($y_new);
1181
                }
1182
            }
1183
            $this->setFont('', 'B', null);
1184
        }
1185
    }
1186
1187
    /**
1188
     * Método que coloca las diferentes observaciones que puede tener el documnto
1189
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1190
     * @version 2017-10-05
1191
     */
1192
    private function agregarObservacion($IdDoc, $x = 10, $y = 190)
1193
    {
1194
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
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...
1195
        if (!$this->papelContinuo and $this->timbre_pie) {
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...
1196
            $y -= 15;
1197
        }
1198
        $this->SetXY($x, $y);
1199
        if (!empty($IdDoc['TermPagoGlosa'])) {
1200
            $this->MultiTexto('Observación: '.$IdDoc['TermPagoGlosa']);
1201
        }
1202
        return $this->GetY();
1203
    }
1204
1205
    /**
1206
     * Método que agrega el timbre de la factura
1207
     *  - Se imprime en el tamaño mínimo: 2x5 cms
1208
     *  - En el lado de abajo con margen izquierdo mínimo de 2 cms
1209
     * @param timbre String con los datos del timbre
1210
     * @param x Posición horizontal de inicio en el PDF
1211
     * @param y Posición vertical de inicio en el PDF
1212
     * @param w Ancho del timbre
1213
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1214
     * @version 2017-10-05
1215
     */
1216
    private function agregarTimbre($timbre, $x_timbre = 20, $x = 20, $y = 190, $w = 70, $font_size = 8)
1217
    {
1218
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
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...
1219
        if ($timbre!==null) {
1220
            $style = [
1221
                'border' => false,
1222
                'padding' => 0,
1223
                'hpadding' => 0,
1224
                'vpadding' => 0,
1225
                'module_width' => 1, // width of a single module in points
1226
                'module_height' => 1, // height of a single module in points
1227
                'fgcolor' => [0,0,0],
1228
                '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...
1229
                'position' => $this->papelContinuo ? 'C' : 'S',
1230
            ];
1231
            $ecl = version_compare(phpversion(), '7.0.0', '<') ? -1 : $this->ecl;
1232
            $this->write2DBarcode($timbre, 'PDF417,,'.$ecl, $x_timbre, $y, $w, 0, $style, 'B');
1233
            $this->setFont('', 'B', $font_size);
1234
            $this->Texto('Timbre Electrónico SII', $x, null, 'C', $w);
1235
            $this->Ln();
1236
            $this->Texto('Resolución '.$this->resolucion['NroResol'].' de '.explode('-', $this->resolucion['FchResol'])[0], $x, null, 'C', $w);
1237
            $this->Ln();
1238
            if ($w>=60) {
1239
                $this->Texto('Verifique documento: '.$this->web_verificacion, $x, null, 'C', $w);
1240
            } else {
1241
                $this->Texto('Verifique documento:', $x, null, 'C', $w);
1242
                $this->Ln();
1243
                $this->Texto($this->web_verificacion, $x, null, 'C', $w);
1244
            }
1245
        }
1246
    }
1247
1248
    /**
1249
     * Método que agrega el acuse de rebido
1250
     * @param x Posición horizontal de inicio en el PDF
1251
     * @param y Posición vertical de inicio en el PDF
1252
     * @param w Ancho del acuse de recibo
1253
     * @param h Alto del acuse de recibo
1254
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1255
     * @version 2017-10-05
1256
     */
1257
    private function agregarAcuseRecibo($x = 93, $y = 190, $w = 50, $h = 40)
1258
    {
1259
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
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...
1260
        $this->SetTextColorArray([0,0,0]);
1261
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1262
        $this->setFont('', 'B', 10);
1263
        $this->Texto('Acuse de recibo', $x, $y+1, 'C', $w);
1264
        $this->setFont('', 'B', 8);
1265
        $this->Texto('Nombre', $x+2, $this->y+8);
1266
        $this->Texto('________________', $x+18);
1267
        $this->Texto('R.U.T.', $x+2, $this->y+6);
1268
        $this->Texto('________________', $x+18);
1269
        $this->Texto('Fecha', $x+2, $this->y+6);
1270
        $this->Texto('________________', $x+18);
1271
        $this->Texto('Recinto', $x+2, $this->y+6);
1272
        $this->Texto('________________', $x+18);
1273
        $this->Texto('Firma', $x+2, $this->y+8);
1274
        $this->Texto('________________', $x+18);
1275
        $this->setFont('', 'B', 7);
1276
        $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);
1277
    }
1278
1279
    /**
1280
     * Método que agrega el acuse de rebido
1281
     * @param x Posición horizontal de inicio en el PDF
1282
     * @param y Posición vertical de inicio en el PDF
1283
     * @param w Ancho del acuse de recibo
1284
     * @param h Alto del acuse de recibo
1285
     * @author Pablo Reyes (https://github.com/pabloxp)
1286
     * @version 2015-11-17
1287
     */
1288
    private function agregarAcuseReciboContinuo($x = 3, $y = null, $w = 68, $h = 40)
1289
    {
1290
        $this->SetTextColorArray([0,0,0]);
1291
        $this->Rect($x, $y, $w, $h, 'D', ['all' => ['width' => 0.1, 'color' => [0, 0, 0]]]);
1292
        $style = array('width' => 0.2,'color' => array(0, 0, 0));
1293
        $this->Line($x, $y+22, $w+3, $y+22, $style);
1294
        //$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...
1295
        //$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...
1296
        $this->setFont('', 'B', 6);
1297
        $this->Texto('Nombre:', $x+2, $this->y+8);
1298
        $this->Texto('_____________________________________________', $x+12);
1299
        $this->Texto('R.U.T.:', $x+2, $this->y+6);
1300
        $this->Texto('________________', $x+12);
1301
        $this->Texto('Firma:', $x+32, $this->y+0.5);
1302
        $this->Texto('___________________', $x+42.5);
1303
        $this->Texto('Fecha:', $x+2, $this->y+6);
1304
        $this->Texto('________________', $x+12);
1305
        $this->Texto('Recinto:', $x+32, $this->y+0.5);
1306
        $this->Texto('___________________', $x+42.5);
1307
1308
        $this->setFont('', 'B', 5);
1309
        $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);
1310
    }
1311
1312
    /**
1313
     * Método que agrega la leyenda de destino
1314
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1315
     * @version 2017-10-05
1316
     */
1317
    private function agregarLeyendaDestino($tipo, $y = 190, $font_size = 10)
1318
    {
1319
        $y = (!$this->papelContinuo and !$this->timbre_pie) ? $this->x_fin_datos : $y;
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...
1320
        $y += 64;
1321
        $this->setFont('', 'B', $font_size);
1322
        $this->Texto('CEDIBLE'.($tipo==52?' CON SU FACTURA':''), null, $y, 'R');
1323
    }
1324
1325
    /**
1326
     * Método que agrega la leyenda de destino
1327
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1328
     * @version 2017-10-05
1329
     */
1330
    private function agregarLeyendaDestinoContinuo($tipo)
1331
    {
1332
        $this->setFont('', 'B', 8);
1333
        $this->Texto('CEDIBLE'.($tipo==52?' CON SU FACTURA':''), null, $this->y+6, 'R');
1334
    }
1335
1336
    /**
1337
     * Método que formatea un número con separador de miles y decimales (si
1338
     * corresponden)
1339
     * @param n Número que se desea formatear
1340
     * @return Número formateado
1341
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1342
     * @version 2016-04-05
1343
     */
1344
    private function num($n)
1345
    {
1346
        if (!is_numeric($n))
1347
            return $n;
1348
        $broken_number = explode('.', (string)$n);
1349
        if (isset($broken_number[1]))
1350
            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...
1351
        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...
1352
    }
1353
1354
    /**
1355
     * Método que formatea una fecha en formato YYYY-MM-DD a un string
1356
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
1357
     * @version 2016-04-28
1358
     */
1359
    public function date($date, $mostrar_dia = true)
1360
    {
1361
        $dias = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];
1362
        $meses = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'];
1363
        $unixtime = strtotime($date);
1364
        $fecha = date(($mostrar_dia?'\D\I\A ':'').'j \d\e \M\E\S \d\e\l Y', $unixtime);
1365
        $dia = $dias[date('w', $unixtime)];
1366
        $mes = $meses[date('n', $unixtime)-1];
1367
        return str_replace(array('DIA', 'MES'), array($dia, $mes), $fecha);
1368
    }
1369
1370
}
1371