AssignRenderer: fix and test NOT on root level

fixes #1777
This commit is contained in:
Thomas Gelf 2019-02-08 12:08:06 +01:00
parent 6d2028706e
commit 0139506494
3 changed files with 35 additions and 13 deletions

View File

@ -14,6 +14,7 @@ before switching to a new version.
* FIX: restoring a basket fails when there is only one configured DB (#1716) * FIX: restoring a basket fails when there is only one configured DB (#1716)
* FIX: creating a new Basket with a "Custom Selection" failed with an error (#1733) * FIX: creating a new Basket with a "Custom Selection" failed with an error (#1733)
* FIX: some new reserved keywords are now escaped correctly (#1765) * FIX: some new reserved keywords are now escaped correctly (#1765)
* FIX: correctly render NOT used in apply rules (fixes #1777)
1.6.0 1.6.0
----- -----

View File

@ -17,6 +17,7 @@ use Icinga\Data\Filter\FilterMatch;
use Icinga\Data\Filter\FilterMatchNot; use Icinga\Data\Filter\FilterMatchNot;
use Icinga\Data\Filter\FilterNotEqual; use Icinga\Data\Filter\FilterNotEqual;
use Icinga\Exception\QueryException; use Icinga\Exception\QueryException;
use InvalidArgumentException;
class AssignRenderer class AssignRenderer
{ {
@ -49,6 +50,14 @@ class AssignRenderer
protected function renderFilter(Filter $filter) protected function renderFilter(Filter $filter)
{ {
if ($filter instanceof FilterNot) {
$parts = [];
foreach ($filter->filters() as $sub) {
$parts[] = $this->renderFilter($sub);
}
return '!(' . implode(' && ', $parts) . ')';
}
if ($filter->isChain()) { if ($filter->isChain()) {
/** @var FilterChain $filter */ /** @var FilterChain $filter */
return $this->renderFilterChain($filter); return $this->renderFilterChain($filter);
@ -235,31 +244,23 @@ class AssignRenderer
} elseif ($filter instanceof FilterOr) { } elseif ($filter instanceof FilterOr) {
$op = ' || '; $op = ' || ';
} elseif ($filter instanceof FilterNot) { } elseif ($filter instanceof FilterNot) {
$op = ' !'; // TODO -> different throw new InvalidArgumentException('renderFilterChain should never get a FilterNot instance');
} else { } else {
throw new QueryException('Cannot render filter: %s', $filter); throw new InvalidArgumentException('Cannot render filter: %s', $filter);
} }
$parts = array(); $parts = array();
if (! $filter->isEmpty()) { if (! $filter->isEmpty()) {
/** @var Filter $f */ /** @var Filter $f */
foreach ($filter->filters() as $f) { foreach ($filter->filters() as $f) {
if ($f->isChain()) { if ($f instanceof FilterChain && $f->count() > 1) {
if ($f instanceof FilterNot) { $parts[] = '(' . $this->renderFilter($f) . ')';
$parts[] = '! (' . $this->renderFilter($f) . ')';
} else {
$parts[] = '(' . $this->renderFilter($f) . ')';
}
} else { } else {
$parts[] = $this->renderFilter($f); $parts[] = $this->renderFilter($f);
} }
} }
} }
if ($filter instanceof FilterNot) { return implode($op, $parts);
return implode(' && ', $parts);
} else {
return implode($op, $parts);
}
} }
} }

View File

@ -18,6 +18,26 @@ class AssignRendererTest extends BaseTestCase
); );
} }
public function testNegationIsRenderedCorrectlyOnRootLevel()
{
$string = '!(host.name="one"&host.name="two")';
$expected = 'assign where !(host.name == "one" && host.name == "two")';
$this->assertEquals(
$expected,
$this->renderer($string)->renderAssign()
);
}
public function testNegationIsRenderedCorrectlyOnDeeperLevel()
{
$string = 'host.address="127.*"&!host.name="localhost"';
$expected = 'assign where match("127.*", host.address) && !(host.name == "localhost")';
$this->assertEquals(
$expected,
$this->renderer($string)->renderAssign()
);
}
public function testWildcardsRenderAMatchMethod() public function testWildcardsRenderAMatchMethod()
{ {
$string = 'host.address="127.0.0.*"'; $string = 'host.address="127.0.0.*"';