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 * @var CView $this 24 */ 25 26// indicator of sort field 27$sort_div = (new CSpan())->addClass(($data['sortorder'] === ZBX_SORT_DOWN) ? ZBX_STYLE_ARROW_DOWN : ZBX_STYLE_ARROW_UP); 28 29$url_details = (new CUrl('tr_events.php')) 30 ->setArgument('triggerid', '') 31 ->setArgument('eventid', ''); 32 33$show_timeline = ($data['sortfield'] === 'clock' && $data['fields']['show_timeline']); 34$show_recovery_data = in_array($data['fields']['show'], [TRIGGERS_OPTION_RECENT_PROBLEM, TRIGGERS_OPTION_ALL]); 35 36$header_time = new CColHeader(($data['sortfield'] === 'clock') ? [_('Time'), $sort_div] : _('Time')); 37 38if ($show_timeline) { 39 $header = [ 40 $header_time->addClass(ZBX_STYLE_RIGHT), 41 (new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH), 42 (new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH) 43 ]; 44} 45else { 46 $header = [$header_time]; 47} 48 49$show_opdata = $data['fields']['show_opdata']; 50 51$table = (new CTableInfo()) 52 ->setHeader(array_merge($header, [ 53 $show_recovery_data ? _('Recovery time') : null, 54 $show_recovery_data ? _('Status') : null, 55 _('Info'), 56 ($data['sortfield'] === 'host') ? [_('Host'), $sort_div] : _('Host'), 57 [ 58 ($data['sortfield'] === 'name') ? [_('Problem'), $sort_div] : _('Problem'), 59 ' • ', 60 ($data['sortfield'] === 'severity') ? [_('Severity'), $sort_div] : _('Severity') 61 ], 62 ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) ? _('Operational data') : null, 63 _('Duration'), 64 _('Ack'), 65 _('Actions'), 66 $data['fields']['show_tags'] ? _('Tags') : null 67 ])); 68 69$today = strtotime('today'); 70$last_clock = 0; 71 72if ($data['data']['problems']) { 73 $triggers_hosts = makeTriggersHostsList($data['data']['triggers_hosts']); 74} 75 76foreach ($data['data']['problems'] as $eventid => $problem) { 77 $trigger = $data['data']['triggers'][$problem['objectid']]; 78 79 if ($problem['r_eventid'] != 0) { 80 $value = TRIGGER_VALUE_FALSE; 81 $value_str = _('RESOLVED'); 82 $value_clock = $problem['r_clock']; 83 } 84 else { 85 $in_closing = false; 86 87 foreach ($problem['acknowledges'] as $acknowledge) { 88 if (($acknowledge['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) { 89 $in_closing = true; 90 break; 91 } 92 } 93 94 $value = $in_closing ? TRIGGER_VALUE_FALSE : TRIGGER_VALUE_TRUE; 95 $value_str = $in_closing ? _('CLOSING') : _('PROBLEM'); 96 $value_clock = $in_closing ? time() : $problem['clock']; 97 } 98 99 $url_details 100 ->setArgument('triggerid', $problem['objectid']) 101 ->setArgument('eventid', $problem['eventid']); 102 103 $cell_clock = ($problem['clock'] >= $today) 104 ? zbx_date2str(TIME_FORMAT_SECONDS, $problem['clock']) 105 : zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['clock']); 106 $cell_clock = new CCol(new CLink($cell_clock, $url_details)); 107 108 $is_acknowledged = ($problem['acknowledged'] == EVENT_ACKNOWLEDGED); 109 110 if ($show_recovery_data) { 111 if ($problem['r_eventid'] != 0) { 112 $cell_r_clock = ($problem['r_clock'] >= $today) 113 ? zbx_date2str(TIME_FORMAT_SECONDS, $problem['r_clock']) 114 : zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['r_clock']); 115 $cell_r_clock = (new CCol(new CLink($cell_r_clock, $url_details))) 116 ->addClass(ZBX_STYLE_NOWRAP) 117 ->addClass(ZBX_STYLE_RIGHT); 118 } 119 else { 120 $cell_r_clock = ''; 121 } 122 123 $cell_status = new CSpan($value_str); 124 125 // Add colors and blinking to span depending on configuration and trigger parameters. 126 addTriggerValueStyle($cell_status, $value, $value_clock, $is_acknowledged); 127 } 128 129 // Info. 130 $info_icons = []; 131 if ($problem['r_eventid'] != 0) { 132 if ($problem['correlationid'] != 0) { 133 $info_icons[] = makeInformationIcon( 134 array_key_exists($problem['correlationid'], $data['data']['correlations']) 135 ? _s('Resolved by correlation rule "%1$s".', 136 $data['data']['correlations'][$problem['correlationid']]['name'] 137 ) 138 : _('Resolved by correlation rule.') 139 ); 140 } 141 elseif ($problem['userid'] != 0) { 142 $info_icons[] = makeInformationIcon( 143 array_key_exists($problem['userid'], $data['data']['users']) 144 ? _s('Resolved by user "%1$s".', getUserFullname($data['data']['users'][$problem['userid']])) 145 : _('Resolved by inaccessible user.') 146 ); 147 } 148 } 149 150 if (array_key_exists('suppression_data', $problem) && $problem['suppression_data']) { 151 $info_icons[] = makeSuppressedProblemIcon($problem['suppression_data']); 152 } 153 154 $opdata = null; 155 if ($show_opdata != OPERATIONAL_DATA_SHOW_NONE) { 156 157 // operational data 158 if ($trigger['opdata'] === '') { 159 if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) { 160 $opdata = (new CCol(CScreenProblem::getLatestValues($trigger['items'])))->addClass('latest-values'); 161 } 162 } else { 163 $opdata = CMacrosResolverHelper::resolveTriggerOpdata( 164 [ 165 'triggerid' => $trigger['triggerid'], 166 'expression' => $trigger['expression'], 167 'opdata' => $trigger['opdata'], 168 'clock' => ($problem['r_eventid'] != 0) ? $problem['r_clock'] : $problem['clock'], 169 'ns' => ($problem['r_eventid'] != 0) ? $problem['r_ns'] : $problem['ns'] 170 ], 171 [ 172 'events' => true, 173 'html' => true 174 ] 175 ); 176 177 if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) { 178 $opdata = (new CCol($opdata)) 179 ->addClass('opdata') 180 ->addClass(ZBX_STYLE_WORDWRAP); 181 } 182 } 183 } 184 185 $problem_link = [ 186 (new CLinkAction($problem['name'])) 187 ->setAjaxHint(CHintBoxHelper::getEventList($trigger['triggerid'], $eventid, $show_timeline, 188 $data['fields']['show_tags'], $data['fields']['tags'], $data['fields']['tag_name_format'], 189 $data['fields']['tag_priority'] 190 )) 191 ->setAttribute('aria-label', _xs('%1$s, Severity, %2$s', 'screen reader', 192 $problem['name'], getSeverityName($problem['severity'], $data['config']) 193 )) 194 ]; 195 196 if ($show_opdata == OPERATIONAL_DATA_SHOW_WITH_PROBLEM && $opdata) { 197 $problem_link = array_merge($problem_link, [' (', $opdata, ')']); 198 } 199 200 $description = (new CCol($problem_link)); 201 202 $description_style = getSeverityStyle($problem['severity']); 203 204 if ($value == TRIGGER_VALUE_TRUE) { 205 $description->addClass($description_style); 206 } 207 208 if (!$show_recovery_data && $data['config'][$is_acknowledged ? 'problem_ack_style' : 'problem_unack_style']) { 209 // blinking 210 $duration = time() - $problem['clock']; 211 212 if ($data['config']['blink_period'] != 0 && $duration < $data['config']['blink_period']) { 213 $description 214 ->addClass('blink') 215 ->setAttribute('data-time-to-blink', $data['config']['blink_period'] - $duration) 216 ->setAttribute('data-toggle-class', ZBX_STYLE_BLINK_HIDDEN); 217 } 218 } 219 220 if ($show_timeline) { 221 if ($last_clock != 0) { 222 CScreenProblem::addTimelineBreakpoint($table, $last_clock, $problem['clock'], $data['sortorder']); 223 } 224 $last_clock = $problem['clock']; 225 226 $row = [ 227 $cell_clock->addClass(ZBX_STYLE_TIMELINE_DATE), 228 (new CCol()) 229 ->addClass(ZBX_STYLE_TIMELINE_AXIS) 230 ->addClass(ZBX_STYLE_TIMELINE_DOT), 231 (new CCol())->addClass(ZBX_STYLE_TIMELINE_TD) 232 ]; 233 } 234 else { 235 $row = [ 236 $cell_clock 237 ->addClass(ZBX_STYLE_NOWRAP) 238 ->addClass(ZBX_STYLE_RIGHT) 239 ]; 240 } 241 242 // Create acknowledge link. 243 $problem_update_link = (new CLink($is_acknowledged ? _('Yes') : _('No'))) 244 ->addClass($is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED) 245 ->addClass(ZBX_STYLE_LINK_ALT) 246 ->onClick('acknowledgePopUp('.json_encode(['eventids' => [$problem['eventid']]]).', this);'); 247 248 $table->addRow(array_merge($row, [ 249 $show_recovery_data ? $cell_r_clock : null, 250 $show_recovery_data ? $cell_status : null, 251 makeInformationList($info_icons), 252 $triggers_hosts[$trigger['triggerid']], 253 $description, 254 ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY ) ? $opdata : null, 255 (new CCol(zbx_date2age($problem['clock'], ($problem['r_eventid'] != 0) ? $problem['r_clock'] : 0))) 256 ->addClass(ZBX_STYLE_NOWRAP), 257 $problem_update_link, 258 makeEventActionsIcons($problem['eventid'], $data['data']['actions'], $data['data']['users'], $data['config']), 259 $data['fields']['show_tags'] ? $data['data']['tags'][$problem['eventid']] : null 260 ])); 261} 262 263if ($data['info'] !== '') { 264 $table->setFooter([ 265 (new CCol($data['info'])) 266 ->setColSpan($table->getNumCols()) 267 ->addClass(ZBX_STYLE_LIST_TABLE_FOOTER) 268 ]); 269} 270 271$output = [ 272 'aria_label' => _xs('%1$s widget', 'screen reader', $data['name']).', '.$data['info'], 273 'header' => $data['name'], 274 'body' => $table->toString() 275]; 276 277if ($data['initial_load']) { 278 $output['script_inline'] = 279 'if (typeof refreshProblemsWidget !== typeof(Function)) {'. 280 'function refreshProblemsWidget(event, response, overlay) {'. 281 'refreshWidgetOnAcknowledgeCreate("problems", response, overlay);'. 282 '}'. 283 284 '$.subscribe("acknowledge.create", refreshProblemsWidget);'. 285 '}'; 286} 287 288if (($messages = getMessages()) !== null) { 289 $output['messages'] = $messages->toString(); 290} 291 292if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) { 293 CProfiler::getInstance()->stop(); 294 $output['debug'] = CProfiler::getInstance()->make()->toString(); 295} 296 297echo json_encode($output); 298