HTML2PDF_parsingCss::analyse()   F
last analyzed

Complexity

Conditions 193
Paths > 20000

Size

Total Lines 561
Code Lines 416

Duplication

Lines 126
Ratio 22.46 %

Importance

Changes 0
Metric Value
cc 193
eloc 416
nc 4294967295
nop 3
dl 126
loc 561
rs 2
c 0
b 0
f 0

How to fix   Long Method    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
 * HTML2PDF Librairy - parsingCss class
4
 *
5
 * HTML => PDF convertor
6
 * distributed under the LGPL License
7
 *
8
 * @author      Laurent MINGUET <[email protected]>
9
 * @version     4.03
10
 */
11
12
class HTML2PDF_parsingCss
13
{
14
    /**
15
     * reference to the pdf object
16
     * @var TCPDF
17
     */
18
    protected $_pdf         = null;
19
20
    protected $_htmlColor   = array(); // list of the HTML colors
21
    protected $_onlyLeft    = false; // flag if we are in a sub html => only "text-align:left" is used
22
    protected $_defaultFont = null; // default font to use if the asked font does not exist
23
24
    public    $value        = array(); // current values
25
    public    $css          = array(); // css values
26
    public    $cssKeys      = array(); // css key, for the execution order
27
    public    $table        = array(); // level history
28
29
    /**
30
     * Constructor
31
     *
32
     * @param  &HTML2PDF_myPdf reference to the PDF $object
33
     * @param HTML2PDF_myPdf $pdf
34
     * @access public
35
     */
36
    public function __construct(&$pdf)
37
    {
38
        $this->_init();
39
        $this->setPdfParent($pdf);
40
    }
41
42
    /**
43
     * Set the HTML2PDF parent object
44
     *
45
     * @param  &HTML2PDF reference to the HTML2PDF parent $object
46
     * @access public
47
     */
48
    public function setPdfParent(&$pdf)
49
    {
50
        $this->_pdf = &$pdf;
51
    }
52
53
    /**
54
     * Inform that we want only "test-align:left" because we are in a sub HTML
55
     *
56
     * @access public
57
     */
58
    public function setOnlyLeft()
59
    {
60
        $this->value['text-align'] = 'left';
61
        $this->_onlyLeft = true;
62
    }
63
64
    /**
65
     * Get the vales of the parent, if exist
66
     *
67
     * @return array CSS values
68
     * @access public
69
     */
70
    public function getOldValues()
71
    {
72
        return isset($this->table[count($this->table) - 1]) ? $this->table[count($this->table) - 1] : $this->value;
73
    }
74
75
    /**
76
    * define the Default Font to use, if the font does not exist, or if no font asked
77
    *
78
    * @param  string  default font-family. If null : Arial for no font asked, and error fot ont does not exist
79
    * @param string $default
80
    * @return string  old default font-family
81
    * @access public
82
    */
83
    public function setDefaultFont($default = null)
84
    {
85
        $old = $this->_defaultFont;
86
        $this->_defaultFont = $default;
87
        if ($default) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $default of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
88
        	$this->value['font-family'] = $default;
89
        }
90
        return $old;
91
    }
92
93
     /**
94
     * Init the object
95
     *
96
     * @access protected
97
     */
98
    protected function _init()
99
    {
100
        // get the Web Colors from TCPDF
101
        require(K_PATH_MAIN.'htmlcolors.php');
102
        $this->_htmlColor = $webcolor;
0 ignored issues
show
Bug introduced by
The variable $webcolor does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
103
104
        // init the Style
105
        $this->table = array();
106
        $this->value = array();
107
        $this->initStyle();
108
109
        // Init the styles without legacy
110
        $this->resetStyle();
111
    }
112
113
    /**
114
     * Init the CSS Style
115
     *
116
     * @access public
117
     */
118
    public function initStyle()
119
    {
120
        $this->value['id_tag'] = 'body'; // tag name
121
        $this->value['id_name']          = null; // tag - attribute name
122
        $this->value['id_id']            = null; // tag - attribute id
123
        $this->value['id_class']         = null; // tag - attribute class
124
        $this->value['id_lst']           = array('*'); // tag - list of legacy
125
        $this->value['mini-size']        = 1.; // specific size report for sup, sub
126
        $this->value['mini-decal']       = 0; // specific position report for sup, sub
127
        $this->value['font-family']      = 'Arial';
128
        $this->value['font-bold']        = false;
129
        $this->value['font-italic']      = false;
130
        $this->value['font-underline']   = false;
131
        $this->value['font-overline']    = false;
132
        $this->value['font-linethrough'] = false;
133
        $this->value['text-transform']   = 'none';
134
        $this->value['font-size']        = $this->convertToMM('10pt');
135
        $this->value['text-indent']      = 0;
136
        $this->value['text-align']       = 'left';
137
        $this->value['vertical-align']   = 'middle';
138
        $this->value['line-height']      = 'normal';
139
140
        $this->value['position']         = null;
141
        $this->value['x']                = null;
142
        $this->value['y']                = null;
143
        $this->value['width']            = 0;
144
        $this->value['height']           = 0;
145
        $this->value['top']              = null;
146
        $this->value['right']            = null;
147
        $this->value['bottom']           = null;
148
        $this->value['left']             = null;
149
        $this->value['float']            = null;
150
        $this->value['display']          = null;
151
        $this->value['rotate']           = null;
152
        $this->value['overflow']         = 'visible';
153
154
        $this->value['color']            = array(0, 0, 0);
155
        $this->value['background']       = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
156
        $this->value['border']           = array();
157
        $this->value['padding']          = array();
158
        $this->value['margin']           = array();
159
        $this->value['margin-auto']      = false;
160
161
        $this->value['list-style-type']  = '';
162
        $this->value['list-style-image'] = '';
163
164
        $this->value['xc'] = null;
165
        $this->value['yc'] = null;
166
    }
167
168
    /**
169
     * Init the CSS Style without legacy
170
     *
171
     * @param  string  tag name
172
     * @access public
173
     */
174
    public function resetStyle($tagName = '')
