Jannis Moßhammer f898e2e367 Fix broken files in Statusdat Expression handler
The function tokens in the Expression handler didn't
work after they were rewritten, as the rewrite was
missing in certain files. This is fixed now

refs #4246
2013-06-10 16:44:58 +02:00

341 lines
7.2 KiB
PHP
Executable File

<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\Query;
class Expression implements IQueryPart
{
/**
*
*/
const ENC_NUMERIC = 0;
/**
*
*/
const ENC_SET = 0;
/**
*
*/
const ENC_STRING = 0;
/**
* @var string
*/
private $expression;
/**
* @var null
*/
private $field = null;
/**
* @var array
*/
private $basedata = array();
/**
* @var null
*/
private $function = null;
/**
* @var string
*/
private $value = "";
/**
* @var null
*/
private $operator = null;
/**
* @var null
*/
private $name = null;
/**
* @var null
*/
public $CB = null;
/**
* @param $token
* @throws \Exception
*/
private function getOperatorType($token)
{
switch (strtoupper($token)) {
case ">":
$this->CB = "isGreater";
break;
case "<":
$this->CB = "isLess";
break;
case ">=":
$this->CB = "isGreaterEq";
break;
case "<=":
$this->CB = "isLessEq";
break;
case "=":
$this->CB = "isEqual";
break;
case "LIKE":
$this->CB = "isLike";
break;
case "!=":
$this->CB = "isNotEqual";
break;
case "IN":
$this->CB = "isIn";
break;
default:
throw new \Exception("Unknown operator $token in expression $this->expression !");
}
}
/**
* @param $tokens
* @return mixed
*/
private function extractAggregationFunction(&$tokens)
{
$token = $tokens[0];
$value = array();
if (preg_match("/COUNT\{(.*)\}/", $token, $value) == false) {
return $token;
}
$this->function = "count";
$tokens[0] = $value[1];
return null;
}
/**
* @param $values
*/
private function parseExpression(&$values)
{
$tokenized = preg_split("/ +/", trim($this->expression), 3);
$this->extractAggregationFunction($tokenized);
if (count($tokenized) != 3) {
echo(
"Currently statusdat query expressions must be in "
. "the format FIELD OPERATOR ? or FIELD OPERATOR :value_name"
);
}
$this->fields = explode(".", trim($tokenized[0]));
$this->field = $this->fields[count($this->fields) - 1];
$this->getOperatorType(trim($tokenized[1]));
$tokenized[2] = trim($tokenized[2]);
if ($tokenized[2][0] === ":") {
$this->name = substr($tokenized, 1);
$this->value = $values[$this->name];
} else {
if ($tokenized[2] === "?") {
$this->value = array_shift($values);
} else {
$this->value = trim($tokenized[2]);
}
}
}
/**
* @param $expression
* @param $values
* @return $this
*/
public function fromString($expression, &$values)
{
$this->expression = $expression;
$this->parseExpression($values);
return $this;
}
/**
* @param null $expression
* @param array $values
*/
public function __construct($expression = null, &$values = array())
{
if ($expression) {
$this->fromString($expression, $values);
}
}
/**
* @param array $base
* @param array $idx
* @return array|mixed
*/
public function filter(array &$base, &$idx = array())
{
if (!$idx) {
$idx = array_keys($base);
}
$this->basedata = $base;
return array_filter($idx, array($this, "filterFn"));
}
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* @return null
*/
public function getField()
{
return $this->field;
}
/**
* @param $idx
* @return bool
*/
protected function filterFn($idx)
{
$values = $this->getFieldValues($idx);
if ($values === false) {
return false;
}
if ($this->CB == "isIn") {
return count(array_intersect($values, $this->value)) > 0;
}
if ($this->CB == "isNotIn") {
return count(array_intersect($values, $this->value)) == 0;
}
if ($this->function) {
$values = call_user_func($this->function, $values);
if (!is_array($values)) {
$values = array($values);
}
}
foreach ($values as $val) {
if ($this->{$this->CB}($val)) {
return true;
}
}
return false;
}
/**
* @param $idx
* @return array
*/
private function getFieldValues($idx)
{
$res = $this->basedata[$idx];
foreach ($this->fields as $field) {
if (!is_array($res)) {
if (!isset($res->$field)) {
$res = array();
break;
}
$res = $res->$field;
continue;
}
// it can be that an element contains more than one value, like it
// happens when using comments, in this case we have to create a new
// array that contains the values/objects we're searching
$swap = array();
foreach ($res as $sub) {
if (!isset($sub->$field)) {
continue;
}
if (!is_array($sub->$field)) {
$swap[] = $sub->$field;
} else {
$swap = array_merge($swap, $sub->$field);
}
}
$res = $swap;
}
if (!is_array($res)) {
return array($res);
}
return $res;
}
/**
* @param $value
* @return bool
*/
public function isGreater($value)
{
return $value > $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLess($value)
{
return $value < $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLike($value)
{
return preg_match("/^" . str_replace("%", ".*", $this->value) . "$/", $value) ? true : false;
}
/**
* @param $value
* @return bool
*/
public function isEqual($value)
{
if (!is_numeric($value)) {
return strtolower($value) == strtolower($this->value);
}
return $value == $this->value;
}
/**
* @param $value
* @return bool
*/
public function isNotEqual($value)
{
return $value != $this->value;
}
/**
* @param $value
* @return bool
*/
public function isGreaterEq($value)
{
return $value >= $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLessEq($value)
{
return $value <= $this->value;
}
}