1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22abstract class CGraphDraw { 23 24 public function __construct($type = GRAPH_TYPE_NORMAL) { 25 $this->stime = null; 26 $this->fullSizeX = null; 27 $this->fullSizeY = null; 28 $this->m_minY = null; 29 $this->m_maxY = null; 30 $this->data = []; 31 $this->items = null; 32 $this->min = null; 33 $this->max = null; 34 $this->avg = null; 35 $this->clock = null; 36 $this->count = null; 37 $this->header = null; 38 $this->from_time = null; 39 $this->to_time = null; 40 $this->colors = null; 41 $this->colorsrgb = null; 42 $this->im = null; 43 $this->period = SEC_PER_HOUR; 44 $this->from = 0; 45 $this->sizeX = 900; // default graph size X 46 $this->sizeY = 200; // default graph size Y 47 $this->shiftXleft = 100; 48 $this->shiftXright = 50; 49 $this->shiftXCaption = 0; 50 $this->shiftY = 36; 51 $this->num = 0; 52 $this->type = $type; // graph type 53 $this->drawLegend = 1; 54 $this->axis_valuetype = []; // overal items type (int/float) 55 $this->graphtheme = [ 56 'theme' => 'blue-theme', 57 'textcolor' => '1F2C33', 58 'highlightcolor' => 'E33734', 59 'backgroundcolor' => 'FFFFFF', 60 'graphcolor' => 'FFFFFF', 61 'gridcolor' => 'CCD5D9', 62 'maingridcolor' => 'ACBBC2', 63 'gridbordercolor' => 'ACBBC2', 64 'nonworktimecolor' => 'EBEBEB', 65 'leftpercentilecolor' => '429E47', 66 'righttpercentilecolor' => 'E33734' 67 ]; 68 $this->applyGraphTheme(); 69 } 70 71 public function initColors() { 72 // red, green, blue, alpha 73 $this->colorsrgb = [ 74 'Red' => [255, 0, 0, 50], 75 'Dark Red' => [150, 0, 0, 50], 76 'Green' => [0, 255, 0, 50], 77 'Dark Green' => [0, 150, 0, 50], 78 'Blue' => [0, 0, 255, 50], 79 'Dark Blue' => [0, 0, 150, 50], 80 'Yellow' => [255, 255, 0, 50], 81 'Dark Yellow' => [150, 150, 0, 50], 82 'Cyan' => [0, 255, 255, 50], 83 'Dark Cyan' => [0, 150, 150, 50], 84 'Black' => [0, 0, 0, 50], 85 'Gray' => [150, 150, 150, 50], 86 'White' => [255, 255, 255], 87 'Dark Red No Alpha' => [150, 0, 0], 88 'Black No Alpha' => [0, 0, 0], 89 'HistoryMinMax' => [90, 150, 185, 50], 90 'HistoryMax' => [255, 100, 100, 50], 91 'HistoryMin' => [50, 255, 50, 50], 92 'HistoryAvg' => [50, 50, 50, 50], 93 'ValueMinMax' => [255, 255, 150, 50], 94 'ValueMax' => [255, 180, 180, 50], 95 'ValueMin' => [100, 255, 100, 50], 96 'Not Work Period' => [230, 230, 230], 97 'UnknownData' => [130, 130, 130, 50] 98 ]; 99 100 // i should rename no alpha to alpha at some point to get rid of some confusion 101 foreach ($this->colorsrgb as $name => $RGBA) { 102 if (isset($RGBA[3]) && function_exists('imagecolorexactalpha') 103 && function_exists('imagecreatetruecolor') && @imagecreatetruecolor(1, 1)) { 104 $this->colors[$name] = imagecolorexactalpha($this->im, $RGBA[0], $RGBA[1], $RGBA[2], $RGBA[3]); 105 } 106 else { 107 $this->colors[$name] = imagecolorallocate($this->im, $RGBA[0], $RGBA[1], $RGBA[2]); 108 } 109 } 110 } 111 112 /** 113 * Load the graph theme from the database. 114 */ 115 public function applyGraphTheme() { 116 $themes = DB::find('graph_theme', [ 117 'theme' => getUserTheme(CWebUser::$data) 118 ]); 119 if ($themes) { 120 $this->graphtheme = $themes[0]; 121 } 122 } 123 124 public function showLegend($type = true) { 125 $this->drawLegend = $type; 126 } 127 128 public function setPeriod($period) { 129 $this->period = $period; 130 } 131 132 public function setSTime($stime) { 133 if ($stime > 19000000000000 && $stime < 21000000000000) { 134 $this->stime = zbxDateToTime($stime); 135 } 136 else { 137 $this->stime = $stime; 138 } 139 } 140 141 public function setFrom($from) { 142 $this->from = $from; 143 } 144 145 public function setWidth($value = null) { 146 // avoid sizex==0, to prevent division by zero later 147 if ($value == 0) { 148 $value = null; 149 } 150 if (is_null($value)) { 151 $value = 900; 152 } 153 $this->sizeX = $value; 154 } 155 156 public function setHeight($value = null) { 157 if ($value == 0) { 158 $value = null; 159 } 160 if (is_null($value)) { 161 $value = 900; 162 } 163 $this->sizeY = $value; 164 } 165 166 public function getLastValue($num) { 167 $data = &$this->data[$this->items[$num]['itemid']][$this->items[$num]['calc_type']]; 168 169 if (isset($data)) { 170 for ($i = $this->sizeX - 1; $i >= 0; $i--) { 171 if (!empty($data['count'][$i])) { 172 switch ($this->items[$num]['calc_fnc']) { 173 case CALC_FNC_MIN: 174 return $data['min'][$i]; 175 case CALC_FNC_MAX: 176 return $data['max'][$i]; 177 case CALC_FNC_ALL: 178 case CALC_FNC_AVG: 179 default: 180 return $data['avg'][$i]; 181 } 182 } 183 } 184 } 185 186 return 0; 187 } 188 189 public function drawRectangle() { 190 imagefilledrectangle($this->im, 0, 0, 191 $this->fullSizeX, 192 $this->fullSizeY, 193 $this->getColor($this->graphtheme['backgroundcolor'], 0) 194 ); 195 } 196 197 public function period2str($period) { 198 return ' ('.zbx_date2age(0, $period).')'; 199 } 200 201 public function drawHeader() { 202 if (!isset($this->header)) { 203 $str = $this->items[0]['hostname'].NAME_DELIMITER.$this->items[0]['name']; 204 } 205 else { 206 // TODO: graphs shouldn't resolve names themselves 207 $str = CMacrosResolverHelper::resolveGraphName($this->header, $this->items); 208 } 209 210 if ($this->period) { 211 $str .= $this->period2str($this->period); 212 } 213 214 // calculate largest font size that can fit graph header 215 // TODO: font size must be dynamic in other parts of the graph as well, like legend, timeline, etc 216 for ($fontsize = 11; $fontsize > 7; $fontsize--) { 217 $dims = imageTextSize($fontsize, 0, $str); 218 $x = $this->fullSizeX / 2 - ($dims['width'] / 2); 219 220 // most important information must be displayed, period can be out of the graph 221 if ($x < 2) { 222 $x = 2; 223 } 224 if ($dims['width'] <= $this->fullSizeX) { 225 break; 226 } 227 } 228 229 imageText($this->im, $fontsize, 0, $x, 24, $this->getColor($this->graphtheme['textcolor'], 0), $str); 230 } 231 232 public function setHeader($header) { 233 $this->header = $header; 234 } 235 236 public function drawLogo() { 237 imagestringup($this->im, 1, 238 $this->fullSizeX - 10, 239 $this->fullSizeY - 50, 240 ZABBIX_HOMEPAGE, 241 $this->getColor('Gray') 242 ); 243 } 244 245 public function getColor($color, $alfa = 50) { 246 if (isset($this->colors[$color])) { 247 return $this->colors[$color]; 248 } 249 250 return get_color($this->im, $color, $alfa); 251 } 252 253 public function getShadow($color, $alfa = 0) { 254 if (isset($this->colorsrgb[$color])) { 255 $red = $this->colorsrgb[$color][0]; 256 $green = $this->colorsrgb[$color][1]; 257 $blue = $this->colorsrgb[$color][2]; 258 } 259 else { 260 list($red, $green, $blue) = hex2rgb($color); 261 } 262 263 if ($this->sum > 0) { 264 $red = (int)($red * 0.6); 265 $green = (int)($green * 0.6); 266 $blue = (int)($blue * 0.6); 267 } 268 269 $RGB = [$red, $green, $blue]; 270 271 if (isset($alfa) && function_exists('imagecolorexactalpha') && function_exists('imagecreatetruecolor') 272 && @imagecreatetruecolor(1, 1)) { 273 return imagecolorexactalpha($this->im, $RGB[0], $RGB[1], $RGB[2], $alfa); 274 } 275 276 return imagecolorallocate($this->im, $RGB[0], $RGB[1], $RGB[2]); 277 } 278} 279