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.
zabbix/ui/app/controllers/CControllerTimeSelectorUpda...

259 lines
7.5 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.
**/
/**
* This controller is used by gtlc.js to update time selector date and time interval in user's profile.
*/
class CControllerTimeSelectorUpdate extends CController {
public static $profiles = ['web.dashboard.filter', 'web.charts.filter', 'web.httpdetails.filter',
'web.problem.filter', 'web.auditlog.filter', 'web.actionlog.filter', 'web.item.graph.filter',
'web.toptriggers.filter', 'web.avail_report.filter', CControllerHost::FILTER_IDX, CControllerProblem::FILTER_IDX
];
/**
* @var CRangeTimeParser
*/
private $range_time_parser;
private $data = [];
public function init() {
$this->disableCsrfValidation();
$this->range_time_parser = new CRangeTimeParser();
}
protected function checkInput() {
$fields = [
'method' => 'required|in increment,zoomout,decrement,rangechange,rangeoffset',
'idx' => 'required|in '.implode(',', static::$profiles),
'idx2' => 'required|id',
'from' => 'required|string',
'to' => 'required|string',
'from_offset' => 'int32|ge 0',
'to_offset' => 'int32|ge 0'
];
$ret = $this->validateInput($fields);
if (!$ret) {
/*
* This block executes if, for example, a missing profile is given. Since this is an AJAX request, it should
* throw a JS alert() with current message in timeSelectorEventHandler() in gtlc.js.
*/
$messages = CMessageHelper::getMessages();
$this->setResponse(new CControllerResponseData([
'main_block' => json_encode(['error' => $messages[0]['message']])
]));
return $ret;
}
$ret = $this->validateInputDateRange();
if ($this->getInput('method') === 'rangeoffset' && (!$this->hasInput('from_offset')
|| !$this->hasInput('to_offset'))) {
$ret = false;
}
if (!$ret) {
$this->setResponse(new CControllerResponseData(['main_block' => json_encode($this->data)]));
}
return $ret;
}
protected function checkPermissions() {
return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
}
protected function doAction() {
$method = $this->getInput('method');
$date = new DateTime();
$value = [];
$date_type = [];
$ts = [];
$ts['now'] = time();
foreach (['from', 'to'] as $field) {
$value[$field] = $this->getInput($field);
$this->range_time_parser->parse($value[$field]);
$date_type[$field] = $this->range_time_parser->getTimeType();
$ts[$field] = $this->range_time_parser
->getDateTime($field === 'from')
->getTimestamp();
}
$period = $ts['to'] - $ts['from'] + 1;
$this->range_time_parser->parse('now-'.CSettingsHelper::get(CSettingsHelper::MAX_PERIOD));
$max_period = 1 + $ts['now'] - $this->range_time_parser
->getDateTime(true)
->getTimestamp();
switch ($method) {
case 'decrement':
$offset = $period;
if ($ts['from'] - $offset < 0) {
$offset = $ts['from'];
}
$ts['from'] -= $offset;
$ts['to'] -= $offset;
$value['from'] = $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME);
$value['to'] = $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME);
break;
case 'increment':
$offset = $period;
if ($ts['to'] + $offset > $ts['now']) {
$offset = $ts['now'] - $ts['to'];
}
$ts['from'] += $offset;
$ts['to'] += $offset;
$value['from'] = $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME);
$value['to'] = $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME);
break;
case 'zoomout':
$right_offset = (int) ($period / 2);
if ($ts['to'] + $right_offset > $ts['now']) {
$right_offset = $ts['now'] - $ts['to'];
}
$left_offset = $period - $right_offset;
if ($ts['from'] - $left_offset < 0) {
$left_offset = $ts['from'];
}
$ts['from'] -= $left_offset;
$ts['to'] += $right_offset;
if ($ts['to'] - $ts['from'] + 1 > $max_period) {
$ts['from'] = $ts['to'] - $max_period + 1;
}
$value['from'] = $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME);
$value['to'] = $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME);
break;
case 'rangeoffset':
$from_offset = $this->getInput('from_offset');
$to_offset = $this->getInput('to_offset');
if ($from_offset > 0) {
$ts['from'] += $from_offset;
$value['from'] = $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME);
}
if ($to_offset > 0) {
$ts['to'] -= $to_offset;
$value['to'] = $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME);
}
break;
case 'rangechange':
// Format only absolute date according ZBX_FULL_DATE_TIME string.
foreach (['from', 'to'] as $field) {
if ($date_type[$field] === CRangeTimeParser::ZBX_TIME_ABSOLUTE) {
$value[$field] = $date->setTimestamp($ts[$field])->format(ZBX_FULL_DATE_TIME);
}
}
break;
}
updateTimeSelectorPeriod([
'profileIdx' => $this->getInput('idx'),
'profileIdx2' => $this->getInput('idx2'),
'from' => $value['from'],
'to' => $value['to']
]);
$this->setResponse(new CControllerResponseData(['main_block' => json_encode([
'label' => relativeDateToText($value['from'], $value['to']),
'from' => $value['from'],
'from_ts' => $ts['from'],
'from_date' => $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME),
'to' => $value['to'],
'to_ts' => $ts['to'],
'to_date' => $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME)
] + getTimeselectorActions($value['from'], $value['to']))]));
}
/**
* Validate input 'from' and 'to' arguments. Returns true on success.
*
* @return bool
*/
protected function validateInputDateRange() {
$this->data['error'] = [];
$ts = [];
$ts['now'] = time();
foreach (['from', 'to'] as $field) {
$value = $this->getInput($field);
if ($this->range_time_parser->parse($value) !== CParser::PARSE_SUCCESS) {
$this->data['error'][$field] = _('Invalid date.');
}
else {
$ts[$field] = $this->range_time_parser
->getDateTime($field === 'from')
->getTimestamp();
}
}
if ($this->data['error']) {
return false;
}
if ($this->getInput('method') === 'rangeoffset') {
$ts['from'] += $this->getInput('from_offset');
$ts['to'] -= $this->getInput('to_offset');
}
$period = $ts['to'] - $ts['from'] + 1;
$this->range_time_parser->parse('now-'.CSettingsHelper::get(CSettingsHelper::MAX_PERIOD));
$max_period = 1 + $ts['now'] - $this->range_time_parser
->getDateTime(true)
->getTimestamp();
if ($period < ZBX_MIN_PERIOD) {
$this->data['error']['from'] = _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) {
$this->data['error']['from'] = _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 !$this->data['error'];
}
}