Completed
Push — master ( 4dae1d...9bdb13 )
by Esteban De La Fuente
02:27
created

PDF   C

Complexity

Total Complexity 76

Size/Duplication

Total Lines 394
Duplicated Lines 14.21 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
wmc 76
lcom 2
cbo 0
dl 56
loc 394
rs 5.488
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A Header() 0 3 1
B Footer() 6 21 9
A setFooterText() 0 19 4
B getTableCellWidth() 0 17 5
F addTableWithoutEmptyCols() 0 43 15
A addTable() 0 9 2
F addHTMLTable() 12 41 20
D addNormalTable() 12 104 13
A Texto() 13 13 3
A MultiTexto() 13 13 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like PDF often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PDF, and based on these observations, apply Extract Interface, too.

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;
25
26
// Directorio para imágenes (no se asume nada)
27
define ('K_PATH_IMAGES', '');
28
29
/**
30
 * Clase para generar PDFs
31
 *
32
 * Los métodos se copiaron desde la clase \sowerphp\general\View_Helper_PDF
33
 * disponible en:
34
 *
35
 * <https://github.com/SowerPHP/extension-general/blob/master/View/Helper/PDF.php>
36
 *
37
 * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
38
 * @version 2016-10-06
39
 */
40
class PDF extends \TCPDF
41
{
42
43
    private $footer; ///< Mensaje a colocar en el footer
44
45
    protected $defaultOptions = [
46
        'font' => ['family' => 'helvetica', 'size' => 10],
47
        'table' => [
48
            'fontsize' => 10,
49
            'width' => 186,
50
            'height' => 6,
51
            'end' => null, // indica la coordenada 'y' donde termina la tabla
52
            'align' => 'C',
53
            'bordercolor' => [0, 0, 0],
54
            'borderwidth' => 0.1,
55
            'headerbackground' => [255, 255, 255],
56
            'headercolor' => [0, 0, 0],
57
            'bodybackground' => [255, 255, 255],
58
            'bodycolor' => [0, 0, 0],
59
            'colorchange' => false,
60
        ],
61
    ];
62
63
    /**
64
     * Constructor de la clase
65
     * @param o Orientación
66
     * @param u Unidad de medida
67
     * @param s Tipo de hoja
68
     * @param top Margen extra (al normal) para la parte de arriba del PDF
69
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
70
     * @version 2016-03-20
71
     */
72
    public function __construct($o = 'P', $u = 'mm', $s = 'LETTER', $top = 0)
73
    {
74
        parent::__construct($o, $u, $s);
75
        $this->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP+$top, PDF_MARGIN_RIGHT);
76
        $this->SetHeaderMargin(PDF_MARGIN_HEADER+$top);
77
        $this->SetFooterMargin(PDF_MARGIN_FOOTER+6);
78
        $this->SetAuthor('Un proyecto de SASCO SpA - https://sasco.cl');
79
        $this->SetCreator('LibreDTE - https://libredte.cl');
80
        $this->setFont($this->defaultOptions['font']['family']);
81
    }
82
83
    /**
84
     * Método para evitar que se renderice el de TCPDF
85
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
86
     * @version 2015-09-08
87
     */
88
    public function Header()
89
    {
90
    }
91
92
    /**
93
     * Método que genera el footer del PDF
94
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
95
     * @version 2015-03-20
96
     */
97
    public function Footer()
98
    {
99
        if (is_array($this->footer) and (!empty($this->footer['left']) or !empty($this->footer['right']))) {
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...
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...
100
            $style = ['width' => 0.5, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => [50, 50, 50]];
101
            $this->Line(0, $this->getY()-1, 290, $this->getY()-2, $style);
102
            $this->SetFont('', 'B', 6);
103
            if (empty($this->papelContinuo)) {
104
                if (!empty($this->footer['left']))
105
                    $this->Texto($this->footer['left']);
106
                if (!empty($this->footer['right']))
107
                    $this->Texto($this->footer['right'], null, null, 'R');
108
            } else {
109 View Code Duplication
                if (!empty($this->footer['left']))
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...
110
                    $this->Texto($this->footer['left'], null, null, 'C');
111 View Code Duplication
                if (!empty($this->footer['right'])) {
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...
112
                    $this->Ln();
113
                    $this->Texto($this->footer['right'], null, null, 'C');
114
                }
115
            }
116
        }
117
    }
