Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 25 additions & 34 deletions src/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,17 +181,7 @@ protected function matchEqual($rule, $row)
$value = $rule->getValue();
$this->normalizeTypes($rowValue, $value);

if (! is_array($rowValue)) {
$rowValue = [$rowValue];
}

foreach ($rowValue as $rowVal) {
if ($this->performEqualityMatch($value, $rowVal, $rule->ignoresCase())) {
return true;
}
}

return false;
return $this->performEqualityMatch($value, $rowValue, $rule->ignoresCase());
}

/**
Expand Down Expand Up @@ -228,21 +218,17 @@ protected function matchSimilar($rule, $row)
));
}

$rowValue = $this->extractValue($rule->getColumn(), $row);
$value = $rule->getValue();
$this->normalizeTypes($rowValue, $value);

if (! is_array($rowValue)) {
$rowValue = [$rowValue];
if (is_array($value)) {
throw new InvalidArgumentException(
'Cannot perform a similarity match if the expression is an array'
);
}

foreach ($rowValue as $rowVal) {
if ($this->performSimilarityMatch($value, $rowVal, $rule->ignoresCase())) {
return true;
}
}
$rowValue = $this->extractValue($rule->getColumn(), $row);
$this->normalizeTypes($rowValue, $value);

return false;
return $this->performSimilarityMatch((string) $value, (string) $rowValue, $rule->ignoresCase());
}

/**
Expand All @@ -256,14 +242,16 @@ protected function matchSimilar($rule, $row)
*/
protected function performEqualityMatch($value, $rowValue, $ignoreCase = false)
{
if ($ignoreCase && is_string($rowValue)) {
$rowValue = strtolower($rowValue);
if ($ignoreCase) {
$rowValue = is_array($rowValue)
? array_map('strtolower', $rowValue)
: strtolower($rowValue);
$value = is_array($value)
? array_map('strtolower', $value)
: strtolower($value);
}

if (is_array($value)) {
if (is_array($value) && ! is_array($rowValue)) {
return in_array($rowValue, $value, true);
} elseif (! is_string($value)) {
if (is_string($rowValue)) {
Expand All @@ -277,23 +265,17 @@ protected function performEqualityMatch($value, $rowValue, $ignoreCase = false)
/**
* Apply similarity matching rules on the given row value
*
* @param string|string[] $value
* @param string $value
* @param string $rowValue
* @param bool $ignoreCase
*
* @return bool
*/
protected function performSimilarityMatch($value, $rowValue, $ignoreCase = false)
protected function performSimilarityMatch(string $value, string $rowValue, bool $ignoreCase = false): bool
{
if ($ignoreCase) {
$rowValue = strtolower($rowValue);
$value = is_array($value)
? array_map('strtolower', $value)
: strtolower($value);
}

if (is_array($value)) {
return in_array($rowValue, $value, true);
$value = strtolower($value);
}

$wildcardSubSegments = preg_split('~\*~', $value);
Expand Down Expand Up @@ -530,6 +512,15 @@ protected function performMatch(Rule $rule, $row)
*/
protected function extractValue($column, $row)
{
if (is_array($column)) {
$value = [];
foreach ($column as $name) {
$value[] = $this->extractValue($name, $row);
}

return $value;
}

try {
return $row->{$column};
} catch (Exception $_) {
Expand Down
125 changes: 41 additions & 84 deletions tests/FilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class FilterTest extends TestCase
'service' => 'www.icinga.com',
'state' => 1,
'handled' => '0'
],
[
'host' => 'LocalHost',
'problem' => '1',
'service' => 'Ping',
'state' => 3,
'handled' => '1'
]
];

Expand Down Expand Up @@ -139,45 +146,10 @@ public function testLikeMismatches()

public function testLikeIgnoresCase()
{
// single string
$like = Filter::like('host', '*LOCAL*')
->ignoreCase();

$this->assertTrue(Filter::match($like, $this->row(0)));

// string array
$like->setValue(['LoCaLhOsT', '127.0.0.1']);

$this->assertTrue(Filter::match($like, $this->row(0)));
}

public function testEqualMatchesMultiValuedColumns()
{
$this->assertTrue(Filter::match(Filter::equal('foo', 'bar'), [
'foo' => ['foo', 'bar']
]));
$this->assertTrue(Filter::match(Filter::equal('foo', 'BAR')->ignoreCase(), [
'foo' => ['FoO', 'bAr']
]));
$this->assertTrue(Filter::match(Filter::equal('foo', ['bar', 'boar']), [
'foo' => ['foo', 'bar']
]));
}

public function testLikeMatchesMultiValuedColumns()
{
$this->assertTrue(Filter::match(Filter::like('foo', 'bar'), [
'foo' => ['foo', 'bar']
]));
$this->assertTrue(Filter::match(Filter::like('foo', 'ba*'), [
'foo' => ['foo', 'bar']
]));
$this->assertTrue(Filter::match(Filter::like('foo', 'BAR')->ignoreCase(), [
'foo' => ['FoO', 'bAr']
]));
$this->assertTrue(Filter::match(Filter::like('foo', ['bar', 'boar']), [
'foo' => ['foo', 'bar']
]));
}

public function testUnequalMatches()
Expand Down Expand Up @@ -224,45 +196,10 @@ public function testUnlikeMismatches()

public function testUnlikeIgnoresCase()
{
// single string
$unlike = Filter::unlike('host', '*LOCAL*')
->ignoreCase();

$this->assertFalse(Filter::match($unlike, $this->row(0)));

// string array
$unlike->setValue(['LoCaLhOsT', '127.0.0.1']);

$this->assertFalse(Filter::match($unlike, $this->row(0)));
}

public function testUnequalMatchesMultiValuedColumns()
{
$this->assertFalse(Filter::match(Filter::unequal('foo', 'bar'), [
'foo' => ['foo', 'bar']
]));
$this->assertFalse(Filter::match(Filter::unequal('foo', 'BAR')->ignoreCase(), [
'foo' => ['FoO', 'bAr']
]));
$this->assertFalse(Filter::match(Filter::unequal('foo', ['bar', 'boar']), [
'foo' => ['foo', 'bar']
]));
}

public function testUnlikeMatchesMultiValuedColumns()
{
$this->assertFalse(Filter::match(Filter::unlike('foo', 'bar'), [
'foo' => ['foo', 'bar']
]));
$this->assertFalse(Filter::match(Filter::unlike('foo', 'ba*'), [
'foo' => ['foo', 'bar']
]));
$this->assertFalse(Filter::match(Filter::unlike('foo', 'BAR')->ignoreCase(), [
'foo' => ['FoO', 'bAr']
]));
$this->assertFalse(Filter::match(Filter::unlike('foo', ['bar', 'boar']), [
'foo' => ['foo', 'bar']
]));
}

public function testGreaterThanMatches()
Expand Down Expand Up @@ -381,32 +318,49 @@ public function testEqualWithArrayMismatches()
$this->assertFalse(Filter::match($equal, $this->row(0)));
}

public function testLikeWithArrayMatches()
public function testEqualWithArrayComparisonMatches()
{
$like = Filter::like('host', ['127.0.0.1', 'localhost']);
$equal = Filter::equal(['host', 'service'], ['localhost', 'ping']);

$this->assertTrue(Filter::match($like, $this->row(0)));
$this->assertTrue(Filter::match($equal, $this->row(0)));
}

public function testLikeWithArrayMismatches()
public function testEqualWithCaseInsensitiveArrayComparisonMatches()
{
$like = Filter::like('host', ['10.0.10.20', '10.0.10.21']);
$equal = Filter::equal(['host', 'service'], ['lOcAlHost', 'PiNg'])->ignoreCase();

$this->assertFalse(Filter::match($like, $this->row(0)));
$this->assertTrue(Filter::match($equal, $this->row(3)));
}

public function testUnequalWithArrayMatches()
public function testUnequalWithArrayComparisonMatches()
{
$unequal = Filter::unequal('host', ['10.0.20.10', '10.0.20.11']);
$unequal = Filter::unequal(['host', 'service'], ['ping', 'localhost']);

$this->assertTrue(Filter::match($unequal, $this->row(0)));
}

public function testUnlikeWithArrayMatches()
public function testUnequalWithCaseInsensitiveArrayComparisonMatches()
{
$unequal = Filter::unequal(['host', 'service'], ['PiNg', 'lOcAlHost'])->ignoreCase();

$this->assertTrue(Filter::match($unequal, $this->row(3)));
}

public function testLikeWithArrayThrows()
{
$unlike = Filter::unlike('host', ['10.0.20.10', '10.0.20.11']);
$like = Filter::like('host', ['127.0.0.*', 'local*']);

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot perform a similarity match if the expression is an array');

$this->assertTrue(Filter::match($unlike, $this->row(0)));
Filter::match($like, $this->row(0));
}

public function testUnequalWithArrayMatches()
{
$unequal = Filter::unequal('host', ['10.0.20.10', '10.0.20.11']);

$this->assertTrue(Filter::match($unequal, $this->row(0)));
}

public function testUnequalWithArrayMismatches()
Expand All @@ -416,11 +370,14 @@ public function testUnequalWithArrayMismatches()
$this->assertFalse(Filter::match($unequal, $this->row(0)));
}

public function testUnlikeWithArrayMismatches()
public function testUnlikeWithArrayThrows()
{
$unlike = Filter::unlike('host', ['127.0.0.1', 'localhost']);
$unlike = Filter::unlike('host', ['127.0.0.*', 'local*']);

$this->assertFalse(Filter::match($unlike, $this->row(0)));
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot perform a similarity match if the expression is an array');

Filter::match($unlike, $this->row(0));
}

public function testConditionsAreValueTypeAgnostic()
Expand Down