You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
6.4 KiB

1 year ago
<?php
/*
** Zabbix
** Copyright (C) 2001-2023 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
abstract class CGraphDraw {
protected $stime;
protected $fullSizeX;
protected $fullSizeY;
protected $m_minY;
protected $m_maxY;
protected $data;
protected $items;
private $header;
protected $from_time;
protected $to_time;
private $colors;
protected $colorsrgb;
protected $im;
protected $period;
protected $sizeX;
protected $sizeY;
protected $shiftXleft;
protected $shiftXright;
protected $num;
protected $type;
protected $drawLegend;
protected $graphtheme;
protected $shiftY;
/**
* Default top padding including header label height and vertical padding.
*/
const DEFAULT_HEADER_PADDING_TOP = 36;
/**
* Default font size for header label text.
*/
const DEFAULT_HEADER_LABEL_FONT_SIZE = 11;
/**
* Default value for top and bottom padding.
*/
const DEFAULT_TOP_BOTTOM_PADDING = 12;
/**
* Header label visibility.
*/
public $draw_header = true;
/**
* Use top and bottom padding for graph image.
*/
public $with_vertical_padding = true;
public function __construct($type = GRAPH_TYPE_NORMAL) {
$this->stime = null;
$this->fullSizeX = null;
$this->fullSizeY = null;
$this->m_minY = null;
$this->m_maxY = null;
$this->data = [];
$this->items = [];
$this->header = null;
$this->from_time = null;
$this->to_time = null;
$this->colors = null;
$this->colorsrgb = null;
$this->im = null;
$this->period = SEC_PER_HOUR;
$this->sizeX = 900; // default graph size X
$this->sizeY = 200; // default graph size Y
$this->shiftXleft = 100;
$this->shiftXright = 50;
$this->num = 0;
$this->type = $type; // graph type
$this->drawLegend = 1;
$this->graphtheme = getUserGraphTheme();
$this->shiftY = 0;
}
/**
* Recalculate $this->shiftY property for graph according header label visibility settings and visibility of graph
* top and bottom padding settings.
*/
protected function calculateTopPadding() {
$shift = static::DEFAULT_HEADER_PADDING_TOP;
if (!$this->draw_header) {
$shift -= static::DEFAULT_HEADER_LABEL_FONT_SIZE;
}
if (!$this->with_vertical_padding) {
$shift -= static::DEFAULT_TOP_BOTTOM_PADDING;
}
$this->shiftY = $shift;
}
public function initColors() {
// red, green, blue, alpha
$this->colorsrgb = [
'Red' => [255, 0, 0, 50],
'Dark Red' => [150, 0, 0, 50],
'Green' => [0, 255, 0, 50],
'Dark Green' => [0, 150, 0, 50],
'Blue' => [0, 0, 255, 50],
'Dark Blue' => [0, 0, 150, 50],
'Yellow' => [255, 255, 0, 50],
'Dark Yellow' => [150, 150, 0, 50],
'Cyan' => [0, 255, 255, 50],
'Dark Cyan' => [0, 150, 150, 50],
'Black' => [0, 0, 0, 50],
'Gray' => [150, 150, 150, 50],
'White' => [255, 255, 255],
'Dark Red No Alpha' => [150, 0, 0],
'Black No Alpha' => [0, 0, 0],
'HistoryMinMax' => [90, 150, 185, 50],
'HistoryMax' => [255, 100, 100, 50],
'HistoryMin' => [50, 255, 50, 50],
'HistoryAvg' => [50, 50, 50, 50],
'ValueMinMax' => [255, 255, 150, 50],
'ValueMax' => [255, 180, 180, 50],
'ValueMin' => [100, 255, 100, 50],
'Not Work Period' => [230, 230, 230],
'UnknownData' => [130, 130, 130, 50]
];
// i should rename no alpha to alpha at some point to get rid of some confusion
foreach ($this->colorsrgb as $name => $RGBA) {
$this->colors[$name] = array_key_exists(3, $RGBA)
? imagecolorexactalpha($this->im, $RGBA[0], $RGBA[1], $RGBA[2], $RGBA[3])
: imagecolorallocate($this->im, $RGBA[0], $RGBA[1], $RGBA[2]);
}
}
public function showLegend($type = true) {
$this->drawLegend = $type;
}
public function setPeriod($period) {
$this->period = $period;
}
public function setSTime($stime) {
if ($stime > 19000000000000 && $stime < 21000000000000) {
$this->stime = zbxDateToTime($stime);
}
else {
$this->stime = $stime;
}
}
public function setWidth($value = null) {
// avoid sizex==0, to prevent division by zero later
if ($value == 0) {
$value = null;
}
if (is_null($value)) {
$value = 900;
}
$this->sizeX = $value;
}
public function setHeight($value = null) {
if ($value == 0) {
$value = null;
}
if (is_null($value)) {
$value = 200;
}
$this->sizeY = $value;
}
public function getWidth() {
return $this->sizeX;
}
public function getHeight() {
return $this->sizeY;
}
public function drawRectangle() {
imagefilledrectangle($this->im, 0, 0,
$this->fullSizeX,
$this->fullSizeY,
$this->getColor($this->graphtheme['backgroundcolor'], 0)
);
}
public function drawHeader() {
if (!$this->draw_header) {
return;
}
if (!isset($this->header)) {
$str = $this->items[0]['hostname'].NAME_DELIMITER.$this->items[0]['name'];
}
else {
// TODO: graphs shouldn't resolve names themselves
$str = CMacrosResolverHelper::resolveGraphName($this->header, $this->items);
}
// calculate largest font size that can fit graph header
// TODO: font size must be dynamic in other parts of the graph as well, like legend, timeline, etc
for ($fontsize = static::DEFAULT_HEADER_LABEL_FONT_SIZE; $fontsize > 7; $fontsize--) {
$dims = imageTextSize($fontsize, 0, $str);
$x = $this->fullSizeX / 2 - ($dims['width'] / 2);
// Most important information must be displayed.
if ($x < 2) {
$x = 2;
}
if ($dims['width'] <= $this->fullSizeX) {
break;
}
}
$y_baseline = 24;
if (!$this->with_vertical_padding) {
$y_baseline -= static::DEFAULT_TOP_BOTTOM_PADDING;
}
imageText($this->im, $fontsize, 0, $x, $y_baseline, $this->getColor($this->graphtheme['textcolor'], 0), $str);
}
public function setHeader($header) {
$this->header = $header;
}
public function getColor($color, $alfa = 50) {
if (isset($this->colors[$color])) {
return $this->colors[$color];
}
return get_color($this->im, $color, $alfa);
}
}