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
22require_once dirname(__FILE__).'/include/config.inc.php';
23
24$page['title'] = _('Notification report');
25$page['file'] = 'report4.php';
26
27require_once dirname(__FILE__).'/include/page_header.php';
28
29// VAR	TYPE	OPTIONAL	FLAGS	VALIDATION	EXCEPTION
30$fields = [
31	'year' =>		[T_ZBX_INT, O_OPT, P_SYS|P_NZERO,	null,	null],
32	'period' =>		[T_ZBX_STR, O_OPT, P_SYS|P_NZERO,	IN('"daily","weekly","monthly","yearly"'), null],
33	'media_type' =>	[T_ZBX_INT, O_OPT, P_SYS,			DB_ID,	null]
34];
35check_fields($fields);
36
37if (getRequest('media_type')) {
38	$mediaTypeData = API::MediaType()->get([
39		'mediatypeids' => [$_REQUEST['media_type']],
40		'countOutput' => true
41	]);
42	if (!$mediaTypeData) {
43		access_deny ();
44	}
45}
46
47$year = getRequest('year', intval(date('Y')));
48$period = getRequest('period', 'weekly');
49$media_type = getRequest('media_type', 0);
50
51$_REQUEST['year'] = $year;
52$_REQUEST['period'] = $period;
53$_REQUEST['media_type'] = $media_type;
54
55$currentYear = date('Y');
56
57// fetch media types
58$media_types = [];
59$db_media_types = API::MediaType()->get([
60	'output' => ['description'],
61	'preservekeys' => true
62]);
63
64CArrayHelper::sort($db_media_types, ['description']);
65foreach ($db_media_types as $mediatypeid => $db_media_type) {
66	$media_types[$mediatypeid] = $db_media_type['description'];
67}
68
69$widget = (new CWidget())->setTitle(_('Notifications'));
70
71// if no media types were defined, we have nothing to show
72if (zbx_empty($media_types)) {
73	$table = new CTableInfo();
74	$widget->addItem($table)->show();
75}
76else {
77	$table = (new CTableInfo())->makeVerticalRotation();
78
79	// fetch the year of the first alert
80	if (($firstAlert = DBfetch(DBselect('SELECT MIN(a.clock) AS clock FROM alerts a'))) && $firstAlert['clock']) {
81		$minYear = date('Y', $firstAlert['clock']);
82	}
83	// if no alerts exist, use the current year
84	else {
85		$minYear = date('Y');
86	}
87
88	$controls = new CList();
89
90	$cmbMedia = new CComboBox('media_type', $media_type, 'submit()');
91	$cmbMedia->addItem(0, _('all'));
92
93	foreach ($media_types as $media_type_id => $media_type_description) {
94		$cmbMedia->addItem($media_type_id, $media_type_description);
95
96		// we won't need other media types in the future, if only one was selected
97		if ($media_type > 0 && $media_type != $media_type_id) {
98			unset($media_types[$media_type_id]);
99		}
100	}
101	$controls
102		->addItem([
103			new CLabel(_('Media type'), 'media_type'),
104			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
105			$cmbMedia
106		])
107		->addItem([
108			new CLabel(_('Period'), 'period'),
109			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
110			new CComboBox('period', $period, 'submit()', [
111				'daily' => _('Daily'),
112				'weekly' => _('Weekly'),
113				'monthly' => _('Monthly'),
114				'yearly' => _('Yearly')
115			])
116		]);
117
118	if ($period != 'yearly') {
119		$cmbYear = new CComboBox('year', $year, 'submit();');
120		for ($y = $minYear; $y <= date('Y'); $y++) {
121			$cmbYear->addItem($y, $y);
122		}
123		$controls->addItem([
124			new CLabel(_('Year'), 'year'),
125			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
126			$cmbYear
127		]);
128	}
129
130	$widget->setControls((new CForm('get'))
131		->cleanItems()
132		->setAttribute('aria-label', _('Main filter'))
133		->addItem($controls)
134	);
135
136	$header = [];
137	$users = [];
138
139	$db_users = API::User()->get([
140		'output' => ['userid', 'alias', 'name', 'surname'],
141		'sortfield' => 'alias'
142	]);
143
144	foreach ($db_users as $user_data) {
145		$full_name = getUserFullname($user_data);
146		$header[] = (new CColHeader($full_name))
147			->addClass('vertical_rotation')
148			->setTitle($full_name);
149		$users[] = $user_data['userid'];
150	}
151
152	$intervals = [];
153	switch ($period) {
154		case 'yearly':
155			$minTime = mktime(0, 0, 0, 1, 1, $minYear);
156
157			$dateFormat = _x('Y', DATE_FORMAT_CONTEXT);
158			array_unshift($header, _('Year'));
159
160			for ($i = $minYear; $i <= date('Y'); $i++) {
161				$intervals[mktime(0, 0, 0, 1, 1, $i)] = mktime(0, 0, 0, 1, 1, $i + 1);
162			}
163
164			break;
165
166		case 'monthly':
167			$minTime = mktime(0, 0, 0, 1, 1, $year);
168
169			$dateFormat = _x('F', DATE_FORMAT_CONTEXT);
170			array_unshift($header, _('Month'));
171
172			$max = ($year == $currentYear) ? date('n') : 12;
173			for ($i = 1; $i <= $max; $i++) {
174				$intervals[mktime(0, 0, 0, $i, 1, $year)] = mktime(0, 0, 0, $i + 1, 1, $year);
175			}
176
177			break;
178
179		case 'daily':
180			$minTime = mktime(0, 0, 0, 1, 1, $year);
181
182			$dateFormat = DATE_FORMAT;
183			array_unshift($header, _('Day'));
184
185			$max = ($year == $currentYear) ? date('z') + 1 : date('z', mktime(0, 0, 0, 12, 31, $year)) + 1;
186			for ($i = 1; $i <= $max; $i++) {
187				$intervals[mktime(0, 0, 0, 1, $i, $year)] = mktime(0, 0, 0, 1, $i + 1, $year);
188			}
189
190			break;
191
192		case 'weekly':
193			$time = mktime(0, 0, 0, 1, 1, $year);
194			$wd = date('w', $time);
195			$wd = ($wd == 0) ? 6 : $wd - 1;
196			$minTime = $time - $wd * SEC_PER_DAY;
197
198			$dateFormat = DATE_TIME_FORMAT;
199			array_unshift($header, _('From'), _('Till'));
200
201			$max = ($year == $currentYear) ? date('W') - 1 : 52;
202			for ($i = 0; $i <= $max; $i++) {
203				$intervals[strtotime('+'.$i.' week', $minTime)] = strtotime('+'.($i + 1).' week', $minTime);
204			}
205
206			break;
207	}
208
209	// time till
210	$maxTime = ($year == $currentYear || $period === 'yearly') ? time() : mktime(0, 0, 0, 1, 1, $year + 1);
211
212	// fetch alerts
213	$alerts = [];
214	foreach (eventSourceObjects() as $sourceObject) {
215		$alerts = array_merge($alerts, API::Alert()->get([
216			'output' => ['mediatypeid', 'userid', 'clock'],
217			'eventsource' => $sourceObject['source'],
218			'eventobject' => $sourceObject['object'],
219			'mediatypeids' => (getRequest('media_type')) ? getRequest('media_type') : null,
220			'time_from' => $minTime,
221			'time_till' => $maxTime
222		]));
223	}
224	// sort alerts in chronological order so we could easily iterate through them later
225	CArrayHelper::sort($alerts, ['clock']);
226
227	$table->setHeader($header);
228	foreach ($intervals as $from => $till) {
229		// interval start
230		$row = [zbx_date2str($dateFormat, $from)];
231
232		// interval end, displayed only for week intervals
233		if ($period == 'weekly') {
234			$row[] = zbx_date2str($dateFormat, min($till, time()));
235		}
236
237		// counting alert count for each user and media type
238		$summary = [];
239		foreach ($users as $userid) {
240			$summary[$userid] = [];
241			$summary[$userid]['total'] = 0;
242			$summary[$userid]['medias'] = [];
243			foreach ($media_types as $media_type_nr => $mt) {
244				$summary[$userid]['medias'][$media_type_nr] = 0;
245			}
246		}
247
248		// loop through alerts until we reach an alert from the next interval
249		while ($alert = current($alerts)) {
250			if ($alert['clock'] >= $till) {
251				break;
252			}
253
254			if (isset($summary[$alert['userid']])) {
255				$summary[$alert['userid']]['total']++;
256				if (isset($summary[$alert['userid']]['medias'][$alert['mediatypeid']])) {
257					$summary[$alert['userid']]['medias'][$alert['mediatypeid']]++;
258				}
259				else {
260					$summary[$alert['userid']]['medias'][$alert['mediatypeid']] = 1;
261				}
262			}
263
264			next($alerts);
265		}
266
267		foreach ($summary as $s) {
268			if ($s['total'] == 0) {
269				array_push($row, '');
270			}
271			else {
272				array_push($row, [$s['total'], ($media_type == 0) ? SPACE.'('.implode('/', $s['medias']).')' : '']);
273			}
274		}
275
276		$table->addRow($row);
277	}
278
279	$widget->addItem($table)->show();
280
281	if ($media_type == 0) {
282		echo BR();
283
284		$links = [];
285		foreach ($media_types as $id => $description) {
286			$links[] = (CWebUser::getType() < USER_TYPE_SUPER_ADMIN)
287				? $description
288				: new CLink($description, 'zabbix.php?action=mediatype.edit&mediatypeid='.$id);
289			$links[] = SPACE.'/'.SPACE;
290		}
291		array_pop($links);
292
293		$linksDiv = new CDiv([SPACE._('all').SPACE.'('.SPACE, $links, SPACE.')']);
294		$linksDiv->show();
295	}
296}
297
298require_once dirname(__FILE__).'/include/page_footer.php';
299