175
    {
176
        // prepare somme values
177
        $border = $this->readBorder('solid 1px #000000');
178
        $units = array(
179
            '1px' => $this->convertToMM('1px'),
180
            '5px' => $this->convertToMM('5px'),
181
        );
182
183
184
        // prepare the Collapse attribute
185
        $collapse = isset($this->value['border']['collapse']) ? $this->value['border']['collapse'] : false;
186
        if ( ! in_array($tagName, array('tr', 'td', 'th', 'thead', 'tbody', 'tfoot'))) $collapse = false;
187
188
        // set the global css values
189
        $this->value['position']   = null;
190
        $this->value['x']          = null;
191
        $this->value['y']          = null;
192
        $this->value['width']      = 0;
193
        $this->value['height']     = 0;
194
        $this->value['top']        = null;
195
        $this->value['right']      = null;
196
        $this->value['bottom']     = null;
197
        $this->value['left']       = null;
198
        $this->value['float']      = null;
199
        $this->value['display']    = null;
200
        $this->value['rotate']     = null;
201
        $this->value['overflow']   = 'visible';
202
        $this->value['background'] = array('color' => null, 'image' => null, 'position' => null, 'repeat' => null);
203
        $this->value['border']     = array(
204
            't' => $this->readBorder('none'),
205
            'r' => $this->readBorder('none'),
206
            'b' => $this->readBorder('none'),
207
            'l' => $this->readBorder('none'),
208
            'radius' => array(
209
                'tl' => array(0, 0),
210
                'tr' => array(0, 0),
211
                'br' => array(0, 0),
212
                'bl' => array(0, 0)
213
            ),
214
            'collapse' => $collapse,
215
        );
216
217
        // specific values for some tags
218
        if ( ! in_array($tagName, array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
219
            $this->value['margin'] = array('t'=>0, 'r'=>0, 'b'=>0, 'l'=>0);
220
        }
221
222
        if (in_array($tagName, array('input', 'select', 'textarea'))) {
223
            $this->value['border']['t'] = null;
224
            $this->value['border']['r'] = null;
225
            $this->value['border']['b'] = null;
226
            $this->value['border']['l'] = null;
227
        }
228
229
        if ($tagName == 'p') {
230
            $this->value['margin']['t'] = null;
231
            $this->value['margin']['b'] = null;
232
        }
233
        if ($tagName == 'blockquote') {
234
            $this->value['margin']['t'] = 3;
235
            $this->value['margin']['r'] = 3;
236
            $this->value['margin']['b'] = 3;
237
            $this->value['margin']['l'] = 6;
238
        }
239
        $this->value['margin-auto'] = false;
240
241
        if (in_array($tagName, array('blockquote', 'div', 'fieldset'))) {
242
            $this->value['vertical-align'] = 'top';
243
        }
244
245
        if (in_array($tagName, array('fieldset', 'legend'))) {
246
            $this->value['border'] = array(
247
                't' => $border,
248
                'r' => $border,
249
                'b' => $border,
250
                'l' => $border,
251
                'radius' => array(
252
                    'tl' => array($units['5px'], $units['5px']),
253
                    'tr' => array($units['5px'], $units['5px']),
254
                    'br' => array($units['5px'], $units['5px']),
255
                    'bl' => array($units['5px'], $units['5px'])
256
                ),
257
                'collapse' => false,
258
            );
259
        }
260
261
        if (in_array($tagName, array('ul', 'li'))) {
262
            $this->value['list-style-type']  = '';
263
            $this->value['list-style-image'] = '';
264
        }
265
266
        if ( ! in_array($tagName, array('tr', 'td'))) {
267
            $this->value['padding'] = array(
268
                't' => 0,
269
                'r' => 0,
270
                'b' => 0,
271
                'l' => 0
272
            );
273
        } else {
274
            $this->value['padding'] = array(
275
                't' => $units['1px'],
276
                'r' => $units['1px'],
277
                'b' => $units['1px'],
278
                'l' => $units['1px']
279
            );
280
        }
281
282
        if ($tagName == 'hr') {
283
            $this->value['border'] = array(
284
                't' => $border,
285
                'r' => $border,
286
                'b' => $border,
287
                'l' => $border,
288
                'radius' => array(
289
                    'tl' => array(0, 0),
290
                    'tr' => array(0, 0),
291
                    'br' => array(0, 0),
292
                    'bl' => array(0, 0)
293
                ),
294
                'collapse' => false,
295
            );
296
            $this->convertBackground('#FFFFFF', $this->value['background']);
297
        }
298
299
        $this->value['xc'] = null;
300
        $this->value['yc'] = null;
301
    }
302
303
    /**
304
     * Init the PDF Font
305
     *
306
     * @access public
307
     */
308
    public function fontSet()
309
    {
310
        $family = strtolower($this->value['font-family']);
311
312
        $b = ($this->value['font-bold'] ? 'B' : '');
313
        $i = ($this->value['font-italic'] ? 'I' : '');
314
        $u = ($this->value['font-underline'] ? 'U' : '');
315
        $d = ($this->value['font-linethrough'] ? 'D' : '');
316
        $o = ($this->value['font-overline'] ? 'O' : '');
317
318
        // font style
319
        $style = $b.$i;
320
321
        if ($this->_defaultFont) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_defaultFont of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
322 View Code Duplication
            if ($family == 'arial')
323
                $family = 'helvetica';
324
            elseif ($family == 'symbol' || $family == 'zapfdingbats')
325
                $style = '';
326
327
            $fontkey = $family.$style;
328
            if ( ! $this->_pdf->isLoadedFont($fontkey))
329
                $family = $this->_defaultFont;
330
        }
331
332 View Code Duplication
        if ($family == 'arial')
333
            $family = 'helvetica';
334
        elseif ($family == 'symbol' || $family == 'zapfdingbats')
335
            $style = '';
336
337
        // complete style
338
        $style .= $u.$d.$o;
339
340
        // size : mm => pt
341
        $size = $this->value['font-size'];
342
        $size = 72 * $size / 25.4;
343
344
        // apply the font
345
        $this->_pdf->SetFont($family, $style, $this->value['mini-size'] * $size);
346
        $this->_pdf->setTextColorArray($this->value['color']);
347
        if ($this->value['background']['color']) {
348
                    $this->_pdf->setFillColorArray($this->value['background']['color']);
349
        } else {
350
                    $this->_pdf->setFillColor(255);
351
        }
352
    }
353
354
     /**
355
     * add a level in the CSS history
356
     *
357
     * @access public
358
     */
359
    public function save()
360
    {
361
        array_push($this->table, $this->value);
362
    }
363
364
     /**
365
     * remove a level in the CSS history
366
     *
367
     * @access public
368
     */
369
    public function load()
370
    {
371
        if (count($this->table)) {
372
            $this->value = array_pop($this->table);
373
        }
374
    }
375
376
     /**
377
     * restore the Y positiony (used after a span)
378
     *
379
     * @access public
380
     */
381
    public function restorePosition()
382
    {
383
        if ($this->value['y'] == $this->_pdf->getY()) $this->_pdf->setY($this->value['yc'], false);
384
    }
385
386
     /**
387
     * set the New position for the current Tag
388
     *
389
     * @access public
390
     */
391
    public function setPosition()
392
    {
393
        // get the current position
394
        $currentX = $this->_pdf->getX();
395
        $currentY = $this->_pdf->getY();
396
397
        // save it
398
        $this->value['xc'] = $currentX;
399
        $this->value['yc'] = $currentY;
400
401
        if ($this->value['position'] == 'relative' || $this->value['position'] == 'absolute') {
402
            if ($this->value['right'] !== null) {
403
                $x = $this->getLastWidth(true) - $this->value['right'] - $this->value['width'];
404
                if ($this->value['margin']['r']) $x -= $this->value['margin']['r'];
405 View Code Duplication
            } else {
406
                $x = $this->value['left'];
407
                if ($this->value['margin']['l']) $x += $this->value['margin']['l'];
408
            }
409
410
            if ($this->value['bottom'] !== null) {
411
                $y = $this->getLastHeight(true) - $this->value['bottom'] - $this->value['height'];
412
                if ($this->value['margin']['b']) $y -= $this->value['margin']['b'];
413 View Code Duplication
            } else {
414
                $y = $this->value['top'];
415
                if ($this->value['margin']['t']) $y += $this->value['margin']['t'];
416
            }
417
418
            if ($this->value['position'] == 'relative') {
419
                $this->value['x'] = $currentX + $x;
420
                $this->value['y'] = $currentY + $y;
421
            } else {
422
                $this->value['x'] = $this->_getLastAbsoluteX() + $x;
423
                $this->value['y'] = $this->_getLastAbsoluteY() + $y;
424
            }
425
        } else {
426
            $this->value['x'] = $currentX;
427
            $this->value['y'] = $currentY;
428 View Code Duplication
            if ($this->value['margin']['l']) $this->value['x'] += $this->value['margin']['l'];
429 View Code Duplication
            if ($this->value['margin']['t']) $this->value['y'] += $this->value['margin']['t'];
430
        }
431
432
        // save the new position
433
        $this->_pdf->setXY($this->value['x'], $this->value['y']);
434
    }
435
436
     /**
437
     * Analise the CSS style to convert it into Form style
438
     *
439
     * @access public
440
     * @param  array    styles
441
     */
442
    public function getFormStyle()
443
    {
444
        $prop = array();
445
446
        $prop['alignment'] = $this->value['text-align'];
447
448
        if (isset($this->value['background']['color']) && is_array($this->value['background']['color'])) {
449
            $prop['fillColor'] = $this->value['background']['color'];
450
        }
451
452
        if (isset($this->value['border']['t']['color'])) {
453
            $prop['strokeColor'] = $this->value['border']['t']['color'];
454
        }
455
456
        if (isset($this->value['border']['t']['width'])) {
457
            $prop['lineWidth'] = $this->value['border']['t']['width'];
458
        }
459
460
        if (isset($this->value['border']['t']['type'])) {
461
            $prop['borderStyle'] = $this->value['border']['t']['type'];
462
        }
463
464
        if ( ! empty($this->value['color'])) {
465
            $prop['textColor'] = $this->value['color'];
466
        }
467
468
        if ( ! empty($this->value['font-size'])) {
469
            $prop['textSize'] = $this->value['font-size'];
470
        }
471
472
        return $prop;
473
    }
474
475
     /**
476
     * Analise the CSS style to convert it into SVG style
477
     *
478
     * @access public
479
     * @param  string   tag name
480
     * @param  array    styles
481
     * @param string $tagName
482
     */
483
    public function getSvgStyle($tagName, &$param)
