diff --git a/src/Factory/SimpleFactory.php b/src/Factory/SimpleFactory.php index f8834182..cc097610 100644 --- a/src/Factory/SimpleFactory.php +++ b/src/Factory/SimpleFactory.php @@ -23,15 +23,40 @@ public function createMatcher() protected function buildMatchers() { $scalarMatchers = $this->buildScalarMatchers(); - $arrayMatcher = new Matcher\ArrayMatcher($scalarMatchers, $this->buildParser()); + $orMatcher = $this->buildOrMatcher(); - return new Matcher\ChainMatcher(array( + $chainMatcher = new Matcher\ChainMatcher(array( $scalarMatchers, - $arrayMatcher, - new Matcher\JsonMatcher($arrayMatcher), - new Matcher\XmlMatcher($arrayMatcher), + $orMatcher, + new Matcher\JsonMatcher($orMatcher), + new Matcher\XmlMatcher($orMatcher), new Matcher\TextMatcher($scalarMatchers, $this->buildParser()) )); + + return $chainMatcher; + } + + /** + * @return Matcher\ChainMatcher + */ + protected function buildOrMatcher() + { + $scalarMatchers = $this->buildScalarMatchers(); + $orMatcher = new Matcher\OrMatcher($scalarMatchers); + $arrayMatcher = new Matcher\ArrayMatcher( + new Matcher\ChainMatcher(array( + $orMatcher, + $scalarMatchers + )), + $this->buildParser() + ); + + $chainMatcher = new Matcher\ChainMatcher(array( + $orMatcher, + $arrayMatcher, + )); + + return $chainMatcher; } /** diff --git a/src/Matcher/OrMatcher.php b/src/Matcher/OrMatcher.php new file mode 100644 index 00000000..5eea2958 --- /dev/null +++ b/src/Matcher/OrMatcher.php @@ -0,0 +1,64 @@ +chainMatcher = $chainMatcher; + } + + /** + * {@inheritDoc} + */ + public function match($value, $pattern) + { + $patterns = explode('||', $pattern); + foreach ($patterns as $childPattern) { + if ($this->matchChild($value, $childPattern)){ + return true; + } + } + + return false; + } + + /** + * Matches single pattern + * + * @param $value + * @param $pattern + * @return bool + */ + private function matchChild($value, $pattern) + { + if (!$this->chainMatcher->canMatch($pattern)) { + return false; + } + + if ($this->chainMatcher->match($value, $pattern)) { + return true; + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function canMatch($pattern) + { + return is_string($pattern) && 0 !== preg_match_all(self::MATCH_PATTERN, $pattern, $matches); + } +} diff --git a/tests/Matcher/OrMatcherTest.php b/tests/Matcher/OrMatcherTest.php new file mode 100644 index 00000000..5ec8909f --- /dev/null +++ b/tests/Matcher/OrMatcherTest.php @@ -0,0 +1,153 @@ +matcher = $factory->createMatcher(); + } + + /** + * @dataProvider positiveMatchData + */ + public function test_positive_match_arrays($value, $pattern) + { + $this->assertTrue( + $this->matcher->match($value, $pattern), + $this->matcher->getError() + ); + } + + /** + * @dataProvider negativeMatchData + */ + public function test_negative_match_arrays($value, $pattern) + { + $this->assertFalse( + $this->matcher->match($value, $pattern), + $this->matcher->getError() + ); + } + + public static function positiveMatchData() + { + $simpleArr = array( + 'users' => array( + array( + 'firstName' => 'Norbert', + 'lastName' => 'Orzechowicz' + ), + array( + 'firstName' => 1, + 'lastName' => 2 + ) + ), + true, + false, + 1, + 6.66 + ); + + $simpleArrPattern = array( + 'users' => array( + array( + 'firstName' => '@string@', + 'lastName' => '@null@||@string@||@integer@' + ), + '@...@' + ), + true, + false, + 1, + 6.66 + ); + + return array( + array('test', '@string@'), + array(null, '@array@||@string@||@null@'), + array( + array( + 'test' => 1 + ), + array( + 'test' => '@integer@' + ) + ), + array( + array( + 'test' => null + ), + array( + 'test' => '@integer@||@null@' + ) + ), + array( + array( + 'first_level' => array('second_level', array('third_level')) + ), + '@array@||@null@||@*@' + ), + array($simpleArr, $simpleArr), + array($simpleArr, $simpleArrPattern), + ); + } + + public static function negativeMatchData() + { + $simpleArr = array( + 'users' => array( + array( + 'firstName' => 'Norbert', + 'lastName' => 'Orzechowicz' + ), + array( + 'firstName' => 'Michał', + 'lastName' => 'Dąbrowski' + ) + ), + true, + false, + 1, + 6.66 + ); + + $simpleDiff = array( + 'users' => array( + array( + 'firstName' => 'Norbert', + 'lastName' => 'Orzechowicz' + ), + array( + 'firstName' => 'Pablo', + 'lastName' => '@integer@||@null@||@double@' + ) + ), + true, + false, + 1, + 6.66 + ); + + return array( + array($simpleArr, $simpleDiff), + array(array("status" => "ok", "data" => array(array('foo'))), array("status" => "ok", "data" => array())), + array(array(1), array()), + array(array('key' => 'val'), array('key' => 'val2')), + array(array(1), array(2)), + array(array('foo', 1, 3), array('foo', 2, 3)), + array(array(), array('foo' => 'bar')), + array(10, '@null@||@integer@.greaterThan(10)'), + ); + } +} diff --git a/tests/MatcherTest.php b/tests/MatcherTest.php index fb200e1e..b41a5d68 100644 --- a/tests/MatcherTest.php +++ b/tests/MatcherTest.php @@ -2,7 +2,7 @@ namespace Coduo\PHPMatcher\Tests; -use Coduo\PHPMatcher\Lexer; +use Coduo\PHPMatcher\Factory\SimpleFactory; use Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\Parser; use Coduo\PHPMatcher\PHPMatcher; @@ -16,29 +16,8 @@ class MatcherTest extends \PHPUnit_Framework_TestCase public function setUp() { - $parser = new Parser(new Lexer(), new Parser\ExpanderInitializer()); - $scalarMatchers = new Matcher\ChainMatcher(array( - new Matcher\CallbackMatcher(), - new Matcher\ExpressionMatcher(), - new Matcher\NullMatcher(), - new Matcher\StringMatcher($parser), - new Matcher\IntegerMatcher($parser), - new Matcher\BooleanMatcher(), - new Matcher\DoubleMatcher($parser), - new Matcher\NumberMatcher(), - new Matcher\ScalarMatcher(), - new Matcher\WildcardMatcher(), - )); - - $arrayMatcher = new Matcher\ArrayMatcher($scalarMatchers, $parser); - - $this->matcher = new Matcher(new Matcher\ChainMatcher(array( - $scalarMatchers, - $arrayMatcher, - new Matcher\JsonMatcher($arrayMatcher), - new Matcher\XmlMatcher($arrayMatcher), - new Matcher\TextMatcher($scalarMatchers, $parser) - ))); + $factory = new SimpleFactory(); + $this->matcher = $factory->createMatcher(); } public function test_matcher_with_array_value() @@ -217,6 +196,15 @@ public function test_matcher_with_wildcard() $this->assertTrue(PHPMatcher::match('test', '@wildcard@')); } + /** + * @dataProvider orExamples() + */ + public function test_matcher_with_or($value, $pattern, $expectedResult) + { + $this->assertSame($expectedResult, $this->matcher->match($value, $pattern)); + $this->assertSame($expectedResult, PHPMatcher::match($value, $pattern)); + } + /** * @dataProvider expanderExamples() */ @@ -235,7 +223,7 @@ public function scalarValueExamples() array(array('foo'), '@array@') ); } - + public static function expanderExamples() { return array( @@ -262,4 +250,17 @@ public static function expanderExamples() array("lorem ipsum", "@string@.matchRegex(\"/^foo/\")", false), ); } + + public static function orExamples() + { + return array( + array("lorem ipsum", "@string@.startsWith(\"lorem\")||@string@.contains(\"lorem\")", true), + array("norbert@coduo.pl", "@string@.isEmail()||@null@", true), + array(null, "@string@.isEmail()||@null@", true), + array(null, "@string@.isEmail()||@null@", true), + array("2014-08-19", "@string@.isDateTime()||@integer@", true), + array(null, "@integer@||@string@", false), + array(1, "@integer@.greaterThan(10)||@string@.contains(\"10\")", false), + ); + } }