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