484
    {
485
        // prepare
486
        $tagName = strtolower($tagName);
487
        $id   = isset($param['id']) ? strtolower(trim($param['id'])) : null; if ( ! $id)   $id   = null;
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
488
        $name = isset($param['name']) ? strtolower(trim($param['name'])) : null; if ( ! $name) $name = null;
0 ignored issues
show
Bug Best Practice introduced by
The expression $name of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
489
490
        // read the class attribute
491
        $class = array();
492
        $tmp = isset($param['class']) ? strtolower(trim($param['class'])) : '';
493
        $tmp = explode(' ', $tmp);
494
        foreach ($tmp as $k => $v) {
495
            $v = trim($v);
496
            if ($v) {
497
            	$class[] = $v;
498
            }
499
        }
500
501
        // identify the tag, and the direct styles
502
        $this->value['id_tag'] = $tagName;
503
        $this->value['id_name']   = $name;
504
        $this->value['id_id']     = $id;
505
        $this->value['id_class']  = $class;
506
        $this->value['id_lst']    = array();
507
        $this->value['id_lst'][] = '*';
508
        $this->value['id_lst'][] = $tagName;
509
        if ( ! isset($this->value['svg'])) {
510
            $this->value['svg'] = array(
511
                'stroke'         => null,
512
                'stroke-width'   => $this->convertToMM('1pt'),
513
                'fill'           => null,
514
                'fill-opacity'   => null,
515
            );
516
        }
517
518 View Code Duplication
        if (count($class)) {
519
            foreach ($class as $v) {
520
                $this->value['id_lst'][] = '*.'.$v;
521
                $this->value['id_lst'][] = '.'.$v;
522
                $this->value['id_lst'][] = $tagName.'.'.$v;
523
            }
524
        }
525 View Code Duplication
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
526
            $this->value['id_lst'][] = '*#'.$id;
527
            $this->value['id_lst'][] = '#'.$id;
528
            $this->value['id_lst'][] = $tagName.'#'.$id;
529
        }
530
531
        // CSS style
532
        $styles = $this->_getFromCSS();
533
534
        // adding the style from the tag
535
        $styles = array_merge($styles, $param['style']);
536
537 View Code Duplication
        if (isset($styles['stroke']))        $this->value['svg']['stroke']       = $this->convertToColor($styles['stroke'], $res);
538
        if (isset($styles['stroke-width']))  $this->value['svg']['stroke-width'] = $this->convertToMM($styles['stroke-width']);
539 View Code Duplication
        if (isset($styles['fill']))          $this->value['svg']['fill']         = $this->convertToColor($styles['fill'], $res);
540
        if (isset($styles['fill-opacity']))  $this->value['svg']['fill-opacity'] = 1. * $styles['fill-opacity'];
541
542
        return $this->value['svg'];
543
    }
544
545
    /**
546
     * analyse the css properties from the HTML parsing
547
     *
548
     * @access public
549
     * @param  string  $tagName
550
     * @param  array   $param
551
     * @param  array   $legacy
552
     */
553
    public function analyse($tagName, &$param, $legacy = null)
554
    {
555
        // prepare the informations
556
        $tagName = strtolower($tagName);
557
        $id   = isset($param['id']) ? strtolower(trim($param['id'])) : null; if ( ! $id)   $id   = null;
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
558
        $name = isset($param['name']) ? strtolower(trim($param['name'])) : null; if ( ! $name) $name = null;
0 ignored issues
show
Bug Best Practice introduced by
The expression $name of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
559
560
        // get the class names to use
561
        $class = array();
562
        $tmp = isset($param['class']) ? strtolower(trim($param['class'])) : '';
563
        $tmp = explode(' ', $tmp);
564
        foreach ($tmp as $k => $v) {
565
            $v = trim($v);
566
            if ($v) {
567
            	$class[] = $v;
568
            }
569
        }
570
571
        // prepare the values, and the list of css tags to identify
572
        $this->value['id_tag']   = $tagName;
573
        $this->value['id_name']  = $name;
574
        $this->value['id_id']    = $id;
575
        $this->value['id_class'] = $class;
576
        $this->value['id_lst']   = array();
577
        $this->value['id_lst'][] = '*';
578
        $this->value['id_lst'][] = $tagName;
579 View Code Duplication
        if (count($class)) {
580
            foreach ($class as $v) {
581
                $this->value['id_lst'][] = '*.'.$v;
582
                $this->value['id_lst'][] = '.'.$v;
583
                $this->value['id_lst'][] = $tagName.'.'.$v;
584
            }
585
        }
586 View Code Duplication
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
587
            $this->value['id_lst'][] = '*#'.$id;
588
            $this->value['id_lst'][] = '#'.$id;
589
            $this->value['id_lst'][] = $tagName.'#'.$id;
590
        }
591
592
        // get the css styles from class
593
        $styles = $this->_getFromCSS();
594
595
        // merge with the css styles from tag
596
        $styles = array_merge($styles, $param['style']);
597
        if (isset($param['allwidth']) && ! isset($styles['width'])) $styles['width'] = '100%';
598
599
        // reset some styles, depending on the tag name
600
        $this->resetStyle($tagName);
601
602
        // add the legacy values
603
        if ($legacy) {
604
            foreach ($legacy as $legacyName => $legacyValue) {
605
                if (is_array($legacyValue)) {
606
                    foreach ($legacyValue as $legacy2Name => $legacy2Value)
607
                        $this->value[$legacyName][$legacy2Name] = $legacy2Value;
608
                } else {
609
                    $this->value[$legacyName] = $legacyValue;
610
                }
611
            }
612
        }
613
614
        // some flags
615
        $correctWidth = false;
616
        $noWidth = true;
617
618
        // read all the css styles
