true, 'with_time_suffix' => true]); $number_parser_wo_suffix = new CNumberParser(); // Percentiles if ($this->getFieldValue('percentile_left') == SVG_GRAPH_PERCENTILE_LEFT_ON) { $percentile_left_value = $this->getFieldValue('percentile_left_value'); if ($percentile_left_value !== '') { $percentile_left_value_calculated = $number_parser_wo_suffix->parse($percentile_left_value) == CParser::PARSE_SUCCESS ? $number_parser_wo_suffix->calcValue() : null; if ($percentile_left_value_calculated === null || $percentile_left_value_calculated < self::PERCENTILE_MIN || $percentile_left_value_calculated > self::PERCENTILE_MAX) { $errors[] = _s('Invalid parameter "%1$s": %2$s.', _('Percentile line (left)'), _s('value must be between "%1$s" and "%2$s"', self::PERCENTILE_MIN, self::PERCENTILE_MAX) ); } } } if ($this->getFieldValue('percentile_right') == SVG_GRAPH_PERCENTILE_RIGHT_ON) { $percentile_right_value = $this->getFieldValue('percentile_right_value'); if ($percentile_right_value !== '') { $percentile_right_value_calculated = $number_parser_wo_suffix->parse($percentile_right_value) == CParser::PARSE_SUCCESS ? $number_parser_wo_suffix->calcValue() : null; if ($percentile_right_value_calculated === null || $percentile_right_value_calculated < self::PERCENTILE_MIN || $percentile_right_value_calculated > self::PERCENTILE_MAX) { $errors[] = _s('Invalid parameter "%1$s": %2$s.', _('Percentile line (right)'), _s('value must be between "%1$s" and "%2$s"', self::PERCENTILE_MIN, self::PERCENTILE_MAX) ); } } } // Test graph custom time period. if ($this->getFieldValue('graph_time') == SVG_GRAPH_CUSTOM_TIME_ON) { $errors = array_merge($errors, self::validateTimeSelectorPeriod($this->getFieldValue('time_from'), $this->getFieldValue('time_to') )); } // Validate Min/Max values in Axes tab. if ($this->getFieldValue('lefty') == SVG_GRAPH_AXIS_ON) { $lefty_min = $number_parser_w_suffix->parse($this->getFieldValue('lefty_min')) == CParser::PARSE_SUCCESS ? $number_parser_w_suffix->calcValue() : null; $lefty_max = $number_parser_w_suffix->parse($this->getFieldValue('lefty_max')) == CParser::PARSE_SUCCESS ? $number_parser_w_suffix->calcValue() : null; if ($lefty_min !== null && $lefty_max !== null && $lefty_min >= $lefty_max) { $errors[] = _s('Invalid parameter "%1$s": %2$s.', _('Left Y').'/'._('Max'), _('Y axis MAX value must be greater than Y axis MIN value') ); } } if ($this->getFieldValue('righty') == SVG_GRAPH_AXIS_ON) { $righty_min = $number_parser_w_suffix->parse($this->getFieldValue('righty_min')) == CParser::PARSE_SUCCESS ? $number_parser_w_suffix->calcValue() : null; $righty_max = $number_parser_w_suffix->parse($this->getFieldValue('righty_max')) == CParser::PARSE_SUCCESS ? $number_parser_w_suffix->calcValue() : null; if ($righty_min !== null && $righty_max !== null && $righty_min >= $righty_max) { $errors[] = _s('Invalid parameter "%1$s": %2$s.', _('Right Y').'/'._('Max'), _('Y axis MAX value must be greater than Y axis MIN value') ); } } return $errors; } protected function normalizeValues(array $values): array { $values = parent::normalizeValues($values); if (array_key_exists('percentile_left', $values)) { $this->percentile_left_on = $values['percentile_left'] == SVG_GRAPH_PERCENTILE_LEFT_ON; } if (!$this->percentile_left_on) { unset($values['percentile_left_value']); } if (array_key_exists('percentile_right', $values)) { $this->percentile_right_on = $values['percentile_right'] == SVG_GRAPH_PERCENTILE_RIGHT_ON; } if (!$this->percentile_right_on) { unset($values['percentile_right_value']); } if (array_key_exists('graph_time', $values)) { $this->graph_time_on = $values['graph_time'] == SVG_GRAPH_CUSTOM_TIME_ON; } if (!$this->graph_time_on) { unset($values['time_from'], $values['time_to']); } if (array_key_exists('lefty', $values)) { $this->lefty_on = $values['lefty'] == SVG_GRAPH_AXIS_ON; } if (!$this->lefty_on) { unset($values['lefty_min'], $values['lefty_max'], $values['lefty_units']); } if (array_key_exists('lefty_units', $values)) { $this->lefty_units_static = $values['lefty_units'] == SVG_GRAPH_AXIS_UNITS_STATIC; } if (!$this->lefty_on || !$this->lefty_units_static) { unset($values['lefty_static_units']); } if (array_key_exists('righty', $values)) { $this->righty_on = $values['righty'] == SVG_GRAPH_AXIS_ON; } if (!$this->righty_on) { unset($values['righty_min'], $values['righty_max'], $values['righty_units']); } if (array_key_exists('righty_units', $values)) { $this->righty_units_static = $values['righty_units'] == SVG_GRAPH_AXIS_UNITS_STATIC; } if (!$this->righty_on || !$this->righty_units_static) { unset($values['righty_static_units']); } if (array_key_exists('legend', $values)) { $this->legend_on = $values['legend'] == SVG_GRAPH_LEGEND_ON; } if (array_key_exists('legend_statistic', $values)) { $this->legend_statistic_on = $values['legend_statistic'] == SVG_GRAPH_LEGEND_STATISTIC_ON; } if (array_key_exists('show_problems', $values)) { $this->problems_on = $values['show_problems'] == SVG_GRAPH_PROBLEMS_ON; } if (!$this->problems_on) { unset($values['graph_item_problems'], $values['problemhosts'], $values['severities'], $values['problem_name'], $values['evaltype'], $values['tags'] ); } return $values; } public function addFields(): self { return $this ->initDataSetFields() ->initDisplayingOptionsFields() ->initTimePeriodFields() ->initAxesFields() ->initLegendFields() ->initProblemsFields() ->initOverridesFields(); } private function initDataSetFields(): self { return $this->addField( (new CWidgetFieldGraphDataSet('ds', _('Data set')))->setFlags(CWidgetField::FLAG_NOT_EMPTY) ); } private function initDisplayingOptionsFields(): self { return $this ->addField( (new CWidgetFieldRadioButtonList('source', _('History data selection'), [ SVG_GRAPH_DATA_SOURCE_AUTO => _x('Auto', 'history source selection method'), SVG_GRAPH_DATA_SOURCE_HISTORY => _('History'), SVG_GRAPH_DATA_SOURCE_TRENDS => _('Trends') ]))->setDefault(SVG_GRAPH_DATA_SOURCE_AUTO) ) ->addField( new CWidgetFieldCheckBox('simple_triggers', _('Simple triggers')) ) ->addField( new CWidgetFieldCheckBox('working_time', _('Working time')) ) ->addField( new CWidgetFieldCheckBox('percentile_left', _('Percentile line (left)')) ) ->addField( (new CWidgetFieldTextBox('percentile_left_value', null)) ->setFlags(!$this->percentile_left_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( new CWidgetFieldCheckBox('percentile_right', _('Percentile line (right)')) ) ->addField( (new CWidgetFieldTextBox('percentile_right_value', null)) ->setFlags(!$this->percentile_right_on ? CWidgetField::FLAG_DISABLED : 0x00) ); } private function initTimePeriodFields(): self { return $this ->addField( new CWidgetFieldCheckBox('graph_time', _('Set custom time period')) ) ->addField( (new CWidgetFieldDatePicker('time_from', _('From'))) ->setDefault('now-1h') ->setFlags($this->graph_time_on ? CWidgetField::FLAG_NOT_EMPTY : CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_DISABLED ) ) ->addField( (new CWidgetFieldDatePicker('time_to', _('To'))) ->setDefault('now') ->setFlags($this->graph_time_on ? CWidgetField::FLAG_NOT_EMPTY : CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_DISABLED ) ); } private function initAxesFields(): self { return $this ->addField( (new CWidgetFieldCheckBox('lefty', _('Left Y'), _('Show')))->setDefault(SVG_GRAPH_AXIS_ON) ) ->addField( (new CWidgetFieldNumericBox('lefty_min', _('Min'))) ->setFullName(_('Left Y').'/'._('Min')) ->setFlags(!$this->lefty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldNumericBox('lefty_max', _('Max'))) ->setFullName(_('Left Y').'/'._('Max')) ->setFlags(!$this->lefty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldSelect('lefty_units', _('Units'), [ SVG_GRAPH_AXIS_UNITS_AUTO => _x('Auto', 'history source selection method'), SVG_GRAPH_AXIS_UNITS_STATIC => _x('Static', 'history source selection method') ])) ->setDefault(SVG_GRAPH_AXIS_UNITS_AUTO) ->setFlags(!$this->lefty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldTextBox('lefty_static_units')) ->setFlags(!$this->lefty_on || !$this->lefty_units_static ? CWidgetField::FLAG_DISABLED : 0x00) ->setMaxLength(255) ) ->addField( (new CWidgetFieldCheckBox('righty', _('Right Y'), _('Show')))->setDefault(SVG_GRAPH_AXIS_ON) ) ->addField( (new CWidgetFieldNumericBox('righty_min', _('Min'))) ->setFullName(_('Right Y').'/'._('Min')) ->setFlags(!$this->righty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldNumericBox('righty_max', _('Max'))) ->setFullName(_('Right Y').'/'._('Max')) ->setFlags(!$this->righty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldSelect('righty_units', _('Units'), [ SVG_GRAPH_AXIS_UNITS_AUTO => _x('Auto', 'history source selection method'), SVG_GRAPH_AXIS_UNITS_STATIC => _x('Static', 'history source selection method') ])) ->setDefault(SVG_GRAPH_AXIS_UNITS_AUTO) ->setFlags(!$this->righty_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldTextBox('righty_static_units', null)) ->setFlags(!$this->righty_on || !$this->righty_units_static ? CWidgetField::FLAG_DISABLED : 0x00) ->setMaxLength(255) ) ->addField( (new CWidgetFieldCheckBox('axisx', _('X-Axis'), _('Show')))->setDefault(SVG_GRAPH_AXIS_ON) ); } private function initLegendFields(): self { return $this ->addField( (new CWidgetFieldCheckBox('legend', _('Show legend')))->setDefault(SVG_GRAPH_LEGEND_ON) ) ->addField( (new CWidgetFieldCheckBox('legend_statistic', _('Display min/max/avg'))) ->setFlags(!$this->legend_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldRangeControl('legend_lines', _('Number of rows'), SVG_GRAPH_LEGEND_LINES_MIN, SVG_GRAPH_LEGEND_LINES_MAX )) ->setDefault(SVG_GRAPH_LEGEND_LINES_MIN) ->setFlags(!$this->legend_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldRangeControl('legend_columns', _('Number of columns'), SVG_GRAPH_LEGEND_COLUMNS_MIN, SVG_GRAPH_LEGEND_COLUMNS_MAX )) ->setDefault(SVG_GRAPH_LEGEND_COLUMNS_MAX) ->setFlags(!$this->legend_on || $this->legend_statistic_on ? CWidgetField::FLAG_DISABLED : 0x00) ); } private function initProblemsFields(): self { return $this ->addField( new CWidgetFieldCheckBox('show_problems', _('Show problems')) ) ->addField( (new CWidgetFieldCheckBox('graph_item_problems', _('Selected items only'))) ->setDefault(SVG_GRAPH_SELECTED_ITEM_PROBLEMS) ->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField($this->isTemplateDashboard() ? null : (new CWidgetFieldHostPatternSelect('problemhosts', _('Problem hosts'))) ->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldSeverities('severities', _('Severity'))) ->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldTextBox('problem_name', _('Problem'))) ->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldRadioButtonList('evaltype', _('Problem tags'), [ TAG_EVAL_TYPE_AND_OR => _('And/Or'), TAG_EVAL_TYPE_OR => _('Or') ])) ->setDefault(TAG_EVAL_TYPE_AND_OR) ->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ) ->addField( (new CWidgetFieldTags('tags'))->setFlags(!$this->problems_on ? CWidgetField::FLAG_DISABLED : 0x00) ); } private function initOverridesFields(): self { return $this->addField( (new CWidgetFieldGraphOverride('or', _('Overrides')))->setFlags(CWidgetField::FLAG_NOT_EMPTY) ); } /** * Check if widget configuration is set to use overridden time. */ public static function hasOverrideTime(array $fields_values): bool { return array_key_exists('graph_time', $fields_values) && $fields_values['graph_time'] == SVG_GRAPH_CUSTOM_TIME_ON; } private static function validateTimeSelectorPeriod(string $from, string $to): array { $errors = []; $ts = []; $ts['now'] = time(); $range_time_parser = new CRangeTimeParser(); foreach (['from' => $from, 'to' => $to] as $field => $value) { $range_time_parser->parse($value); $ts[$field] = $range_time_parser->getDateTime($field === 'from')->getTimestamp(); } $period = $ts['to'] - $ts['from'] + 1; $range_time_parser->parse('now-'.CSettingsHelper::get(CSettingsHelper::MAX_PERIOD)); $max_period = 1 + $ts['now'] - $range_time_parser->getDateTime(true)->getTimestamp(); if ($period < ZBX_MIN_PERIOD) { $errors[] = _n('Minimum time period to display is %1$s minute.', 'Minimum time period to display is %1$s minutes.', (int) (ZBX_MIN_PERIOD / SEC_PER_MIN) ); } elseif ($period > $max_period) { $errors[] = _n('Maximum time period to display is %1$s day.', 'Maximum time period to display is %1$s days.', (int) round($max_period / SEC_PER_DAY) ); } return $errors; } }