118
119
    /**
120
     * Método que asigna el texto que se deberá usar en el footer
121
     * @param footer =true se asignará texto por defecto. String al lado izquiero o bien arreglo con índices left y right con sus textos
122
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
123
     * @version 2016-03-20
124
     */
125
    public function setFooterText($footer = true)
126
    {
127
        if ($footer) {
128
            // asignar valor por defecto
129
            if ($footer===true) {
130
                $footer = [
131
                    'left' => 'LibreDTE ¡facturación electrónica libre para Chile!',
132
                    'right' => 'https://libredte.cl',
133
                ];
134
            }
135
            // si no es arreglo se convierte en uno
136
            if (!is_array($footer))
137
                $footer = ['left'=>$footer];
138
            // asignar footer
139
            $this->footer = array_merge(['left'=>'', 'right'=>''], $footer);
140
        } else {
141
            $this->footer = null;
142
        }
143
    }
144
145
    /**
146
     * Obtener el ancho de las columnas de una tabla
147
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
148
     * @version 2016-01-22
149
     */
150
    private function getTableCellWidth($total, $cells)
151
    {
152
        $widths = [];
153
        if (is_int($cells)) {
154
            $width = floor($total/$cells);
155
            for ($i=0; $i<$cells; ++$i) {
156
                $widths[] = $width;
157
            }
158
        }
159
        else if (is_array($cells)){
160
            $width = floor($total/count($cells));
161
            foreach ($cells as $i) {
162
                $widths[$i] = $width;
163
            }
164
        }
165
        return $widths;
166
    }
167
168
    /**
169
     * Agregar una tabla al PDF removiendo aquellas columnas donde no existen
170
     * datos en la columna para todas las filas
171
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
172
     * @version 2016-10-06
173
     */
174
    public function addTableWithoutEmptyCols($titles, $data, $options = [], $html = true)
175
    {
176
        $cols_empty = [];
177
        foreach ($data as $row) {
178
            foreach ($row as $col => $value) {
179
                if (empty($value)) {
180
                    if (!array_key_exists($col, $cols_empty))
181
                        $cols_empty[$col] = 0;
182
                    $cols_empty[$col]++;
183
                }
184
            }
185
        }
186
        $n_rows = count($data);
187
        $titles_keys = array_flip(array_keys($titles));
188
        foreach ($cols_empty as $col => $rows) {
189
            if ($rows==$n_rows) {
190
                unset($titles[$col]);
191
                foreach ($data as &$row) {
192
                    unset($row[$col]);
193
                }
194
                if (isset($options['width']))
195
                    unset($options['width'][$titles_keys[$col]]);
196
                if (isset($options['align']))
197
                    unset($options['align'][$titles_keys[$col]]);
198
            }
199
        }
200
        if (isset($options['width'])) {
201
            $options['width'] = array_slice($options['width'], 0);
202
            $key_0 = null;
203
            $suma = 0;
204
            foreach ($options['width'] as $key => $val) {
205
                if ($val===0)
206
                    $key_0 = $key;
207
                $suma += $val;
208
            }
209
            if ($key_0!==null) {
210
                $options['width'][$key_0] = 190 - $suma;
211
            }
212
        }
213
        if (isset($options['align']))
214
            $options['align'] = array_slice($options['align'], 0);
215
        $this->addTable($titles, $data, $options, $html);
216
    }
217
218
    /**
219
     * Agregar una tabla generada al PDF (puede ser en HTML o normal)
220
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
221
     * @version 2016-10-06
222
     */
223
    public function addTable($headers, $data, $options = [], $html = true)
224
    {
225
        $options = array_merge($this->defaultOptions['table'], $options);
226
        if ($html) {
227
            $this->addHTMLTable($headers, $data, $options);
228
        } else {
229
            $this->addNormalTable($headers, $data, $options);
230
        }
231
    }
232
233
    /**
234
     * Agregar una tabla generada a través de código HTML al PDF
235
     * @todo Utilizar las opciones para definir estilo de la tabla HTML
236
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
237
     * @version 2016-10-06
238
     */
239
    private function addHTMLTable($headers, $data, $options = [])