619
        foreach ($styles as $nom => $val) {
620
            switch ($nom)
621
            {
622
                case 'font-family':
623
                    $val = explode(',', $val);
624
                    $val = trim($val[0]);
625
                    if ($val) {
626
                    	$this->value['font-family'] = $val;
627
                    }
628
                    break;
629
630
                case 'font-weight':
631
                    $this->value['font-bold'] = ($val == 'bold');
632
                    break;
633
634
                case 'font-style':
635
                    $this->value['font-italic'] = ($val == 'italic');
636
                    break;
637
638
                case 'text-decoration':
639
                    $val = explode(' ', $val);
640
                    $this->value['font-underline']   = (in_array('underline', $val));
641
                    $this->value['font-overline']    = (in_array('overline', $val));
642
                    $this->value['font-linethrough'] = (in_array('line-through', $val));
643
                    break;
644
645
                case 'text-indent':
646
                    $this->value['text-indent'] = $this->convertToMM($val);
647
                    break;
648
649
                case 'text-transform':
650
                    if ( ! in_array($val, array('none', 'capitalize', 'uppercase', 'lowercase'))) $val = 'none';
651
                    $this->value['text-transform'] = $val;
652
                    break;
653
654
                case 'font-size':
655
                    $val = $this->convertToMM($val, $this->value['font-size']);
656
                    if ($val) $this->value['font-size'] = $val;
657
                    break;
658
659
                case 'color':
660
                    $res = null;
661
                    $this->value['color'] = $this->convertToColor($val, $res);
662
                    if ($tagName == 'hr') {
663
                        $this->value['border']['l']['color'] = $this->value['color'];
664
                        $this->value['border']['t']['color'] = $this->value['color'];
665
                        $this->value['border']['r']['color'] = $this->value['color'];
666
                        $this->value['border']['b']['color'] = $this->value['color'];
667
                    }
668
                    break;
669
670
                case 'text-align':
671
                    $val = strtolower($val);
672
                    if ( ! in_array($val, array('left', 'right', 'center', 'justify', 'li_right'))) $val = 'left';
673
                    $this->value['text-align'] = $val;
674
                    break;
675
676
                case 'vertical-align':
677
                    $this->value['vertical-align'] = $val;
678
                    break;
679
680
                case 'width':
681
                    $this->value['width'] = $this->convertToMM($val, $this->getLastWidth());
682
                    if ($this->value['width'] && substr($val, -1) == '%') $correctWidth = true;
683
                    $noWidth = false;
684
                    break;
685
686
                case 'height':
687
                    $this->value['height'] = $this->convertToMM($val, $this->getLastHeight());
688
                    break;
689
690
                case 'line-height':
691
                    if (preg_match('/^[0-9\.]+$/isU', $val)) $val = floor($val * 100).'%';
692
                    $this->value['line-height'] = $val;
693
                    break;
694
695
                case 'rotate':
696
                    if ( ! in_array($val, array(0, -90, 90, 180, 270, -180, -270))) $val = null;
697
                    if ($val < 0) $val += 360;
698
                    $this->value['rotate'] = $val;
699
                    break;
700
701
                case 'overflow':
702
                    if ( ! in_array($val, array('visible', 'hidden'))) $val = 'visible';
703
                    $this->value['overflow'] = $val;
704
                    break;
705
706
                case 'padding':
707
                    $val = explode(' ', $val);
708
                    foreach ($val as $k => $v) {
709
                        $v = trim($v);
710
                        if ($v != '') {
711
                            $val[$k] = $v;
712
                        } else {
713
                            unset($val[$k]);
714
                        }
715
                    }
716
                    $val = array_values($val);
717
                    $this->_duplicateBorder($val);
718
                    $this->value['padding']['t'] = $this->convertToMM($val[0], 0);
719
                    $this->value['padding']['r'] = $this->convertToMM($val[1], 0);
720
                    $this->value['padding']['b'] = $this->convertToMM($val[2], 0);
721
                    $this->value['padding']['l'] = $this->convertToMM($val[3], 0);
722
                    break;
723
724
                case 'padding-top':
725
                    $this->value['padding']['t'] = $this->convertToMM($val, 0);
726
                    break;
727
728
                case 'padding-right':
729
                    $this->value['padding']['r'] = $this->convertToMM($val, 0);
730
                    break;
731
732
                case 'padding-bottom':
733
                    $this->value['padding']['b'] = $this->convertToMM($val, 0);
734
                    break;
735
736
                case 'padding-left':
737
                    $this->value['padding']['l'] = $this->convertToMM($val, 0);
738
                    break;
739
740
                case 'margin':
741
                    if ($val == 'auto') {
742
                        $this->value['margin-auto'] = true;
743
                        break;
744
                    }
745
                    $val = explode(' ', $val);
746
                    foreach ($val as $k => $v) {
747
                        $v = trim($v);
748
                        if ($v != '') {
749
                            $val[$k] = $v;
750
                        } else {
751
                            unset($val[$k]);
752
                        }
753
                    }
754
                    $val = array_values($val);
755
                    $this->_duplicateBorder($val);
756
                    $this->value['margin']['t'] = $this->convertToMM($val[0], 0);
757
                    $this->value['margin']['r'] = $this->convertToMM($val[1], 0);
758
                    $this->value['margin']['b'] = $this->convertToMM($val[2], 0);
759
                    $this->value['margin']['l'] = $this->convertToMM($val[3], 0);
760
                    break;
761
762
                case 'margin-top':
763
                    $this->value['margin']['t'] = $this->convertToMM($val, 0);
764
                    break;
765
766
                case 'margin-right':
767
                    $this->value['margin']['r'] = $this->convertToMM($val, 0);
768
                    break;
769
770
                case 'margin-bottom':
771
                    $this->value['margin']['b'] = $this->convertToMM($val, 0);
772
                    break;
773
774
                case 'margin-left':
775
                    $this->value['margin']['l'] = $this->convertToMM($val, 0);
776
                    break;
777
778
                case 'border':
779
                    $val = $this->readBorder($val);
780
                    $this->value['border']['t'] = $val;
781
                    $this->value['border']['r'] = $val;
782
                    $this->value['border']['b'] = $val;
783
                    $this->value['border']['l'] = $val;
784
                    break;
785
786
                case 'border-style':
787
                    $val = explode(' ', $val);
788
                    foreach ($val as $valK => $valV) {
789
                        if ( ! in_array($valV, array('solid', 'dotted', 'dashed'))) {
790
                            $val[$valK] = null;
791
                        }
792
                    }
793
                    $this->_duplicateBorder($val);
794 View Code Duplication
                    if ($val[0]) {
795
                    	$this->value['border']['t']['type'] = $val[0];
796
                    }
797 View Code Duplication
                    if ($val[1]) {
798
                    	$this->value['border']['r']['type'] = $val[1];
799
                    }
800 View Code Duplication
                    if ($val[2]) {
801
                    	$this->value['border']['b']['type'] = $val[2];
802
                    }
803 View Code Duplication
                    if ($val[3]) {
804
                    	$this->value['border']['l']['type'] = $val[3];
805
                    }
806
                    break;
807
808 View Code Duplication
                case 'border-top-style':
809
                    if (in_array($val, array('solid', 'dotted', 'dashed'))) {
810
                        $this->value['border']['t']['type'] = $val;
811
                    }
812
                    break;
813
814 View Code Duplication
                case 'border-right-style':
815
                    if (in_array($val, array('solid', 'dotted', 'dashed'))) {
816
                        $this->value['border']['r']['type'] = $val;
817
                    }
818
                    break;
819
820 View Code Duplication
                case 'border-bottom-style':
821
                    if (in_array($val, array('solid', 'dotted', 'dashed'))) {
822
                        $this->value['border']['b']['type'] = $val;
823
                    }
824
                    break;
825
826 View Code Duplication
                case 'border-left-style':
827
                    if (in_array($val, array('solid', 'dotted', 'dashed'))) {
828
                                            $this->value['border']['l']['type'] = $val;
829
                    }
830
                    break;
831
832
                case 'border-color':
833
                    $res = false;
834
                    $val = preg_replace('/,[\s]+/', ',', $val);
835
                    $val = explode(' ', $val);
836
                    foreach ($val as $valK => $valV) {
837
                            $val[$valK] = $this->convertToColor($valV, $res);
838
                            if ( ! $res) {
839
                                $val[$valK] = null;
840
                            }
841
                    }
842
                    $this->_duplicateBorder($val);
843 View Code Duplication
                    if (is_array($val[0])) {
844
                    	$this->value['border']['t']['color'] = $val[0];
845
                    }
846 View Code Duplication
                    if (is_array($val[1])) {
847
                    	$this->value['border']['r']['color'] = $val[1];
848
                    }
849 View Code Duplication
                    if (is_array($val[2])) {
850
                    	$this->value['border']['b']['color'] = $val[2];
851
                    }
852 View Code Duplication
                    if (is_array($val[3])) {
853
                    	$this->value['border']['l']['color'] = $val[3];
854
                    }
855
856
                    break;
857
858 View Code Duplication
                case 'border-top-color':
859
                    $res = false;
860
                    $val = $this->convertToColor($val, $res);
861
                    if ($res) {
862
                    	$this->value['border']['t']['color'] = $val;
863
                    }
864
                    break;
865
866 View Code Duplication
                case 'border-right-color':
867
                    $res = false;
868
                    $val = $this->convertToColor($val, $res);
869
                    if ($res) {
870
                    	$this->value['border']['r']['color'] = $val;
871
                    }
872
                    break;
873
874 View Code Duplication
                case 'border-bottom-color':
875
                    $res = false;
876
                    $val = $this->convertToColor($val, $res);
877
                    if ($res) {
878
                    	$this->value['border']['b']['color'] = $val;
879
                    }
880
                    break;
881
882 View Code Duplication
                case 'border-left-color':
883
                    $res = false;
884
                    $val = $this->convertToColor($val, $res);
885
                    if ($res) {
886
                    	$this->value['border']['l']['color'] = $val;
887
                    }
888
                    break;
889
890
                case 'border-width':
891
                    $val = explode(' ', $val);
892
                    foreach ($val as $valK => $valV) {
893
                            $val[$valK] = $this->convertToMM($valV, 0);
894
                    }
895
                    $this->_duplicateBorder($val);
896 View Code Duplication
                    if ($val[0]) $this->value['border']['t']['width'] = $val[0];
897 View Code Duplication
                    if ($val[1]) $this->value['border']['r']['width'] = $val[1];
898 View Code Duplication
                    if ($val[2]) $this->value['border']['b']['width'] = $val[2];
899 View Code Duplication
                    if ($val[3]) $this->value['border']['l']['width'] = $val[3];
900
                    break;
901
902 View Code Duplication
                case 'border-top-width':
903
                    $val = $this->convertToMM($val, 0);
904
                    if ($val) $this->value['border']['t']['width'] = $val;
905
                    break;
906
907 View Code Duplication
                case 'border-right-width':
908
                    $val = $this->convertToMM($val, 0);
909
                    if ($val) $this->value['border']['r']['width'] = $val;
910
                    break;
911
912 View Code Duplication
                case 'border-bottom-width':
913
                    $val = $this->convertToMM($val, 0);
914
                    if ($val) $this->value['border']['b']['width'] = $val;
915
                    break;
916
917 View Code Duplication
                case 'border-left-width':
918
                    $val = $this->convertToMM($val, 0);
919
                    if ($val) $this->value['border']['l']['width'] = $val;
920
                    break;
921
922
                case 'border-collapse':
923
                    if ($tagName == 'table') $this->value['border']['collapse'] = ($val == 'collapse');
924
                    break;
925
926
                case 'border-radius':
927
                    $val = explode('/', $val);
928
                    if (count($val) > 2) {
929
                        break;
930
                    }
931
                    $valH = $this->convertToRadius(trim($val[0]));
932
                    if (count($valH) < 1 || count($valH) > 4) {
933
                        break;
934
                    }
935
                    if ( ! isset($valH[1])) $valH[1] = $valH[0];
936 View Code Duplication
                    if ( ! isset($valH[2])) $valH = array($valH[0], $valH[0], $valH[1], $valH[1]);
937
                    if ( ! isset($valH[3])) $valH[3] = $valH[1];
938
                    if (isset($val[1])) {
939
                        $valV = $this->convertToRadius(trim($val[1]));
940
                        if (count($valV) < 1 || count($valV) > 4) {
941
                            break;
942
                        }
943
                        if ( ! isset($valV[1])) $valV[1] = $valV[0];
944 View Code Duplication
                        if ( ! isset($valV[2])) $valV = array($valV[0], $valV[0], $valV[1], $valV[1]);
945
                        if ( ! isset($valV[3])) $valV[3] = $valV[1];
946
                    } else {
947
                        $valV = $valH;
948
                    }
949
                    $this->value['border']['radius'] = array(
950
                                'tl' => array($valH[0], $valV[0]),
951
                                'tr' => array($valH[1], $valV[1]),
952
                                'br' => array($valH[2], $valV[2]),
953
                                'bl' => array($valH[3], $valV[3])
954
                            );
955
                    break;
956
957 View Code Duplication
                case 'border-top-left-radius':
958
                    $val = $this->convertToRadius($val);
959
                    if (count($val) < 1 || count($val) > 2) {
960
                        break;
961
                    }
962
                    $this->value['border']['radius']['tl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
963
                    break;
964
965 View Code Duplication
                case 'border-top-right-radius':
966
                    $val = $this->convertToRadius($val);
967
                    if (count($val) < 1 || count($val) > 2) {
968
                        break;
969
                    }
970
                    $this->value['border']['radius']['tr'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
971
                    break;
972
973 View Code Duplication
                case 'border-bottom-right-radius':
974
                    $val = $this->convertToRadius($val);
975
                    if (count($val) < 1 || count($val) > 2) {
976
                        break;
977
                    }
978
                    $this->value['border']['radius']['br'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
979
                    break;
980
981 View Code Duplication
                case 'border-bottom-left-radius':
982
                    $val = $this->convertToRadius($val);
983
                    if (count($val) < 1 || count($val) > 2) {
984
                        break;
985
                    }
986
                    $this->value['border']['radius']['bl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
987
                    break;
988
989
                case 'border-top':
990
                    $this->value['border']['t'] = $this->readBorder($val);
991
                    break;
992
993
                case 'border-right':
994
                    $this->value['border']['r'] = $this->readBorder($val);
995
                    break;
996
997
                case 'border-bottom':
998
                    $this->value['border']['b'] = $this->readBorder($val);
999
                    break;
1000
1001
                case 'border-left':
1002
                    $this->value['border']['l'] = $this->readBorder($val);
1003
                    break;
1004
1005
                case 'background-color':
1006
                    $this->value['background']['color'] = $this->convertBackgroundColor($val);
1007
                    break;
1008
1009
                case 'background-image':
1010
                    $this->value['background']['image'] = $this->convertBackgroundImage($val);
1011
                    break;
1012
1013
                case 'background-position':
1014
                    $res = null;
1015
                    $this->value['background']['position'] = $this->convertBackgroundPosition($val, $res);
1016
                    break;
1017
1018
                case 'background-repeat':
1019
                    $this->value['background']['repeat'] = $this->convertBackgroundRepeat($val);
1020
                    break;
1021
1022
                case 'background':
1023
                    $this->convertBackground($val, $this->value['background']);
1024
                    break;
1025
1026
                case 'position':
1027
                    if ($val == 'absolute')       $this->value['position'] = 'absolute';
1028
                    else if ($val == 'relative')  $this->value['position'] = 'relative';
1029
                    else                        $this->value['position'] = null;
1030
                    break;
1031
1032
                case 'float':
1033
                    if ($val == 'left')           $this->value['float'] = 'left';
1034
                    else if ($val == 'right')     $this->value['float'] = 'right';
1035
                    else                        $this->value['float'] = null;
1036
                    break;
1037
1038
                case 'display':
1039
                    if ($val == 'inline')         $this->value['display'] = 'inline';
1040
                    else if ($val == 'block')     $this->value['display'] = 'block';
1041
                    else if ($val == 'none')      $this->value['display'] = 'none';
1042
                    else                        $this->value['display'] = null;
1043
                    break;
1044
1045
                case 'top':
1046
                case 'bottom':
1047
                case 'left':
1048
                case 'right':
1049
                    $this->value[$nom] = $val;
1050
                    break;
1051
1052
                case 'list-style':
1053
                case 'list-style-type':
1054
                case 'list-style-image':
1055
                    if ($nom == 'list-style') $nom = 'list-style-type';
1056
                    $this->value[$nom] = $val;
1057
                    break;
1058
1059
                default:
1060
                    break;
1061
            }
1062
        }
1063
1064
        $return = true;
1065
1066
        // only for P tag
1067 View Code Duplication
        if ($this->value['margin']['t'] === null) $this->value['margin']['t'] = $this->value['font-size'];
1068
        if ($this->value['margin']['b'] === null) $this->value['margin']['b'] = $this->value['font-size'];
1069
1070
        // force the text align to left, if asked by html2pdf
1071
        if ($this->_onlyLeft) $this->value['text-align'] = 'left';
1072
1073
        // correction on the width (quick box)
1074
        if ($noWidth && in_array($tagName, array('div', 'blockquote', 'fieldset')) && $this->value['position'] != 'absolute') {
1075
            $this->value['width'] = $this->getLastWidth();
1076
            $this->value['width'] -= $this->value['margin']['l'] + $this->value['margin']['r'];
1077
        } else {
1078
            if ($correctWidth) {
1079
                if ( ! in_array($tagName, array('table', 'div', 'blockquote', 'fieldset', 'hr'))) {
1080
                    $this->value['width'] -= $this->value['padding']['l'] + $this->value['padding']['r'];
1081
                    $this->value['width'] -= $this->value['border']['l']['width'] + $this->value['border']['r']['width'];
1082
                }
1083
                if (in_array($tagName, array('th', 'td'))) {
1084
                    $this->value['width'] -= $this->convertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
1085
                    $return = false;
1086
                }
1087
                if ($this->value['width'] < 0) $this->value['width'] = 0;
1088 View Code Duplication
            } else {
1089
                if ($this->value['width']) {
1090
                    if ($this->value['border']['l']['width']) $this->value['width'] += $this->value['border']['l']['width'];
1091
                    if ($this->value['border']['r']['width']) $this->value['width'] += $this->value['border']['r']['width'];
1092
                    if ($this->value['padding']['l'])         $this->value['width'] += $this->value['padding']['l'];
1093
                    if ($this->value['padding']['r'])         $this->value['width'] += $this->value['padding']['r'];
1094
                }
1095
            }
1096
        }
1097 View Code Duplication
        if ($this->value['height']) {
1098
            if ($this->value['border']['b']['width']) $this->value['height'] += $this->value['border']['b']['width'];
1099
            if ($this->value['border']['t']['width']) $this->value['height'] += $this->value['border']['t']['width'];
1100
            if ($this->value['padding']['b'])         $this->value['height'] += $this->value['padding']['b'];
1101
            if ($this->value['padding']['t'])         $this->value['height'] += $this->value['padding']['t'];
1102
        }
1103
1104
        if ($this->value['top'] != null)      $this->value['top']     = $this->convertToMM($this->value['top'], $this->getLastHeight(true));
1105
        if ($this->value['bottom'] != null)   $this->value['bottom']  = $this->convertToMM($this->value['bottom'], $this->getLastHeight(true));
1106 View Code Duplication
        if ($this->value['left'] != null)     $this->value['left']    = $this->convertToMM($this->value['left'], $this->getLastWidth(true));
1107 View Code Duplication
        if ($this->value['right'] != null)    $this->value['right']   = $this->convertToMM($this->value['right'], $this->getLastWidth(true));
1108
1109
        if ($this->value['top'] && $this->value['bottom'] && $this->value['height'])    $this->value['bottom']  = null;
1110
        if ($this->value['left'] && $this->value['right'] && $this->value['width'])     $this->value['right']   = null;
1111
1112
        return $return;
1113
    }
1114
1115
     /**
1116
     * get the height of the current line
1117
     *
1118
     * @access public
1119
     * @return float $height in mm
1120
     */
1121
    public function getLineHeight()
1122
    {
1123
        $val = $this->value['line-height'];
1124
        if ($val == 'normal') $val = '108%';
1125
        return $this->convertToMM($val, $this->value['font-size']);
1126
    }
1127
1128
     /**
1129
     * get the width of the parent
1130
     *
1131
     * @access public
1132
     * @param  boolean $mode true => adding padding and border
1133
     * @return float $width in mm
1134
     */
1135 View Code Duplication
    public function getLastWidth($mode = false)
1136
    {
1137
        for ($k = count($this->table) - 1; $k >= 0; $k--) {
1138
            if ($this->table[$k]['width']) {
1139
                $w = $this->table[$k]['width'];
1140
                if ($mode) {
1141
                    $w += $this->table[$k]['border']['l']['width'] + $this->table[$k]['padding']['l'] + 0.02;
1142
                    $w += $this->table[$k]['border']['r']['width'] + $this->table[$k]['padding']['r'] + 0.02;
1143
                }
1144
                return $w;
1145
            }
1146
        }
1147
        return $this->_pdf->getW() - $this->_pdf->getlMargin() - $this->_pdf->getrMargin();
1148
    }
1149
1150
     /**
1151
     * get the height of the parent
1152
     *
1153
     * @access public
1154
     * @param  boolean $mode true => adding padding and border
1155
     * @return float $height in mm
1156
     */
1157 View Code Duplication
    public function getLastHeight($mode = false)
1158
    {
1159
        for ($k = count($this->table) - 1; $k >= 0; $k--) {
1160
            if ($this->table[$k]['height']) {
1161
                $h = $this->table[$k]['height'];
1162
                if ($mode) {
1163
                    $h += $this->table[$k]['border']['t']['width'] + $this->table[$k]['padding']['t'] + 0.02;
1164
                    $h += $this->table[$k]['border']['b']['width'] + $this->table[$k]['padding']['b'] + 0.02;
1165
                }
1166
                return $h;
1167
            }
1168
        }
1169
        return $this->_pdf->getH() - $this->_pdf->gettMargin() - $this->_pdf->getbMargin();
1170
    }
1171
1172
    /**
1173
     * get the value of the float property
1174
     *
1175
     * @access public
1176
     * @return $float left/right
0 ignored issues
show
Documentation introduced by
The doc-type $float could not be parsed: Unknown type name "$float" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1177
     */
1178
    public function getFloat()
1179
    {
1180
        if ($this->value['float'] == 'left')    return 'left';
1181
        if ($this->value['float'] == 'right')   return 'right';
1182
        return null;
1183
    }
1184
1185
    /**
1186
     * get the last value for a specific key
1187
     *
1188
     * @access public
1189
     * @param  string $key
1190
     * @return mixed
1191
     */
1192
    public function getLastValue($key)
1193
    {
1194
        $nb = count($this->table);
1195
        if ($nb > 0) {
1196
            return $this->table[$nb - 1][$key];
1197
        } else {
1198
            return null;
1199
        }
1200
    }
1201
1202
    /**
1203
     * get the last absolute X
1204
     *
1205
     * @access protected
1206
     * @return float $x
1207
     */
1208 View Code Duplication
    protected function _getLastAbsoluteX()
1209
    {
1210
        for ($k = count($this->table) - 1; $k >= 0; $k--) {
1211
            if ($this->table[$k]['x'] && $this->table[$k]['position']) return $this->table[$k]['x'];
1212
        }
1213
        return $this->_pdf->getlMargin();
1214
    }
1215
1216
    /**
1217
     * get the last absolute Y
1218
     *
1219
     * @access protected
1220
     * @return float $y
1221
     */
1222 View Code Duplication
    protected function _getLastAbsoluteY()
1223
    {
1224
        for ($k = count($this->table) - 1; $k >= 0; $k--) {
1225
            if ($this->table[$k]['y'] && $this->table[$k]['position']) return $this->table[$k]['y'];
1226
        }
1227
        return $this->_pdf->gettMargin();
1228
    }
1229
1230
    /**
1231
     * get the CSS properties of the current tag
1232
     *
1233
     * @access protected
1234
     * @return array $styles
1235
     */
1236
    protected function _getFromCSS()
1237
    {
1238
        // styles to apply
1239
        $styles = array();
1240
1241
        // list of the selectors to get in the CSS files
1242
        $getit  = array();
1243
1244
        // get the list of the selectors of each tags
1245
        $lst = array();
1246
        $lst[] = $this->value['id_lst'];
1247
        for ($i = count($this->table) - 1; $i >= 0; $i--) {
1248
            $lst[] = $this->table[$i]['id_lst'];
1249
        }
1250
1251
        // foreach selectors in the CSS files, verify if it match with the list of selectors
1252
        foreach ($this->cssKeys as $key => $num) {
1253
            if ($this->_getReccursiveStyle($key, $lst)) {
1254
                $getit[$key] = $num;
1255
            }
1256
        }
1257
1258
        // if we have selectors
1259
        if (count($getit)) {
1260
            // get them, but in the definition order, because of priority
1261
            asort($getit);
1262
            foreach ($getit as $key => $val) {
1263
            	$styles = array_merge($styles, $this->css[$key]);
1264
            }
1265
        }
1266
1267
        return $styles;
1268
    }
1269
1270
    /**
1271
     * identify if the selector $key match with the list of tag selectors
1272
     *
1273
     * @access protected
1274
     * @param  string   $key CSS selector to analyse
1275
     * @param  array    $lst list of the selectors of each tags
1276
     * @param  string   $next next step of parsing the selector
1277
     * @return boolean
1278
     */
1279
    protected function _getReccursiveStyle($key, $lst, $next = null)
1280
    {
1281
        // if next step
1282
        if ($next !== null) {
1283
            // we remove this step
1284
            if ($next) {
1285
            	$key = trim(substr($key, 0, -strlen($next)));
1286
            }
1287
            array_shift($lst);
1288
1289
            // if no more step to identify => return false
1290
            if ( ! count($lst)) {
1291
                return false;
1292
            }
1293
        }
1294
1295
        // for each selector of the current step
1296
        foreach ($lst[0] as $name) {
1297
            // if selector = key => ok
1298
            if ($key == $name) {
1299
                return true;
1300
            }
1301
1302
            // if the end of the key = the selector and the next step is ok => ok
1303
            if (substr($key, -strlen(' '.$name)) == ' '.$name && $this->_getReccursiveStyle($key, $lst, $name)) {
1304
                return true;
1305
            }
1306
        }
1307
1308
        // if we are not in the first step, we analyse the sub steps (the pareng tag of the current tag)
1309
        if ($next !== null && $this->_getReccursiveStyle($key, $lst, '')) {
1310
            return true;
1311
        }
1312
1313
        // no corresponding found
1314
        return false;
1315
    }
1316
1317
    /**
1318
     * Analyse a border
1319
     *
1320
     * @access  public
1321
     * @param   string $css css border properties
1322
     * @return  array  border properties
1323
     */
1324
    public function readBorder($css)
1325
    {
1326
        // border none
1327
        $none = array('type' => 'none', 'width' => 0, 'color' => array(0, 0, 0));
1328
1329
        // default value
1330
        $type  = 'solid';
1331
        $width = $this->convertToMM('1pt');
1332
        $color = array(0, 0, 0);
1333
1334
        // clean up the values
1335
        $css = explode(' ', $css);
1336
        foreach ($css as $k => $v) {
1337
            $v = trim($v);
1338
            if ($v) {
1339
            	$css[$k] = $v;
1340
            } else {
1341
            	unset($css[$k]);
1342
            }
1343
        }
1344
        $css = array_values($css);
1345
1346
        // read the values
1347
        $res = null;
1348
        foreach ($css as $value) {
1349
1350
            // if no border => return none
1351
            if ($value == 'none' || $value == 'hidden') {
1352
                return $none;
1353
            }
1354
1355
            // try to convert the value as a distance
1356
            $tmp = $this->convertToMM($value);
1357
1358
            // if the convert is ok => it is a width
1359
            if ($tmp !== null) {
1360
                $width = $tmp;
1361
            // else, it could be the type
1362
            } else if (in_array($value, array('solid', 'dotted', 'dashed', 'double'))) {
1363
                $type = $value;
1364
            // else, it could be the color
1365
            } else {
1366
                $tmp = $this->convertToColor($value, $res);
1367
                if ($res) $color = $tmp;
1368
            }
1369
        }
1370
1371
        // if no witdh => return none
1372
        if ( ! $width) return $none;
1373
1374
        // return the border properties
1375
        return array('type' => $type, 'width' => $width, 'color' => $color);
1376
    }
1377
1378
    /**
1379
     * duplicate the borders if needed
1380
     *
1381
     * @access protected
1382
     * @param  &array $val
0 ignored issues
show
Documentation introduced by
The doc-type &array could not be parsed: Unknown type name "&array" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1383
     */
1384
    protected function _duplicateBorder(&$val)
1385
    {
1386
        // 1 value => L => RTB
1387
        if (count($val) == 1) {
1388
            $val[1] = $val[0];
1389
            $val[2] = $val[0];
1390
            $val[3] = $val[0];
1391
        // 2 values => L => R & T => B
1392
        } else if (count($val) == 2) {
1393
            $val[2] = $val[0];
1394
            $val[3] = $val[1];
1395
        // 3 values => T => B
1396
        } else if (count($val) == 3) {
1397
            $val[3] = $val[1];
1398
        }
1399
    }
1400
1401
    /**
1402
     * Analyse a background
1403
     *
1404
     * @access public
1405
     * @param  string $css css background properties
1406
     * @param  &array $value parsed values (by reference, because, ther is a legacy of the parent CSS properties)
0 ignored issues
show
Documentation introduced by
The doc-type &array could not be parsed: Unknown type name "&array" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1407
     */
1408
    public function convertBackground($css, &$value)
1409
    {
1410
        // is there a image ?
1411
        $text = '/url\(([^)]*)\)/isU';
1412
        if (preg_match($text, $css, $match)) {
1413
            // get the image
1414
            $value['image'] = $this->convertBackgroundImage($match[0]);
1415
1416
            // remove if from the css properties
1417
            $css = preg_replace($text, '', $css);
1418
            $css = preg_replace('/[\s]+/', ' ', $css);
1419
        }
1420
1421
        // protect some spaces
1422
        $css = preg_replace('/,[\s]+/', ',', $css);
1423
1424
        // explode the values
1425
        $css = explode(' ', $css);
1426
1427
        // background position to parse
1428
        $pos = '';
1429
1430
        // foreach value
1431
        foreach ($css as $val) {
1432
            // try to parse the value as a color
1433
            $ok = false;
1434
            $color = $this->convertToColor($val, $ok);
1435
1436
            // if ok => it is a color
1437
            if ($ok) {
1438
                $value['color'] = $color;
1439
            // else if transparent => no coloàr
1440
            } else if ($val == 'transparent') {
1441
                $value['color'] = null;
1442
            // else
1443
            } else {
1444
                // try to parse the value as a repeat
1445
                $repeat = $this->convertBackgroundRepeat($val);
1446
1447
                // if ok => it is repeat
1448
                if ($repeat) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $repeat of type boolean[] 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...
1449
                    $value['repeat'] = $repeat;
1450
                // else => it could only be a position
1451
                } else {
1452
                    $pos .= ($pos ? ' ' : '').$val;
1453
                }
1454
            }
1455
        }
1456
1457
        // if we have a position to parse
1458
        if ($pos) {
1459
            // try to read it
1460
            $pos = $this->convertBackgroundPosition($pos, $ok);
1461
            if ($ok) {
1462
            	$value['position'] = $pos;
1463
            }
1464
        }
1465
    }
1466
1467
    /**
1468
     * parse a background color
1469
     *
1470
     * @access public
1471
     * @param  string $css
1472
     * @return string $value
1473
     */
1474
    public function convertBackgroundColor($css)
1475
    {
1476
        $res = null;
1477
        if ($css == 'transparent') return null;
1478
        else                     return $this->convertToColor($css, $res);
1479
    }
1480
1481
    /**
1482
     * parse a background image
1483
     *
1484
     * @access public
1485
     * @param  string $css
1486
     * @return string $value
1487
     */
1488
    public function convertBackgroundImage($css)
1489
    {
1490
        if ($css == 'none')
1491
            return null;
1492
        else if (preg_match('/^url\(([^)]*)\)$/isU', $css, $match))
1493
            return $match[1];
1494
        else
1495
            return null;
1496
    }
1497
1498
    /**
1499
     * parse a background position
1500
     *
1501
     * @access public
1502
     * @param  string $css
1503
     * @param  &boolean $res flag if conver is ok or not
0 ignored issues
show
Documentation introduced by
The doc-type &boolean could not be parsed: Unknown type name "&boolean" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1504
     * @return array ($x, $y)
1505
     */
1506
    public function convertBackgroundPosition($css, &$res)
1507
    {
1508
        // init the res
1509
        $res = false;
1510
1511
        // explode the value
1512
        $css = explode(' ', $css);
1513
1514
        // we must have 2 values. if 0 or >2 : error. if 1 => put center for 2
1515
        if (count($css) < 2) {
1516
            if ( ! $css[0]) return null;
1517
            $css[1] = 'center';
1518
        }
1519
        if (count($css) > 2) return null;
1520
1521
        // prepare the values
1522
        $x = 0;
1523
        $y = 0;
1524
        $res = true;
1525
1526
        // convert the first value
1527 View Code Duplication
        if ($css[0] == 'left')        $x = '0%';
1528
        else if ($css[0] == 'center') $x = '50%';
1529
        else if ($css[0] == 'right')  $x = '100%';
1530
        else if ($css[0] == 'top')    $y = '0%';
1531
        else if ($css[0] == 'bottom') $y = '100%';
1532
        else if (preg_match('/^[-]?[0-9\.]+%$/isU', $css[0])) $x = $css[0];
1533
        else if ($this->convertToMM($css[0])) $x = $this->convertToMM($css[0]);
1534
        else $res = false;
1535
1536
        // convert the second value
1537 View Code Duplication
        if ($css[1] == 'left')        $x = '0%';
1538
        else if ($css[1] == 'right')  $x = '100%';
1539
        else if ($css[1] == 'top')    $y = '0%';
1540
        else if ($css[1] == 'center') $y = '50%';
1541
        else if ($css[1] == 'bottom') $y = '100%';
1542
        else if (preg_match('/^[-]?[0-9\.]+%$/isU', $css[1])) $y = $css[1];
1543
        else if ($this->convertToMM($css[1])) $y = $this->convertToMM($css[1]);
1544
        else $res = false;
1545
1546
        // return the values
1547
        return array($x, $y);
1548
    }
1549
1550
    /**
1551
     * parse a background repeat
1552
     *
1553
     * @access public
1554
     * @param  string $css
1555
     * @return string $value
1556
     */
1557
    public function convertBackgroundRepeat($css)
1558
    {
1559
        switch ($css)
1560
        {
1561
            case 'repeat':
1562
                return array(true, true);
1563
            case 'repeat-x':
1564
                return array(true, false);
1565
            case 'repeat-y':
1566
                return array(false, true);
1567
            case 'no-repeat':
1568
                return array(false, false);
1569
        }
1570
        return null;
1571
    }
1572
1573
     /**
1574
     * convert a distance to mm
1575
     *
1576
     * @access public
1577
     * @param  string $css distance to convert
1578
     * @param  float  $old parent distance
1579
     * @return float  $value
1580
     */
1581
    public function convertToMM($css, $old = 0.)
1582
    {
1583
        $css = trim($css);
1584
        if (preg_match('/^[0-9\.\-]+$/isU', $css))        $css .= 'px';
1585
        if (preg_match('/^[0-9\.\-]+px$/isU', $css))      $css = 25.4 / 96. * str_replace('px', '', $css);
1586
        else if (preg_match('/^[0-9\.\-]+pt$/isU', $css)) $css = 25.4 / 72. * str_replace('pt', '', $css);
1587
        else if (preg_match('/^[0-9\.\-]+in$/isU', $css)) $css = 25.4 * str_replace('in', '', $css);
1588
        else if (preg_match('/^[0-9\.\-]+mm$/isU', $css)) $css = 1. * str_replace('mm', '', $css);
1589
        else if (preg_match('/^[0-9\.\-]+%$/isU', $css))  $css = 1. * $old * str_replace('%', '', $css) / 100.;
1590
        else                                              $css = null;
1591
1592
        return $css;
1593
    }
1594
1595
    /**
1596
     * convert a css radius
1597
     *
1598
     * @access public
1599
     * @param  string $css
1600
     * @return float  $value
1601
     */
1602
    public function convertToRadius($css)
1603
    {
1604
        // explode the value
1605
        $css = explode(' ', $css);
1606
1607
        foreach ($css as $k => $v) {
1608
            $v = trim($v);
1609
            if ($v) {
1610
                $v = $this->convertToMM($v, 0);
1611
                if ($v !== null) {
1612
                    $css[$k] = $v;
1613
                } else {
1614
                    unset($css[$k]);
1615
                }
1616
            } else {
1617
                unset($css[$k]);
1618
            }
1619
        }
1620
1621
        return array_values($css);
1622
    }
1623
1624
    /**
1625
     * convert a css color
1626
     *
1627
     * @access public
1628
     * @param  string $css
1629
     * @param  &boolean $res
0 ignored issues
show
Documentation introduced by
The doc-type &boolean could not be parsed: Unknown type name "&boolean" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1630
     * @return array (r,g, b)
1631
     */
1632
    public function convertToColor($css, &$res)
1633
    {
1634
        // prepare the value
1635
        $css = trim($css);
1636
        $res = true;
1637
1638
        // if transparent => return null
1639
        if (strtolower($css) == 'transparent') return array(null, null, null);
1640
1641
        // HTML color
1642
        if (isset($this->_htmlColor[strtolower($css)])) {
1643
            $css = $this->_htmlColor[strtolower($css)];
1644
            $r = floatVal(hexdec(substr($css, 0, 2)));
1645
            $v = floatVal(hexdec(substr($css, 2, 2)));
1646
            $b = floatVal(hexdec(substr($css, 4, 2)));
1647
            return array($r, $v, $b);
1648
        }
1649
1650
        // like #FFFFFF
1651
        if (preg_match('/^#[0-9A-Fa-f]{6}$/isU', $css)) {
1652
            $r = floatVal(hexdec(substr($css, 1, 2)));
1653
            $v = floatVal(hexdec(substr($css, 3, 2)));
1654
            $b = floatVal(hexdec(substr($css, 5, 2)));
1655
            return array($r, $v, $b);
1656
        }
1657
1658
        // like #FFF
1659
        if (preg_match('/^#[0-9A-F]{3}$/isU', $css)) {
1660
            $r = floatVal(hexdec(substr($css, 1, 1).substr($css, 1, 1)));
1661
            $v = floatVal(hexdec(substr($css, 2, 1).substr($css, 2, 1)));
1662
            $b = floatVal(hexdec(substr($css, 3, 1).substr($css, 3, 1)));
1663
            return array($r, $v, $b);
1664
        }
1665
1666
        // like rgb(100, 100, 100)
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
1667
        if (preg_match('/rgb\([\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*\)/isU', $css, $match)) {
1668
            $r = $this->_convertSubColor($match[1]);
1669
            $v = $this->_convertSubColor($match[2]);
1670
            $b = $this->_convertSubColor($match[3]);
1671
            return array($r * 255., $v * 255., $b * 255.);
1672
        }
1673
1674
        // like cmyk(100, 100, 100, 100)
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% 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...
1675
        if (preg_match('/cmyk\([\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*,[\s]*([0-9%\.]+)[\s]*\)/isU', $css, $match)) {
1676
            $c = $this->_convertSubColor($match[1]);
1677
            $m = $this->_convertSubColor($match[2]);
1678
            $y = $this->_convertSubColor($match[3]);
1679
            $k = $this->_convertSubColor($match[4]);
1680
            return array($c * 100., $m * 100., $y * 100., $k * 100.);
1681
        }
1682
1683
        $res = false;
1684
        return array(0., 0., 0.);
1685
    }
1686
1687
    /**
1688
     * color value to convert
1689
     *
1690
     * @access protected
1691
     * @param  string $c
1692
     * @return float $c 0.->1.
1693
     */
1694
    protected function _convertSubColor($c)
1695
    {
1696
        if (substr($c, -1) == '%') {
1697
            $c = floatVal(substr($c, 0, -1)) / 100.;
1698
        } else {
1699
            $c = floatVal($c);
1700
            if ($c > 1) $c = $c / 255.;
1701
        }
1702
1703
        return $c;
1704
    }
1705
1706
    /**
1707
     * read a css content
1708
     *
1709
     * @access protected
1710
     * @param  string $code
1711
     */
1712
    protected function _analyseStyle(&$code)
1713
    {
1714
        // clean the spaces
1715
        $code = preg_replace('/[\s]+/', ' ', $code);
1716
1717
        // remove the comments
1718
        $code = preg_replace('/\/\*.*?\*\//s', '', $code);
1719
1720
        // split each CSS code "selector { value }"
1721
        preg_match_all('/([^{}]+){([^}]*)}/isU', $code, $match);
1722
1723
        // for each CSS code
1724
        for ($k = 0; $k < count($match[0]); $k++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1725
1726
            // selectors
1727
            $names = strtolower(trim($match[1][$k]));
1728
1729
            // css style
1730
            $styles = trim($match[2][$k]);
1731
1732
            // explode each value
1733
            $styles = explode(';', $styles);
1734
1735
            // parse each value
1736
            $css = array();
1737
            foreach ($styles as $style) {
1738
                $tmp = explode(':', $style);
1739
                if (count($tmp) > 1) {
1740
                    $cod = $tmp[0]; unset($tmp[0]); $tmp = implode(':', $tmp);
1741
                    $css[trim(strtolower($cod))] = trim($tmp);
1742
                }
1743
            }
1744
1745
            // explode the names
1746
            $names = explode(',', $names);
1747
1748
            // save the values for each names
1749
            foreach ($names as $name) {
1750
                // clean the name
1751
                $name = trim($name);
1752
1753
                // if a selector with somethink lige :hover => continue
1754
                if (strpos($name, ':') !== false) continue;
1755
1756
                // save the value
1757 View Code Duplication
                if ( ! isset($this->css[$name]))
1758
                    $this->css[$name] = $css;
1759
                else
1760
                    $this->css[$name] = array_merge($this->css[$name], $css);
1761
1762
            }
1763
        }
1764
1765
        // get he list of the keys
1766
        $this->cssKeys = array_flip(array_keys($this->css));
1767
    }
1768
1769
    /**
1770
     * Extract the css files from a html code
1771
     *
1772
     * @access public
1773
     * @param  string   &$html
1774
     * @param string $html
1775
     */
1776
    public function readStyle(&$html)
1777
    {
1778
        // the CSS content
1779
        $style = ' ';
1780
1781
        // extract the link tags, and remove them in the html code
1782
        preg_match_all('/<link([^>]*)>/isU', $html, $match);
1783
        $html = preg_replace('/<link[^>]*>/isU', '', $html);
1784
        $html = preg_replace('/<\/link[^>]*>/isU', '', $html);
1785
1786
        // analyse each link tag
1787
        foreach ($match[1] as $code) {
1788
            $tmp = array();
1789
1790
            // read the attributes name=value
1791
            $prop = '([a-zA-Z0-9_]+)=([^"\'\s>]+)';
1792
            preg_match_all('/'.$prop.'/is', $code, $match);
1793 View Code Duplication
            for ($k = 0; $k < count($match[0]); $k++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1794
                $tmp[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);
1795
            }
1796
1797
            // read the attributes name="value"
1798
            $prop = '([a-zA-Z0-9_]+)=["]([^"]*)["]';
1799
            preg_match_all('/'.$prop.'/is', $code, $match);
1800 View Code Duplication
            for ($k = 0; $k < count($match[0]); $k++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1801
                $tmp[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);
1802
            }
1803
1804
            // read the attributes name='value'
1805
            $prop = "([a-zA-Z0-9_]+)=[']([^']*)[']";
1806
            preg_match_all('/'.$prop.'/is', $code, $match);
1807 View Code Duplication
            for ($k = 0; $k < count($match[0]); $k++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1808
                $tmp[trim(strtolower($match[1][$k]))] = trim($match[2][$k]);
1809
            }
1810
1811
            // if type text/css => we keep it
1812
            if (isset($tmp['type']) && strtolower($tmp['type']) == 'text/css' && isset($tmp['href'])) {
1813
1814
                // get the href
1815
                $url = $tmp['href'];
1816
1817
                // get the content of the css file
1818
                $content = @file_get_contents($url);
1819
1820
                // if "http://" in the url
1821
                if (strpos($url, 'http://') !== false) {
1822
1823
                    // get the domain "http://xxx/"
1824
                    $url = str_replace('http://', '', $url);
1825
                    $url = explode('/', $url);
1826
                    $urlMain = 'http://'.$url[0].'/';
1827
1828
                    // get the absolute url of the path
1829
                    $urlSelf = $url; unset($urlSelf[count($urlSelf) - 1]); $urlSelf = 'http://'.implode('/', $urlSelf).'/';
1830
1831
                    // adapt the url in the css content
1832
                    $content = preg_replace('/url\(([^\\\\][^)]*)\)/isU', 'url('.$urlSelf.'$1)', $content);
1833
                    $content = preg_replace('/url\((\\\\[^)]*)\)/isU', 'url('.$urlMain.'$1)', $content);
1834
                } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
1835
// @TODO correction on url in absolute on a local css content
1836
                    // $content = preg_replace('/url\(([^)]*)\)/isU', 'url('.dirname($url).'/$1)', $content);
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% 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...
1837
                }
1838
1839
                // add to the CSS content
1840
                $style .= $content."\n";
1841
            }
1842
        }
1843
1844
        // extract the style tags des tags style, and remove them in the html code
1845
        preg_match_all('/<style[^>]*>(.*)<\/style[^>]*>/isU', $html, $match);
1846
        $html = preg_replace('/<style[^>]*>(.*)<\/style[^>]*>/isU', '', $html);
1847
1848
        // analyse each style tags
1849
        foreach ($match[1] as $code) {
1850
            // add to the CSS content
1851
            $code = str_replace('<!--', '', $code);
1852
            $code = str_replace('-->', '', $code);
1853
            $style .= $code."\n";
1854
        }
1855
1856
        //analyse the css content
1857
        $this->_analyseStyle($style);
1858
    }
1859
}