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