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
22/**
23 * Shows surrogate screen filled with graphs generated by selected graph prototype or preview of graph prototype.
24 */
25class CScreenLldGraph extends CScreenLldGraphBase {
26
27	/**
28	 * @var array
29	 */
30	protected $createdGraphIds = [];
31
32	/**
33	 * @var array
34	 */
35	protected $graphPrototype = null;
36
37	/**
38	 * Returns screen items for surrogate screen.
39	 *
40	 * @return array
41	 */
42	protected function getSurrogateScreenItems() {
43		$createdGraphIds = $this->getCreatedGraphIds();
44		return $this->getGraphsForSurrogateScreen($createdGraphIds);
45	}
46
47	public function get() {
48		$output = parent::get();
49
50		if ($output === null) {
51			$item = (new CTableInfo())->setNoDataMessage(_('No permissions to referred object or it does not exist!'));
52
53			return $this->getOutput($item);
54		}
55
56		return $output;
57	}
58
59	/**
60	 * Retrieves graphs created for graph prototype given as resource for this screen item
61	 * and returns array of the graph IDs.
62	 *
63	 * @return array
64	 */
65	protected function getCreatedGraphIds() {
66		if (!$this->createdGraphIds) {
67			$graphPrototype = $this->getGraphPrototype();
68
69			if ($graphPrototype) {
70				// Get all created (discovered) graphs for host of graph prototype.
71				$allCreatedGraphs = API::Graph()->get([
72					'output' => ['graphid', 'name'],
73					'hostids' => [$graphPrototype['discoveryRule']['hostid']],
74					'selectGraphDiscovery' => ['graphid', 'parent_graphid'],
75					'expandName' => true,
76					'filter' => ['flags' => ZBX_FLAG_DISCOVERY_CREATED]
77				]);
78
79				// Collect those graph IDs where parent graph is graph prototype selected for
80				// this screen item as resource.
81				foreach ($allCreatedGraphs as $graph) {
82					if ($graph['graphDiscovery']['parent_graphid'] == $graphPrototype['graphid']) {
83						$this->createdGraphIds[$graph['graphid']] = $graph['name'];
84					}
85				}
86				natsort($this->createdGraphIds);
87				$this->createdGraphIds = array_keys($this->createdGraphIds);
88			}
89		}
90
91		return $this->createdGraphIds;
92	}
93
94	/**
95	 * Makes graph screen items from given graph IDs.
96	 *
97	 * @param array $graphIds
98	 *
99	 * @return array
100	 */
101	protected function getGraphsForSurrogateScreen(array $graphIds) {
102		$screenItemTemplate = $this->getScreenItemTemplate(SCREEN_RESOURCE_GRAPH);
103
104		$screenItems = [];
105		foreach ($graphIds as $graphId) {
106			$screenItem = $screenItemTemplate;
107
108			$screenItem['resourceid'] = $graphId;
109			$screenItem['screenitemid'] = $graphId;
110
111			$screenItems[] = $screenItem;
112		}
113
114		return $screenItems;
115	}
116
117	/**
118	 * Resolves and retrieves effective graph prototype used in this screen item.
119	 *
120	 * @return array|bool
121	 */
122	protected function getGraphPrototype() {
123		if ($this->graphPrototype === null) {
124			$resourceid = array_key_exists('real_resourceid', $this->screenitem)
125				? $this->screenitem['real_resourceid']
126				: $this->screenitem['resourceid'];
127
128			$options = [
129				'output' => ['graphid', 'name', 'graphtype', 'show_legend', 'show_3d', 'show_work_period', 'templated'],
130				'selectDiscoveryRule' => ['hostid']
131			];
132
133			/*
134			 * If screen item is dynamic or is templated screen, real graph prototype is looked up by "name"
135			 * used as resource ID for this screen item and by current host.
136			 */
137			if ($this->screenitem['dynamic'] == SCREEN_DYNAMIC_ITEM && $this->hostid) {
138				$currentGraphPrototype = API::GraphPrototype()->get([
139					'output' => ['name'],
140					'graphids' => [$resourceid]
141				]);
142				$currentGraphPrototype = reset($currentGraphPrototype);
143
144				$options['hostids'] = [$this->hostid];
145				$options['filter'] = ['name' => $currentGraphPrototype['name']];
146			}
147			// otherwise just use resource ID given to this screen item.
148			else {
149				$options['graphids'] = [$resourceid];
150			}
151
152			$selectedGraphPrototype = API::GraphPrototype()->get($options);
153			$this->graphPrototype = reset($selectedGraphPrototype);
154		}
155
156		return $this->graphPrototype;
157	}
158
159	/**
160	 * Returns output for preview of graph prototype.
161	 *
162	 * @return CTag
163	 */
164	protected function getPreviewOutput() {
165		$graph_prototype = $this->getGraphPrototype();
166
167		switch ($graph_prototype['graphtype']) {
168			case GRAPH_TYPE_NORMAL:
169			case GRAPH_TYPE_STACKED:
170				$src = (new CUrl('chart3.php'))->setArgument('showworkperiod', $graph_prototype['show_work_period']);
171				break;
172
173			case GRAPH_TYPE_EXPLODED:
174			case GRAPH_TYPE_3D_EXPLODED:
175			case GRAPH_TYPE_3D:
176			case GRAPH_TYPE_PIE:
177				$src = new CUrl('chart7.php');
178				break;
179
180			default:
181				show_error_message(_('Graph prototype not found.'));
182				exit;
183		}
184
185		$graph_prototype_items = API::GraphItem()->get([
186			'output' => [
187				'gitemid', 'itemid', 'sortorder', 'flags', 'type', 'calc_fnc', 'drawtype', 'yaxisside', 'color'
188			],
189			'graphids' => [$graph_prototype['graphid']]
190		]);
191
192		$src
193			->setArgument('items', $graph_prototype_items)
194			->setArgument('graphtype', $graph_prototype['graphtype'])
195			->setArgument('period', 3600)
196			->setArgument('legend', $graph_prototype['show_legend'])
197			->setArgument('graph3d', $graph_prototype['show_3d'])
198			->setArgument('width', $this->screenitem['width'])
199			->setArgument('height', $this->screenitem['height'])
200			->setArgument('name', $graph_prototype['name']);
201
202		return new CSpan(new CImg($src->getUrl()));
203	}
204}
205