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 22class CControllerPopupTriggerExpr extends CController { 23 private $metrics = []; 24 private $param1SecCount = []; 25 private $param1Sec = []; 26 private $param1Str = []; 27 private $param2SecCount = []; 28 private $param3SecVal = []; 29 private $param3SecPercent = []; 30 private $paramSecIntCount = []; 31 private $paramForecast = []; 32 private $paramTimeleft = []; 33 private $allowedTypesAny = []; 34 private $allowedTypesNumeric = []; 35 private $allowedTypesStr = []; 36 private $allowedTypesLog = []; 37 private $allowedTypesInt = []; 38 private $functions = []; 39 private $operators = []; 40 41 protected function init() { 42 $this->disableSIDvalidation(); 43 44 $this->metrics = [ 45 PARAM_TYPE_TIME => _('Time'), 46 PARAM_TYPE_COUNTS => _('Count') 47 ]; 48 49 /* 50 * C - caption 51 * T - type 52 * M - metrics 53 * A - asterisk 54 */ 55 $this->param1SecCount = [ 56 'last' => [ 57 'C' => _('Last of').' (T)', 58 'T' => T_ZBX_INT, 59 'M' => $this->metrics, 60 'A' => true 61 ], 62 'shift' => [ 63 'C' => _('Time shift'), 64 'T' => T_ZBX_INT, 65 'A' => false 66 ] 67 ]; 68 69 $this->param1Sec = [ 70 'last' => [ 71 'C' => _('Last of').' (T)', 72 'T' => T_ZBX_INT, 73 'A' => true 74 ] 75 ]; 76 77 $this->param1Str = [ 78 'pattern' => [ 79 'C' => 'T', 80 'T' => T_ZBX_STR, 81 'A' => false 82 ] 83 ]; 84 85 $this->param2SecCount = [ 86 'pattern' => [ 87 'C' => 'V', 88 'T' => T_ZBX_STR, 89 'A' => false 90 ], 91 'last' => [ 92 'C' => _('Last of').' (T)', 93 'T' => T_ZBX_INT, 94 'M' => $this->metrics, 95 'A' => false 96 ] 97 ]; 98 99 $this->param3SecVal = [ 100 'last' => [ 101 'C' => _('Last of').' (T)', 102 'T' => T_ZBX_INT, 103 'M' => $this->metrics, 104 'A' => true 105 ], 106 'v' => [ 107 'C' => 'V', 108 'T' => T_ZBX_STR, 109 'A' => false 110 ], 111 'o' => [ 112 'C' => 'O', 113 'T' => T_ZBX_STR, 114 'A' => false 115 ], 116 'shift' => [ 117 'C' => _('Time shift'), 118 'T' => T_ZBX_INT, 119 'A' => false 120 ] 121 ]; 122 123 $this->param3SecPercent = [ 124 'last' => [ 125 'C' => _('Last of').' (T)', 126 'T' => T_ZBX_INT, 127 'M' => $this->metrics, 128 'A' => true 129 ], 130 'shift' => [ 131 'C' => _('Time shift'), 132 'T' => T_ZBX_INT, 133 'A' => false 134 ], 135 'p' => [ 136 'C' => _('Percentage').' (P)', 137 'T' => T_ZBX_DBL, 138 'A' => true 139 ] 140 ]; 141 142 $this->paramSecIntCount = [ 143 'last' => [ 144 'C' => _('Last of').' (T)', 145 'T' => T_ZBX_INT, 146 'M' => $this->metrics, 147 'A' => true 148 ], 149 'mask' => [ 150 'C' => _('Mask'), 151 'T' => T_ZBX_STR, 152 'A' => true 153 ], 154 'shift' => [ 155 'C' => _('Time shift'), 156 'T' => T_ZBX_INT, 157 'A' => false 158 ] 159 ]; 160 161 $this->paramForecast = [ 162 'last' => [ 163 'C' => _('Last of').' (T)', 164 'T' => T_ZBX_INT, 165 'M' => $this->metrics, 166 'A' => true 167 ], 168 'shift' => [ 169 'C' => _('Time shift'), 170 'T' => T_ZBX_INT, 171 'A' => false 172 ], 173 'time' => [ 174 'C' => _('Time').' (t)', 175 'T' => T_ZBX_INT, 176 'A' => true 177 ], 178 'fit' => [ 179 'C' => _('Fit'), 180 'T' => T_ZBX_STR, 181 'A' => false 182 ], 183 'mode' => [ 184 'C' => _('Mode'), 185 'T' => T_ZBX_STR, 186 'A' => false 187 ] 188 ]; 189 190 $this->paramTimeleft = [ 191 'last' => [ 192 'C' => _('Last of').' (T)', 193 'T' => T_ZBX_INT, 194 'M' => $this->metrics, 195 'A' => true 196 ], 197 'shift' => [ 198 'C' => _('Time shift'), 199 'T' => T_ZBX_INT, 200 'A' => false 201 ], 202 't' => [ 203 'C' => _('Threshold'), 204 'T' => T_ZBX_DBL, 205 'A' => true 206 ], 207 'fit' => [ 208 'C' => _('Fit'), 209 'T' => T_ZBX_STR, 210 'A' => false 211 ] 212 ]; 213 214 $this->allowedTypesAny = [ 215 ITEM_VALUE_TYPE_FLOAT => 1, 216 ITEM_VALUE_TYPE_STR => 1, 217 ITEM_VALUE_TYPE_LOG => 1, 218 ITEM_VALUE_TYPE_UINT64 => 1, 219 ITEM_VALUE_TYPE_TEXT => 1 220 ]; 221 222 $this->allowedTypesNumeric = [ 223 ITEM_VALUE_TYPE_FLOAT => 1, 224 ITEM_VALUE_TYPE_UINT64 => 1 225 ]; 226 227 $this->allowedTypesStr = [ 228 ITEM_VALUE_TYPE_STR => 1, 229 ITEM_VALUE_TYPE_LOG => 1, 230 ITEM_VALUE_TYPE_TEXT => 1 231 ]; 232 233 $this->allowedTypesLog = [ 234 ITEM_VALUE_TYPE_LOG => 1 235 ]; 236 237 $this->allowedTypesInt = [ 238 ITEM_VALUE_TYPE_UINT64 => 1 239 ]; 240 241 $this->functions = [ 242 'abschange' => [ 243 'description' => _('abschange() - Absolute difference between last and previous value'), 244 'allowed_types' => $this->allowedTypesAny, 245 'operators' => ['=', '<>', '>', '<', '>=', '<='] 246 ], 247 'avg' => [ 248 'description' => _('avg() - Average value of a period T'), 249 'params' => $this->param1SecCount, 250 'allowed_types' => $this->allowedTypesNumeric, 251 'operators' => ['=', '<>', '>', '<', '>=', '<='] 252 ], 253 'delta' => [ 254 'description' => _('delta() - Difference between MAX and MIN value of a period T'), 255 'params' => $this->param1SecCount, 256 'allowed_types' => $this->allowedTypesNumeric, 257 'operators' => ['=', '<>', '>', '<', '>=', '<='] 258 ], 259 'change' => [ 260 'description' => _('change() - Difference between last and previous value'), 261 'allowed_types' => $this->allowedTypesAny, 262 'operators' => ['=', '<>', '>', '<', '>=', '<='] 263 ], 264 'count' => [ 265 'description' => _('count() - Number of successfully retrieved values V (which fulfill operator O) for period T'), 266 'params' => $this->param3SecVal, 267 'allowed_types' => $this->allowedTypesAny, 268 'operators' => ['=', '<>', '>', '<', '>=', '<='] 269 ], 270 'diff' => [ 271 'description' => _('diff() - Difference between last and preceding values (1 - true, 0 - false)'), 272 'allowed_types' => $this->allowedTypesAny, 273 'operators' => ['=', '<>'] 274 ], 275 'last' => [ 276 'description' => _('last() - Last (most recent) T value'), 277 'params' => $this->param1SecCount, 278 'allowed_types' => $this->allowedTypesAny, 279 'operators' => ['=', '<>', '>', '<', '>=', '<='] 280 ], 281 'max' => [ 282 'description' => _('max() - Maximum value for period T'), 283 'params' => $this->param1SecCount, 284 'allowed_types' => $this->allowedTypesNumeric, 285 'operators' => ['=', '<>', '>', '<', '>=', '<='] 286 ], 287 'min' => [ 288 'description' => _('min() - Minimum value for period T'), 289 'params' => $this->param1SecCount, 290 'allowed_types' => $this->allowedTypesNumeric, 291 'operators' => ['=', '<>', '>', '<', '>=', '<='] 292 ], 293 'percentile' => [ 294 'description' => _('percentile() - Percentile P of a period T'), 295 'params' => $this->param3SecPercent, 296 'allowed_types' => $this->allowedTypesNumeric, 297 'operators' => ['=', '<>', '>', '<', '>=', '<='] 298 ], 299 'prev' => [ 300 'description' => _('prev() - Previous value'), 301 'allowed_types' => $this->allowedTypesAny, 302 'operators' => ['=', '<>', '>', '<', '>=', '<='] 303 ], 304 'str' => [ 305 'description' => _('str() - Find string V in last (most recent) value (1 - found, 0 - not found)'), 306 'params' => $this->param2SecCount, 307 'allowed_types' => $this->allowedTypesStr, 308 'operators' => ['=', '<>'] 309 ], 310 'strlen' => [ 311 'description' => _('strlen() - Length of last (most recent) T value in characters'), 312 'params' => $this->param1SecCount, 313 'allowed_types' => $this->allowedTypesStr, 314 'operators' => ['=', '<>', '>', '<', '>=', '<='] 315 ], 316 'sum' => [ 317 'description' => _('sum() - Sum of values of a period T'), 318 'params' => $this->param1SecCount, 319 'allowed_types' => $this->allowedTypesNumeric, 320 'operators' => ['=', '<>', '>', '<', '>=', '<='] 321 ], 322 'date' => [ 323 'description' => _('date() - Current date'), 324 'allowed_types' => $this->allowedTypesAny, 325 'operators' => ['=', '<>', '>', '<', '>=', '<='] 326 ], 327 'dayofweek' => [ 328 'description' => _('dayofweek() - Day of week'), 329 'allowed_types' => $this->allowedTypesAny, 330 'operators' => ['=', '<>', '>', '<', '>=', '<='] 331 ], 332 'dayofmonth' => [ 333 'description' => _('dayofmonth() - Day of month'), 334 'allowed_types' => $this->allowedTypesAny, 335 'operators' => ['=', '<>', '>', '<', '>=', '<='] 336 ], 337 'fuzzytime' => [ 338 'description' => _('fuzzytime() - Difference between item value (as timestamp) and Zabbix server timestamp is less than or equal to T seconds (1 - true, 0 - false)'), 339 'params' => $this->param1Sec, 340 'allowed_types' => $this->allowedTypesNumeric, 341 'operators' => ['=', '<>'] 342 ], 343 'regexp' => [ 344 'description' => _('regexp() - Regular expression V matching last value in period T (1 - match, 0 - no match)'), 345 'params' => $this->param2SecCount, 346 'allowed_types' => $this->allowedTypesStr, 347 'operators' => ['=', '<>'] 348 ], 349 'iregexp' => [ 350 'description' => _('iregexp() - Regular expression V matching last value in period T (non case-sensitive; 1 - match, 0 - no match)'), 351 'params' => $this->param2SecCount, 352 'allowed_types' => $this->allowedTypesStr, 353 'operators' => ['=', '<>'] 354 ], 355 'logeventid' => [ 356 'description' => _('logeventid() - Event ID of last log entry matching regular expression T (1 - match, 0 - no match)'), 357 'params' => $this->param1Str, 358 'allowed_types' => $this->allowedTypesLog, 359 'operators' => ['=', '<>'] 360 ], 361 'logseverity' => [ 362 'description' => _('logseverity() - Log severity of the last log entry'), 363 'allowed_types' => $this->allowedTypesLog, 364 'operators' => ['=', '<>', '>', '<', '>=', '<='] 365 ], 366 'logsource' => [ 367 'description' => _('logsource() - Log source of the last log entry matching parameter T (1 - match, 0 - no match)'), 368 'params' => $this->param1Str, 369 'allowed_types' => $this->allowedTypesLog, 370 'operators' => ['=', '<>'] 371 ], 372 'now' => [ 373 'description' => _('now() - Number of seconds since the Epoch'), 374 'allowed_types' => $this->allowedTypesAny, 375 'operators' => ['=', '<>', '>', '<', '>=', '<='] 376 ], 377 'time' => [ 378 'description' => _('time() - Current time'), 379 'allowed_types' => $this->allowedTypesAny, 380 'operators' => ['=', '<>', '>', '<', '>=', '<='] 381 ], 382 'nodata' => [ 383 'description' => _('nodata() - No data received during period of time T (1 - true, 0 - false)'), 384 'params' => $this->param1Sec, 385 'allowed_types' => $this->allowedTypesAny, 386 'operators' => ['=', '<>'] 387 ], 388 'band' => [ 389 'description' => _('band() - Bitwise AND of last (most recent) T value and mask'), 390 'params' => $this->paramSecIntCount, 391 'allowed_types' => $this->allowedTypesInt, 392 'operators' => ['=', '<>'] 393 ], 394 'forecast' => [ 395 'description' => _('forecast() - Forecast for next t seconds based on period T'), 396 'params' => $this->paramForecast, 397 'allowed_types' => $this->allowedTypesNumeric, 398 'operators' => ['=', '<>', '>', '<', '>=', '<='] 399 ], 400 'timeleft' => [ 401 'description' => _('timeleft() - Time to reach threshold estimated based on period T'), 402 'params' => $this->paramTimeleft, 403 'allowed_types' => $this->allowedTypesNumeric, 404 'operators' => ['=', '<>', '>', '<', '>=', '<='] 405 ] 406 ]; 407 408 CArrayHelper::sort($this->functions, ['description']); 409 410 foreach ($this->functions as $function) { 411 foreach ($function['operators'] as $operator) { 412 $this->operators[$operator] = true; 413 } 414 } 415 } 416 417 protected function checkInput() { 418 $fields = [ 419 'dstfrm' => 'string|fatal', 420 'dstfld1' => 'string|not_empty', 421 'expression' => 'string', 422 'itemid' => 'db items.itemid', 423 'parent_discoveryid' => 'db items.itemid', 424 'function' => 'in '.implode(',', array_keys($this->functions)), 425 'operator' => 'in '.implode(',', array_keys($this->operators)), 426 'params' => '', 427 'paramtype' => 'in '.implode(',', [PARAM_TYPE_TIME, PARAM_TYPE_COUNTS]), 428 'value' => 'string|not_empty', 429 'hostid' => 'db hosts.hostid', 430 'groupid' => 'db hosts_groups.hostgroupid', 431 'add' => 'in 1' 432 ]; 433 434 $ret = $this->validateInput($fields); 435 436 if (!$ret) { 437 $output = []; 438 if (($messages = getMessages()) !== null) { 439 $output['errors'] = $messages->toString(); 440 } 441 442 if ($this->hasInput('add')) { 443 $this->setResponse( 444 (new CControllerResponseData(['main_block' => CJs::encodeJson($output)]))->disableView() 445 ); 446 } 447 else { 448 $ret = true; 449 } 450 } 451 452 return $ret; 453 } 454 455 protected function checkPermissions() { 456 return true; 457 } 458 459 protected function doAction() { 460 $itemid = $this->getInput('itemid', 0); 461 $function = $this->getInput('function', 'last'); 462 $operator = $this->getInput('operator', '='); 463 $param_type = $this->getInput('paramtype', PARAM_TYPE_TIME); 464 $dstfld1 = $this->getInput('dstfld1'); 465 $expression = $this->getInput('expression', ''); 466 $params = $this->getInput('params', []); 467 $value = $this->getInput('value', 0); 468 469 // Opening the popup when editing an expression in the trigger constructor. 470 if (($dstfld1 === 'expr_temp' || $dstfld1 === 'recovery_expr_temp') && $expression !== '') { 471 $expression = utf8RawUrlDecode($expression); 472 473 $expression_data = new CTriggerExpression(); 474 $result = $expression_data->parse($expression); 475 476 if ($result) { 477 $function_macro_tokens = $result->getTokensByType( 478 CTriggerExprParserResult::TOKEN_TYPE_FUNCTION_MACRO 479 ); 480 481 if ($function_macro_tokens) { 482 $function_macro_token = $function_macro_tokens[0]; 483 $function = $function_macro_token['data']['functionName']; 484 485 // Determine param type. 486 $params = $function_macro_token['data']['functionParams']; 487 $param_number = in_array($function, ['regexp', 'iregexp', 'str']) ? 1 : 0; 488 if (array_key_exists($param_number, $params) && is_string($params[$param_number]) 489 && $params[$param_number] !== '' && $params[$param_number][0] === '#' 490 && !in_array($function, ['fuzzytime', 'nodata'])) { 491 $param_type = PARAM_TYPE_COUNTS; 492 $params[$param_number] = substr($params[$param_number], 1); 493 } 494 else { 495 $param_type = PARAM_TYPE_TIME; 496 } 497 498 /* 499 * Try to find an operator and a value. 500 * The value and operator can be extracted only if they immediately follow the item function macro. 501 */ 502 $tokens = $result->getTokens(); 503 foreach ($tokens as $key => $token) { 504 if ($token['type'] == CTriggerExprParserResult::TOKEN_TYPE_FUNCTION_MACRO) { 505 if (array_key_exists($key + 2, $tokens) 506 && $tokens[$key + 1]['type'] == CTriggerExprParserResult::TOKEN_TYPE_OPERATOR 507 && array_key_exists($function, $this->functions) 508 && in_array($tokens[$key + 1]['value'], 509 $this->functions[$function]['operators'])) { 510 $operator = $tokens[$key + 1]['value']; 511 512 if (array_key_exists($key + 3, $tokens) 513 && $tokens[$key + 2]['type'] == CTriggerExprParserResult::TOKEN_TYPE_OPERATOR) { 514 $value = $tokens[$key + 2]['value'].$tokens[$key + 3]['value']; 515 } 516 else { 517 $value = $tokens[$key + 2]['value']; 518 } 519 } 520 else { 521 break; 522 } 523 } 524 } 525 526 // Find the item. 527 $item = API::Item()->get([ 528 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 529 'selectHosts' => ['name'], 530 'webitems' => true, 531 'filter' => [ 532 'host' => $function_macro_token['data']['host'], 533 'key_' => $function_macro_token['data']['item'], 534 'flags' => null 535 ] 536 ]); 537 538 if (($item = reset($item)) !== false) { 539 $itemid = $item['itemid']; 540 } 541 else { 542 error(_('Unknown host item, no such item in selected host')); 543 } 544 } 545 } 546 } 547 // Opening an empty form or switching a function. 548 else { 549 $item = API::Item()->get([ 550 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 551 'selectHosts' => ['host', 'name'], 552 'itemids' => $itemid, 553 'webitems' => true, 554 'filter' => ['flags' => null] 555 ]); 556 557 $item = reset($item); 558 } 559 560 if ($itemid) { 561 $items = CMacrosResolverHelper::resolveItemNames([$item]); 562 $item = $items[0]; 563 564 $item_value_type = $item['value_type']; 565 $item_key = $item['key_']; 566 $item_host_data = reset($item['hosts']); 567 $description = $item_host_data['name'].NAME_DELIMITER.$item['name_expanded']; 568 } 569 else { 570 $item_key = ''; 571 $description = ''; 572 $item_value_type = null; 573 } 574 575 if ($param_type === null && array_key_exists($function, $this->functions) 576 && array_key_exists('params', $this->functions[$function]) 577 && array_key_exists('M', $this->functions[$function]['params'])) { 578 $param_type = is_array($this->functions[$function]['params']['M']) 579 ? reset($this->functions[$function]['params']['M']) 580 : $this->functions[$function]['params']['M']; 581 } 582 elseif ($param_type === null) { 583 $param_type = PARAM_TYPE_TIME; 584 } 585 586 $data = [ 587 'parent_discoveryid' => $this->getInput('parent_discoveryid', ''), 588 'dstfrm' => $this->getInput('dstfrm'), 589 'dstfld1' => $dstfld1, 590 'itemid' => $itemid, 591 'value' => $value, 592 'params' => $params, 593 'paramtype' => $param_type, 594 'item_description' => $description, 595 'functions' => $this->functions, 596 'function' => $function, 597 'operator' => $operator, 598 'item_key' => $item_key, 599 'itemValueType' => $item_value_type, 600 'selectedFunction' => null, 601 'groupid' => $this->getInput('groupid', 0), 602 'hostid' => $this->getInput('hostid', 0) 603 ]; 604 605 // Check if submitted function is usable with selected item. 606 foreach ($data['functions'] as $id => $f) { 607 if (($data['itemValueType'] === null || array_key_exists($item_value_type, $f['allowed_types'])) 608 && $id === $function) { 609 $data['selectedFunction'] = $id; 610 break; 611 } 612 } 613 614 if ($data['selectedFunction'] === null) { 615 $data['selectedFunction'] = 'last'; 616 $data['function'] = 'last'; 617 } 618 619 // Remove functions that not correspond to chosen item. 620 foreach ($data['functions'] as $id => $f) { 621 if ($data['itemValueType'] !== null && !array_key_exists($data['itemValueType'], $f['allowed_types'])) { 622 unset($data['functions'][$id]); 623 624 // Take first available function from list and change to first available operator for that function. 625 if ($id === $data['function']) { 626 $data['function'] = key($data['functions']); 627 $data['operator'] = reset($data['functions'][$data['function']]['operators']); 628 } 629 } 630 } 631 632 // Create and validate trigger expression before inserting it into textarea field. 633 if ($this->getInput('add', false)) { 634 try { 635 if ($data['item_description']) { 636 if ($data['paramtype'] == PARAM_TYPE_COUNTS 637 && array_key_exists('last', $data['params']) 638 && $data['params']['last'] !== '') { 639 $data['params']['last'] = zbx_is_int($data['params']['last']) 640 ? '#'.$data['params']['last'] 641 : $data['params']['last']; 642 } 643 elseif ($data['paramtype'] == PARAM_TYPE_TIME && in_array($function, ['last', 'band', 'strlen'])) { 644 $data['params']['last'] = ''; 645 } 646 647 // Quote function param. 648 $quoted_params = []; 649 foreach ($data['params'] as $param) { 650 $quoted_params[] = quoteFunctionParam($param); 651 } 652 653 $data['expression'] = sprintf('{%s:%s.%s(%s)}%s%s', 654 $item_host_data['host'], 655 $data['item_key'], 656 $function, 657 rtrim(implode(',', $quoted_params), ','), 658 $operator, 659 $data['value'] 660 ); 661 662 // Validate trigger expression. 663 $trigger_expression = new CTriggerExpression(); 664 665 if ($trigger_expression->parse($data['expression'])) { 666 $expression_data = reset($trigger_expression->expressions); 667 668 // Validate trigger function. 669 $trigger_function_validator = new CFunctionValidator(); 670 $is_valid = $trigger_function_validator->validate([ 671 'function' => $expression_data['function'], 672 'functionName' => $expression_data['functionName'], 673 'functionParamList' => $expression_data['functionParamList'], 674 'valueType' => $data['itemValueType'] 675 ]); 676 677 if ($is_valid === false) { 678 error($trigger_function_validator->getError()); 679 } 680 } 681 else { 682 error($trigger_expression->error); 683 } 684 685 // Quote function param. 686 if (array_key_exists('insert', $data)) { 687 foreach ($data['params'] as $pnum => $param) { 688 $data['params'][$pnum] = quoteFunctionParam($param); 689 } 690 } 691 } 692 else { 693 error(_('Item not selected')); 694 } 695 } 696 catch (Exception $e) { 697 error($e->getMessage()); 698 error(_('Cannot insert trigger expression')); 699 } 700 701 if (($messages = getMessages()) !== null) { 702 $output = [ 703 'errors' => $messages->toString() 704 ]; 705 } 706 else { 707 $output = [ 708 'expression' => $data['expression'], 709 'dstfld1' => $data['dstfld1'], 710 'dstfrm' => $data['dstfrm'] 711 ]; 712 } 713 714 $this->setResponse( 715 (new CControllerResponseData(['main_block' => CJs::encodeJson($output)]))->disableView() 716 ); 717 } 718 else { 719 $this->setResponse(new CControllerResponseData( 720 $data + [ 721 'title' => _('Condition'), 722 'errors' => hasErrorMesssages() ? getMessages() : null, 723 'user' => [ 724 'debug_mode' => $this->getDebugMode() 725 ] 726 ] 727 )); 728 } 729 } 730} 731