Completed
Push — master ( 03c145...62ce4c )
by Esteban De La Fuente
02:18
created

Dte::agregarEmisor()   F

Complexity

Conditions 20
Paths 288

Size

Total Lines 49
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 49
rs 3.8278
c 0
b 0
f 0
cc 20
eloc 38
nc 288
nop 7

How to fix   Complexity   

Long Method

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

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

Commonly applied refactorings include:

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