4 $pg = new Chart('bar'); // Width and Height is set automatically4
5 $pg->setTitle("Testing the Chart");
6 $pg->setLabels(array('Jan', 'Feb', 'Mar'));
7 $pg->addSerie('Sales', array(10345, 15666, 12222), false, true);
8 $pg->addSerie('Costs', array(20767, 10456, 2888), false, false);
9 $pg->addSerie('Result', array(15657, 7567, 12890), 'spline', false);
10 $pg->setXTitle("Names");
11 $pg->setYTitle("Amount");
12 $pg->setDTitle(number_format("15666")); // only printed on donut or half donut
13 //$filename = "test.png";
14 $pg->display(); // with filename to file
16 In your html file you set it up as:
18 <img src="example.php" border="1" />
21 You can supply extra parameters to display(). Ex. $pg->display("test.png") will save the image to a file.
22 Ex. $pg->display("", true) will paint a border around the image. It might be suitable if you choose to save to
23 file for later presentation.
25 ///// END OF EXAMPLE.PHP /////
27 Here is a list of all types you may set:
31 'bar' 1 => Vertical bars (default)
32 'horizontalBar' 2 => Horizontal bars
34 'line' 4 => Lines - Series Type Fill => Area
37 'halfDonut' 7 => Half Donut
38 'spline' 8 => Splines - Series Type fill => Area
39 'table' 9 => Simple HTML table
41 labels[0] => Name of the first parameter in Axis X
42 labels[1] => Name of the second parameter in Axis X
45 series[0]['data'][0] => Value relative for "labels[0]"
46 series[0]['data'][1] => Value relative for "labels[1]"
49 series[1]['data'][0] => Value relative for "labels[0]"
50 series[1]['data'][1] => Value relative for "labels[1]"
53 NOTE: When using 'pie', 'donut' and 'halfDonut' only the first data set is used.
55 That's all! Hope you make a good use of it!
56 It would be nice to receive feedback from others users. All comments are welcome!
62 define('MAXLEN', 27); // we cut after 25 chars + ...
66 var $labels = array();
67 var $series = array();
68 static $palette = array('#008cc9','#4db625','#ef5500','#eef100','#05c6e6', '#5ee66a'); // Currently in Use
75 var $donut_title = "";
76 var $set_values = true;
85 var $sum_total = array();
86 var $higher_value_size = 0;
90 var $legend_box_height;
91 var $stream = 'svg'; // stream = 'svg', 'png', 'jpg' or 'gif'
92 var $svg; // The SVG engine class.
93 var $img; // png image
106 var $space_between_dots = 0;
107 var $higher_value = 0;
108 var $higher_value_str = null;
109 var $graphic_area_width = 0;
110 var $graphic_area_height = 0;
111 var $graphic_area_x1 = 0;
112 var $graphic_area_x2 = 0;
113 var $graphic_area_y1 = 0;
114 var $graphic_area_y2 = 0;
115 var $legend_exists = false;
116 var $legend_box_width = 0;
117 var $legend_box_x1 = 0;
118 var $legend_box_x2 = 0;
119 var $legend_box_y1 = 0;
120 var $legend_box_y2 = 0;
123 function __construct($type = 1, $id = 'id', $width = 0, $height = 0)
126 $this->encoding = strtoupper($_SESSION['language']->encoding);
127 //$this->encoding = "UTF-8"; // Use alternative if used in FA
128 $this->dir = $_SESSION['language']->dir;
129 //$this->dir = 'ltr';
130 $this->lang = $_SESSION['language']->code == 'C' ? 'en' : substr($_SESSION['language']->code, 0, 2);
131 //$this->lang = 'en';
132 $this->path = dirname(__FILE__).'/../fonts/';
133 //$this->path = dirname(__FILE__).'/';
134 // You can use another UTF-8 font and put it in config.php with the name in $UTF8_fontfile
135 if ($this->encoding == 'UTF-8' && !empty($SysPrefs->UTF8_fontfile))
136 $this->fontfile = $this->path.$SysPrefs->UTF8_fontfile;
137 elseif ($this->dir == 'rtl')
138 $this->fontfile = $this->path.'zarnormal.ttf';
140 $this->fontfile = $this->path.'FreeSans.ttf';
141 //$this->fontfile = $this->path.'FreeSans.ttf';
142 //$this->fontfile = $this->path.'zarnormal.ttf';
144 if ($type == 'bar') $type = 1;
145 elseif ($type == 'horizontalBar') $type = 2;
146 elseif ($type == 'dot') $type = 3;
147 elseif ($type == 'line') $type = 4;
148 elseif ($type == 'spline') $type = 8;
149 elseif ($type == 'pie') $type = 5;
150 elseif ($type == 'donut') $type = 6;
151 elseif ($type == 'halfDonut') $type = 7;
152 elseif ($type == 'table') $type = 9;
153 elseif ($type < 1 || $type > 9) $type = 1;
154 elseif (!is_numeric($type)) $type = 1;
155 $this->width = $width;
156 $this->height = $height;
157 $this->max_label = "";
158 $this->max_value = NULL;
159 $this->num_labels = 0;
161 $this->latin_notation = false;
162 $this->align = $this->dir == 'rtl' ? "end" : "start";
163 $this->font = "Tahoma,Arial,sans-serif";
164 if ($this->stream != 'svg')
169 if ($this->dir == 'rtl')
176 function setDirection($dir='ltr')
181 function setLanguage($lang='en')
186 function setStream($stream = 'svg')
188 $this->stream = $stream;
189 if ($this->stream == 'png')
196 function setLabels($labels)
198 $this->labels = $labels;
201 function addSerie($label, $data, $type = false, $fill = false)
204 $label = "Serie $this->num_series";
205 $type = $type == 'line' ? 4 : ($type == 'spline' ? 8 : $type);
206 $this->series[$this->num_series]['label'] = $label;
207 $this->series[$this->num_series]['data'] = $data;
208 $this->series[$this->num_series]['type'] = $type;
209 $this->series[$this->num_series]['fill'] = $fill;
213 function setXTitle($xtitle)
215 $this->axis_x = $xtitle;
218 function setYTitle($ytitle)
220 $this->axis_y = $ytitle;
223 function setTitle($title)
225 $this->title = $title;
228 function setDTitle($dtitle)
230 $this->donut_title = $dtitle;
233 function setValues($values = false)
235 $this->set_values = $values;
238 function setOutDir($dir)
240 $this->out_dir = $dir;
245 return (!isset($this->series[0]['data']) || count($this->series[0]['data']) == 0);
248 function display($save="")
250 $this->encoding = strtoupper($_SESSION['language']->encoding);
251 $this->title_height = (!empty($this->title)) ? $this->tsize + 15 : 0;
252 $this->bar_width = ($this->type == 1) ? 20 : 15;
253 $this->space_between_dots = 40;
254 $this->higher_value = 0;
255 $this->higher_value_str = 0;
256 $this->graphic_area_width = 0;
257 $this->graphic_area_height = 0;
258 $this->graphic_area_x1 = 30;
259 $this->graphic_area_y1 = 30 + $this->title_height;
260 $this->num_labels = count($this->labels);
261 $this->max_legend_str = "";
262 $this->legend_box_height += (14 * $this->num_labels);
263 for ($i = 0; $i < $this->num_labels; $i++)
265 if (strlen($this->labels[$i]) > MAXLEN)
266 $this->labels[$i] = substr($this->labels[$i], 0, MAXLEN)."...";
267 if (strlen($this->labels[$i]) > strlen($this->max_label))
268 $this->max_label = $this->labels[$i];
270 for ($j = 0; $j < $this->num_series; $j++)
272 $this->sum_total[$j] = 0;
273 if (strlen($this->series[$j]['label']) > strlen($this->max_legend_str))
274 $this->max_legend_str = $this->series[$j]['label'];
275 for ($i = 0; $i < $this->num_labels; $i++)
277 if ($this->series[$j]['data'][$i] > $this->max_value)
278 $this->max_value = $this->series[$j]['data'][$i];
279 $this->sum_total[$j] += $this->series[$j]['data'][$i];
282 $this->max_value = number_format(round($this->max_value, 1), 1, ".", "");
283 if ($this->num_series)
284 $this->legend_exists = true;
285 if ($this->type == 8 && $this->num_labels < 4)
287 $this->calculate_higher_value();
288 $this->calculate_width();
289 $this->calculate_height();
290 if ($this->type == 9)
295 $this->create_graphic($save);
298 function create_graphic($save="")
300 if ($this->stream == 'svg')
302 $this->svg = new SVG($this->width, $this->height, $this->dir, $this->lang);
303 $this->svg->style("svg{font-family:{$this->font};background-color:inherit}.tips:hover{cursor:pointer;opacity:0.8;}");
304 $this->load_color_palette($this->type);
308 $this->img = imagecreatetruecolor($this->width, $this->height);
309 $this->load_color_palette($this->type);
311 imagefill($this->img, 0, 0, $this->color['background']);
314 if (!empty($this->title))
316 if ($this->stream == 'svg')
318 $center = $this->width / 2;
319 $this->svg->text($center, 20, $this->title, $this->tsize, $this->color['title'], false, "middle");
323 $center = ($this->width / 2) - ($this->string_width($this->title, $this->tsize) / 2);
324 $this->_imagestring($this->img, $this->tsize, $center, 10, $this->title, $this->color['title']);
327 // Draw axis and background lines for "vertical bars", "dots", "lines" and "splines"
328 if (preg_match("/^(1|3|4|8)$/", $this->type))
330 if ($this->legend_exists == true)
332 $this->draw_legend();
334 $higher_value_y = $this->graphic_area_y1 + (0.1 * $this->graphic_area_height);
335 $this->higher_value_size = 0.9 * $this->graphic_area_height;
336 $less = 7 * strlen($this->higher_value_str);
337 if ($this->stream == 'svg')
339 $this->svg->line($this->graphic_area_x1, $higher_value_y, $this->graphic_area_x2, $higher_value_y, $this->color['bg_lines']);
340 $this->svg->text($this->graphic_area_x1-$less-7, $higher_value_y, $this->higher_value_str, $this->size, $this->color['axis_values'], false, $this->align);
344 imageline($this->img, $this->graphic_area_x1, $higher_value_y, $this->graphic_area_x2, $higher_value_y, $this->color['bg_lines']);
345 $this->_imagestring($this->img, $this->size, ($this->graphic_area_x1-$less-7), ($higher_value_y-7), $this->higher_value_str, $this->color['axis_values']);
347 for ($i = 1; $i < 10; $i++)
349 $dec_y = $i * ($this->higher_value_size / 10);
350 $x1 = round($this->graphic_area_x1);
351 $y1 = round($this->graphic_area_y2 - $dec_y);
352 $x2 = round($this->graphic_area_x2);
354 if ($this->stream == 'svg')
355 $this->svg->line($x1, $y1, $x2, $y2, $this->color['bg_lines']);
357 imageline($this->img, $x1, $y1, $x2, $y2, $this->color['bg_lines']);
360 $value = $this->number_formated($this->higher_value * $i / 10, $this->dec1);
361 $len1 = strlen($this->higher_value_str);
362 $len2 = strlen($value);
364 $len2 += ($len1-$len2-1);
366 if ($this->stream == 'svg')
367 $this->svg->text($x1-$less-7, ($y1), $value, $this->size, $this->color['axis_values'], false, $this->align);
369 $this->_imagestring($this->img, $this->size, ($x1-$less-7), ($y2-7), $value, $this->color['axis_values']);
373 if ($this->stream == 'svg')
375 $this->svg->text($this->graphic_area_x2+10, $this->graphic_area_y2+10, $this->axis_x, $this->size, $this->color['title'], false, $this->align);
376 $this->svg->line($this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
380 $this->_imagestring($this->img, $this->size, $this->graphic_area_x2+20, $this->graphic_area_y2+3, $this->axis_x, $this->color['title']);
381 imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
384 if ($this->stream == 'svg')
386 $lex = $this->dir == 'rtl' ? 35 : 25;
387 $this->svg->text($lex, $this->graphic_area_y1-10, $this->axis_y, $this->size, $this->color['title'], false, $this->align);
388 $this->svg->line($this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
392 $this->_imagestring($this->img, $this->size, 10, $this->graphic_area_y1-20, $this->axis_y, $this->color['title']);
393 imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
396 // Draw axis and background lines for "horizontal bars"
397 else if ($this->type == 2)
399 if ($this->legend_exists == true)
401 $this->draw_legend();
403 $this->higher_value_size = 0.9 * $this->graphic_area_width;
404 if ($this->stream == 'svg')
406 $this->svg->line(($this->graphic_area_x1+$this->higher_value_size), $this->graphic_area_y1, ($this->graphic_area_x1+$this->higher_value_size), $this->graphic_area_y2, $this->color['bg_lines']);
407 $this->svg->text((($this->graphic_area_x1+$this->higher_value_size) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2 + 20), $this->higher_value_str, $this->size, $this->color['axis_values'], false, $this->align);
411 imageline($this->img, ($this->graphic_area_x1+$this->higher_value_size), $this->graphic_area_y1, ($this->graphic_area_x1+$this->higher_value_size), $this->graphic_area_y2, $this->color['bg_lines']);
412 $this->_imagestring($this->img, $this->size, (($this->graphic_area_x1+$this->higher_value_size) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2+2), $this->higher_value_str, $this->color['axis_values']);
414 for ($i = 1, $alt = 15; $i < 10; $i++)
416 $dec_x = number_format(round($i * ($this->higher_value_size / 10), 1), 1, ".", "");
417 if ($this->stream == 'svg')
418 $this->svg->line(($this->graphic_area_x1+$dec_x), $this->graphic_area_y1, ($this->graphic_area_x1+$dec_x), $this->color['bg_lines']);
420 imageline($this->img, ($this->graphic_area_x1+$dec_x), $this->graphic_area_y1, ($this->graphic_area_x1+$dec_x), $this->graphic_area_y2, $this->color['bg_lines']);
423 $alt = (strlen($this->max_value) > 4 && $alt != 15) ? 15 : 2;
424 $value = $this->number_formated($this->higher_value * $i / 10, $this->dec1);
425 if ($this->stream == 'svg')
426 $this->svg->text((($this->graphic_area_x1+$dec_x) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2+$alt+18), $value, $this->size, $this->color['axis_values'], false, $this->align);
428 $this->_imagestring($this->img, $this->size, (($this->graphic_area_x1+$dec_x) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2), $value, $this->color['axis_values'], $alt);
432 if ($this->stream == 'svg')
434 $this->svg->text($this->graphic_area_x2+10, ($this->graphic_area_y2+10), $this->axis_y, $this->size, $this->color['title'], false, $this->align);
435 $this->svg->line($this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
439 $this->_imagestring($this->img, $this->size, ($this->graphic_area_x2+10), ($this->graphic_area_y2+3), $this->axis_y, $this->color['title']);
440 imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
443 if ($this->stream == 'svg')
445 $lex = ($this->string_width($this->max_label, $this->size)) / 2;
446 $this->svg->text($lex, ($this->graphic_area_y1-10), $this->axis_x, $this->size, $this->color['title'], false, $this->align);
447 $this->svg->line($this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
451 $this->_imagestring($this->img, $this->size, 20, ($this->graphic_area_y1-20), $this->axis_x, $this->color['title']);
452 imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
455 else if (preg_match("/^(5|6|7)$/", $this->type))
457 // Draw legend box for "pie", "donut" or "half donut"
458 $this->draw_legend();
460 $average_width = $this->graphic_area_width / $this->num_labels;
461 $biggest_width = $this->string_width($this->max_label, $this->size) + 10;
462 if ($biggest_width > $average_width)
467 * Draw graphic: VERTICAL BARS
469 if ($this->type == 1)
471 $this->draw_vertical_bars();
474 * Draw graphic: HORIZONTAL BARS
476 else if ($this->type == 2)
478 $this->draw_horizontal_bars();
481 * Draw graphic: DOTS. LINE or SPLINE
483 else if (preg_match("/^(3|4|8)$/", $this->type))
486 if ($this->stream != 'svg' && $this->type == 8)
487 $this->draw_splines();
490 * Draw graphic: PIE, DONUT or HALF DONUT
492 else if (preg_match("/^(5|6|7)$/", $this->type))
494 // Draw PIE, DONUT OR HALF DONUT
497 if ($this->stream == 'svg')
500 return $this->svg->draw();
501 //$this->out_dir = company_path(). '/pdf_files/';
502 //$filename = $this->out_dir.uniqid().".svg";
503 //$this->svg->save($filename);
504 //echo "<img src='$filename' border='0' alt='$this->title'>";
508 $filename = $this->out_dir.uniqid().".".$this->stream;
509 if ($this->stream == 'png')
510 imagepng($this->img, $save != "" ? $save : $filename);
511 elseif ($this->stream == 'jpg')
512 imagejpeg($this->img, $save != "" ? $save : $filename);
513 elseif ($this->stream == 'gif')
514 imagegif($this->img, $save != "" ? $save : $filename);
515 echo "<img src='$filename' border='0' alt='$this->title'>";
517 header('Content-type: image/png');
518 imagepng($this->img, NULL, 5);
520 imagedestroy($this->img);
524 function draw_vertical_bars()
526 $x = $this->graphic_area_x1 + 10;
529 foreach ($this->labels as $i => $parameter)
531 for ($j = 0; $j < $this->num_series; $j++)
533 $size = round($this->series[$j]['data'][$i] * $this->higher_value_size / $this->higher_value);
535 $y1 = ($this->graphic_area_y2 - $size) + 1;
536 $x2 = $this->bar_width;
537 $y2 = $this->graphic_area_y2;
538 if ($this->series[$j]['type'] == 8 && $this->num_labels < 4)
539 $this->series[$j]['type'] = 4;
540 if ($this->stream == 'svg')
542 if ($this->series[$j]['type'] == 4 || $this->series[$j]['type'] == 8) // line
544 if (!isset($this->color['line'][0]))
545 $this->load_color_palette($this->series[$j]['type']);
546 if ($i == $this->num_labels - 1)
548 $dx = ($this->num_series-1) * ($this->bar_width + 10);
549 $xx = $this->graphic_area_x1 + $dx;
550 foreach($this->series[$j]['data'] as $i => $v)
552 $size = round($this->series[$j]['data'][$i] * $this->higher_value_size / $this->higher_value);
553 $y = $this->graphic_area_y2 - $size;
558 $path = "M ".$p[0][0].",".$p[0][1];
559 foreach ($p as $ix => $y)
561 $this->svg->circle($p[$ix][0], $p[$ix][1], 2.5, $this->color['line'][$j], 2, $this->color['line'][$j], "class=\"tips\"", $this->series[$j]['label'].": ".number_format($this->series[$j]['data'][$ix], 2));
564 if ($this->series[$j]['type'] == 4) // normal line
565 $path .= " L".$p[$ix][0].",".$p[$ix][1];
566 elseif ($this->series[$j]['type'] == 8) // spline
567 $path .= $this->_splineCommand($p[$ix], $ix, $p);
570 if ($this->series[$j]['fill'] == true)
573 $fpath .= " L ".($p[$ix][0]+1).",".($this->graphic_area_y2-2)." L ".$p[0][0].",".($this->graphic_area_y2-2)." L ".$p[0][0].",".$p[0][1];
574 $this->svg->path($fpath, $this->color['line_light'][$j], 1, $this->color['line_light'][$j]);
576 $this->svg->path($path, $this->color['line'][$j], 3, "none");
581 $this->svg->rect( $x1, $y1, $x2, $y2-$y1, $this->color['bars'][$j], 1, $this->color['bars'][$j], "class=\"tips\"", $this->series[$j]['label'].": ".number_format($this->series[$j]['data'][$i], 2));
582 $x += $this->bar_width + 5;
587 if ($this->series[$j]['type'] == 4) // line
589 if (!isset($this->color['line'][0]))
590 $this->load_color_palette($this->series[$j]['type']);
593 $this->_imageline($this->img, $oldx, $oldy, $x1, $y1, $this->color['line'][$j], 3);
594 if ($this->series[$j]['fill'] == true)
596 $pt = array($oldx, $oldy+3, $x1, $y1 + 3, $x1, $this->graphic_area_y2-2, $oldx, $this->graphic_area_y2-2, $oldx, $oldy+4);
597 imagefilledpolygon($this->img, $pt, 5, $this->color['line_light'][$j]);
600 imagefilledrectangle($this->img, $x1-2, $y1-2, $x1+2, $y1+2, $this->color['line'][$j]);
605 elseif ($this->series[$j]['type'] == 8) // spline
607 if (!isset($this->color['line'][0]))
608 $this->load_color_palette($this->series[$j]['type']);
609 imagefilledrectangle($this->img, $x1-2, $y1-2, $x1+2, $y1+2, $this->color['line'][$j]);
610 $p[$x1] = $this->graphic_area_y2 - $size;
611 if ($i == $this->num_labels - 1)
613 $r = $this->imageSpline($p);
616 while (list ($xx, $yy) = each($r))
618 imagefilledellipse($this->img, round($xx), round($yy)+1, 3, 3, $this->color['line'][$j]);
619 if ($this->series[$j]['fill'] == true)
621 $this->_imageline($this->img, round($xx), round($yy+4), round($xx), $this->graphic_area_y2-2, $this->color['line_light'][$j], 3);
630 imageline($this->img, ($x1+1), ($y1-1), $xx2, ($y1-1), $this->color['bars'][$j]);
631 imageline($this->img, ($xx2+1), ($y1-1), ($xx2+1), $y2, $this->color['bars'][$j]);
632 imageline($this->img, ($xx2+2), ($y1-1), ($xx2+2), $y2, $this->color['bars'][$j]);
633 imagefilledrectangle($this->img, $x1, $y1, $xx2, $y2, $this->color['bars'][$j]);
634 $x += $this->bar_width + 5;
639 if ($this->stream == 'svg')
641 $lex = $this->angle == 0 ? $x1 + 40 : $x1+20;
642 $al = $this->dir == 'rtl' ? "start" : "end";
643 $this->svg->text($lex, ($y2+15), $parameter, $this->size, $this->color['axis_values'], false, $al, $this->angle);
647 $this->_imagestring($this->img, $this->size, $x1, ($y2+2), $parameter, $this->color['axis_values'], 0, $this->angle);
655 function draw_horizontal_bars()
658 $label_len = $this->string_width($this->max_label, $this->size);
659 foreach ($this->labels as $i => $parameter)
661 for ($j = 0; $j < $this->num_series; $j++)
663 $size = round($this->series[$j]['data'][$i] / $this->higher_value * $this->higher_value_size);
664 $x1 = $this->graphic_area_x1 + 1;
665 $y1 = $this->graphic_area_y1 + $y;
667 $y2 = $y1 + $this->bar_width;
668 if ($this->stream == 'svg')
670 $this->svg->rect($x1, $y1, $x2-$x1, $y2-$y1, $this->color['bars'][$j], 1, $this->color['bars'][$j], "class=\"tips\"", $this->series[$j]['label'].": ".number_format($this->series[$j]['data'][$i], 2));
671 $this->svg->text(($x2+10), ($y1+12), $this->number_formated($this->series[$j]['data'][$i], $this->dec2), $this->size, $this->color['bars'][$j], false, $this->align);
672 $y += $this->bar_width + 1;
676 $this->_imageline($this->img, ($x1), ($y2+1), $x2, ($y2+1), $this->color['bars'][$j], 3);
677 imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bars'][$j]);
678 $this->_imagestring($this->img, $this->size, ($x2+7), ($y1+2), $this->number_formated($this->series[$j]['data'][$i], $this->dec2), $this->color['bars'][$j]);
679 $y += $this->bar_width + 4;
682 if ($this->stream == 'svg')
684 $lex = $this->dir == 'rtl' ? $label_len : 20;
685 $this->svg->text($lex, ($y2-5), $parameter, $this->size, $this->color['axis_values'], false, "start");
690 $lex = $this->dir == 'rtl' ? $label_len+10 : 20;
691 $this->_imagestring($this->img, $this->size, $lex, ($y1-5), $parameter, $this->color['axis_values'], 0, 0, $this->align);
697 function draw_lines()
699 for ($j = 0; $j < $this->num_series; $j++)
701 $x = $this->graphic_area_x1+1;
703 if ($this->type == 8 && $this->num_labels < 4)
705 if ($this->stream == 'svg')
708 foreach ($this->labels as $i => $parameter)
710 $size = round($this->series[$j]['data'][$i] * $this->higher_value_size / $this->higher_value);
711 $y = $this->graphic_area_y2 - $size;
716 $lex = $this->angle == 0 ? $x + 30 : $x+10;
717 $al = $this->dir == 'rtl' ? "start" : "end";
718 $this->svg->text($lex, ($this->graphic_area_y2+15), $parameter, $this->size, $this->color['axis_values'], false, $al, $this->angle);
720 $x += $this->space_between_dots;
722 $path = "M ".$p[0][0].",".$p[0][1];
723 foreach ($p as $i => $y)
725 $this->svg->circle($p[$i][0], $p[$i][1], 2.5, $this->color['line'][$j], 3, $this->color['line'][$j], "class=\"tips\"", $this->series[$j]['label'].": ".number_format($this->series[$j]['data'][$i], 2));
728 if ($this->type == 4) // normal line
729 $path .= " L".$p[$i][0].",".$p[$i][1];
730 elseif ($this->type == 8) // spline
731 $path .= $this->_splineCommand($p[$i], $i, $p);
734 if ($this->series[$j]['fill'] == true)
737 $fpath .= " L ".($p[$i][0]+1).",".($this->graphic_area_y2-1)." L ".$p[0][0].",".($this->graphic_area_y2-1)." L ".$p[0][0].",".$p[0][1];
738 $this->svg->path($fpath, $this->color['line_light'][$j], 1, $this->color['line_light'][$j]);
740 $this->svg->path($path, $this->color['line'][$j], 3, "none");
741 $x += $this->space_between_dots;
745 foreach ($this->labels as $i => $parameter)
747 $size = round($this->series[$j]['data'][$i] * $this->higher_value_size / $this->higher_value);
748 $y = $this->graphic_area_y2 - $size;
750 if ($this->type == 4 && $i > 0) // lINES
752 $this->_imageline($this->img, $oldx, $oldy, $x, $y, $this->color['line'][$j], 3);
753 if ($this->series[$j]['fill'] == true)
755 $pt = array($oldx, $oldy+3, $x, $y + 3, $x, $this->graphic_area_y2-2, $oldx, $this->graphic_area_y2-2, $oldx, $oldy+4);
756 imagefilledpolygon($this->img, $pt, 5, $this->color['line_light'][$j]);
759 imagefilledrectangle($this->img, $x-2, $y-2, $x+2, $y+2, $this->color['line'][$j]);
763 $this->_imagestring($this->img, $this->size, $oldx, ($this->graphic_area_y2+2), $parameter, $this->color['axis_values'], 0, $this->angle);
764 $x += $this->space_between_dots;
770 function draw_splines()
772 for ($j = 0; $j < $this->num_series; $j++)
774 $n = $this->graphic_area_x1+1;
775 foreach ($this->labels as $i => $parameter)
777 $size = round($this->series[$j]['data'][$i] * $this->higher_value_size / $this->higher_value);
778 $y = $this->graphic_area_y2 - $size;
780 $n += $this->space_between_dots;
782 $r = $this->imageSpline($p);
786 foreach ($r as $x => $y)
788 imagefilledellipse($this->img, round($x), round($y)+1, 3, 3, $this->color['line'][$j]);
790 if ($this->series[$j]['fill'] == true)
792 $this->_imageline($this->img, round($x), round($y+4), round($x), $this->graphic_area_y2-2, $this->color['line_light'][$j], 1);
798 function imageSpline($p, $step = 1, $minx = -1, $maxx = -1)
803 $cx = $cy = $p1 = array();
805 foreach ($p as $x => $y)
815 for ($i = 0; $i < $n; ++$i)
817 $splines[$i]['x'] = $cx[$i];
818 $splines[$i]['a'] = $cy[$i];
820 $splines[0]['c'] = $splines[$n - 1]['c'] = 0;
821 $alpha[0] = $beta[0] = 0;
822 for ($i = 1; $i < $n - 1; ++$i)
824 $h_i = $cx[$i] - $cx[$i - 1];
825 $h_i1 = $cx[$i + 1] - $cx[$i];
827 $C = 2.0 * ($h_i + $h_i1);
829 $F = 6.0 * (($cy[$i + 1] - $cy[$i]) / $h_i1 - ($cy[$i] - $cy[$i - 1]) / $h_i);
830 $z = ($A * $alpha[$i - 1] + $C);
831 $alpha[$i] = - $B / $z;
832 $beta[$i] = ($F - $A * $beta[$i - 1]) / $z;
834 for ($i = $n - 2; $i > 0; --$i)
835 $splines[$i]['c'] = $alpha[$i] * $splines[$i + 1]['c'] + $beta[$i];
836 for ($i = $n - 1; $i > 0; --$i)
838 $h_i = $cx[$i] - $cx[$i - 1];
839 $splines[$i]['d'] = ($splines[$i]['c'] - $splines[$i - 1]['c']) / $h_i;
840 $splines[$i]['b'] = $h_i * (2.0 * $splines[$i]['c'] + $splines[$i - 1]['c']) / 6.0 + ($cy[$i] - $cy[$i - 1]) / $h_i;
842 for ($x = $minx; $x <= $maxx; $x += $step)
844 $n = count($splines);
845 if ($x <= $splines[0]['x']) {
848 if ($x >= $splines[$n - 1]['x']) {
849 $s = $splines[$n - 1];
853 while ($i + 1 < $j) {
854 $k = $i + ($j - $i) / 2;
855 if ($x <= $splines[round($k)]['x']) {
861 $s = $splines[round($j)];
864 $dx = ($x - $s['x']);
865 $p1[$x] = $s['a'] + ($s['b'] + ($s['c'] / 2.0 + $s['d'] * $dx / 6.0) * $dx) * $dx;
872 $n = count(self::$palette);
873 if ($this->stream == 'svg')
875 $cx = ($this->graphic_area_x1 + $this->graphic_area_x2) / 2;
876 $cy = ($this->graphic_area_y1 + $this->graphic_area_y2) / 2;
877 $width = $this->graphic_area_width;
878 $height = $this->graphic_area_height;
879 if ($this->sum_total[0] == 0)
880 $this->sum_total[0] = 1;
882 $rc = $this->type == 5 ? 0.01 : $r - 25;
883 $d = $this->type == 7 ? 180 : 360; // half donut or all
884 $area = $d / $this->sum_total[0];
885 $start = $this->type == 7 ? 180 : 90;
889 $ang1=0; // start angle
890 foreach ($this->labels as $i => $num)
892 $n = count(self::$palette);
893 $pct[$i] = round($this->series[0]['data'][$i] / $this->sum_total[0] * 100, 1);
894 $dang = $this->series[0]['data'][$i] * $area; // delta angle
895 $laf = $dang > 180 ? 1 : 0; // Large Arc Flag
896 $ang2 = $ang1 + $dang; // second angle
897 $a = ($ang1 - $start) * $rad + asin($gap / $rc);
898 $p1 = sprintf('%0.2f,%0.2f', $cx + $rc * cos($a), $cy + $rc * sin($a));
899 $a = ($ang1 - $start) * $rad + asin($gap / $r);
900 $p2 = sprintf('%0.2f,%0.2f', $cx + $r * cos($a), $cy + $r * sin($a));
901 $a = ($ang2 - $start) * $rad - asin($gap / $r);
902 $p3 = sprintf('%0.2f,%0.2f', $cx + $r * cos($a), $cy + $r * sin($a));
903 $a = ($ang2 - $start) * $rad - asin($gap / $rc);
904 $p4 = sprintf('%0.2f,%0.2f', $cx + $rc * cos($a), $cy + $rc * sin($a));
905 $a = ($ang1 - $start) * $rad + asin($gap / $rc);
906 $p5 = sprintf('%0.2f,%0.2f', $cx + $rc * cos($a), $cy + $rc * sin($a));
907 $this->svg->path("M$p1 L$p2 A$r,$r 0 $laf,1 $p3 L$p4 A$rc,$rc 0 $laf,0 $p5", $this->color[$i % $n], 0, $this->color[$i % $n], "class=\"tips\"", "$num: ".number_format($pct[$i], 1)."%");
910 if (!empty($this->donut_title) && $this->type != 5)
912 // Display center text
913 if ($this->type == 6)
915 $this->svg->text($cx, $cy, $this->donut_title, $this->size, $this->color[0], "style=\"font-size:18px;font-weight:bold;\"", "middle");
922 $degrees = $this->type == 7 ? 180 : 360; // half donut or all
923 foreach ($this->labels as $i => $parameter)
925 if ($this->sum_total[0] == 0)
926 $this->sum_total[0] = 1;
927 if ($this->series[0]['data'][$i] < 0)
928 $this->series[0]['data'][$i] = 0;
929 $size = $this->series[0]['data'][$i] * $degrees / $this->sum_total[0];
930 $size = round($size, 0);
934 $center_x = ($this->graphic_area_x1 + $this->graphic_area_x2) / 2;
935 $center_y = ($this->graphic_area_y1 + $this->graphic_area_y2) / 2;
936 $width = $this->graphic_area_width;
937 $height = $this->graphic_area_height;
938 $start = $this->type == 7 ? 180 : 270;
940 foreach ($sizes as $i => $size)
943 $color = 'arc_' . $j;
945 imagefilledarc($this->img, $center_x, $center_y, $width, $height, $start, ($start+$size), $this->color[$color], IMG_ARC_PIE);
948 if ($this->type != 5) // DONUTS
950 // 85 pixels width hole
951 $start = $this->type == 7 ? 180 : 0;
952 imagefilledarc($this->img, $center_x, $center_y, 85, 85, $start, 360, $this->color['background'], IMG_ARC_PIE);
953 imagearc($this->img, $center_x, $center_y, 85, 85, $start, 360, $this->color['bg_legend']);
954 imagearc($this->img, $center_x, $center_y, ($width+1), ($height+1), $start, 360, $this->color['bg_legend']);
955 if (!empty($this->donut_title))
957 $plen = $this->string_width($this->donut_title, $this->size);
958 $x1 = $center_x - $plen / 2 - 6;
959 $co = $this->type == 7 ? 20 : 10; // HALF or ALL
960 $this->_imagestring($this->img, $this->size + 4, $x1, $center_y - $co, $this->donut_title, $this->color['arc_0'], 2, 0);
961 $this->_imagestring($this->img, $this->size + 4, $x1+1, $center_y - $co, $this->donut_title, $this->color['arc_0'], 2, 0);
967 function draw_table()
969 $cs = $this->num_labels + 1;
970 $html = "<table cellspacing='0' //style='width:{$this->width}px;font-family:{$this->font};font-size:12px;background:inherit;'>\n";
971 if (!empty($this->title))
972 $html .= "<tr><th colspan=$cs style='text-align:center;'><h3>$this->title</th><tr>\n";
973 $html .= "<tr><th style='border-bottom:1px solid #444'>#</th>";
974 for ($i = 0; $i < $this->num_labels; $i++)
975 $html .= "<th style='text-align:right;border-bottom:1px solid #444'>{$this->labels[$i]}</th>";
977 for ($j = 0; $j < $this->num_series; $j++)
979 $html .= "<tr><td style=''>{$this->series[$j]['label']}</td>";
980 for ($i = 0; $i < $this->num_labels; $i++)
981 $html .= "<td style='text-align:right;'>".number_format($this->series[$j]['data'][$i], 0)."</td>";
984 $html .= "</table>\n";
988 function calculate_width()
990 $this->legend_box_width = ($this->legend_exists == true) ? ($this->string_width($this->max_legend_str, $this->size) + 70) : 0;
993 // Vertical bars or Table
996 $this->graphic_area_x1 += $this->string_width($this->higher_value_str, $this->size);
997 if (!empty($this->width))
998 $this->graphic_area_width = $this->width - $this->graphic_area_x1 - 30 - $this->legend_box_width;
1004 for ($j = 0; $j < $this->num_series; $j++)
1006 if ($this->series[$j]['type'] != 4 && $this->series[$j]['type'] != 8)
1007 $serie_width += $this->bar_width;
1008 $serie_width += $gap_labels;
1010 $serie_width += $gap_series;
1011 $this->graphic_area_width = $serie_width * $this->num_labels;
1012 $this->width += $this->graphic_area_width;
1013 $this->width += $this->graphic_area_x1;
1014 $this->width += $this->legend_box_width;
1019 $this->graphic_area_x1 += $this->string_width($this->max_label, $this->size);
1020 if (!empty($this->width))
1021 $this->graphic_area_width = $this->width - $this->graphic_area_x1 - 30 - $this->legend_box_width;
1024 $this->graphic_area_width = ($this->string_width($this->higher_value_str, $this->size) > 50) ? (5 * ($this->string_width($this->higher_value_str, $this->size)) * 0.85) : 200;
1025 $this->width += $this->graphic_area_x1;
1026 $this->width += $this->graphic_area_width;
1027 $this->width += $this->legend_box_width;
1036 $this->graphic_area_x1 += $this->string_width(($this->higher_value_str), $this->size);
1037 if (!empty($this->width))
1038 $this->graphic_area_width = $this->width - $this->graphic_area_x1 - 30 - $this->legend_box_width;
1041 $this->graphic_area_width = $this->space_between_dots * ($this->num_labels - 1) + 5;
1042 $this->width += $this->graphic_area_width;
1043 $this->width += $this->graphic_area_x1 + 30;
1044 $this->width += $this->legend_box_width;
1053 $this->legend_box_width += 60;
1054 if (!empty($this->width))
1055 $this->graphic_area_width = $this->width - $this->graphic_area_x1 - 30 - $this->legend_box_width;
1058 $this->graphic_area_width = 150;
1059 $this->width += $this->graphic_area_x1 +20;
1060 $this->width += $this->legend_box_width;
1061 $this->width += $this->graphic_area_width;
1066 $this->graphic_area_width = max($this->graphic_area_width, $this->string_width($this->title, $this->size));
1067 $this->graphic_area_x2 = $this->graphic_area_x1 + $this->graphic_area_width;
1068 $this->legend_box_x1 = $this->graphic_area_x2 + 20;
1069 $this->legend_box_x2 = $this->legend_box_x1 + $this->legend_box_width;
1072 function calculate_height()
1074 switch ($this->type)
1078 if (!empty($this->height))
1079 $this->graphic_area_height = $this->height - $this->title_height;
1082 $this->graphic_area_height = 150;
1083 $this->height += 65;
1088 if (!empty($this->height))
1089 $this->graphic_area_height = $this->height - $this->title_height;
1093 if ($this->stream != 'svg')
1095 $this->graphic_area_height = $this->num_series * $this->bar_width * $this->num_labels + $this->num_labels * $gap_labels;
1096 $this->height += 65;
1105 if (!empty($this->height))
1106 $this->graphic_area_height = $this->height - $this->title_height;
1109 $this->graphic_area_height = 150;
1110 $this->height += 65;
1119 if (!empty($this->height))
1120 $this->graphic_area_height = $this->height - $this->title_height;
1123 $this->graphic_area_height = 150;
1124 $this->height += 65;
1128 //if ($this->type == 7) // Half Donut;
1129 $this->graphic_area_y1 -= 10;
1130 $this->legend_box_y1 = $this->graphic_area_y1;
1131 $this->height += $this->graphic_area_height + 40;
1132 $this->graphic_area_y2 = $this->graphic_area_y1 + $this->graphic_area_height;
1133 $this->legend_box_y2 = $this->legend_box_y1 + $this->legend_box_height;
1136 function draw_legend()
1138 $x1 = $this->legend_box_x1;
1139 $y1 = $this->legend_box_y1;
1140 $x2 = $this->legend_box_x2;
1141 $y2 = $this->legend_box_y2;
1142 if ($this->stream == 'svg')
1143 $this->svg->rect($x1, $y1, $x2, $y2, $this->color['bg_legend']);
1145 imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bg_legend']);
1148 // Draw legend values for VERTICAL BARS, HORIZONTAL BARS, DOTS, LINES AND SPLINES
1149 if (preg_match("/^(1|2|3|4|8)$/", $this->type))
1151 for ($j = 0; $j < $this->num_series; $j++)
1153 $color = (preg_match("/^(1|2)$/", $this->type)) ? $this->color['bars'][$j] : $this->color['line'][$j];
1154 $len = $this->string_width($this->max_legend_str, $this->size)-20;
1155 if ($this->stream == 'svg')
1157 $lex = $this->dir == 'rtl' ? $x1+$len : $x1-5;
1158 $this->svg->circle($lex, $y-5, 6, "#fff", 1, $color);
1159 //$this->svg->rect($lex, $y-10, 10, 10, "#fff", 1, $color);
1160 $lex = $this->dir == 'rtl' ? $x1+$len-15 : $x-5;
1161 $this->svg->text($lex, ($y-2), $this->series[$j]['label'], $this->size, $this->color['axis_values'], false, "start");
1165 $lex = $this->dir == 'rtl' ? $x1+$len+20 : $x-10;
1166 imagefilledrectangle($this->img, $lex, $y, ($lex+10), ($y+10), $color);
1167 imagerectangle($this->img, $lex, $y, ($lex+10), ($y+10), $this->color['title']);
1168 $lex = $this->dir == 'rtl' ? $x1+$len+20 : $x+10;
1169 $this->_imagestring($this->img, $this->size, $lex, ($y-2), $this->series[$j]['label'], $this->color['axis_values'], 0, 0, $this->align);
1174 // Draw legend values for PIE, DONUT or HALF DONUT
1175 else if (preg_match("/^(5|6|7)$/", $this->type))
1177 $n = count(self::$palette);
1178 if ($this->sum_total[0] == 0)
1180 $label_len = $this->string_width($this->max_label, $this->size);
1181 //$value_len = $this->string_width($this->max_value, $this->size);
1182 $value_len = $this->string_width(number_format($this->max_value), $this->size);
1183 $total_len = $label_len + $value_len;
1184 $total_len = max($total_len, $x2-$x1);
1185 if (!empty($this->axis_x)) // Only first serie [0]
1187 if ($this->stream == 'svg')
1188 $this->svg->text(((($x1+$x1+$total_len)/2) - (strlen($this->axis_x)*7/2)), $y, $this->axis_x." (".$this->series[0]['label'].")", $this->size, $this->color['title'], false, $this->align);
1190 $this->_imagestring($this->img, $this->size, (($x1+$x1+$total_len)/2 - strlen($this->axis_x)*7/2)+30, $y,
1191 $this->axis_x."-".$this->series[0]['label'], $this->color['title']);
1194 foreach ($this->labels as $i => $parameter)
1196 if ($this->set_values)
1197 $text = number_format($this->series[0]['data'][$i]);
1199 $text = number_format($this->series[0]['data'][$i] * 100 / $this->sum_total[0], 2) . ' %';
1200 if ($this->stream == 'svg')
1203 $lex = $this->dir == 'rtl' ? $x1+$total_len-25 : $x1;
1204 $this->svg->circle($lex, $y-5, 6, "#fff", 1, $this->color[$j]);
1205 // $this->svg->rect($lex-5, $y-10, 10, 10, "#fff", 1, $this->color[$j]);
1206 // Display label text
1207 $lex = $this->dir == 'rtl' ? $x1+$total_len-40 : $x1+15;
1208 $this->svg->text($lex, ($y-2), $parameter, $this->size, $this->color['axis_values'], false, "start");
1209 $lex = $this->dir == 'rtl' ? $x1+$value_len-25 : $x1+$total_len;
1210 $al = $this->dir == 'rtl' ? "start" : "end";
1211 $this->svg->text($lex, ($y-2), $text, $this->size, $this->color['axis_values'], false, $al);
1212 $lex2 = $this->dir == 'rtl' ? $x1+$total_len-25 : $x1+$total_len;
1213 $this->svg->line($x1, $y+1, $lex2, $y+1, $this->color['bg_lines']);
1218 $color = 'arc_' . $j;
1219 $width = $this->string_width($text, $this->size);
1220 imageline($this->img, $x1+15, ($y+11), $x2+20, ($y+11), $this->color['bg_lines']);
1221 $lex = $this->dir == 'rtl' ? $x2+20 : $x;
1222 imagefilledrectangle($this->img, $lex, $y, ($lex+10), ($y+10), $this->color[$color]);
1223 imagerectangle($this->img, $lex, $y, ($lex+10), ($y+10), $this->color['title']);
1224 $lex = $this->dir == 'rtl' ? $x2+5 : $x+15;
1225 $this->_imagestring($this->img, $this->size, $lex, ($y-2), $parameter, $this->color['axis_values'], 0, 0, $this->align);
1226 //$lex = $this->dir == 'rtl' ? $x+10 : $x2-$width;
1227 $lex = $this->dir == 'rtl' ? $x1+$value_len : $x2-$width;
1228 $al = $this->dir == 'rtl' ? "end" : $this->align;
1229 $this->_imagestring($this->img, $this->size, $lex, ($y-2), $text, $this->color['axis_values'], 0, 0, $al);
1236 function string_width($string, $size)
1238 if ($string == NULL)
1240 $p = imageftbbox($size, 0, $this->fontfile, $string);
1241 return $p[4] - $p[0];
1244 function calculate_higher_value()
1246 $digits = strlen(round($this->max_value));
1247 $interval = pow(10, ($digits-1));
1248 $this->higher_value = round(($this->max_value - (round($this->max_value) % $interval) + $interval), 1);
1249 $this->higher_value_str = $this->number_formated($this->higher_value, $this->dec1);
1252 function number_formated($number, $dec_size = 1)
1254 if ($this->latin_notation == true)
1255 return number_format(round($number, $dec_size), $dec_size, ",", ".");
1256 return number_format(round($number, $dec_size), $dec_size, ".", ",");
1259 function load_color_palette($type)
1261 // The usual color palette. Change if you like. Must be 6 colors.
1262 $color = self::$palette;
1263 if ($this->stream == 'svg')
1265 $this->color['title'] = sprintf("#%02x%02x%02x", 40, 70, 130);
1266 $this->color['background'] = sprintf("#%02x%02x%02x", 255, 255, 255);
1267 $this->color['axis_values'] = sprintf("#%02x%02x%02x", 50, 50, 50);
1268 $this->color['axis_line'] = sprintf("#%02x%02x%02x", 100, 100, 100);
1269 $this->color['bg_lines'] = sprintf("#%02x%02x%02x", 220, 220, 220);
1270 $this->color['bg_legend'] = sprintf("#%02x%02x%02x", 255, 255, 255);
1271 $this->color['shadow'] = sprintf("#%02x%02x%02x", 255, 255, 255);
1273 if (preg_match("/^(1|2)$/", $type)) // Vertical Bar or Horizontal bar
1275 for ($j = 0; $j < $this->num_series; $j++)
1277 $this->color['bars'][$j] = $color[$j];
1280 elseif (preg_match("/^(3|4|8)$/", $type)) // Dots, Lines or Splines
1282 for ($j = 0; $j < $this->num_series; $j++)
1284 $this->color['line'][$j] = $color[$j];
1285 $this->color['line_light'][$j] = $this->colorLuminate($color[$j], 0.8);
1288 elseif (preg_match("/^(5|6|7)$/", $type)) // Pie, Donut or Half Donut
1291 for ($j = 0; $j < $n; $j++)
1292 $this->color[$j] = $color[$j];
1297 $this->color['title'] = imagecolorallocate($this->img, 40, 70, 130);
1298 $this->color['background'] = imagecolorallocate($this->img, 255, 255, 255);
1299 $this->color['axis_values'] = imagecolorallocate($this->img, 50, 50, 50);
1300 $this->color['axis_line'] = imagecolorallocate($this->img, 100, 100, 100);
1301 $this->color['bg_lines'] = imagecolorallocate($this->img, 220, 220, 220);
1302 $this->color['bg_legend'] = imagecolorallocate($this->img, 255, 255, 255);
1303 $this->color['shadow'] = imagecolorallocate($this->img, 255, 255, 255);
1305 if (preg_match("/^(1|2)$/", $type)) // Vertical Bar or Horizontal bar
1307 for ($j = 0; $j < $this->num_series; $j++)
1309 $c = $this->hex2rgb($color[$j]);
1310 $this->color['bars'][$j] = imagecolorallocate($this->img, $c[0], $c[1], $c[2]);
1313 else if (preg_match("/^(3|4|8)$/", $type)) // Dots, Lines or Splines
1315 for ($j = 0; $j < $this->num_series; $j++)
1317 $c = $this->hex2rgb($color[$j]);
1318 $this->color['line'][$j] = imagecolorallocate($this->img, $c[0], $c[1], $c[2]);
1319 $c = $this->hex2rgb($this->colorLuminate($color[$j], 0.8)); // lighten for Areas
1320 $this->color['line_light'][$j] = imagecolorallocate($this->img, $c[0], $c[1], $c[2]);
1323 else if (preg_match("/^(5|6|7)$/", $type)) // Pie, Donut or Half Donut
1326 for ($j = 0; $j < $n; $j++)
1328 $c = $this->hex2rgb($color[$j]);
1329 $this->color["arc_{$j}"] = imagecolorallocate($this->img, $c[0], $c[1], $c[2]);
1335 function colorLuminate($hex, $percent) // Color lightner, minus is darker
1337 $hex = ltrim($hex, '#');
1338 if (strlen($hex) == 3) {
1339 $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
1341 $hex = array_map('hexdec', str_split($hex, 2));
1342 foreach ($hex as &$color) {
1343 $limit = $percent < 0 ? $color : 255 - $color;
1344 $value = ceil($limit * $percent);
1345 $color = str_pad(dechex($color + $value), 2, '0', STR_PAD_LEFT);
1347 return '#' . implode($hex);
1350 function _imageline($image, $x1, $y1, $x2, $y2, $color, $thick = 1)
1353 return imageline($image, $x1, $y1, $x2, $y2, $color);
1354 $t = $thick / 2 - 0.5;
1355 if ($x1 == $x2 || $y1 == $y2)
1356 return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
1357 $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
1358 $a = $t / sqrt(1 + pow($k, 2));
1360 round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
1361 round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
1362 round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
1363 round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
1365 if (PHP_MAJOR_VERSION >= 8) { // num_points is deprecated
1366 imagefilledpolygon($image, $points, $color);
1367 return imagepolygon($image, $points, $color);
1370 imagefilledpolygon($image, $points, 4, $color);
1371 return imagepolygon($image, $points, 4, $color);
1375 function _imagestring($img, $size, $x, $y, $string, $col, $alt=0, $angle=0, $align=false)
1377 if ($align == 'end')
1379 $p = imagettfbbox($size, $angle, $this->fontfile, $string);
1383 if ($this->encoding != 'UTF-8')
1385 if (function_exists('iconv'))
1386 $string = iconv($this->encoding, 'UTF-8', $string);
1388 $string = mb_convert_encoding($string, 'UTF-8', $this->encoding);
1391 // Handling ev. RTL languages
1394 if ($this->encoding == 'UTF-8' && $this->dir == 'rtl')
1398 if (strlen($string) > $alt_len)
1399 $string = substr($string, 0, $alt_len);
1401 if ($this->encoding == 'UTF-8')
1403 if (is_arabic($string))
1404 $string = arabic($string);
1405 elseif (is_hebrew($string))
1406 $string = hebrew($string);
1409 if ($this->encoding == 'UTF-8' && is_arabic($string))
1412 $string = str_replace(" ", " ", $string);
1414 imagettftext($img, $size, $angle, round($x), $y + $alt, $col, $this->fontfile, $string);
1417 function hex2rgb($hex)
1419 list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
1420 return array($r, $g, $b);
1423 function _controlPoint($curr, $prev, $next, $reverse = false)
1425 $p = $prev ? $prev : $curr;
1426 $n = $next ? $next : $curr;
1428 $lenx = $n[0] - $p[0];
1429 $leny = $n[1] - $p[1];
1430 $len = sqrt(pow($lenx, 2) + pow($leny, 2));
1431 $angle = atan2($leny, $lenx);
1433 $angle += ($reverse ? pi() : 0);
1434 $x = $curr[0] + cos($angle) * $len;
1435 $y = $curr[1] + sin($angle) * $len;
1436 return array($x, $y);
1439 function _splineCommand($p, $i, $a)
1441 $c = isset($a[$i - 1]) ? $a[$i - 1] : false;
1442 $d = isset($a[$i - 2]) ? $a[$i - 2] : false;
1443 $e = isset($a[$i + 1]) ? $a[$i + 1] : false;
1444 $cps = $this->_controlPoint($c, $d, $p);
1445 $cpe = $this->_controlPoint($p, $c, $e, true);
1446 return " C".round($cps[0],1).",".round($cps[1],1)." ".round($cpe[0],1).",".round($cpe[1], 1)." $p[0],$p[1]";
1449 function clean_out_dir()
1451 $dir = $this->out_dir;
1452 if ($d = @opendir($dir)) {
1453 while (($file = readdir($d)) !== false) {
1454 if (!is_file($dir.'/'.$file) || $file == 'index.php') continue;
1455 // then check to see if this one is too old
1456 $ftime = filemtime($dir.'/'.$file);
1457 // seems 3 min is enough for any report download, isn't it?
1458 if (time()-$ftime > 180){
1459 unlink($dir.'/'.$file);
1471 function __construct($width=0, $height=0, $dir='ltr', $lang='en')
1473 $this->svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" direction=\"$dir\" xml:lang=\"$lang\" width=\"$width\" height=\"$height\" viewPort=\"0 0 $width $height\"";
1474 $this->svg .= ">\n";
1476 function circle($x, $y, $r, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1478 $this->svg .= "<circle cx=\"$x\" cy=\"$y\" r=\"$r\"";
1479 if (!empty($line_width))
1480 $this->svg .= " stroke-width=\"$line_width\"";
1481 if (!empty($bcolor))
1482 $this->svg .= " stroke=\"$bcolor\"";
1485 $this->svg .= " fill=\"$color\"";
1487 $this->svg .= " $style";
1488 if (!empty($tooltip))
1489 $this->svg .= "><title>$tooltip</title></circle>\n";
1491 $this->svg .= " />\n";
1493 function rect($x1, $y1, $x2, $y2, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1495 $this->svg .= "<rect x=\"$x1\" y=\"$y1\" width=\"$x2\" height=\"$y2\"";
1496 if (!empty($line_width))
1497 $this->svg .= " stroke-width=\"$line_width\"";
1498 if (!empty($bcolor))
1499 $this->svg .= " stroke=\"$bcolor\"";
1502 $this->svg .= " fill=\"$color\"";
1504 $this->svg .= " $style";
1505 if (!empty($tooltip))
1506 $this->svg .= "><title>$tooltip</title></rect>\n";
1508 $this->svg .= " />\n";
1510 function line($x1, $y1, $x2, $y2, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1512 $this->svg .= "<line x1=\"$x1\" y1=\"$y1\" x2=\"$x2\" y2=\"$y2\"";
1513 if (!empty($line_width))
1514 $this->svg .= " stroke-width=\"$line_width\"";
1515 if (!empty($bcolor))
1516 $this->svg .= " stroke=\"$bcolor\"";
1519 $this->svg .= " fill=\"$color\"";
1521 $this->svg .= " $style";
1522 if (!empty($tooltip))
1523 $this->svg .= "><title>$tooltip</title></line>\n";
1525 $this->svg .= " />\n";
1527 function polygon($p, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1529 $this->svg .= "<polygon points=\"$p\"";
1530 if (!empty($line_width))
1531 $this->svg .= " stroke-width=\"$line_width\"";
1532 if (!empty($bcolor))
1533 $this->svg .= " stroke=\"$bcolor\"";
1536 $this->svg .= " fill=\"$color\"";
1538 $this->svg .= " $style";
1539 if (!empty($tooltip))
1540 $this->svg .= "><title>$tooltip</title></polygon>\n";
1542 $this->svg .= " />\n";
1544 function polyline($p, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1546 $this->svg .= "<polyline points=\"$p\"";
1547 if (!empty($line_width))
1548 $this->svg .= " stroke-width=\"$line_width\"";
1549 if (!empty($bcolor))
1550 $this->svg .= " stroke=\"$bcolor\"";
1553 $this->svg .= " fill=\"$color\"";
1555 $this->svg .= " $style";
1556 if (!empty($tooltip))
1557 $this->svg .= "><title>$tooltip</title></polyline>\n";
1559 $this->svg .= " />\n";
1561 function path($d, $bcolor=false, $line_width=1, $color=false, $style=false, $tooltip=false)
1563 $this->svg .= "<path d=\"$d\"";
1564 if (!empty($line_width))
1565 $this->svg .= " stroke-width=\"$line_width\"";
1566 if (!empty($bcolor))
1567 $this->svg .= " stroke=\"$bcolor\"";
1570 $this->svg .= " fill=\"$color\"";
1572 $this->svg .= " $style";
1573 if (!empty($tooltip))
1574 $this->svg .= "><title>$tooltip</title></path>\n";
1576 $this->svg .= " />\n";
1578 function text($x, $y, $text, $size=false, $color=false, $style=false, $align=false, $angle=false) // align start, middle, end.
1580 $this->svg .= "<text x=\"$x\" y=\"$y\"";
1582 $this->svg .= " fill=\"$color\"";
1584 $this->svg .= " font-size=\"$size\"";
1586 $this->svg .= " $style";
1588 $this->svg .= " text-anchor=\"$align\"";
1590 $this->svg .= " transform=\"rotate($angle $x $y)\"";
1591 $this->svg .= ">$text</text>\n";
1597 function style($s='')
1599 $this->svg .= "<defs><style type=\"text/css\"><![CDATA[ $s ]]></style></defs>\n";
1601 function open_group($p = '')
1603 $this->svg .= "<g $p>\n";
1605 function close_group()
1607 $this->svg .= "</g>\n";
1611 $this->svg .= "</svg>\n";
1615 //header('Content-Type: image/svg+xml');
1619 function save($fileName)
1621 file_put_contents($fileName, $this->svg);
1625 // The following is for handling RTL texts. GD does not handle RTL at all.
1626 // The function, arabic, has been taken from Milad Rastian and
1627 // modified by Bagram Siadat.
1628 // The function has been further modified and several bugs are fixed.
1630 function is_arabic($text)
1632 return preg_match('/\p{Arabic}/u', $text);
1635 function is_hebrew($text)
1637 return preg_match('/\p{Hebrew}/u', $text);
1640 function utf8_strlen($str)
1642 return preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $dummy);
1645 function utf8_chr($uni)
1648 # ASCII range (including control chars)
1649 if ( ($uni >= 0) && ($uni <= 0x007f) )
1651 elseif ($uni <= 0x07ff) // 2 byte sequence
1653 $r .= chr(0xc0 | ($uni >> 6));
1654 $r .= chr(0x80 | ($uni & 0x003f));
1656 elseif($uni == 0xFEFF) // Byte order mark (skip)
1657 return chr(0); // nop -- zap the BOM
1658 elseif ($uni >= 0xD800 && $uni <= 0xDFFF) // Test for illegal surrogates
1659 return chr(0); // found a surrogate
1660 elseif ($uni <= 0xffff) // 3 byte sequence
1662 $r .= chr(0xe0 | ($uni >> 12));
1663 $r .= chr(0x80 | (($uni >> 6) & 0x003f));
1664 $r .= chr(0x80 | ($uni & 0x003f));
1666 elseif ($uni <= 0x10ffff) // 4 byte sequence
1668 $r .= chr(0xf0 | ($uni >> 18));
1669 $r .= chr(0x80 | (($uni >> 12) & 0x3f));
1670 $r .= chr(0x80 | (($uni >> 6) & 0x3f));
1671 $r .= chr(0x80 | ($uni & 0x3f));
1679 function arabic($str,$z="",$method='normal')
1682 utf8_chr(0x0622) => array (utf8_chr(0xfe82), utf8_chr(0xfe82), utf8_chr(0x0622)),
1683 utf8_chr(0x0627) => array (utf8_chr(0xfe8e), utf8_chr(0xfe8e), utf8_chr(0x0627)),
1684 utf8_chr(0x0628) => array (utf8_chr(0xfe90), utf8_chr(0xfe92), utf8_chr(0xfe91)),
1685 utf8_chr(0x067e) => array (utf8_chr(0xfb57), utf8_chr(0xfb59), utf8_chr(0xfb58)),
1686 utf8_chr(0x062a) => array (utf8_chr(0xfe96), utf8_chr(0xfe98), utf8_chr(0xfe97)),
1687 utf8_chr(0x062b) => array (utf8_chr(0xfe9a), utf8_chr(0xfe9c), utf8_chr(0xfe9b)),
1688 utf8_chr(0x062c) => array (utf8_chr(0xfe9e), utf8_chr(0xfea0), utf8_chr(0xfe9f)),
1689 utf8_chr(0x0686) => array (utf8_chr(0xfb7b), utf8_chr(0xfb7d), utf8_chr(0xfb7c)),
1690 utf8_chr(0x062d) => array (utf8_chr(0xfea2), utf8_chr(0xfea4), utf8_chr(0xfea3)),
1691 utf8_chr(0x062e) => array (utf8_chr(0xfea6), utf8_chr(0xfea8), utf8_chr(0xfea7)),
1692 utf8_chr(0x062f) => array (utf8_chr(0xfeaa), utf8_chr(0xfeaa), utf8_chr(0xfea9)),
1693 utf8_chr(0x0630) => array (utf8_chr(0xfeac), utf8_chr(0xfeac), utf8_chr(0xfeab)),
1694 utf8_chr(0x0631) => array (utf8_chr(0xfeae), utf8_chr(0xfeae), utf8_chr(0xfead)),
1695 utf8_chr(0x0632) => array (utf8_chr(0xfeb0), utf8_chr(0xfeb0), utf8_chr(0xfeaf)),
1696 utf8_chr(0x0698) => array (utf8_chr(0xfb8b), utf8_chr(0xfb8b), utf8_chr(0xfb8a)),
1697 utf8_chr(0x0633) => array (utf8_chr(0xfeb2), utf8_chr(0xfeb4), utf8_chr(0xfeb3)),
1698 utf8_chr(0x0634) => array (utf8_chr(0xfeb6), utf8_chr(0xfeb8), utf8_chr(0xfeb7)),
1699 utf8_chr(0x0635) => array (utf8_chr(0xfeba), utf8_chr(0xfebc), utf8_chr(0xfebb)),
1700 utf8_chr(0x0636) => array (utf8_chr(0xfebe), utf8_chr(0xfec0), utf8_chr(0xfebf)),
1701 utf8_chr(0x0637) => array (utf8_chr(0xfec2), utf8_chr(0xfec4), utf8_chr(0xfec3)),
1702 utf8_chr(0x0638) => array (utf8_chr(0xfec6), utf8_chr(0xfec8), utf8_chr(0xfec7)),
1703 utf8_chr(0x0639) => array (utf8_chr(0xfeca), utf8_chr(0xfecc), utf8_chr(0xfecb)),
1704 utf8_chr(0x063a) => array (utf8_chr(0xfece), utf8_chr(0xfed0), utf8_chr(0xfecf)),
1705 utf8_chr(0x0641) => array (utf8_chr(0xfed2), utf8_chr(0xfed4), utf8_chr(0xfed3)),
1706 utf8_chr(0x0642) => array (utf8_chr(0xfed6), utf8_chr(0xfed8), utf8_chr(0xfed7)),
1707 utf8_chr(0x06a9) => array (utf8_chr(0xfeda), utf8_chr(0xfedc), utf8_chr(0xfedb)),
1708 utf8_chr(0x06af) => array (utf8_chr(0xfb93), utf8_chr(0xfb95), utf8_chr(0xfb94)),
1709 utf8_chr(0x0644) => array (utf8_chr(0xfede), utf8_chr(0xfee0), utf8_chr(0xfedf)),
1710 utf8_chr(0x0645) => array (utf8_chr(0xfee2), utf8_chr(0xfee4), utf8_chr(0xfee3)),
1711 utf8_chr(0x0646) => array (utf8_chr(0xfee6), utf8_chr(0xfee8), utf8_chr(0xfee7)),
1712 utf8_chr(0x0648) => array (utf8_chr(0xfeee), utf8_chr(0xfeee), utf8_chr(0xfeed)),
1713 utf8_chr(0x06cc) => array (utf8_chr(0xfbfd), utf8_chr(0xfbff), utf8_chr(0xfbfe)),
1714 utf8_chr(0x0643) => array (utf8_chr(0xfeda), utf8_chr(0xfedc), utf8_chr(0xfedb)),
1715 utf8_chr(0x064a) => array (utf8_chr(0xfef2), utf8_chr(0xfef4), utf8_chr(0xfef3)),
1716 utf8_chr(0x0623) => array (utf8_chr(0xfe84), utf8_chr(0xfe84), utf8_chr(0xfe83)),
1717 utf8_chr(0x0624) => array (utf8_chr(0xfe86), utf8_chr(0xfe86), utf8_chr(0xfe85)),
1718 utf8_chr(0x0625) => array (utf8_chr(0xfe88), utf8_chr(0xfe88), utf8_chr(0xfe87)),
1719 utf8_chr(0x0626) => array (utf8_chr(0xfe8a), utf8_chr(0xfe8c), utf8_chr(0xfe8b)),
1720 utf8_chr(0x0629) => array (utf8_chr(0xfe94), utf8_chr(0xfe98), utf8_chr(0xfe97))
1723 $nastaligh = array (
1724 utf8_chr(0x0647) => array (utf8_chr(0xfbab), utf8_chr(0xfbad), utf8_chr(0xfbac))
1728 utf8_chr(0x0647) => array (utf8_chr(0xfeea), utf8_chr(0xfeec), utf8_chr(0xfeeb))
1731 $mp_chars = array (utf8_chr(0x0622), utf8_chr(0x0627), utf8_chr(0x062f), utf8_chr(0x0630), utf8_chr(0x0631), utf8_chr(0x0632),
1732 utf8_chr(0x0698), utf8_chr(0x0648), utf8_chr(0x0623), utf8_chr(0x0625), utf8_chr(0x0624));
1734 $ignorelist = array (utf8_chr(0x0000), utf8_chr(0x064c), utf8_chr(0x064d), utf8_chr(0x064b), utf8_chr(0x064f), utf8_chr(0x0650),
1735 utf8_chr(0x064e), utf8_chr(0x0651), utf8_chr(0x0653), utf8_chr(0x0670), utf8_chr(0x0654), utf8_chr(0xfe76), utf8_chr(0xfe7a),
1736 utf8_chr(0xfe78), utf8_chr(0xfe7c), utf8_chr(0xfe7e), utf8_chr(0xfe74), utf8_chr(0xfe70), utf8_chr(0xfc5e), utf8_chr(0xfc5f),
1737 utf8_chr(0xfc60), utf8_chr(0xfc61), utf8_chr(0xfc62), utf8_chr(0xfc63));
1739 $str_back = $output = $e_output = $str_next = $str1 = $num = "";
1740 if ($method == 'nastaligh')
1741 $p_chars = array_merge($p_chars, $nastaligh);
1743 $p_chars = array_merge($p_chars, $normal);
1744 $str_len = utf8_strlen($str);
1745 preg_match_all("/./u", $str, $ar);
1746 for ($i = 0; $i < $str_len; $i++)
1748 if (isset($ar[0][$i]))
1750 if(isset($ar[0][$i+1]) && in_array($ar[0][$i+1], $ignorelist))
1752 if (isset($ar[0][$i+2]))
1753 $str_next = $ar[0][$i+2];
1755 $str_back = $ar[0][$i-2];
1756 if ($i > 1 && $i != 2)
1757 $str_back = $ar[0][$i-1];
1759 elseif ($i > 0 && isset($ar[0][$i-1]) && !in_array($ar[0][$i-1], $ignorelist))
1761 if (isset($ar[0][$i+1]))
1762 $str_next = $ar[0][$i+1];
1764 $str_back = $ar[0][$i-1];
1768 if (isset($ar[0][$i+1]) && !empty($ar[0][$i+1]))
1769 $str_next = $ar[0][$i+1];
1770 elseif ($i > 0 && isset($ar[0][$i-1]))
1771 $str_next = $ar[0][$i-1];
1772 if ($i > 1 && isset($ar[0][$i-2]))
1773 $str_back = $ar[0][$i-2];
1775 if (!in_array($str1,$ignorelist))
1777 if (array_key_exists($str1,$p_chars))
1779 if (!$str_back || $str_back==" " || !array_key_exists($str_back,$p_chars))
1781 if (!array_key_exists($str_back, $p_chars) && !array_key_exists($str_next, $p_chars))
1782 $output = $str1.$output;
1784 $output = $p_chars[$str1][2].$output;
1787 elseif (array_key_exists($str_next, $p_chars) && array_key_exists($str_back, $p_chars))
1789 if (in_array($str_back, $mp_chars) && array_key_exists($str_next, $p_chars))
1790 $output = $p_chars[$str1][2].$output;
1792 $output = $p_chars[$str1][1].$output;
1795 elseif (array_key_exists($str_back, $p_chars) && !array_key_exists($str_next, $p_chars))
1797 if (in_array($str_back, $mp_chars))
1798 $output = $str1.$output;
1800 $output = $p_chars[$str1][0].$output;
1806 $number = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1807 "\xD9\xA0", "\xD9\xA1", "\xD9\xA2", "\xD9\xA3", "\xD9\xA4", "\xD9\xA5", "\xD9\xA6",
1808 "\xD9\xA7", "\xD9\xA8", "\xD9\xA9", "\xDB\xB0", "\xDB\xB1", "\xDB\xB2", "\xDB\xB3",
1809 "\xDB\xB4", "\xDB\xB5", "\xDB\xB6", "\xDB\xB7", "\xDB\xB8", "\xDB\xB9");
1810 if (in_array($str1, $number))
1815 if (!in_array($str_next, $number))
1820 //$output = $str1.$output;
1821 $output = $output.$str1;
1825 $number = array (utf8_chr(0x0660), utf8_chr(0x0661), utf8_chr(0x0662),
1826 utf8_chr(0x0663), utf8_chr(0x0664), utf8_chr(0x0665), utf8_chr(0x0666),
1827 utf8_chr(0x0667), utf8_chr(0x0668), utf8_chr(0x0669), utf8_chr(0x06f4),
1828 utf8_chr(0x06f5), utf8_chr(0x06f6), utf8_chr(0x0030), utf8_chr(0x0031),
1829 utf8_chr(0x0032), utf8_chr(0x0033), utf8_chr(0x0034), utf8_chr(0x0035),
1830 utf8_chr(0x0036), utf8_chr(0x0037), utf8_chr(0x0038), utf8_chr(0x0039));
1858 if (in_array($str1, $number))
1863 if (!in_array($str_next, $number))
1868 $output = $str1.$output;
1872 if (($str1 == utf8_chr(0x060c)) || ($str1 == utf8_chr(0x061f)) || ($str1 == utf8_chr(0x0621)) ||
1873 (array_key_exists($str_next, $p_chars) && array_key_exists($str_back, $p_chars)) ||
1874 ($str1 == " " && array_key_exists($str_back, $p_chars)) || ($str1 == " " &&
1875 array_key_exists($str_next, $p_chars)))
1879 $output = $e_output.$output;
1882 $output = $str1.$output;
1887 if (array_key_exists($str_next, $p_chars) || $str_next == "")
1889 $output = $e_output.$output;
1896 $output = $str1.$output;
1904 if (!function_exists('dump'))
1908 $req_dump = print_r($str, true);
1909 $fp = fopen('dump.log', 'a');
1910 date_default_timezone_set("Europe/Amsterdam");
1911 $msg = "[" . date('Y-m-d / H:i:s') . "] - $req_dump\n";