diff --git a/src/QueryExpressionFilter.php b/src/QueryExpressionFilter.php index 16ae54d..1710b84 100644 --- a/src/QueryExpressionFilter.php +++ b/src/QueryExpressionFilter.php @@ -30,26 +30,26 @@ private function matchFilter($data, $filter) private function matchOr($data, $filter) { + $empty = true; if ($this->isVector($filter)) { - if (!$filter) { - return true; - } foreach ($filter as $element) { if ($this->matchFilter($data, $element)) { return true; } + $empty = false; } } elseif ($this->isObject($filter)) { foreach ($filter as $key => $value) { if ($this->matchValue($data, $key, $value)) { return true; } + $empty = false; } } else { throw new DomainException('Invalid data type for $or combinator'); } - return false; + return $empty; } private function matchAnd($data, $filter) @@ -90,23 +90,21 @@ private function matchValue($data, $column, $expectation) $expectedValue = $expectation; $comparator = '$is'; - if (is_array($expectedValue)) { - if ($this->isVector($expectedValue)) { - // list of possible values - $comparator = '$in'; - } else { - // custom comparator ('>', '<', ...) - $comparator = key($expectedValue); - $expectedValue = reset($expectedValue); + if ($this->isVector($expectedValue)) { + // list of possible values + $comparator = '$in'; + } elseif ($this->isObject($expectedValue)) { + // custom comparator ('>', '<', ...) + $comparator = key($expectedValue); + $expectedValue = reset($expectedValue); - if ($comparator === '$not') { - $comparator = ($this->isVector($expectedValue)) ? '!$in' : '!$is'; - } + if ($comparator === '$not') { + $comparator = ($this->isVector($expectedValue)) ? '!$in' : '!$is'; + } - if ($comparator[0] === '!') { - $comparator = substr($comparator, 1); - return !$this->matchValue($data, $column, array($comparator => $expectedValue)); - } + if ($comparator[0] === '!') { + $comparator = substr($comparator, 1); + return !$this->matchValue($data, $column, array($comparator => $expectedValue)); } } @@ -137,6 +135,8 @@ private function fetchValue($data, $column) foreach ($path as $field) { if (is_array($current) && isset($current[$field])) { $current = $current[$field]; + } elseif (is_object($current) && isset($current->$field)) { + $current = $current->$field; } else { return null; } @@ -147,7 +147,7 @@ private function fetchValue($data, $column) private function isObject($value) { - return (is_array($value) && ($value === array() || !isset($value[0]))); + return (is_object($value) || (is_array($value) && ($value === array() || !isset($value[0])))); } private function isVector($value) diff --git a/tests/QueryExpressionFilterTest.php b/tests/QueryExpressionFilterTest.php index b348110..dd2753c 100644 --- a/tests/QueryExpressionFilterTest.php +++ b/tests/QueryExpressionFilterTest.php @@ -18,22 +18,6 @@ public function testAttributeValue() 'id' => 200 ))); - $filterNested = new QueryExpressionFilter(array( - 'nested.attribute' => 250 - )); - - $this->assertTrue($filterNested->doesMatch(array( - 'nested' => array( - 'attribute' => 250 - ) - ))); - - $this->assertFalse($filterNested->doesMatch(array( - 'nested' => array( - 'attribute' => 300 - ) - ))); - return $filter; } @@ -59,6 +43,34 @@ public function testAttributeMissingDoesNotMatch(QueryExpressionFilter $filter) ))); } + public function testNestedAttributeValue() + { + $filter = new QueryExpressionFilter(array( + 'nested.attribute' => 250 + )); + + $this->assertFalse($filter->doesMatch(array())); + $this->assertFalse($filter->doesMatch((object)array())); + + $this->assertTrue($filter->doesMatch(array( + 'nested' => array( + 'attribute' => 250 + ) + ))); + + $this->assertTrue($filter->doesMatch((object)array( + 'nested' => (object)array( + 'attribute' => 250 + ) + ))); + + $this->assertFalse($filter->doesMatch(array( + 'nested' => array( + 'attribute' => 300 + ) + ))); + } + public function testAttributeListOfValues() { $filter = new QueryExpressionFilter(array( @@ -137,6 +149,26 @@ public function testAndObject() ))); } + public function testAndStdObject() + { + $filter = new QueryExpressionFilter((object)array( + '$and' => (object)array( + 'id' => 100, + 'name' => 'Test' + ) + )); + + $this->assertTrue($filter->doesMatch((object)array( + 'id' => 100, + 'name' => 'Test' + ))); + + $this->assertFalse($filter->doesMatch((object)array( + 'id' => 100, + 'name' => 'invalid' + ))); + } + public function testOrList() { $filter = new QueryExpressionFilter(array( @@ -210,6 +242,15 @@ public function testEmptyOrAlwaysMatches() $this->assertTrue($filter->doesMatch(array('id' => 100))); } + public function testEmptyOrObjectAlwaysMatches() + { + $filter = new QueryExpressionFilter((object)array( + '$or' => (object)array() + )); + + $this->assertTrue($filter->doesMatch((object)array('id' => 100))); + } + public function testEmptyNotNeverMatches() { $filter = new QueryExpressionFilter(array(