240
    {
241
        $w = (isset($options['width']) and is_array($options['width'])) ? $options['width'] : null;
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...
242
        $a = (isset($options['align']) and is_array($options['align'])) ? $options['align'] : [];
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...
243
        $buffer = '<table style="border:1px solid #333">';
244
        // Definir títulos de columnas
245
        $thead = isset($options['width']) and is_array($options['width']) and count($options['width']) == count($headers);
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...
246
        if ($thead)
247
            $buffer .= '<thead>';
248
        $buffer .= '<tr>';
249
        $i = 0;
250 View Code Duplication
        foreach ($headers as &$col) {
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...
251
            $width = ($w and isset($w[$i])) ? (';width:'.$w[$i].'mm') : '';
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...
252
            $align = isset($a[$i]) ? $a[$i] : 'center';
253
            $buffer .= '<th style="border-right:1px solid #333;border-bottom:1px solid #333;text-align:'.$align.$width.'"><strong>'.strip_tags($col).'</strong></th>';
254
            $i++;
255
        }
256
        $buffer .= '</tr>';
257
        if ($thead)
258
            $buffer .= '</thead>';
259
        // Definir datos de la tabla
260
        if ($thead)
261
            $buffer .= '<tbody>';
262
        foreach ($data as &$row) {
263
            $buffer .= '<tr>';
264
            $i = 0;
265 View Code Duplication
            foreach ($row as &$col) {
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...
266
                $width = ($w and isset($w[$i])) ? (';width:'.$w[$i].'mm') : '';
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...
267
                $align = isset($a[$i]) ? $a[$i] : 'center';
268
                $buffer .= '<td style="border-right:1px solid #333;text-align:'.$align.$width.'">'.$col.'</td>';
269
                $i++;
270
            }
271
            $buffer .= '</tr>';
272
        }
273
        if ($thead)
274
            $buffer .= '</tbody>';
275
        // Finalizar tabla
276
        $buffer .= '</table>';
277
        // generar tabla en HTML
278
        $this->writeHTML($buffer, true, false, false, false, '');
279
    }
280
281
    /**
282
     * Agregar una tabla generada mediante el método Cell
283
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
284
     * @version 2018-04-15
285
     */
286
    private function addNormalTable(array $headers, array $data, array $options = [])
