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 24 private $metrics = []; 25 private $param1SecCount = []; 26 private $param1Period = []; 27 private $param1Sec = []; 28 private $param1Str = []; 29 private $param2SecCount = []; 30 private $param2SecMode = []; 31 private $param3SecVal = []; 32 private $param_find = []; 33 private $param3SecPercent = []; 34 private $paramForecast = []; 35 private $paramTimeleft = []; 36 private $allowedTypesAny = []; 37 private $allowedTypesNumeric = []; 38 private $allowedTypesStr = []; 39 private $allowedTypesLog = []; 40 private $allowedTypesInt = []; 41 private $functions = []; 42 private $operators = ['=', '<>', '>', '<', '>=', '<=']; 43 private $period_optional = []; 44 45 protected function init() { 46 $this->disableSIDvalidation(); 47 48 $this->metrics = [ 49 PARAM_TYPE_TIME => _('Time'), 50 PARAM_TYPE_COUNTS => _('Count') 51 ]; 52 53 /* 54 * C - caption 55 * T - type 56 * M - metrics 57 * A - asterisk 58 */ 59 $this->param1SecCount = [ 60 'last' => [ 61 'C' => _('Last of').' (T)', 62 'T' => T_ZBX_INT, 63 'M' => $this->metrics, 64 'A' => true 65 ], 66 'shift' => [ 67 'C' => _('Time shift'), 68 'T' => T_ZBX_INT, 69 'A' => false 70 ] 71 ]; 72 73 $this->period_optional = [ 74 'last' => [ 75 'C' => _('Last of').' (T)', 76 'T' => T_ZBX_INT, 77 'M' => $this->metrics, 78 'A' => false 79 ], 80 'shift' => [ 81 'C' => _('Time shift'), 82 'T' => T_ZBX_INT, 83 'A' => false 84 ] 85 ]; 86 87 $this->param1Period = [ 88 'last' => [ 89 'C' => _('Last of').' (T)', 90 'T' => T_ZBX_INT, 91 'A' => true 92 ], 93 'period_shift' => [ 94 'C' => _('Period shift'), 95 'T' => T_ZBX_INT, 96 'A' => true 97 ] 98 ]; 99 100 $this->param1Sec = [ 101 'last' => [ 102 'C' => _('Last of').' (T)', 103 'T' => T_ZBX_INT, 104 'A' => true 105 ] 106 ]; 107 108 $this->param1Str = [ 109 'pattern' => [ 110 'C' => 'V', 111 'T' => T_ZBX_STR, 112 'A' => false 113 ] 114 ]; 115 116 $this->param2SecCount = [ 117 'pattern' => [ 118 'C' => 'V', 119 'T' => T_ZBX_STR, 120 'A' => false 121 ], 122 'last' => [ 123 'C' => _('Last of').' (T)', 124 'T' => T_ZBX_INT, 125 'M' => $this->metrics, 126 'A' => false 127 ] 128 ]; 129 130 $this->param2SecMode = [ 131 'last' => [ 132 'C' => _('Last of').' (T)', 133 'T' => T_ZBX_INT, 134 'A' => true 135 ], 136 'mode' => [ 137 'C' => 'Mode', 138 'T' => T_ZBX_STR, 139 'A' => false 140 ] 141 ]; 142 143 $this->param3SecVal = [ 144 'last' => [ 145 'C' => _('Last of').' (T)', 146 'T' => T_ZBX_INT, 147 'M' => $this->metrics, 148 'A' => true 149 ], 150 'shift' => [ 151 'C' => _('Time shift'), 152 'T' => T_ZBX_INT, 153 'A' => false 154 ], 155 'o' => [ 156 'C' => 'O', 157 'T' => T_ZBX_STR, 158 'A' => false 159 ], 160 'v' => [ 161 'C' => 'V', 162 'T' => T_ZBX_STR, 163 'A' => false 164 ] 165 ]; 166 167 $this->param_find = [ 168 'o' => [ 169 'C' => 'O', 170 'T' => T_ZBX_STR, 171 'A' => false 172 ], 173 'v' => [ 174 'C' => 'V', 175 'T' => T_ZBX_STR, 176 'A' => false 177 ] 178 ]; 179 180 $this->param3SecPercent = [ 181 'last' => [ 182 'C' => _('Last of').' (T)', 183 'T' => T_ZBX_INT, 184 'M' => $this->metrics, 185 'A' => true 186 ], 187 'shift' => [ 188 'C' => _('Time shift'), 189 'T' => T_ZBX_INT, 190 'A' => false 191 ], 192 'p' => [ 193 'C' => _('Percentage').' (P)', 194 'T' => T_ZBX_DBL, 195 'A' => true 196 ] 197 ]; 198 199 $this->paramForecast = [ 200 'last' => [ 201 'C' => _('Last of').' (T)', 202 'T' => T_ZBX_INT, 203 'M' => $this->metrics, 204 'A' => true 205 ], 206 'shift' => [ 207 'C' => _('Time shift'), 208 'T' => T_ZBX_INT, 209 'A' => false 210 ], 211 'time' => [ 212 'C' => _('Time').' (t)', 213 'T' => T_ZBX_INT, 214 'A' => true 215 ], 216 'fit' => [ 217 'C' => _('Fit'), 218 'T' => T_ZBX_STR, 219 'A' => false 220 ], 221 'mode' => [ 222 'C' => _('Mode'), 223 'T' => T_ZBX_STR, 224 'A' => false 225 ] 226 ]; 227 228 $this->paramTimeleft = [ 229 'last' => [ 230 'C' => _('Last of').' (T)', 231 'T' => T_ZBX_INT, 232 'M' => $this->metrics, 233 'A' => true 234 ], 235 'shift' => [ 236 'C' => _('Time shift'), 237 'T' => T_ZBX_INT, 238 'A' => false 239 ], 240 't' => [ 241 'C' => _('Threshold'), 242 'T' => T_ZBX_DBL, 243 'A' => true 244 ], 245 'fit' => [ 246 'C' => _('Fit'), 247 'T' => T_ZBX_STR, 248 'A' => false 249 ] 250 ]; 251 252 $this->allowedTypesAny = [ 253 ITEM_VALUE_TYPE_FLOAT => 1, 254 ITEM_VALUE_TYPE_STR => 1, 255 ITEM_VALUE_TYPE_LOG => 1, 256 ITEM_VALUE_TYPE_UINT64 => 1, 257 ITEM_VALUE_TYPE_TEXT => 1 258 ]; 259 260 $this->allowedTypesNumeric = [ 261 ITEM_VALUE_TYPE_FLOAT => 1, 262 ITEM_VALUE_TYPE_UINT64 => 1 263 ]; 264 265 $this->allowedTypesStr = [ 266 ITEM_VALUE_TYPE_STR => 1, 267 ITEM_VALUE_TYPE_LOG => 1, 268 ITEM_VALUE_TYPE_TEXT => 1 269 ]; 270 271 $this->allowedTypesLog = [ 272 ITEM_VALUE_TYPE_LOG => 1 273 ]; 274 275 $this->allowedTypesInt = [ 276 ITEM_VALUE_TYPE_UINT64 => 1 277 ]; 278 279 $this->functions = [ 280 'abs' => [ 281 'types' => [ZBX_FUNCTION_TYPE_MATH], 282 'description' => _('abs() - Absolute value'), 283 'allowed_types' => $this->allowedTypesAny, 284 'operators' => $this->operators 285 ], 286 'acos' => [ 287 'types' => [ZBX_FUNCTION_TYPE_MATH], 288 'description' => _('acos() - The arccosine of a value as an angle, expressed in radians'), 289 'params' => $this->param1SecCount, 290 'allowed_types' => $this->allowedTypesNumeric, 291 'operators' => $this->operators 292 ], 293 'ascii' => [ 294 'types' => [ZBX_FUNCTION_TYPE_STRING], 295 'description' => _('ascii() - Returns the ASCII code of the leftmost character of the value'), 296 'params' => $this->param1SecCount, 297 'allowed_types' => $this->allowedTypesStr, 298 'operators' => $this->operators 299 ], 300 'asin' => [ 301 'types' => [ZBX_FUNCTION_TYPE_MATH], 302 'description' => _('asin() - The arcsine of a value as an angle, expressed in radians'), 303 'params' => $this->param1SecCount, 304 'allowed_types' => $this->allowedTypesNumeric, 305 'operators' => $this->operators 306 ], 307 'atan' => [ 308 'types' => [ZBX_FUNCTION_TYPE_MATH], 309 'description' => _('atan() - The arctangent of a value as an angle, expressed in radians'), 310 'params' => $this->param1SecCount, 311 'allowed_types' => $this->allowedTypesNumeric, 312 'operators' => $this->operators 313 ], 314 'atan2' => [ 315 'types' => [ZBX_FUNCTION_TYPE_MATH], 316 'description' => _('atan2() - The arctangent of the ordinate (exprue) and abscissa coordinates specified as an angle, expressed in radians'), 317 'params' => $this->param1SecCount + [ 318 'abscissa' => [ 319 'C' => _('Abscissa'), 320 'T' => T_ZBX_STR, 321 'A' => true 322 ] 323 ], 324 'allowed_types' => $this->allowedTypesNumeric, 325 'operators' => $this->operators 326 ], 327 'avg' => [ 328 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE, ZBX_FUNCTION_TYPE_MATH], 329 'description' => _('avg() - Average value of a period T'), 330 'params' => $this->param1SecCount, 331 'allowed_types' => $this->allowedTypesNumeric, 332 'operators' => $this->operators 333 ], 334 'between' => [ 335 'types' => [ZBX_FUNCTION_TYPE_OPERATOR], 336 'description' => _('between() - Checks if a value belongs to the given range (1 - in range, 0 - otherwise)'), 337 'params' => $this->param1SecCount + [ 338 'min' => [ 339 'C' => _('Min'), 340 'T' => T_ZBX_STR, 341 'A' => true 342 ], 343 'max' => [ 344 'C' => _('Max'), 345 'T' => T_ZBX_STR, 346 'A' => true 347 ] 348 ], 349 'allowed_types' => $this->allowedTypesNumeric, 350 'operators' => ['=', '<>'] 351 ], 352 'bitand' => [ 353 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 354 'description' => _('bitand() - Bitwise AND'), 355 'params' => $this->param1SecCount + [ 356 'mask' => [ 357 'C' => _('Mask'), 358 'T' => T_ZBX_STR, 359 'A' => true 360 ] 361 ], 362 'allowed_types' => $this->allowedTypesInt, 363 'operators' => $this->operators 364 ], 365 'bitlength' => [ 366 'types' => [ZBX_FUNCTION_TYPE_STRING], 367 'description' => _('bitlength() - Returns the length in bits'), 368 'params' => $this->param1SecCount, 369 'allowed_types' => $this->allowedTypesAny, 370 'operators' => $this->operators 371 ], 372 'bitlshift' => [ 373 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 374 'description' => _('bitlshift() - Bitwise shift left'), 375 'params' => $this->param1SecCount + [ 376 'bits' => [ 377 'C' => _('Bits to shift'), 378 'T' => T_ZBX_STR, 379 'A' => true 380 ] 381 ], 382 'allowed_types' => $this->allowedTypesInt, 383 'operators' => $this->operators 384 ], 385 'bitnot' => [ 386 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 387 'description' => _('bitnot() - Bitwise NOT'), 388 'params' => $this->param1SecCount, 389 'allowed_types' => $this->allowedTypesInt, 390 'operators' => $this->operators 391 ], 392 'bitor' => [ 393 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 394 'description' => _('bitor() - Bitwise OR'), 395 'params' => $this->param1SecCount + [ 396 'mask' => [ 397 'C' => _('Mask'), 398 'T' => T_ZBX_STR, 399 'A' => true 400 ] 401 ], 402 'allowed_types' => $this->allowedTypesInt, 403 'operators' => $this->operators 404 ], 405 'bitrshift' => [ 406 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 407 'description' => _('bitrshift() - Bitwise shift right'), 408 'params' => $this->param1SecCount + [ 409 'bits' => [ 410 'C' => _('Bits to shift'), 411 'T' => T_ZBX_STR, 412 'A' => true 413 ] 414 ], 415 'allowed_types' => $this->allowedTypesInt, 416 'operators' => $this->operators 417 ], 418 'bitxor' => [ 419 'types' => [ZBX_FUNCTION_TYPE_BITWISE], 420 'description' => _('bitxor() - Bitwise exclusive OR'), 421 'params' => $this->param1SecCount + [ 422 'mask' => [ 423 'C' => _('Mask'), 424 'T' => T_ZBX_STR, 425 'A' => true 426 ] 427 ], 428 'allowed_types' => $this->allowedTypesInt, 429 'operators' => $this->operators 430 ], 431 'bytelength' => [ 432 'types' => [ZBX_FUNCTION_TYPE_STRING], 433 'description' => _('bytelength() - Returns the length in bytes'), 434 'params' => $this->param1SecCount, 435 'allowed_types' => $this->allowedTypesAny, 436 'operators' => $this->operators 437 ], 438 'cbrt' => [ 439 'types' => [ZBX_FUNCTION_TYPE_MATH], 440 'description' => _('cbrt() - Cube root'), 441 'params' => $this->param1SecCount, 442 'allowed_types' => $this->allowedTypesNumeric, 443 'operators' => $this->operators 444 ], 445 'ceil' => [ 446 'types' => [ZBX_FUNCTION_TYPE_MATH], 447 'description' => _('ceil() - Rounds up to the nearest greater integer'), 448 'params' => $this->param1SecCount, 449 'allowed_types' => $this->allowedTypesNumeric, 450 'operators' => $this->operators 451 ], 452 'change' => [ 453 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 454 'description' => _('change() - Difference between last and previous value'), 455 'allowed_types' => $this->allowedTypesAny, 456 'operators' => $this->operators 457 ], 458 'char' => [ 459 'types' => [ZBX_FUNCTION_TYPE_STRING], 460 'description' => _('char() - Returns the character which represents the given ASCII code'), 461 'params' => $this->param1SecCount, 462 'allowed_types' => $this->allowedTypesInt, 463 'operators' => $this->operators 464 ], 465 'concat' => [ 466 'types' => [ZBX_FUNCTION_TYPE_STRING], 467 'description' => _('concat() - Returns a string that is the result of concatenating value to string'), 468 'params' => $this->param1SecCount + [ 469 'string' => [ 470 'C' => _('String'), 471 'T' => T_ZBX_STR, 472 'A' => true 473 ] 474 ], 475 'allowed_types' => $this->allowedTypesAny, 476 'operators' => $this->operators 477 ], 478 'cos' => [ 479 'types' => [ZBX_FUNCTION_TYPE_MATH], 480 'description' => _('cos() - The cosine of a value, where the value is an angle expressed in radians'), 481 'params' => $this->param1SecCount, 482 'allowed_types' => $this->allowedTypesNumeric, 483 'operators' => $this->operators 484 ], 485 'cosh' => [ 486 'types' => [ZBX_FUNCTION_TYPE_MATH], 487 'description' => _('cosh() - The hyperbolic cosine of a value'), 488 'params' => $this->param1SecCount, 489 'allowed_types' => $this->allowedTypesNumeric, 490 'operators' => $this->operators 491 ], 492 'cot' => [ 493 'types' => [ZBX_FUNCTION_TYPE_MATH], 494 'description' => _('cot() - The cotangent of a value, where the value is an angle expressed in radians'), 495 'params' => $this->param1SecCount, 496 'allowed_types' => $this->allowedTypesNumeric, 497 'operators' => $this->operators 498 ], 499 'count' => [ 500 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 501 'description' => _('count() - Number of successfully retrieved values V (which fulfill operator O) for period T'), 502 'params' => $this->param3SecVal, 503 'allowed_types' => $this->allowedTypesAny, 504 'operators' => $this->operators 505 ], 506 'countunique' => [ 507 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 508 'description' => _('countunique() - The number of unique values'), 509 'params' => $this->param3SecVal, 510 'allowed_types' => $this->allowedTypesAny, 511 'operators' => $this->operators 512 ], 513 'date' => [ 514 'types' => [ZBX_FUNCTION_TYPE_DATE_TIME], 515 'description' => _('date() - Current date'), 516 'allowed_types' => $this->allowedTypesAny, 517 'operators' => $this->operators 518 ], 519 'dayofmonth' => [ 520 'types' => [ZBX_FUNCTION_TYPE_DATE_TIME], 521 'description' => _('dayofmonth() - Day of month'), 522 'allowed_types' => $this->allowedTypesAny, 523 'operators' => $this->operators 524 ], 525 'dayofweek' => [ 526 'types' => [ZBX_FUNCTION_TYPE_DATE_TIME], 527 'description' => _('dayofweek() - Day of week'), 528 'allowed_types' => $this->allowedTypesAny, 529 'operators' => $this->operators 530 ], 531 'degrees' => [ 532 'types' => [ZBX_FUNCTION_TYPE_MATH], 533 'description' => _('degrees() - Converts a value from radians to degrees'), 534 'params' => $this->param1SecCount, 535 'allowed_types' => $this->allowedTypesNumeric, 536 'operators' => $this->operators 537 ], 538 'e' => [ 539 'types' => [ZBX_FUNCTION_TYPE_MATH], 540 'description' => _("e() - Returns Euler's number"), 541 'allowed_types' => $this->allowedTypesAny 542 ], 543 'exp' => [ 544 'types' => [ZBX_FUNCTION_TYPE_MATH], 545 'description' => _("exp() - Euler's number at a power of a value"), 546 'params' => $this->param1SecCount, 547 'allowed_types' => $this->allowedTypesNumeric, 548 'operators' => $this->operators 549 ], 550 'expm1' => [ 551 'types' => [ZBX_FUNCTION_TYPE_MATH], 552 'description' => _("expm1() - Euler's number at a power of a value minus 1"), 553 'params' => $this->param1SecCount, 554 'allowed_types' => $this->allowedTypesNumeric, 555 'operators' => $this->operators 556 ], 557 'find' => [ 558 'types' => [ZBX_FUNCTION_TYPE_STRING], 559 'description' => _('find() - Check occurrence of pattern V (which fulfill operator O) for period T (1 - match, 0 - no match)'), 560 'params' => $this->period_optional + $this->param_find, 561 'allowed_types' => $this->allowedTypesAny, 562 'operators' => ['=', '<>'] 563 ], 564 'first' => [ 565 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 566 'description' => _('first() - The oldest value in the specified time interval'), 567 'params' => $this->param1Sec + $this->period_optional, 568 'allowed_types' => $this->allowedTypesAny, 569 'operators' => $this->operators 570 ], 571 'floor' => [ 572 'types' => [ZBX_FUNCTION_TYPE_MATH], 573 'description' => _('floor() - Rounds down to the nearest smaller integer'), 574 'params' => $this->param1SecCount, 575 'allowed_types' => $this->allowedTypesNumeric, 576 'operators' => $this->operators 577 ], 578 'forecast' => [ 579 'types' => [ZBX_FUNCTION_TYPE_PREDICTION], 580 'description' => _('forecast() - Forecast for next t seconds based on period T'), 581 'params' => $this->paramForecast, 582 'allowed_types' => $this->allowedTypesNumeric, 583 'operators' => $this->operators 584 ], 585 'fuzzytime' => [ 586 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 587 'description' => _('fuzzytime() - Difference between item value (as timestamp) and Zabbix server timestamp is less than or equal to T seconds (1 - true, 0 - false)'), 588 'params' => $this->param1Sec, 589 'allowed_types' => $this->allowedTypesNumeric, 590 'operators' => ['=', '<>'] 591 ], 592 'in' => [ 593 'types' => [ZBX_FUNCTION_TYPE_OPERATOR], 594 'description' => _('in() - Checks if a value equals to one of the listed values (1 - equals, 0 - otherwise)'), 595 'params' => $this->param1SecCount + [ 596 'values' => [ 597 'C' => _('Values'), 598 'T' => T_ZBX_STR, 599 'A' => true 600 ] 601 ], 602 'allowed_types' => $this->allowedTypesAny, 603 'operators' => ['=', '<>'] 604 ], 605 'insert' => [ 606 'types' => [ZBX_FUNCTION_TYPE_STRING], 607 'description' => _('insert() - Inserts specified characters or spaces into a character string, beginning at a specified position in the string'), 608 'params' => $this->param1SecCount + [ 609 'start' => [ 610 'C' => _('Start'), 611 'T' => T_ZBX_STR, 612 'A' => true 613 ], 614 'length' => [ 615 'C' => _('Length'), 616 'T' => T_ZBX_STR, 617 'A' => true 618 ], 619 'replace' => [ 620 'C' => _('Replacement'), 621 'T' => T_ZBX_STR, 622 'A' => true 623 ] 624 ], 625 'allowed_types' => $this->allowedTypesStr, 626 'operators' => $this->operators 627 ], 628 'kurtosis' => [ 629 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 630 'description' => _('kurtosis() - Measures the "tailedness" of the probability distribution'), 631 'params' => $this->param1SecCount, 632 'allowed_types' => $this->allowedTypesNumeric, 633 'operators' => $this->operators 634 ], 635 'last' => [ 636 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 637 'description' => _('last() - Last (most recent) T value'), 638 'params' => $this->param1SecCount, 639 'allowed_types' => $this->allowedTypesAny, 640 'operators' => $this->operators 641 ], 642 'left' => [ 643 'types' => [ZBX_FUNCTION_TYPE_STRING], 644 'description' => _('left() - Returns the leftmost count characters'), 645 'params' => $this->param1SecCount + [ 646 'count' => [ 647 'C' => _('Count'), 648 'T' => T_ZBX_STR, 649 'A' => true 650 ] 651 ], 652 'allowed_types' => $this->allowedTypesStr, 653 'operators' => $this->operators 654 ], 655 'length' => [ 656 'types' => [ZBX_FUNCTION_TYPE_STRING], 657 'description' => _('length() - Length of last (most recent) T value in characters'), 658 'allowed_types' => $this->allowedTypesStr, 659 'operators' => $this->operators 660 ], 661 'log' => [ 662 'types' => [ZBX_FUNCTION_TYPE_MATH], 663 'description' => _('log() - Natural logarithm'), 664 'params' => $this->param1SecCount, 665 'allowed_types' => $this->allowedTypesNumeric, 666 'operators' => $this->operators 667 ], 668 'log10' => [ 669 'types' => [ZBX_FUNCTION_TYPE_MATH], 670 'description' => _('log10() - Decimal logarithm'), 671 'params' => $this->param1SecCount, 672 'allowed_types' => $this->allowedTypesNumeric, 673 'operators' => $this->operators 674 ], 675 'logeventid' => [ 676 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 677 'description' => _('logeventid() - Event ID of last log entry matching regular expression V for period T (1 - match, 0 - no match)'), 678 'params' => $this->period_optional + $this->param1Str, 679 'allowed_types' => $this->allowedTypesLog, 680 'operators' => ['=', '<>'] 681 ], 682 'logseverity' => [ 683 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 684 'description' => _('logseverity() - Log severity of the last log entry for period T'), 685 'params' => $this->period_optional, 686 'allowed_types' => $this->allowedTypesLog, 687 'operators' => $this->operators 688 ], 689 'logsource' => [ 690 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 691 'description' => _('logsource() - Log source of the last log entry matching parameter V for period T (1 - match, 0 - no match)'), 692 'params' => $this->period_optional + $this->param1Str, 693 'allowed_types' => $this->allowedTypesLog, 694 'operators' => ['=', '<>'] 695 ], 696 'ltrim' => [ 697 'types' => [ZBX_FUNCTION_TYPE_STRING], 698 'description' => _('ltrim() - Remove specified characters from the beginning of a string'), 699 'params' => $this->param1SecCount + [ 700 'chars' => [ 701 'C' => _('Chars'), 702 'T' => T_ZBX_STR, 703 'A' => false 704 ] 705 ], 706 'allowed_types' => $this->allowedTypesStr, 707 'operators' => $this->operators 708 ], 709 'mad' => [ 710 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 711 'description' => _('mad() - Median absolute deviation'), 712 'params' => $this->param1SecCount, 713 'allowed_types' => $this->allowedTypesNumeric, 714 'operators' => $this->operators 715 ], 716 'max' => [ 717 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE, ZBX_FUNCTION_TYPE_MATH], 718 'description' => _('max() - Maximum value for period T'), 719 'params' => $this->param1SecCount, 720 'allowed_types' => $this->allowedTypesNumeric, 721 'operators' => $this->operators 722 ], 723 'mid' => [ 724 'types' => [ZBX_FUNCTION_TYPE_STRING], 725 'description' => _('mid() - Returns a substring beginning at the character position specified by start for N characters'), 726 'params' => $this->param1SecCount + [ 727 'start' => [ 728 'C' => _('Start'), 729 'T' => T_ZBX_STR, 730 'A' => true 731 ], 732 'length' => [ 733 'C' => _('Length'), 734 'T' => T_ZBX_STR, 735 'A' => true 736 ] 737 ], 738 'allowed_types' => $this->allowedTypesStr, 739 'operators' => $this->operators 740 ], 741 'min' => [ 742 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE, ZBX_FUNCTION_TYPE_MATH], 743 'description' => _('min() - Minimum value for period T'), 744 'params' => $this->param1SecCount, 745 'allowed_types' => $this->allowedTypesNumeric, 746 'operators' => $this->operators 747 ], 748 'mod' => [ 749 'types' => [ZBX_FUNCTION_TYPE_MATH], 750 'description' => _('mod() - Division remainder'), 751 'params' => $this->param1SecCount + [ 752 'denominator' => [ 753 'C' => _('Division denominator'), 754 'T' => T_ZBX_STR, 755 'A' => true 756 ] 757 ], 758 'allowed_types' => $this->allowedTypesNumeric, 759 'operators' => $this->operators 760 ], 761 'nodata' => [ 762 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 763 'description' => _('nodata() - No data received during period of time T (1 - true, 0 - false), Mode (strict - ignore proxy time delay in sending data)'), 764 'params' => $this->param2SecMode, 765 'allowed_types' => $this->allowedTypesAny, 766 'operators' => ['=', '<>'] 767 ], 768 'now' => [ 769 'types' => [ZBX_FUNCTION_TYPE_DATE_TIME], 770 'description' => _('now() - Number of seconds since the Epoch'), 771 'allowed_types' => $this->allowedTypesAny, 772 'operators' => $this->operators 773 ], 774 'percentile' => [ 775 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 776 'description' => _('percentile() - Percentile P of a period T'), 777 'params' => $this->param3SecPercent, 778 'allowed_types' => $this->allowedTypesNumeric, 779 'operators' => $this->operators 780 ], 781 'pi' => [ 782 'types' => [ZBX_FUNCTION_TYPE_MATH], 783 'description' => _('pi() - Returns the Pi constant'), 784 'allowed_types' => $this->allowedTypesAny 785 ], 786 'power' => [ 787 'types' => [ZBX_FUNCTION_TYPE_MATH], 788 'description' => _('power() - The power of a base value to a power value'), 789 'params' => $this->param1SecCount + [ 790 'power' => [ 791 'C' => _('Power value'), 792 'T' => T_ZBX_STR, 793 'A' => true 794 ] 795 ], 796 'allowed_types' => $this->allowedTypesNumeric, 797 'operators' => $this->operators 798 ], 799 'radians' => [ 800 'types' => [ZBX_FUNCTION_TYPE_MATH], 801 'description' => _('radians() - Converts a value from degrees to radians'), 802 'params' => $this->param1SecCount, 803 'allowed_types' => $this->allowedTypesNumeric, 804 'operators' => $this->operators 805 ], 806 'rand' => [ 807 'types' => [ZBX_FUNCTION_TYPE_MATH], 808 'description' => _('rand() - A random integer value'), 809 'allowed_types' => $this->allowedTypesAny 810 ], 811 'repeat' => [ 812 'types' => [ZBX_FUNCTION_TYPE_STRING], 813 'description' => _('repeat() - Returns a string composed of value repeated count times'), 814 'params' => $this->param1SecCount + [ 815 'count' => [ 816 'C' => _('Count'), 817 'T' => T_ZBX_STR, 818 'A' => true 819 ] 820 ], 821 'allowed_types' => $this->allowedTypesStr, 822 'operators' => $this->operators 823 ], 824 'replace' => [ 825 'types' => [ZBX_FUNCTION_TYPE_STRING], 826 'description' => _('replace() - Search value for occurrences of pattern, and replace with replacement'), 827 'params' => $this->param1SecCount + [ 828 'pattern' => [ 829 'C' => _('Pattern'), 830 'T' => T_ZBX_STR, 831 'A' => true 832 ], 833 'replace' => [ 834 'C' => _('Replacement'), 835 'T' => T_ZBX_STR, 836 'A' => true 837 ] 838 ], 839 'allowed_types' => $this->allowedTypesStr, 840 'operators' => $this->operators 841 ], 842 'right' => [ 843 'types' => [ZBX_FUNCTION_TYPE_STRING], 844 'description' => _('right() - Returns the rightmost count characters'), 845 'params' => $this->param1SecCount + [ 846 'count' => [ 847 'C' => _('Count'), 848 'T' => T_ZBX_STR, 849 'A' => true 850 ] 851 ], 852 'allowed_types' => $this->allowedTypesStr, 853 'operators' => $this->operators 854 ], 855 'round' => [ 856 'types' => [ZBX_FUNCTION_TYPE_MATH], 857 'description' => _('round() - Rounds a value to decimal places'), 858 'params' => $this->param1SecCount + [ 859 'decimals' => [ 860 'C' => _('Decimal places'), 861 'T' => T_ZBX_STR, 862 'A' => true 863 ] 864 ], 865 'allowed_types' => $this->allowedTypesNumeric, 866 'operators' => $this->operators 867 ], 868 'rtrim' => [ 869 'types' => [ZBX_FUNCTION_TYPE_STRING], 870 'description' => _('rtrim() - Removes specified characters from the end of a string'), 871 'params' => $this->param1SecCount + [ 872 'chars' => [ 873 'C' => _('Chars'), 874 'T' => T_ZBX_STR, 875 'A' => false 876 ] 877 ], 878 'allowed_types' => $this->allowedTypesStr, 879 'operators' => $this->operators 880 ], 881 'signum' => [ 882 'types' => [ZBX_FUNCTION_TYPE_MATH], 883 'description' => _('signum() - Returns -1 if a value is negative, 0 if a value is zero, 1 if a value is positive'), 884 'params' => $this->param1SecCount, 885 'allowed_types' => $this->allowedTypesNumeric, 886 'operators' => $this->operators 887 ], 888 'sin' => [ 889 'types' => [ZBX_FUNCTION_TYPE_MATH], 890 'description' => _('sin() - The sine of a value, where the value is an angle expressed in radians'), 891 'params' => $this->param1SecCount, 892 'allowed_types' => $this->allowedTypesNumeric, 893 'operators' => $this->operators 894 ], 895 'sinh' => [ 896 'types' => [ZBX_FUNCTION_TYPE_MATH], 897 'description' => _('sinh() - The hyperbolic sine of a value'), 898 'params' => $this->param1SecCount, 899 'allowed_types' => $this->allowedTypesNumeric, 900 'operators' => $this->operators 901 ], 902 'skewness' => [ 903 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 904 'description' => _('skewness() - Measures the asymmetry of the probability distribution'), 905 'params' => $this->param1SecCount, 906 'allowed_types' => $this->allowedTypesNumeric, 907 'operators' => $this->operators 908 ], 909 'sqrt' => [ 910 'types' => [ZBX_FUNCTION_TYPE_MATH], 911 'description' => _('sqrt() - Square root of a value'), 912 'params' => $this->param1SecCount, 913 'allowed_types' => $this->allowedTypesNumeric, 914 'operators' => $this->operators 915 ], 916 'stddevpop' => [ 917 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 918 'description' => _('stddevpop() - Population standard deviation'), 919 'params' => $this->param1SecCount, 920 'allowed_types' => $this->allowedTypesNumeric, 921 'operators' => $this->operators 922 ], 923 'stddevsamp' => [ 924 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 925 'description' => _('stddevsamp() - Sample standard deviation'), 926 'params' => $this->param1SecCount, 927 'allowed_types' => $this->allowedTypesNumeric, 928 'operators' => $this->operators 929 ], 930 'sum' => [ 931 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE, ZBX_FUNCTION_TYPE_MATH], 932 'description' => _('sum() - Sum of values of a period T'), 933 'params' => $this->param1SecCount, 934 'allowed_types' => $this->allowedTypesNumeric, 935 'operators' => $this->operators 936 ], 937 'sumofsquares' => [ 938 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 939 'description' => _('sumofsquares() - The sum of squares'), 940 'params' => $this->param1SecCount, 941 'allowed_types' => $this->allowedTypesNumeric, 942 'operators' => $this->operators 943 ], 944 'tan' => [ 945 'types' => [ZBX_FUNCTION_TYPE_MATH], 946 'description' => _('tan() - The tangent of a value'), 947 'params' => $this->param1SecCount, 948 'allowed_types' => $this->allowedTypesNumeric, 949 'operators' => $this->operators 950 ], 951 'time' => [ 952 'types' => [ZBX_FUNCTION_TYPE_DATE_TIME], 953 'description' => _('time() - Current time'), 954 'allowed_types' => $this->allowedTypesAny, 955 'operators' => $this->operators 956 ], 957 'timeleft' => [ 958 'types' => [ZBX_FUNCTION_TYPE_PREDICTION], 959 'description' => _('timeleft() - Time to reach threshold estimated based on period T'), 960 'params' => $this->paramTimeleft, 961 'allowed_types' => $this->allowedTypesNumeric, 962 'operators' => $this->operators 963 ], 964 'trendavg' => [ 965 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 966 'description' => _('trendavg() - Average value of a period T with exact period shift'), 967 'params' => $this->param1Period, 968 'allowed_types' => $this->allowedTypesNumeric, 969 'operators' => $this->operators 970 ], 971 'trendcount' => [ 972 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 973 'description' => _('trendcount() - Number of successfully retrieved values for period T'), 974 'params' => $this->param1Period, 975 'allowed_types' => $this->allowedTypesAny, 976 'operators' => $this->operators 977 ], 978 'trendmax' => [ 979 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 980 'description' => _('trendmax() - Maximum value for period T with exact period shift'), 981 'params' => $this->param1Period, 982 'allowed_types' => $this->allowedTypesNumeric, 983 'operators' => $this->operators 984 ], 985 'trendmin' => [ 986 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 987 'description' => _('trendmin() - Minimum value for period T with exact period shift'), 988 'params' => $this->param1Period, 989 'allowed_types' => $this->allowedTypesNumeric, 990 'operators' => $this->operators 991 ], 992 'trendsum' => [ 993 'types' => [ZBX_FUNCTION_TYPE_HISTORY], 994 'description' => _('trendsum() - Sum of values of a period T with exact period shift'), 995 'params' => $this->param1Period, 996 'allowed_types' => $this->allowedTypesNumeric, 997 'operators' => $this->operators 998 ], 999 'trim' => [ 1000 'types' => [ZBX_FUNCTION_TYPE_STRING], 1001 'description' => _('trim() - Remove specified characters from the beginning and the end of a string'), 1002 'params' => $this->param1SecCount + [ 1003 'chars' => [ 1004 'C' => _('Chars'), 1005 'T' => T_ZBX_STR, 1006 'A' => false 1007 ] 1008 ], 1009 'allowed_types' => $this->allowedTypesStr, 1010 'operators' => $this->operators 1011 ], 1012 'truncate' => [ 1013 'types' => [ZBX_FUNCTION_TYPE_MATH], 1014 'description' => _('truncate() - Truncates a value to decimal places'), 1015 'params' => $this->param1SecCount + [ 1016 'decimals' => [ 1017 'C' => _('Decimal places'), 1018 'T' => T_ZBX_STR, 1019 'A' => true 1020 ] 1021 ], 1022 'allowed_types' => $this->allowedTypesNumeric, 1023 'operators' => $this->operators 1024 ], 1025 'varpop' => [ 1026 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 1027 'description' => _('varpop() - Population variance'), 1028 'params' => $this->param1SecCount, 1029 'allowed_types' => $this->allowedTypesNumeric, 1030 'operators' => $this->operators 1031 ], 1032 'varsamp' => [ 1033 'types' => [ZBX_FUNCTION_TYPE_AGGREGATE], 1034 'description' => _('varsamp() - Sample variance'), 1035 'params' => $this->param1SecCount, 1036 'allowed_types' => $this->allowedTypesNumeric, 1037 'operators' => $this->operators 1038 ] 1039 ]; 1040 1041 CArrayHelper::sort($this->functions, ['description']); 1042 } 1043 1044 protected function checkInput() { 1045 $fields = [ 1046 'dstfrm' => 'string|fatal', 1047 'dstfld1' => 'string|not_empty', 1048 'expression' => 'string', 1049 'itemid' => 'db items.itemid', 1050 'parent_discoveryid' => 'db items.itemid', 1051 'function' => 'in '.implode(',', array_keys($this->functions)), 1052 'operator' => 'in '.implode(',', $this->operators), 1053 'params' => '', 1054 'paramtype' => 'in '.implode(',', [PARAM_TYPE_TIME, PARAM_TYPE_COUNTS]), 1055 'value' => 'string|not_empty', 1056 'hostid' => 'db hosts.hostid', 1057 'groupid' => 'db hosts_groups.hostgroupid', 1058 'add' => 'in 1' 1059 ]; 1060 1061 $ret = $this->validateInput($fields); 1062 1063 if (!$ret) { 1064 $output = []; 1065 if (($messages = getMessages()) !== null) { 1066 $output['errors'] = $messages->toString(); 1067 } 1068 1069 if ($this->hasInput('add')) { 1070 $this->setResponse( 1071 (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView() 1072 ); 1073 } 1074 else { 1075 $ret = true; 1076 } 1077 } 1078 1079 return $ret; 1080 } 1081 1082 protected function checkPermissions() { 1083 return true; 1084 } 1085 1086 protected function doAction() { 1087 $expression_parser = new CExpressionParser(['usermacros' => true, 'lldmacros' => true]); 1088 $expression_validator = new CExpressionValidator([ 1089 'usermacros' => true, 1090 'lldmacros' => true, 1091 'partial' => true 1092 ]); 1093 1094 $itemid = $this->getInput('itemid', 0); 1095 $function = $this->getInput('function', 'last'); 1096 $operator = $this->getInput('operator', '='); 1097 $param_type = $this->getInput('paramtype', PARAM_TYPE_TIME); 1098 $dstfld1 = $this->getInput('dstfld1'); 1099 $expression = $this->getInput('expression', ''); 1100 $params = $this->getInput('params', []); 1101 $value = $this->getInput('value', 0); 1102 1103 $item = false; 1104 1105 // Opening the popup when editing an expression in the trigger constructor. 1106 if (($dstfld1 === 'expr_temp' || $dstfld1 === 'recovery_expr_temp') && $expression !== '') { 1107 $expression = utf8RawUrlDecode($expression); 1108 1109 if ($expression_parser->parse($expression) == CParser::PARSE_SUCCESS) { 1110 $math_function_token = null; 1111 $hist_function_token = null; 1112 $function_token_index = null; 1113 $tokens = $expression_parser->getResult()->getTokens(); 1114 1115 foreach ($tokens as $index => $token) { 1116 switch ($token['type']) { 1117 case CExpressionParserResult::TOKEN_TYPE_MATH_FUNCTION: 1118 $math_function_token = $token; 1119 $function_token_index = $index; 1120 1121 foreach ($token['data']['parameters'] as $parameter) { 1122 foreach ($parameter['data']['tokens'] as $parameter_token) { 1123 if ($parameter_token['type'] == CExpressionParserResult::TOKEN_TYPE_HIST_FUNCTION) { 1124 $hist_function_token = $parameter_token; 1125 break 2; 1126 } 1127 } 1128 } 1129 break 2; 1130 1131 case CExpressionParserResult::TOKEN_TYPE_HIST_FUNCTION: 1132 $hist_function_token = $token; 1133 $function_token_index = $index; 1134 break 2; 1135 } 1136 } 1137 1138 if ($function_token_index !== null) { 1139 /* 1140 * Try to find an operator and a value. 1141 * The value and operator can be extracted only if they immediately follow the function. 1142 */ 1143 $index = $function_token_index + 1; 1144 1145 if (array_key_exists($index, $tokens) 1146 && $tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_OPERATOR 1147 && in_array($tokens[$index]['match'], $this->operators)) { 1148 $operator = $tokens[$index]['match']; 1149 $index++; 1150 1151 if (array_key_exists($index, $tokens)) { 1152 if ($tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_NUMBER 1153 || $tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_MACRO 1154 || $tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_USER_MACRO 1155 || $tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_LLD_MACRO) { 1156 $value = $tokens[$index]['match']; 1157 } 1158 elseif ($tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_STRING) { 1159 $value = CExpressionParser::unquoteString($tokens[$index]['match']); 1160 } 1161 elseif ($tokens[$index]['type'] == CExpressionParserResult::TOKEN_TYPE_OPERATOR 1162 && array_key_exists($index + 1, $tokens) 1163 && $tokens[$index + 1]['type'] == CExpressionParserResult::TOKEN_TYPE_NUMBER) { 1164 $value = '-'.$tokens[$index + 1]['match']; 1165 } 1166 } 1167 } 1168 1169 // Get function parameters. 1170 $parameters = null; 1171 1172 if ($math_function_token) { 1173 $function = $math_function_token['data']['function']; 1174 1175 if ($hist_function_token && $hist_function_token['data']['function'] === 'last') { 1176 $parameters = $hist_function_token['data']['parameters']; 1177 } 1178 } 1179 else { 1180 $function = $hist_function_token['data']['function']; 1181 $parameters = $hist_function_token['data']['parameters']; 1182 } 1183 1184 if ($parameters !== null) { 1185 $host = $hist_function_token['data']['parameters'][0]['data']['host']; 1186 $key = $hist_function_token['data']['parameters'][0]['data']['item']; 1187 1188 $items = API::Item()->get([ 1189 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 1190 'selectHosts' => ['name'], 1191 'webitems' => true, 1192 'filter' => [ 1193 'host' => $host, 1194 'key_' => $key 1195 ] 1196 ]); 1197 1198 if (!$items) { 1199 $items = API::ItemPrototype()->get([ 1200 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 1201 'selectHosts' => ['name'], 1202 'filter' => [ 1203 'host' => $host, 1204 'key_' => $key 1205 ] 1206 ]); 1207 } 1208 1209 if (($item = reset($items)) === false) { 1210 error(_('Unknown host item, no such item in selected host')); 1211 } 1212 } 1213 1214 $params = []; 1215 1216 if ($parameters !== null && array_key_exists(1, $parameters)) { 1217 if ($function === "nodata" || $function === "fuzzytime") { 1218 $params[] = ($parameters[1]['type'] == CHistFunctionParser::PARAM_TYPE_QUOTED) 1219 ? CHistFunctionParser::unquoteParam($parameters[1]['match']) 1220 : $parameters[1]['match']; 1221 } 1222 else { 1223 if ($parameters[1]['type'] == CHistFunctionParser::PARAM_TYPE_PERIOD) { 1224 $sec_num = $parameters[1]['data']['sec_num']; 1225 if ($sec_num !== '' && $sec_num[0] === '#') { 1226 $params[] = substr($sec_num, 1); 1227 $param_type = PARAM_TYPE_COUNTS; 1228 } 1229 else { 1230 $params[] = $sec_num; 1231 $param_type = PARAM_TYPE_TIME; 1232 } 1233 $params[] = $parameters[1]['data']['time_shift']; 1234 } 1235 else { 1236 $params[] = ''; 1237 $params[] = ''; 1238 } 1239 } 1240 1241 for ($i = 2; $i < count($parameters); $i++) { 1242 $parameter = $parameters[$i]; 1243 $params[] = $parameter['type'] == CHistFunctionParser::PARAM_TYPE_QUOTED 1244 ? CHistFunctionParser::unquoteParam($parameter['match']) 1245 : $parameter['match']; 1246 } 1247 } 1248 } 1249 } 1250 } 1251 // Opening an empty form or switching a function. 1252 else { 1253 $item = API::Item()->get([ 1254 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 1255 'selectHosts' => ['host', 'name'], 1256 'itemids' => $itemid, 1257 'webitems' => true, 1258 'filter' => ['flags' => null] 1259 ]); 1260 1261 $item = reset($item); 1262 } 1263 1264 if ($item) { 1265 $items = CMacrosResolverHelper::resolveItemNames([$item]); 1266 $item = $items[0]; 1267 1268 $itemid = $item['itemid']; 1269 $item_value_type = $item['value_type']; 1270 $item_key = $item['key_']; 1271 $item_host_data = reset($item['hosts']); 1272 $description = $item_host_data['name'].NAME_DELIMITER.$item['name_expanded']; 1273 } 1274 else { 1275 $item_key = ''; 1276 $description = ''; 1277 $item_value_type = null; 1278 } 1279 1280 if ($param_type === null && array_key_exists($function, $this->functions) 1281 && array_key_exists('params', $this->functions[$function]) 1282 && array_key_exists('M', $this->functions[$function]['params'])) { 1283 $param_type = is_array($this->functions[$function]['params']['M']) 1284 ? reset($this->functions[$function]['params']['M']) 1285 : $this->functions[$function]['params']['M']; 1286 } 1287 elseif ($param_type === null) { 1288 $param_type = PARAM_TYPE_TIME; 1289 } 1290 1291 $data = [ 1292 'parent_discoveryid' => $this->getInput('parent_discoveryid', ''), 1293 'dstfrm' => $this->getInput('dstfrm'), 1294 'dstfld1' => $dstfld1, 1295 'itemid' => $itemid, 1296 'value' => $value, 1297 'params' => $params, 1298 'paramtype' => $param_type, 1299 'item_description' => $description, 1300 'item_required' => !in_array($function, array_merge(getStandaloneFunctions(), getFunctionsConstants())), 1301 'functions' => $this->functions, 1302 'function' => $function, 1303 'function_type' => reset($this->functions[$function]['types']), 1304 'operator' => $operator, 1305 'item_key' => $item_key, 1306 'itemValueType' => $item_value_type, 1307 'selectedFunction' => null, 1308 'groupid' => $this->getInput('groupid', 0), 1309 'hostid' => $this->getInput('hostid', 0) 1310 ]; 1311 1312 // Check if submitted function is usable with selected item. 1313 foreach ($data['functions'] as $id => $f) { 1314 if (($data['itemValueType'] === null || array_key_exists($item_value_type, $f['allowed_types'])) 1315 && $id === $function) { 1316 $data['selectedFunction'] = $id; 1317 break; 1318 } 1319 } 1320 1321 if ($data['selectedFunction'] === null) { 1322 $data['selectedFunction'] = 'last'; 1323 $data['function'] = 'last'; 1324 $data['function_type'] = ZBX_FUNCTION_TYPE_HISTORY; 1325 } 1326 1327 // Remove functions that not correspond to chosen item. 1328 foreach ($data['functions'] as $id => $f) { 1329 if ($data['itemValueType'] !== null && !array_key_exists($data['itemValueType'], $f['allowed_types'])) { 1330 unset($data['functions'][$id]); 1331 1332 // Take first available function from list. 1333 if ($id === $data['function']) { 1334 $data['function'] = key($data['functions']); 1335 $data['function_type'] = reset($data['functions'][$data['function']]['types']); 1336 $data['operator'] = reset($data['functions'][$data['function']]['operators']); 1337 } 1338 } 1339 } 1340 1341 // Create and validate trigger expression before inserting it into textarea field. 1342 if ($this->getInput('add', false)) { 1343 try { 1344 if (in_array($function, getFunctionsConstants())) { 1345 $data['expression'] = sprintf('%s()', $function); 1346 } 1347 elseif (in_array($function, getStandaloneFunctions())) { 1348 $data['expression'] = sprintf('%s()%s%s', $function, $operator, 1349 CExpressionParser::quoteString($data['value']) 1350 ); 1351 } 1352 elseif ($data['item_description']) { 1353 // Quote function string parameters. 1354 foreach ($data['params'] as $param_key => $param) { 1355 if (!in_array($param_key, ['v', 'o', 'chars', 'fit', 'mode', 'pattern', 'replace', 'string']) 1356 || !array_key_exists($param_key, $data['params']) 1357 || $data['params'][$param_key] === '') { 1358 continue; 1359 } 1360 1361 $data['params'][$param_key] = quoteFunctionParam($param, true); 1362 } 1363 1364 // Combine sec|#num and <time_shift|period_shift> parameters into one. 1365 if (array_key_exists('last', $data['params'])) { 1366 if ($data['paramtype'] == PARAM_TYPE_COUNTS && zbx_is_int($data['params']['last'])) { 1367 $data['params']['last'] = '#'.$data['params']['last']; 1368 } 1369 } 1370 else { 1371 $data['params']['last'] = ''; 1372 } 1373 1374 if (array_key_exists('shift', $data['params']) && $data['params']['shift'] !== '') { 1375 $data['params']['last'] .= ':'.$data['params']['shift']; 1376 } 1377 elseif (array_key_exists('period_shift', $data['params']) 1378 && $data['params']['period_shift'] !== '') { 1379 $data['params']['last'] .= ':'.$data['params']['period_shift']; 1380 } 1381 unset($data['params']['shift'], $data['params']['period_shift']); 1382 1383 // Functions where item is wrapped in last() like func(last(/host/item)). 1384 $last_functions = [ 1385 'abs', 'acos', 'ascii', 'asin', 'atan', 'atan2', 'between', 'bitand', 'bitlength', 'bitlshift', 1386 'bitnot', 'bitor', 'bitrshift', 'bitxor', 'bytelength', 'cbrt', 'ceil', 'char', 'concat', 'cos', 1387 'cosh', 'cot', 'degrees', 'exp', 'expm1', 'floor', 'in', 'insert', 'left', 'log', 'log10', 1388 'ltrim', 'mid', 'mod', 'power', 'radians', 'repeat', 'replace', 'right', 'round', 'signum', 1389 'sin', 'sinh', 'sqrt', 'tan', 'trim', 'truncate' 1390 ]; 1391 1392 if (in_array($function, $last_functions)) { 1393 $last_params = $data['params']['last']; 1394 unset($data['params']['last']); 1395 $fn_params = rtrim(implode(',', $data['params']), ','); 1396 1397 $data['expression'] = sprintf('%s(last(/%s/%s%s)%s)%s%s', 1398 $function, 1399 $item_host_data['host'], 1400 $data['item_key'], 1401 ($last_params === '') ? '' : ','.$last_params, 1402 ($fn_params === '') ? '' : ','.$fn_params, 1403 $operator, 1404 CExpressionParser::quoteString($data['value']) 1405 ); 1406 } 1407 else { 1408 $fn_params = rtrim(implode(',', $data['params']), ','); 1409 1410 $data['expression'] = sprintf('%s(/%s/%s%s)%s%s', 1411 $function, 1412 $item_host_data['host'], 1413 $data['item_key'], 1414 ($fn_params === '') ? '' : ','.$fn_params, 1415 $operator, 1416 CExpressionParser::quoteString($data['value']) 1417 ); 1418 } 1419 } 1420 else { 1421 error(_('Item not selected')); 1422 } 1423 1424 if (array_key_exists('expression', $data)) { 1425 // Parse and validate trigger expression. 1426 if ($expression_parser->parse($data['expression']) == CParser::PARSE_SUCCESS) { 1427 if (!$expression_validator->validate($expression_parser->getResult()->getTokens())) { 1428 error(_s('Invalid condition: %1$s.', $expression_validator->getError())); 1429 } 1430 } 1431 else { 1432 error($expression_parser->getError()); 1433 } 1434 } 1435 } 1436 catch (Exception $e) { 1437 error($e->getMessage()); 1438 error(_('Cannot insert trigger expression')); 1439 } 1440 1441 if (($messages = getMessages()) !== null) { 1442 $output = [ 1443 'errors' => $messages->toString() 1444 ]; 1445 } 1446 else { 1447 $output = [ 1448 'expression' => $data['expression'], 1449 'dstfld1' => $data['dstfld1'], 1450 'dstfrm' => $data['dstfrm'] 1451 ]; 1452 } 1453 1454 $this->setResponse( 1455 (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView() 1456 ); 1457 } 1458 else { 1459 $this->setResponse(new CControllerResponseData( 1460 $data + [ 1461 'title' => _('Condition'), 1462 'errors' => hasErrorMesssages() ? getMessages() : null, 1463 'user' => [ 1464 'debug_mode' => $this->getDebugMode() 1465 ] 1466 ] 1467 )); 1468 } 1469 } 1470} 1471