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