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
22class CControllerDashboardView extends CController {
23
24	protected function init() {
25		$this->disableSIDValidation();
26	}
27
28	protected function checkInput() {
29		$fields = [
30			'dashboardid' => 'db dashboard.dashboardid',
31			'source_dashboardid' => 'db dashboard.dashboardid',
32			'hostid' => 'db hosts.hostid',
33			'new' => 'in 1',
34			'cancel' => 'in 1',
35			'from' => 'range_time',
36			'to' => 'range_time',
37			'slideshow' => 'in 1'
38		];
39
40		$ret = $this->validateInput($fields) && $this->validateTimeSelectorPeriod();
41
42		if (!$ret) {
43			$this->setResponse(new CControllerResponseFatal());
44		}
45
46		return $ret;
47	}
48
49	protected function checkPermissions() {
50		if (!$this->checkAccess(CRoleHelper::UI_MONITORING_DASHBOARD)) {
51			return false;
52		}
53
54		if ($this->hasInput('new') || $this->hasInput('source_dashboardid')) {
55			return $this->checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS);
56		}
57
58		if ($this->hasInput('hostid')) {
59			$hosts = API::Host()->get([
60				'output' => [],
61				'hostids' => [$this->getInput('hostid')]
62			]);
63
64			if (!$hosts) {
65				return false;
66			}
67		}
68
69		return true;
70	}
71
72	protected function doAction() {
73		[$dashboard, $error] = $this->getDashboard();
74
75		if ($error !== null) {
76			$this->setResponse(new CControllerResponseData(['error' => $error]));
77
78			return;
79		}
80
81		if ($dashboard === null) {
82			$this->setResponse(new CControllerResponseRedirect((new CUrl('zabbix.php'))
83				->setArgument('action', 'dashboard.list')
84				->setArgument('page', $this->hasInput('cancel') ? CPagerHelper::loadPage('dashboard.list', null) : null)
85			));
86
87			return;
88		}
89
90		if ($this->hasInput('slideshow')) {
91			$dashboard['auto_start'] = '1';
92		}
93
94		$dashboard['can_edit_dashboards'] = $this->checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS);
95		$dashboard['can_view_reports'] = $this->checkAccess(CRoleHelper::UI_REPORTS_SCHEDULED_REPORTS);
96		$dashboard['can_create_reports'] = $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_SCHEDULED_REPORTS);
97
98		$time_selector_options = [
99			'profileIdx' => 'web.dashboard.filter',
100			'profileIdx2' => ($dashboard['dashboardid'] !== null) ? $dashboard['dashboardid'] : 0,
101			'from' => $this->hasInput('from') ? $this->getInput('from') : null,
102			'to' => $this->hasInput('to') ? $this->getInput('to') : null
103		];
104
105		updateTimeSelectorPeriod($time_selector_options);
106
107		$data = [
108			'dashboard' => $dashboard,
109			'widget_defaults' => CWidgetConfig::getDefaults(CWidgetConfig::CONTEXT_DASHBOARD),
110			'has_time_selector' => CDashboardHelper::hasTimeSelector($dashboard['pages']),
111			'time_period' => getTimeSelectorPeriod($time_selector_options),
112			'active_tab' => CProfile::get('web.dashboard.filter.active', 1)
113		];
114
115		if (self::hasDynamicWidgets($dashboard['pages'])) {
116			$hostid = $this->getInput('hostid', CProfile::get('web.dashboard.hostid', 0));
117
118			$hosts = ($hostid != 0)
119				? CArrayHelper::renameObjectsKeys(API::Host()->get([
120					'output' => ['hostid', 'name'],
121					'hostids' => [$hostid]
122				]), ['hostid' => 'id'])
123				: [];
124
125			$data['dynamic'] = [
126				'has_dynamic_widgets' => true,
127				'host' => $hosts ? $hosts[0] : null
128			];
129		}
130		else {
131			$data['dynamic'] = [
132				'has_dynamic_widgets' => false,
133				'host' => null
134			];
135		}
136
137		$response = new CControllerResponseData($data);
138		$response->setTitle(_('Dashboard'));
139		$this->setResponse($response);
140	}
141
142	/**
143	 * Get dashboard data from API.
144	 *
145	 * @return array
146	 */
147	private function getDashboard() {
148		$dashboard = null;
149		$error = null;
150
151		if ($this->hasInput('new')) {
152			$dashboard = [
153				'dashboardid' => null,
154				'name' => _('New dashboard'),
155				'display_period' => DB::getDefault('dashboard', 'display_period'),
156				'auto_start' => DB::getDefault('dashboard', 'auto_start'),
157				'editable' => true,
158				'pages' => [
159					[
160						'dashboard_pageid' => null,
161						'name' => '',
162						'display_period' => 0,
163						'widgets' => []
164					]
165				],
166				'owner' => [
167					'id' => CWebUser::$data['userid'],
168					'name' => CDashboardHelper::getOwnerName(CWebUser::$data['userid'])
169				],
170				'has_related_reports' => false
171			];
172		}
173		elseif ($this->hasInput('source_dashboardid')) {
174			// Clone dashboard and show as new.
175			$dashboards = API::Dashboard()->get([
176				'output' => ['name', 'private', 'display_period', 'auto_start'],
177				'selectPages' => ['dashboard_pageid', 'name', 'display_period', 'widgets'],
178				'selectUsers' => ['userid', 'permission'],
179				'selectUserGroups' => ['usrgrpid', 'permission'],
180				'dashboardids' => [$this->getInput('source_dashboardid')]
181			]);
182
183			if ($dashboards) {
184				$dashboard = [
185					'dashboardid' => null,
186					'name' => $dashboards[0]['name'],
187					'display_period' => $dashboards[0]['display_period'],
188					'auto_start' => $dashboards[0]['auto_start'],
189					'editable' => true,
190					'pages' => CDashboardHelper::preparePagesForGrid(
191						CDashboardHelper::unsetInaccessibleFields($dashboards[0]['pages']), null, true
192					),
193					'owner' => [
194						'id' => CWebUser::$data['userid'],
195						'name' => CDashboardHelper::getOwnerName(CWebUser::$data['userid'])
196					],
197					'sharing' => [
198						'private' => $dashboards[0]['private'],
199						'users' => $dashboards[0]['users'],
200						'userGroups' => $dashboards[0]['userGroups']
201					],
202					'has_related_reports' => false
203				];
204			}
205			else {
206				$error = _('No permissions to referred object or it does not exist!');
207			}
208		}
209		else {
210			// Getting existing dashboard.
211			$dashboardid = $this->hasInput('dashboardid')
212				? $this->getInput('dashboardid')
213				: CProfile::get('web.dashboard.dashboardid');
214
215			if ($dashboardid === null && CProfile::get('web.dashboard.list_was_opened') != 1) {
216				// Get first available dashboard that user has read permissions.
217				$dashboards = API::Dashboard()->get([
218					'output' => ['dashboardid'],
219					'sortfield' => 'name',
220					'limit' => 1
221				]);
222
223				if ($dashboards) {
224					$dashboardid = $dashboards[0]['dashboardid'];
225				}
226			}
227
228			if ($dashboardid !== null) {
229				$dashboards = API::Dashboard()->get([
230					'output' => ['dashboardid', 'name', 'userid', 'display_period', 'auto_start'],
231					'selectPages' => ['dashboard_pageid', 'name', 'display_period', 'widgets'],
232					'dashboardids' => [$dashboardid],
233					'preservekeys' => true
234				]);
235
236				if ($dashboards) {
237					CDashboardHelper::updateEditableFlag($dashboards);
238
239					$dashboard = array_shift($dashboards);
240					$dashboard['pages'] = CDashboardHelper::preparePagesForGrid($dashboard['pages'], null, true);
241					$dashboard['owner'] = [
242						'id' => $dashboard['userid'],
243						'name' => CDashboardHelper::getOwnerName($dashboard['userid'])
244					];
245					$dashboard['has_related_reports'] = (bool) API::Report()->get([
246						'output' => [],
247						'filter' => ['dashboardid' => $dashboard['dashboardid']],
248						'limit' => 1
249					]);
250
251					CProfile::update('web.dashboard.dashboardid', $dashboardid, PROFILE_TYPE_ID);
252				}
253				elseif ($this->hasInput('dashboardid')) {
254					$error = _('No permissions to referred object or it does not exist!');
255				}
256				else {
257					// In case if previous dashboard is deleted, show dashboard list.
258				}
259			}
260		}
261
262		return [$dashboard, $error];
263	}
264
265	/**
266	 * Checks, if any of widgets has checked dynamic field.
267	 *
268	 * @param array $grid_pages
269	 *
270	 * @static
271	 *
272	 * @return bool
273	 */
274	private static function hasDynamicWidgets($grid_pages) {
275		foreach ($grid_pages as $page) {
276			foreach ($page['widgets'] as $widget) {
277				if (array_key_exists('dynamic', $widget['fields']) && $widget['fields']['dynamic'] == 1) {
278					return true;
279				}
280			}
281		}
282
283		return false;
284	}
285}
286