287
    {
288
        // Colors, line width and bold font
289
        $this->SetFillColor(
290
            $options['headerbackground'][0],
291
            $options['headerbackground'][1],
292
            $options['headerbackground'][2]
293
        );
294
        $this->SetTextColor(
295
            $options['headercolor'][0],
296
            $options['headercolor'][1],
297
            $options['headercolor'][2]
298
        );
299
        $this->SetDrawColor(
300
            $options['bordercolor'][0],
301
            $options['bordercolor'][1],
302
            $options['bordercolor'][2]
303
        );
304
        $this->SetLineWidth($options['borderwidth']);
305
        $this->SetFont($this->defaultOptions['font']['family'], 'B',  $options['fontsize']);
306
        // corregir indices
307
        $headers_keys = array_keys($headers);
308
        if (is_array($options['width'])) {
309
            $options['width'] = array_combine($headers_keys, $options['width']);
310
        } else {
311
            $options['width'] = $this->getTableCellWidth($options['width'], $headers_keys);
312
        }
313
        if (is_array($options['width'])) {
314
            $options['align'] = array_combine($headers_keys, $options['align']);
315
            foreach ($options['align'] as &$a) {
316
                $a = strtoupper($a[0]);
317
            }
318
        }
319
        // Header
320
        $x = $this->GetX();
321 View Code Duplication
        foreach($headers as $i => $header) {
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...
322
            $this->Cell($options['width'][$i], $options['height'], $headers[$i], 1, 0, $options['align'][$i], 1);
323
        }
324
        $this->Ln();
325
        // Color and font restoration
326
        $this->SetFillColor (
327
            $options['bodybackground'][0],
328
            $options['bodybackground'][1],
329
            $options['bodybackground'][2]
330
        );
331
        $this->SetTextColor(
332
            $options['bodycolor'][0],
333
            $options['bodycolor'][1],
334
            $options['bodycolor'][2]
335
        );
336
        $this->SetDrawColor(
337
            $options['bordercolor'][0],
338
            $options['bordercolor'][1],
339
            $options['bordercolor'][2]
340
        );
341
        $this->SetLineWidth($options['borderwidth']);
342
        $this->SetFont($this->defaultOptions['font']['family']);
343
        // Data
344
        $fill = false;
345
        foreach ($data as &$row) {
346
            $num_pages = $this->getNumPages();
347
            $this->startTransaction();
348
            $this->SetX($x);
349 View Code Duplication
            foreach($headers as $i => $header) {
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...
350
                $this->Cell($options['width'][$i], $options['height'], $row[$i], 'LR', 0, $options['align'][$i], $fill);
351
            }
352
            $this->Ln();
353
            if($num_pages < $this->getNumPages()) {
354
                $this->rollbackTransaction(true);
355
                $this->AddPage();
356
                $this->SetX($x);
357 View Code Duplication
                foreach($headers as $i => $header) {
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...
358
                    $this->Cell($options['width'][$i], $options['height'], $headers[$i], 1, 0, $options['align'][$i], 1);
359
                }
360
                $this->Ln();
361
                $this->SetX($x);
362 View Code Duplication
                foreach($headers as $i => $header) {
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...
363
                    $this->Cell($options['width'][$i], $options['height'], $row[$i], 'LR', 0, $options['align'][$i], $fill);
364
                }
365
                $this->Ln();
366
            } else {
367
                $this->commitTransaction();
368
            }
369
            if ($options['colorchange']) {
370
                $fill = !$fill;
371
            }
372
        }
373
        // si la tabla tiene indicado un punto específico en Y donde terminar se usa ese punto
374
        if ($options['end']) {
375
            $y = $this->GetY();
376
            $lx = $x;
377
            $this->Line($lx, $y, $lx, $options['end']);
378
            foreach ($options['width'] as $ancho) {
379
                $lx += $ancho;
380
                $this->Line($lx, $y, $lx, $options['end']);
381
            }
382
            $this->SetXY($x, $options['end']);
383
        } else {
384
            $this->SetX($x);
385
        }
386
        // asignar línea final
387
        $this->Cell(array_sum($options['width']), 0, '', 'T');
388
        $this->Ln();
389
    }
390
391
    /**
392
     * Agregar texto al PDF, es una variación del método Text que permite
393
     * definir un ancho al texto. Además recibe menos parámetros para ser
394
     * más simple (parámetros comunes solamente).
395
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
396
     * @version 2014-09-20
397
     */
398 View Code Duplication
    public function Texto($txt, $x=null, $y=null, $align='', $w=0, $link='', $border=0, $fill=false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
399
    {
400
        if ($x==null) $x = $this->GetX();
401
        if ($y==null) $y = $this->GetY();
402
        $textrendermode = $this->textrendermode;
403
        $textstrokewidth = $this->textstrokewidth;
404
        $this->setTextRenderingMode(0, true, false);
405
        $this->SetXY($x, $y);
406
        $this->Cell($w, 0, $txt, $border, 0, $align, $fill, $link);
407
        // restore previous rendering mode
408
        $this->textrendermode = $textrendermode;
409
        $this->textstrokewidth = $textstrokewidth;
410
    }
411
412
    /**
413
     * Método idéntico a Texto, pero en vez de utilizar Cell utiliza
414
     * MultiCell. La principal diferencia es que este método no permite
415
     * agregar un enlace y Texto si.
416
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl)
417
     * @version 2014-09-20
418
     */
419 View Code Duplication
    public function MultiTexto($txt, $x=null, $y=null, $align='', $w=0, $border=0, $fill=false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
420
    {
421
        if ($x==null) $x = $this->GetX();
422
        if ($y==null) $y = $this->GetY();
423
        $textrendermode = $this->textrendermode;
424
        $textstrokewidth = $this->textstrokewidth;
425
        $this->setTextRenderingMode(0, true, false);
426
        $this->SetXY($x, $y);
427
        $this->MultiCell($w, 0, $txt, $border, $align, $fill);
428
        // restore previous rendering mode
429
        $this->textrendermode = $textrendermode;
430
        $this->textstrokewidth = $textstrokewidth;
431
    }
432
433
}
434