Passed
Push — master ( 63d1f8...7c50e7 )
by Joe Nilson
02:33
created

EasyTable::set_style()   F

Complexity

Conditions 79
Paths 0

Size

Total Lines 212
Code Lines 140

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 79
eloc 140
c 1
b 0
f 0
nc 0
nop 3
dl 0
loc 212
rs 3.3333

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
 * FPDF easyTable                                                     *
4
 *                                                                    *
5
 * Version: 2.0                                                       *
6
 * Date:    12-10-2017                                                *
7
 * Author:  Dan Machado                                               *
8
 * Require  exFPDF v2.0                                              *
9
 **********************************************************************/
10
  
11
class EasyTable
12
{
13
   const LP=0.4;
14
   const XPadding=1;
15
   const YPadding=1;
16
   const IMGPadding=0.5;
17
   const PBThreshold=30;
18
   static private $table_counter=false;
19
   static private $style=array('width'=>false, 'border'=>false, 'border-color'=>false,
20
   'border-width'=>false, 'line-height'=>false,
21
   'align'=>'', 'valign'=>'', 'bgcolor'=>false, 'split-row'=>false, 'l-margin'=>false,
22
   'font-family'=>false, 'font-style'=>false,'font-size'=>false, 'font-color'=>false,
23
   'paddingX'=>false, 'paddingY'=>false);
24
   private $pdf_obj;
25
   private $document_style;
26
   private $table_style;
27
   private $col_num;
28
   private $col_width;
29
   private $baseX;
30
   private $row_style_def;
31
   private $row_style;
32
   private $row_heights;
33
   private $row_data;
34
   private $rows;
35
   private $total_rowspan;
36
   private $col_counter;
37
   private $grid;
38
   private $blocks;
39
   private $overflow;
40
   private $header_row;
41
   private $new_table;
42
43
   private function get_available($colspan, $rowspan){
44
      static $k=0;
45
      if(count($this->grid)==0){
46
         $k=0;
47
      }
48
      while(isset($this->grid[$k])){
49
         $k++;
50
      }
51
      for($i=0; $i<=$colspan; $i++){
52
         for($j=0; $j<=$rowspan; $j++){
53
            $this->grid[$k+$i+$j*$this->col_num]=true;
54
         }
55
      }
56
      return $k;
57
   }
58
59
   private function get_style($str, $c){
60
      $result=self::$style;
61
      if($c=='C'){
62
         $result['colspan']=0;
63
         $result['rowspan']=0;
64
         $result['img']=false;
65
      }
66
      if($c=='C' || $c=='R'){
67
         unset($result['width']);
68
         unset($result['border-width']);
69
         unset($result['split-row']);
70
         unset($result['l-margin']);
71
      }
72
      if($c=='R' || $c=='T'){
73
         if($c=='R'){
74
            $result['c-align']=array_pad(array(), $this->col_num, 'L');
75
         }
76
         else{
77
            $result['c-align']=array();
78
         }
79
      }
80
      if($c=='R'){
81
         $result['min-height']=false;
82
      }
83
      $tmp=explode(';', $str);
84
      foreach($tmp as $x){
85
         if($x && strpos($x,':')>0){
86
            $r=explode(':',$x);
87
            $r[0]=trim($r[0]);
88
            $r[1]=trim($r[1]);
89
            if(isset($result[$r[0]])){
90
               $result[$r[0]]=$r[1];
91
            }
92
         }
93
      }
94
      return $result;
95
   }
96
97
   private function inherating(&$sty, $setting, $c){
98
      if($c=='C'){
99
         $sty[$setting]=$this->row_style[$setting];
100
      }
101
      elseif($c=='R'){
102
         $sty[$setting]=$this->table_style[$setting];
103
      }
104
      else{
105
         $sty[$setting]=$this->document_style[$setting];
106
      }
107
   }
108
   
109
110
   private function set_style($str, $c, $pos=''){
111
      $sty=$this->get_style($str, $c);
112
      if($c=='T'){
113
         if(is_numeric($sty['width'])){
114
            $sty['width']=min(abs($sty['width']),$this->document_style['document_width']);
115
            if($sty['width']==0){
116
               $sty['width']=$this->document_style['document_width'];
117
            }
118
         }
119
         else{
120
            $x=strpos($sty['width'], '%');
121
            if($x!=false){
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $x of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
122
               $x=min(abs(substr($sty['width'], 0, $x)), 100);
0 ignored issues
show
Bug introduced by
substr($sty['width'], 0, $x) of type string is incompatible with the type double|integer expected by parameter $num of abs(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

122
               $x=min(abs(/** @scrutinizer ignore-type */ substr($sty['width'], 0, $x)), 100);
Loading history...
123
               if($x){
124
                  $sty['width']=$x*$this->document_style['document_width']/100.0;
125
               }
126
               else{
127
                  $sty['width']=$this->document_style['document_width'];
128
               }
129
            }
130
            else{
131
               $sty['width']=$this->document_style['document_width'];
132
            }
133
         }
134
         if(!is_numeric($sty['l-margin'])){
135
            $sty['l-margin']=0;
136
         }
137
         else{
138
            $sty['l-margin']=abs($sty['l-margin']);
139
         }
140
         if(is_numeric($sty['border-width'])){
141
            $sty['border-width']=abs($sty['border-width']);
142
         }
143
         else{
144
            $sty['border-width']=false;
145
         }
146
         if($sty['split-row']=='false'){
147
            $sty['split-row']=false;
148
         }
149
         elseif($sty['split-row']!==false){
150
            $sty['split-row']=true;
151
         }
152
      }
153
      if($c=='R'){
154
         if(!is_numeric($sty['min-height']) || $sty['min-height']<0){
155
            $sty['min-height']=0;
156
         }
157
      }
158
      if(!is_numeric($sty['paddingX'])){
159
         if($c=='C' || $c=='R'){
160
            $this->inherating($sty, 'paddingX', $c);
161
         }
162
         else{
163
            $sty['paddingX']=self::XPadding;
164
         }
165
      }
166
      $sty['paddingX']=abs($sty['paddingX']);
167
      if(!is_numeric($sty['paddingY'])){
168
         if($c=='C' || $c=='R'){
169
            $this->inherating($sty, 'paddingY', $c);
170
         }
171
         else{
172
            $sty['paddingY']=self::YPadding;
173
         }
174
      }
175
      $sty['paddingY']=abs($sty['paddingY']);
176
      if($sty['border']===false && ($c=='C' || $c=='R')){
177
         $this->inherating($sty, 'border', $c);
178
      }
179
      else{
180
         $border=array('T'=>1, 'R'=>1, 'B'=>1, 'L'=>1);
181
         if(!(is_numeric($sty['border']) && $sty['border']==1)){
182
            foreach($border as $k=>$v){
183
               $border[$k]=0;
184
               if(strpos($sty['border'], $k)!==false){
185
                  $border[$k]=1;
186
               }
187
            }
188
         }
189
         $sty['border']=$border;
190
      }
191
      $color_settings=array('bgcolor', 'font-color', 'border-color');
192
      foreach($color_settings as $setting){
193
         if($sty[$setting]===false || !($this->pdf_obj->is_hex($sty[$setting]) || $this->pdf_obj->is_rgb($sty[$setting]))){
194
            if($c=='C' || $c=='R'){
195
               $this->inherating($sty, $setting, $c);
196
            }
197
            elseif($setting=='font-color'){
198
               $sty[$setting]=$this->document_style[$setting];
199
            }
200
         }
201
         else{
202
            $sty[$setting]=$sty[$setting];
203
         }
204
      }
205
      $font_settings=array('font-family', 'font-style', 'font-size');
206
      foreach($font_settings as $setting){
207
         if($sty[$setting]===false){
208
            $this->inherating($sty, $setting, $c);
209
         }
210
      }
211
      if(is_numeric($sty['line-height'])){
212
         $sty['line-height']=self::LP*abs($sty['line-height']);
213
      }
214
      else{
215
         if($c=='C' || $c=='R'){
216
            $this->inherating($sty,'line-height', $c);
217
         }
218
         else{
219
            $sty['line-height']=self::LP;
220
         }
221
      }
222
      if($c=='C'){
223
         if($sty['img']){
224
            $tmp=explode(',', $sty['img']);
225
            if(file_exists($tmp[0])){
226
               $sty['img']=array('path'=>'', 'h'=>0, 'w'=>0);
227
               $img=@ getimagesize($tmp[0]);
228
               $sty['img']['path']=$tmp[0];
229
               for($i=1; $i<3; $i++){
230
                  if(isset($tmp[$i])){
231
                     $tmp[$i]=trim(strtolower($tmp[$i]));
232
                     if($tmp[$i][0]=='w' || $tmp[$i][0]=='h'){
233
                        $t=substr($tmp[$i],1);
234
                        if(is_numeric($t)){
235
                           $sty['img'][$tmp[$i][0]]=abs($t);
236
                        }
237
                     }
238
                  }
239
               }
240
               $ration=$img[0]/$img[1];
241
               if($sty['img']['w']+$sty['img']['h']==0){
242
                  $sty['img']['w']=$img[0];
243
                  $sty['img']['h']=$img[1];
244
               }
245
               elseif($sty['img']['w']==0){
246
                  $sty['img']['w']=$sty['img']['h']*$ration;
247
               }
248
               elseif($sty['img']['h']==0){
249
                  $sty['img']['h']=$sty['img']['w']/$ration;
250
               }
251
            }
252
            else{
253
               $sty['img']='failed to open stream: file ' . $tmp[0] .' does not exist';
254
            }
255
         }
256
         if(is_numeric($sty['colspan']) && $sty['colspan']>0){
257
            $sty['colspan']--;
258
         }
259
         else{
260
            $sty['colspan']=0;
261
         }
262
         if(is_numeric($sty['rowspan']) && $sty['rowspan']>0){
263
            $sty['rowspan']--;
264
         }
265
         else{
266
            $sty['rowspan']=0;
267
         }
268
         if($sty['valign']==false && ($sty['rowspan']>0 || $sty['img']!==false)){
269
            $sty['valign']='M';
270
         }
271
         if($sty['align']==false && $sty['img']!==false){
272
            $sty['align']='C';
273
         }
274
      }
275
      if($c=='T' || $c=='R'){
276
         $tmp=explode('{',$sty['align']);
277
         if($c=='T'){
278
            $sty['align']=trim($tmp[0]);
279
         }
280
         if(isset($tmp[1])){
281
            $tmp[1]=trim($tmp[1], '}');
282
            if(strlen($tmp[1])){
283
               for($i=0; $i<strlen($tmp[1]); $i++){
284
                  if(preg_match("/[LCRJ]/", $tmp[1][$i])!=0){
285
                     $sty['c-align'][$i]=$tmp[1][$i];
286
                  }
287
                  else{
288
                     $sty['c-align'][$i]='L';
289
                  }
290
               }
291
            }
292
            if($c=='R'){
293
               $sty['align']='L';
294
               $sty['c-align']=array_slice($sty['c-align'],0,$this->col_num);
295
            }
296
         }
297
      }
298
      if($sty['align']!='L' && $sty['align']!='C' && $sty['align']!='R' && $sty['align']!='J'){
299
         if($c=='C'){
300
            $sty['align']=$this->row_style['c-align'][$pos];
301
         }
302
         elseif($c=='R'){
303
            $sty['align']='L';
304
            $sty['c-align']=$this->table_style['c-align'];
305
         }
306
         else{
307
            $sty['align']='C';
308
         }
309
      }
310
      elseif($c=='T' && $sty['align']=='J'){
311
         $sty['align']='C';
312
      }
313
      if($sty['valign']!='T' && $sty['valign']!='M' && $sty['valign']!='B'){
314
         if($c=='C' || $c=='R'){
315
            $this->inherating($sty, 'valign', $c);
316
         }
317
         else{
318
            $sty['valign']='T';
319
         }
320
      }
321
      return $sty;
322
   }
323
324
   private function row_content_loop($counter, $f){
325
      $t=0;
326
      if($counter>0){
327
         $t=$this->rows[$counter-1];
328
      }
329
      for($index=$t; $index<$this->rows[$counter]; $index++){
330
         $f($index);
331
      }
332
   }
333
334
   private function mk_border($i, $y, $split){
335
      $w=$this->row_data[$i][2];
336
      $h=$this->row_data[$i][5];
337
      if($split){
338
         $h=$this->pdf_obj->PageBreak()-$y;
339
      }
340
      if($this->row_data[$i][1]['border-color']!=false){
341
         $this->pdf_obj->resetColor($this->row_data[$i][1]['border-color'], 'D');
342
      }
343
      $a=array(1, 1, 1, 0);
344
      $borders=array('L'=>3, 'T'=>0, 'R'=>1, 'B'=>2);
345
      foreach($borders as $border=>$j){
346
         if($this->row_data[$i][1]['border'][$border]){
347
            if($border=='B'){
348
               if($split==0){
349
                  $this->pdf_obj->Line($this->row_data[$i][6]+(1+$a[($j+2)%4])%2*$w, $y+(1+$a[($j+1)%4])%2 * $h, $this->row_data[$i][6]+$a[$j%4]*$w, $y+($a[($j+3)%4])%2 *$h);
350
               }
351
            }
352
            else{
353
               $this->pdf_obj->Line($this->row_data[$i][6]+(1+$a[($j+2)%4])%2*$w, $y+(1+$a[($j+1)%4])%2 * $h, $this->row_data[$i][6]+$a[$j%4]*$w, $y+($a[($j+3)%4])%2 *$h);
354
            }
355
         }
356
      }
357
      
358
      if($this->row_data[$i][1]['border-color']!=false){
359
         $this->pdf_obj->resetColor($this->document_style['bgcolor'], 'D');
360
      }
361
      if($split){
362
         $this->pdf_obj->row_data[$i][1]['border']['T']=0;
363
      }
364
   }
365
366
   private function print_text($i, $y, $split){
0 ignored issues
show
Unused Code introduced by
The parameter $split is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

366
   private function print_text($i, $y, /** @scrutinizer ignore-unused */ $split){

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
367
      $padding=$this->row_data[$i][1]['padding-y'];
368
      $k=$padding;
369
      if($this->row_data[$i][1]['img']!==false){
370
         if($this->row_data[$i][1]['valign']=='B'){
371
            $k+=$this->row_data[$i][1]['img']['h']+self::IMGPadding;
372
         }
373
      }
374
      $l=0;
375
      if(count($this->row_data[$i][0])){
376
         $x=$this->row_data[$i][6]+$this->row_data[$i][1]['paddingX'];
377
         $xpadding=2*$this->row_data[$i][1]['paddingX'];
378
         $l=count($this->row_data[$i][0])* $this->row_data[$i][1]['line-height']*$this->row_data[$i][1]['font-size'];
379
         $this->pdf_obj->SetXY($x, $y+$k);
380
         $this->pdf_obj->CellBlock($this->row_data[$i][2]-$xpadding, $this->row_data[$i][1]['line-height'], $this->row_data[$i][0], $this->row_data[$i][1]['align']);
381
         $this->pdf_obj->resetFont($this->document_style['font-family'], $this->document_style['font-style'], $this->document_style['font-size']);
382
         $this->pdf_obj->resetColor($this->document_style['font-color'], 'T');
383
      }
384
      if($this->row_data[$i][1]['img']!==false ){
385
         $x=$this->row_data[$i][6];
386
         $k=$padding;
387
         if($this->row_data[$i][1]['valign']!='B'){
388
            $k+=$l+self::IMGPadding;
389
         }
390
         if($this->imgbreak($i, $y)==0 && $y+$k+$this->row_data[$i][1]['img']['h']<$this->pdf_obj->PageBreak()){
391
            $x+=$this->row_data[$i][1]['paddingX'];
392
            if($this->row_data[$i][2]>$this->row_data[$i][1]['img']['w']){
393
               if($this->row_data[$i][1]['align']=='C'){
394
                  $x-=$this->row_data[$i][1]['paddingX'];
395
                  $x+=($this->row_data[$i][2]-$this->row_data[$i][1]['img']['w'])/2;
396
               }
397
               elseif($this->row_data[$i][1]['align']=='R'){
398
                  $x+=$this->row_data[$i][2]-$this->row_data[$i][1]['img']['w'];
399
                  $x-=2*$this->row_data[$i][1]['paddingX'];
400
               }
401
            }
402
            $this->pdf_obj->Image($this->row_data[$i][1]['img']['path'], $x, $y+$k, $this->row_data[$i][1]['img']['w'], $this->row_data[$i][1]['img']['h']);
403
         }
404
      }
405
   }
406
   
407
408
   private function mk_bg($i, $T, $split){
409
      $h=$this->row_data[$i][5];
410
      if($split){
411
         $h=$this->pdf_obj->PageBreak()-$T;
412
      }
413
      if($this->row_data[$i][1]['bgcolor']!=false){
414
         $this->pdf_obj->resetColor($this->row_data[$i][1]['bgcolor']);
415
         $this->pdf_obj->Rect($this->row_data[$i][6], $T, $this->row_data[$i][2], $h, 'F');
416
         $this->pdf_obj->resetColor($this->document_style['bgcolor']);
417
      }
418
   }
419
420
   private function printing_loop($swap=false){
421
      $this->swap_data($swap);
422
      $y=$this->pdf_obj->GetY();
423
      $tmp=array();
424
      $rw=array();
425
      $ztmp=array();
426
      $total_cells=count($this->row_data);
427
      while(count($tmp)!=$total_cells){
428
         $a=count($this->rows);
429
         $h=0;
430
         $y=$this->pdf_obj->GetY();
431
         for($j=0; $j<count($this->rows); $j++){
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...
432
            $T=$y+$h;
433
            if($T<$this->pdf_obj->PageBreak()){
434
435
                  $this->row_content_loop($j, function($index)use($T, $tmp){
436
                  if(!isset($tmp[$index])){
437
                     $split_cell=$this->scan_for_breaks($index,$T, false);
438
                     $this->mk_bg($index, $T, $split_cell);
439
                  }
440
               });
441
               if(!isset($rw[$j])){
442
                  if($this->pdf_obj->PageBreak()-($T+$this->row_heights[$j])>=0){
443
                     $h+=$this->row_heights[$j];
444
                  }
445
                  else{
446
                     $a=$j+1;
447
                     break;
448
                  }
449
               }
450
            }
451
            else{
452
               $a=$j+1;
453
               break;
454
            }
455
         }
456
         $h=0;
457
         for($j=0; $j<$a; $j++){
458
            $T=$y+$h;
459
            if($T<$this->pdf_obj->PageBreak()){
460
461
                  $this->row_content_loop($j, function($index)use($T, &$tmp, &$ztmp){
462
                  if(!isset($tmp[$index])){
463
                     $split_cell=$this->scan_for_breaks($index,$T);
464
                     $this->mk_border($index, $T, $split_cell);
465
                     $this->print_text($index, $T, $split_cell);
466
                     if($split_cell==0){
467
                        $tmp[$index]=$index;
468
                     }
469
                     else{
470
                        $ztmp[]=$index;
471
                     }
472
                  }
473
               });
474
               if(!isset($rw[$j])){
475
                  $tw=$this->pdf_obj->PageBreak()-($T+$this->row_heights[$j]);
476
                  if($tw>=0){
477
                     $h+=$this->row_heights[$j];
478
                     $rw[$j]=$j;
479
                  }
480
                  else{
481
                     $this->row_heights[$j]=$this->overflow-$tw;
482
                  }
483
               }
484
            }
485
         }
486
         if(count($tmp)!=$total_cells){
487
            foreach($ztmp as $index){
488
               $this->row_data[$index][5]=$this->row_data[$index][7]+$this->overflow;
489
               if(isset($this->row_data[$index][8])){
490
                  $this->row_data[$index][1]['padding-y']=$this->row_data[$index][8];
491
                  unset($this->row_data[$index][8]);
492
               }
493
            }
494
            $this->overflow=0;
495
            $ztmp=array();
496
            $this->pdf_obj->addPage($this->document_style['orientation']);
497
         }
498
         else{
499
            $y+=$h;
500
         }
501
      }
502
      $this->pdf_obj->SetXY($this->baseX, $y);
503
      $this->swap_data($swap);
504
   }
505
506
   private function imgbreak($i, $y){
507
      $li=$y+$this->row_data[$i][1]['padding-y'];
508
      $ls=$this->row_data[$i][1]['img']['h'];
509
      if($this->row_data[$i][1]['valign']=='B'){
510
         $ls+=$li;
511
      }
512
      else{
513
         $li+=$this->row_data[$i][3]-$this->row_data[$i][1]['img']['h'];
514
         $ls+=$li;
515
      }
516
      $result=0;
517
      if($li<$this->pdf_obj->PageBreak() && $this->pdf_obj->PageBreak()<$ls){
518
         $result=$this->pdf_obj->PageBreak()-$li;
519
      }
520
      return $result;
521
   }
522
523
   private function scan_for_breaks($index, $H, $l=true){
524
      $print_cell=0;
525
      $h=($H+$this->row_data[$index][5])-$this->pdf_obj->PageBreak();
526
      if($h>0){
527
         if($l){
528
            $rr=$this->pdf_obj->PageBreak()-($H+$this->row_data[$index][1]['padding-y']);
529
            if($rr>0){
530
               $mx=0;
531
               if(count($this->row_data[$index][0]) && $this->row_data[$index][1]['img']!==false){
532
                  $mx=$this->imgbreak($index, $H);
533
                  if($mx==0){
534
                     if($this->row_data[$index][1]['valign']=='B'){
535
                        $rr-=$this->row_data[$index][1]['img']['h'];
536
                     }
537
                  }
538
               }
539
               $nh=0;
540
               $keys=array_keys($this->row_data[$index][0]);
541
               foreach($keys as $i){
542
                  $nh+=$this->row_data[$index][0][$i]['height'];
543
               }
544
               $nh*=$this->row_data[$index][1]['line-height'];
545
               if($mx==0 && $rr<$nh){
546
                  $nw=0;
547
                  foreach($keys as $i){
548
                     $nw+=$this->row_data[$index][0][$i]['height']*$this->row_data[$index][1]['line-height'];
549
                     if($nw>$rr){
550
                        $nw-=$this->row_data[$index][0][$i]['height']*$this->row_data[$index][1]['line-height'];
551
                        $mx=$rr-$nw;
552
                        break;
553
                     }
554
                  }
555
               }
556
               $this->overflow=max($this->overflow, $mx);
557
               $this->row_data[$index][8]=1;
558
            }
559
            else{
560
               $this->row_data[$index][8]=-1*$rr;
561
            }
562
            $this->row_data[$index][7]=$h;
563
         }
564
         $print_cell=1;
565
      }
566
      return $print_cell;
567
   }
568
569
   private function swap_data($swap){
570
      if($swap==false){
571
         return;
572
      }
573
      static $data=array();
574
      if(count($data)==0){
575
         $data=array('header_data'=>$this->header_row['row_data'], 'row_heights'=>&$this->row_heights, 'row_data'=>&$this->row_data, 'rows'=>&$this->rows);
576
         unset($this->row_heights, $this->row_data, $this->rows);
577
         $this->row_heights=&$this->header_row['row_heights'];
578
         $this->row_data=&$this->header_row['row_data'];
579
         $this->rows=&$this->header_row['rows'];
580
      }
581
      else{
582
         $this->header_row['row_data']=$data['header_data'];
583
         unset($this->row_heights, $this->row_data, $this->rows);
584
         $this->row_heights=$data['row_heights'];
585
         $this->row_data=$data['row_data'];
586
         $this->rows=$data['rows'];
587
         $data=array();
588
      }
589
   }
590
   /********************************************************************
591
592
   function __construct( FPDF-object $fpdf_obj, Mix $num_cols[, string $style = '' ])
593
   -----------------------------------------------------
594
   Description:
595
   Constructs an easyTable object
596
   Parameters:
597
   fpdf_obj
598
   the current FPDF object (constructed with the FPDF library)
599
   that is being used to write the current PDF document
600
   num_cols
601
   this parameter can be a positive integer (the number of columns)
602
   or a string of the following form
603
   I) a positive integer, the number of columns for the table. The width
604
   of every column will be equal to the width of the table (given by the width property)
605
   divided by the number of columns ($num_cols)
606
   II) a string of the form '{c1, c2, c3,... cN}'. In this case every
607
   element in the curly brackets is a positive numeric value that represent
608
   the width of a column. Thus, the n-th numeric value is the width
609
   of the n-th colum. If the sum of all the width of the columns is bigger than
610
   the width of the table but less than the width of the document, the table
611
   will stretch to the sum of the columns width. However, if the sum of the
612
   columns is bigger than the width of the document, the width of every column
613
   will be reduce proportionally to make the total sum equal to the width of the document.
614
   III) a string of the form '%{c1, c2, c3,... cN}'. Similar to the previous case, but
615
   this time every element represents a percentage of the width of the table.
616
   In this case it the sum of this percentages is bigger than 100, the execution will
617
   be terminated.
618
   style
619
   the global style for the table (see documentation)
620
   a semicolon-separated string of attribute values that defines the
621
   default layout of the table and all the cells and their contents
622
   (see Documentation section in README.md)
623
   Examples:
624
   $table= new easyTable($fpdf, 3);
625
   $table= new easyTable($fpdf, '{35, 45, 55}', 'width:135;');
626
   $table= new easyTable($fpdf, '%{35, 45, 55}', 'width:190;');
627
   Return value:
628
   An easyTable object
629
   ***********************************************************************/
630
631
   public function __construct($fpdf_obj, $num_cols, $style=''){
632
      if(self::$table_counter){
633
         error_log('Please use the end_table method to terminate the last table');
634
         exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
635
      }
636
      self::$table_counter=true;
637
      $this->pdf_obj=&$fpdf_obj;
638
      $this->document_style['bgcolor']=$this->pdf_obj->get_color('fill');
639
      $this->document_style['font-family']=$this->pdf_obj->current_font('family');
640
      $this->document_style['font-style']=$this->pdf_obj->current_font('style');
641
      $this->document_style['font-size']=$this->pdf_obj->current_font('size');
642
      $this->document_style['font-color']=$this->pdf_obj->get_color('text');
643
      $this->document_style['document_width']=$this->pdf_obj->GetPageWidth()-$this->pdf_obj->get_margin('l')-$this->pdf_obj->get_margin('r');
644
      $this->document_style['orientation']=$this->pdf_obj->get_orientation();
645
      $this->document_style['line-width']=$this->pdf_obj->get_linewidth();
646
      $this->table_style=$this->set_style($style, 'T');
647
      $this->col_num=false;
648
      $this->col_width=array();
649
      if(is_int($num_cols) && $num_cols!=0){
650
         $this->col_num=abs($num_cols);
651
         $this->col_width=array_pad(array(), abs($num_cols), $this->table_style['width']/abs($num_cols));
0 ignored issues
show
Bug introduced by
It seems like abs($num_cols) can also be of type double; however, parameter $length of array_pad() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

651
         $this->col_width=array_pad(array(), /** @scrutinizer ignore-type */ abs($num_cols), $this->table_style['width']/abs($num_cols));
Loading history...
652
      }
653
      elseif(is_string($num_cols)){
654
         $num_cols=trim($num_cols, '}, ');
655
         if($num_cols[0]!='{' && $num_cols[0]!='%'){
656
            error_log('Bad format for columns in Table constructor');
657
            exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
658
         }
659
         $tmp=explode('{', $num_cols);
660
         $tp=trim($tmp[0]);
661
         $num_cols=explode(',', $tmp[1]);
662
         $w=0;
663
         foreach($num_cols as $c){
664
            if(!is_numeric($c)){
665
               error_log('Bad parameter format for columns in Table constructor');
666
               exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
667
            }
668
            if(abs($c)){
0 ignored issues
show
Bug introduced by
$c of type string is incompatible with the type double|integer expected by parameter $num of abs(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

668
            if(abs(/** @scrutinizer ignore-type */ $c)){
Loading history...
669
               $w+=abs($c);
670
               $this->col_width[]=abs($c);
671
            }
672
            else{
673
               error_log('Column width can not be zero');
674
            }
675
         }
676
         $this->col_num=count($this->col_width);
677
         if($tp=='%'){
678
            if($w!=100){
0 ignored issues
show
introduced by
The condition $w != 100 is always true.
Loading history...
679
               error_log('The sum of the percentages of the columns is not 100');
680
               exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
681
            }
682
            foreach($this->col_width as $i=>$c){
683
               $this->col_width[$i]=$c*$this->table_style['width']/100;
684
            }
685
         }
686
         elseif($w!=$this->table_style['width'] && $w){
687
            if($w<$this->document_style['document_width']){
688
               $this->table_style['width']=$w;
689
            }
690
            else{
691
               $this->table_style['width']=$this->document_style['document_width'];
692
               $d=$this->table_style['width']/$w;
693
               for($i=0; $i<count($num_cols); $i++){
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...
694
                  $this->col_width[$i]*=$d;
695
               }
696
            }
697
         }
698
      }
699
      if($this->col_num==false){
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->col_num of type double|false|integer against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
700
         error_log('Unspecified number of columns in Table constructor');
701
         exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
702
      }
703
      $this->table_style['c-align']=array_pad($this->table_style['c-align'], $this->col_num, 'L');
704
      if($this->table_style['l-margin']){
705
         $this->baseX=$this->pdf_obj->get_margin('l')+min($this->table_style['l-margin'],$this->document_style['document_width']-$this->table_style['width']);
706
      }
707
      else{
708
         if($this->table_style['align']=='L'){
709
            $this->baseX=$this->pdf_obj->get_margin('l');
710
         }
711
         elseif($this->table_style['align']=='R'){
712
            $this->baseX=$this->pdf_obj->get_margin('l')+$this->document_style['document_width']-$this->table_style['width'];
713
         }
714
         else{
715
            $this->baseX=$this->pdf_obj->get_margin('l')+($this->document_style['document_width']-$this->table_style['width'])/2;
716
         }
717
      }
718
      $this->row_style_def=$this->set_style('', 'R');
719
      $this->row_style=$this->row_style_def;
720
      $this->row_heights=array();
721
      $this->row_data=array();
722
      $this->rows=array();
723
      $this->total_rowspan=0;
724
      $this->col_counter=0;
725
      $this->grid=array();
726
      $this->blocks=array();
727
      $this->overflow=0;
728
      if($this->table_style['border-width']!=false){
729
         $this->pdf_obj->SetLineWidth($this->table_style['border-width']);
730
      }
731
      $this->header_row=array();
732
      $this->new_table=true;
733
   }
734
   /***********************************************************************
735
736
   function rowStyle( string $style )
737
   -------------------------------------------------------------
738
   Description:
739
   Set or overwrite the style for all the cells in the current row.
740
   Parameters:
741
   style
742
   a semicolon-separated string of attribute values that defines the
743
   layout of all the cells and its content in the current row
744
   (see Documentation section in README.md)
745
   Return values
746
   Void
747
   Notes:
748
749
   This function should be called before the first cell of the current row
750
   ***********************************************************************/
751
752
   public function rowStyle($style){
753
      $this->row_style=$this->set_style($style, 'R');
754
   }
755
   /***********************************************************************
756
757
   function easyCell( string $data [, string $style = '' ])
758
   ------------------------------------------------------------------------
759
   Description:
760
   Makes a cell in the table
761
   Parameters:
762
   data
763
   the content of the respective cell
764
   style (optional)
765
   a semicolon-separated string of attribute values that defines the
766
   layout of the cell and its content (see Documentation section in README.md)
767
   Return value
768
   void
769
   ***********************************************************************/
770
771
   public function easyCell($data, $style=''){
772
      if($this->col_counter<$this->col_num){
773
         $sty=$this->set_style($style, 'C', $this->col_counter);
774
         $this->col_counter++;
775
         $row_number=count($this->rows);
776
         $cell_index=count($this->row_data);
777
         $cell_pos=$this->get_available($sty['colspan'], $sty['rowspan']);
778
         $colm=$cell_pos %$this->col_num;
779
         if($sty['img']!=false && $data!='' && $sty['valign']=='M'){
780
            $sty['valign']=$this->row_style['valign'];
781
         }
782
         if($sty['rowspan']){
783
            $this->total_rowspan=max($this->total_rowspan, $sty['rowspan']);
784
            $this->blocks[$cell_index]=array($cell_index, $row_number, $sty['rowspan']);
785
         }
786
         $w=$this->col_width[$colm];
787
         $r=0;
788
         while($r<$sty['colspan'] && $this->col_counter<$this->col_num){
789
            $this->col_counter++;
790
            $colm++;
791
            $w+=$this->col_width[$colm];
792
            $r++;
793
         }
794
         $w-=2*$sty['paddingX'];
795
         if($sty['img']!==false && is_string($sty['img'])){
796
            $data=$sty['img'];
797
            $sty['img']=false;
798
         }
799
         $data=& $this->pdf_obj->extMultiCell($sty['font-family'], $sty['font-style'], $sty['font-size'], $sty['font-color'], $w, $data);
800
         $h=0;
801
         $rn=count($data);
802
         for($ri=0; $ri<$rn; $ri++){
803
            $h+=$data[$ri]['height']*$sty['line-height'];
804
         }
805
         if($sty['img']){
806
            if($sty['img']['w']>$w){
807
               $sty['img']['h']=$w*$sty['img']['h']/$sty['img']['w'];
808
               $sty['img']['w']=$w;
809
            }
810
            if($h){
811
               $h+=self::IMGPadding;
812
            }
813
            $h+=$sty['img']['h'];
814
         }
815
         $w+=2*$sty['paddingX'];
816
         
817
         $posx=$this->baseX;
818
         $d=$cell_pos %$this->col_num;
819
         for($k=0; $k<$d; $k++){
820
            $posx+=$this->col_width[$k];
821
         }
822
         $this->row_data[$cell_index]=array($data, $sty, $w, $h, $cell_pos, 0, $posx, 0);
823
         
824
      }
825
   }
826
   /***********************************************************************
827
828
   function printRow ( [ bool $setAsHeader = false ] )
829
   ------------------------------------------------------------------------
830
   Description:
831
832
   This function indicates the end of the current row.
833
   Parameters:
834
   setAsHeader (optional)
835
   Optional. When it is set as true, it sets the current row as the header
836
   for the table; this means that the current row will be printed as the first
837
   row of the table (table header) on every page that the table splits on.
838
   Remark: 1. In order to work, the table attribute split-row should set as true.
839
   2. Just the first row where this parameter is set as true will be
840
   used as header any other will printed as a normal row.
841
   Return values
842
   Void
843
   Note:
844
845
   This function will print the current row as far as the following holds:
846
   total_rowspan=0
847
   where total_rowspan is set as
848
   total_rowspan=max(total_rowspan, max(rowspan of cell in the current row))-1;
849
   ***********************************************************************/
850
851
   public function printRow($setAsHeader=false){
852
      $this->col_counter=0;
853
      $row_number=count($this->rows);
854
      $this->rows[$row_number]=count($this->row_data);
855
      $mx=$this->row_style['min-height'];
856
857
         $this->row_content_loop($row_number, function($index)use(&$mx){
858
         if($this->row_data[$index][1]['rowspan']==0){
859
            $mx=max($mx, $this->row_data[$index][3]+2*$this->row_data[$index][1]['paddingY']);
860
         }
861
      });
862
      $this->row_heights[$row_number]=$mx;
863
      
864
      if($this->total_rowspan>0){
865
         $this->total_rowspan--;
866
      }
867
      else{
868
         $row_number=count($this->rows);
869
         if(count($this->blocks)>0){
870
            
871
            foreach($this->blocks as $bk_id=>$block){
872
               $h=0;
873
               for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
874
                  $h+=$this->row_heights[$i];
875
               }
876
               $t=$this->row_data[$block[0]][3]+2*$this->row_data[$block[0]][1]['paddingY'];
877
               if($h>0 && $h<$t){
878
                  for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
879
                     $this->row_heights[$i]*=$t/$h;
880
                  }
881
               }
882
            }
883
            foreach($this->blocks as $j=>$block){
884
               $h=0;
885
               for($i=$block[1]; $i<=$block[1]+$block[2]; $i++){
886
                  $h+=$this->row_heights[$i];
887
               }
888
               $this->row_data[$j][5]=$h;
889
            }
890
         }
891
         $block_height=0;
892
         for($j=0; $j<$row_number; $j++){
893
894
               $this->row_content_loop($j, function($index)use($j, $block_height){
0 ignored issues
show
Unused Code introduced by
The import $block_height is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
895
               if($this->row_data[$index][1]['rowspan']==0){
896
                  $this->row_data[$index][5]=$this->row_heights[$j];
897
               }
898
               $this->row_data[$index][1]['padding-y']=$this->row_data[$index][1]['paddingY'];
899
               if($this->row_data[$index][1]['valign']=='M' || ($this->row_data[$index][1]['img'] && count($this->row_data[$index][0]))){
900
                  $this->row_data[$index][1]['padding-y']=($this->row_data[$index][5]-$this->row_data[$index][3])/2;
901
               }
902
               elseif($this->row_data[$index][1]['valign']=='B'){
903
                  $this->row_data[$index][1]['padding-y']=$this->row_data[$index][5]-($this->row_data[$index][3]+$this->row_data[$index][1]['paddingY']);
904
               }
905
            });
906
            $block_height+=$this->row_heights[$j];
907
         }
908
         if($setAsHeader===true){
909
            if(count($this->header_row)==0){
910
               $this->header_row['row_heights']=$this->row_heights;
911
               $this->header_row['row_data']=$this->row_data;
912
               $this->header_row['rows']=$this->rows;
913
            }
914
         }
915
         if($this->table_style['split-row']==false && $this->pdf_obj->PageBreak()<$this->pdf_obj->GetY()+max($block_height,$this->row_heights[0])){
916
            $this->pdf_obj->addPage($this->document_style['orientation']);
917
            if(count($this->header_row)>0){
918
               $this->printing_loop(true);
919
            }
920
         }
921
         
922
         if($this->new_table){
923
            if(count($this->header_row)>0){
924
               $r=$this->pdf_obj->PageBreak()-($this->pdf_obj->GetY()+$block_height);
925
               if($r<0 || $r<self::PBThreshold){
926
                  $this->pdf_obj->addPage($this->document_style['orientation']);
927
               }
928
            }
929
            $this->new_table=false;
930
         }
931
         $this->printing_loop();
932
         $this->grid=array();
933
         $this->row_data=array();
934
         $this->rows=array();
935
         $this->row_heights=array();
936
         $this->blocks=array();
937
         $this->overflow=0;
938
         $this->new_table=false;
939
      }
940
      $this->row_style=$this->row_style_def;
941
   }
942
   /***********************************************************************
943
944
   function endTable( [int $bottomMargin=2])
945
   ------------------------------------------
946
   Description:
947
   Unset all the data members of the easyTable object
948
   Parameters:
949
   bottomMargin (optional)
950
   Optional. Specify the number of white lines left after
951
   the last row of the table. Default 2.
952
   If it is negative, the vertical position will be set before
953
   the end of the table.
954
   Return values
955
   Void
956
   ***********************************************************************/
957
958
   public function endTable($bottomMargin=2){
959
      self::$table_counter=false;
960
      if($this->table_style['border-width']!=false){
961
         $this->pdf_obj->SetLineWidth($this->document_style['line-width']);
962
      }
963
      $this->pdf_obj->SetX($this->pdf_obj->get_margin('l'));
964
      $this->pdf_obj->Ln($bottomMargin);
965
      $this->pdf_obj->resetStaticData();
966
      unset($this->pdf_obj);
967
      unset($this->document_style);
968
      unset($this->table_style);
969
      unset($this->col_num);
970
      unset($this->col_width);
971
      unset($this->baseX);
972
      unset($this->row_style_def);
973
      unset($this->row_style);
974
      unset($this->row_heights);
975
      unset($this->row_data);
976
      unset($this->rows);
977
      unset($this->total_rowspan);
978
      unset($this->col_counter);
979
      unset($this->grid);
980
      unset($this->blocks);
981
      unset($this->overflow);
982
      unset($this->header_row);
983
   }
984
   
985
}
986
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
987