diff --git a/README.md b/README.md index fca9d1d5..b28ad18b 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,9 @@ if (!PHPMatcher::match("lorem ipsum dolor", "@string@", $error)) { ```php createMatcher(); $match = $matcher->match("lorem ipsum dolor", "@string@"); @@ -98,9 +98,9 @@ $matcher->getError(); // returns null or error message ```php createMatcher(); $matcher->match(1, 1); @@ -112,9 +112,9 @@ $matcher->match('string', 'string'); ```php createMatcher(); $matcher->match('Norbert', '@string@'); @@ -127,9 +127,9 @@ $matcher->match("lorem ipsum dolor", "@string@.startsWith('lorem').contains('ips ```php createMatcher(); $matcher->match('2014-08-19', '@string@.isDateTime()'); @@ -143,9 +143,9 @@ $matcher->match('2014-08-19', '@string@.isDateTime().before("today").after("+ 10 ```php createMatcher(); $matcher->match(100, '@integer@'); @@ -158,9 +158,9 @@ $matcher->match(100, '@integer@.lowerThan(200).greaterThan(10)'); ```php createMatcher(); $matcher->match(100, '@number@'); @@ -175,9 +175,9 @@ $matcher->match(0b10100111001, '@number@'); ```php createMatcher(); $matcher->match(10.1, "@double@"); @@ -189,9 +189,9 @@ $matcher->match(10.1, "@double@.lowerThan(50.12).greaterThan(10)"); ```php createMatcher(); $matcher->match(true, "@boolean@"); @@ -203,9 +203,9 @@ $matcher->match(false, "@boolean@"); ```php createMatcher(); $matcher->match("@integer@", "@*@"); @@ -221,9 +221,9 @@ $matcher->match(new \stdClass, "@wildcard@"); ```php createMatcher(); $matcher->match(new \DateTime('2014-04-01'), "expr(value.format('Y-m-d') == '2014-04-01'"); @@ -235,9 +235,9 @@ $matcher->match("Norbert", "expr(value === 'Norbert')"); ```php createMatcher(); $matcher->match('9f4db639-0e87-4367-9beb-d64e3f42ae18', '@uuid@'); @@ -248,9 +248,9 @@ $matcher->match('9f4db639-0e87-4367-9beb-d64e3f42ae18', '@uuid@'); ```php createMatcher(); $matcher->match( @@ -307,9 +307,9 @@ $matcher->match( ```php createMatcher(); $matcher->match( @@ -341,9 +341,9 @@ $matcher->match( ```php createMatcher(); $matcher->match( @@ -399,9 +399,9 @@ $matcher->match( ```php createMatcher(); $matcher->match(<<buildMatchers($this->buildParser())); + } + + protected function buildMatchers(Parser $parser) : Matcher\ChainMatcher + { + $scalarMatchers = $this->buildScalarMatchers($parser); + $arrayMatcher = $this->buildArrayMatcher($scalarMatchers, $parser); + + $chainMatcher = new Matcher\ChainMatcher([ + $scalarMatchers, + $arrayMatcher, + new Matcher\OrMatcher($scalarMatchers), + new Matcher\JsonMatcher($arrayMatcher), + new Matcher\XmlMatcher($arrayMatcher), + new Matcher\TextMatcher($scalarMatchers, $parser) + ]); + + return $chainMatcher; + } + + protected function buildArrayMatcher(Matcher\ChainMatcher $scalarMatchers, Parser $parser) : Matcher\ArrayMatcher + { + $orMatcher = new Matcher\OrMatcher($scalarMatchers); + $arrayMatcher = new Matcher\ArrayMatcher( + new Matcher\ChainMatcher([ + $orMatcher, + $scalarMatchers, + new Matcher\TextMatcher($scalarMatchers, $parser) + ]), + $parser + ); + + return $arrayMatcher; + } + + protected function buildScalarMatchers(Parser $parser) : Matcher\ChainMatcher + { + return new Matcher\ChainMatcher([ + new Matcher\CallbackMatcher(), + new Matcher\ExpressionMatcher(), + new Matcher\NullMatcher(), + new Matcher\StringMatcher($parser), + new Matcher\IntegerMatcher($parser), + new Matcher\BooleanMatcher($parser), + new Matcher\DoubleMatcher($parser), + new Matcher\NumberMatcher($parser), + new Matcher\ScalarMatcher(), + new Matcher\WildcardMatcher(), + new Matcher\UuidMatcher($parser), + new Matcher\JsonObjectMatcher($parser) + ]); + } + + protected function buildParser() : Parser + { + return new Parser(new Lexer(), new Parser\ExpanderInitializer()); + } +} diff --git a/src/Factory/SimpleFactory.php b/src/Factory/SimpleFactory.php index db8ba0f6..5248030e 100644 --- a/src/Factory/SimpleFactory.php +++ b/src/Factory/SimpleFactory.php @@ -5,87 +5,15 @@ namespace Coduo\PHPMatcher\Factory; use Coduo\PHPMatcher\Factory; -use Coduo\PHPMatcher\Lexer; use Coduo\PHPMatcher\Matcher; -use Coduo\PHPMatcher\Parser; +/** + * @deprecated Please use \Coduo\PHPMatcher\Factory\MatcherFactory instead + */ class SimpleFactory implements Factory { - private $parser; - public function createMatcher() : Matcher { - return new Matcher($this->buildMatchers()); - } - - protected function buildMatchers() : Matcher\ChainMatcher - { - $scalarMatchers = $this->buildScalarMatchers(); - $orMatcher = $this->buildOrMatcher(); - - $chainMatcher = new Matcher\ChainMatcher([ - $scalarMatchers, - $orMatcher, - new Matcher\JsonMatcher($orMatcher, $this->buildParser()), - new Matcher\XmlMatcher($orMatcher), - new Matcher\TextMatcher($scalarMatchers, $this->buildParser()) - ]); - - return $chainMatcher; - } - - protected function buildOrMatcher() : Matcher\ChainMatcher - { - $scalarMatchers = $this->buildScalarMatchers(); - $orMatcher = new Matcher\OrMatcher($scalarMatchers); - $arrayMatcher = new Matcher\ArrayMatcher( - new Matcher\ChainMatcher([ - $orMatcher, - $scalarMatchers, - new Matcher\TextMatcher($scalarMatchers, $this->buildParser()) - ]), - $this->buildParser() - ); - - $chainMatcher = new Matcher\ChainMatcher([ - $orMatcher, - $arrayMatcher, - ]); - - return $chainMatcher; - } - - /** - * @return Matcher\ChainMatcher - */ - protected function buildScalarMatchers() : Matcher\ChainMatcher - { - $parser = $this->buildParser(); - - return new Matcher\ChainMatcher([ - new Matcher\CallbackMatcher(), - new Matcher\ExpressionMatcher(), - new Matcher\NullMatcher(), - new Matcher\StringMatcher($parser), - new Matcher\IntegerMatcher($parser), - new Matcher\BooleanMatcher($parser), - new Matcher\DoubleMatcher($parser), - new Matcher\NumberMatcher($parser), - new Matcher\ScalarMatcher(), - new Matcher\WildcardMatcher(), - new Matcher\UuidMatcher($parser), - new Matcher\JsonObjectMatcher($parser) - ]); - } - - protected function buildParser() : Parser - { - if ($this->parser) { - return $this->parser; - } - - $this->parser = new Parser(new Lexer(), new Parser\ExpanderInitializer()); - - return $this->parser; + return (new MatcherFactory())->createMatcher(); } } diff --git a/src/Matcher/JsonMatcher.php b/src/Matcher/JsonMatcher.php index 93267045..c7327589 100644 --- a/src/Matcher/JsonMatcher.php +++ b/src/Matcher/JsonMatcher.php @@ -5,14 +5,15 @@ namespace Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\Matcher\Pattern\Assert\Json; +use Coduo\ToString\StringConverter; final class JsonMatcher extends Matcher { - private $matcher; + private $arrayMatcher; - public function __construct(ValueMatcher $matcher) + public function __construct(ArrayMatcher $arrayMatcher) { - $this->matcher = $matcher; + $this->arrayMatcher = $arrayMatcher; } public function match($value, $pattern) : bool @@ -22,19 +23,26 @@ public function match($value, $pattern) : bool } if (!Json::isValid($value)) { - $this->error = \sprintf('Invalid given JSON of value. %s', $this->getErrorMessage()); + $this->error = \sprintf('Invalid given JSON of value. %s', Json::getErrorMessage()); return false; } if (!Json::isValidPattern($pattern)) { - $this->error = \sprintf('Invalid given JSON of pattern. %s', $this->getErrorMessage()); + $this->error = \sprintf('Invalid given JSON of pattern. %s', Json::getErrorMessage()); return false; } $transformedPattern = Json::transformPattern($pattern); - $match = $this->matcher->match(\json_decode($value, true), \json_decode($transformedPattern, true)); + + $match = $this->arrayMatcher->match(\json_decode($value, true), \json_decode($transformedPattern, true)); + if (!$match) { - $this->error = $this->matcher->getError(); + $this->error = \sprintf( + 'Value %s does not match pattern %s', + new StringConverter($value), + new StringConverter($pattern) + ); + return false; } @@ -45,22 +53,4 @@ public function canMatch($pattern) : bool { return Json::isValidPattern($pattern); } - - private function getErrorMessage() - { - switch (\json_last_error()) { - case JSON_ERROR_DEPTH: - return 'Maximum stack depth exceeded'; - case JSON_ERROR_STATE_MISMATCH: - return 'Underflow or the modes mismatch'; - case JSON_ERROR_CTRL_CHAR: - return 'Unexpected control character found'; - case JSON_ERROR_SYNTAX: - return 'Syntax error, malformed JSON'; - case JSON_ERROR_UTF8: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - default: - return 'Unknown error'; - } - } } diff --git a/src/Matcher/JsonObjectMatcher.php b/src/Matcher/JsonObjectMatcher.php index ad844eae..499b8b32 100644 --- a/src/Matcher/JsonObjectMatcher.php +++ b/src/Matcher/JsonObjectMatcher.php @@ -25,7 +25,7 @@ public function match($value, $pattern) : bool } if (!Json::isValid($value) && !\is_null($value) && !\is_array($value)) { - $this->error = \sprintf('Invalid given JSON of value. %s', $this->getErrorMessage()); + $this->error = \sprintf('Invalid given JSON of value. %s', Json::getErrorMessage()); return false; } @@ -61,22 +61,4 @@ private function allExpandersMatch($value, $pattern) return true; } - - private function getErrorMessage() - { - switch (\json_last_error()) { - case JSON_ERROR_DEPTH: - return 'Maximum stack depth exceeded'; - case JSON_ERROR_STATE_MISMATCH: - return 'Underflow or the modes mismatch'; - case JSON_ERROR_CTRL_CHAR: - return 'Unexpected control character found'; - case JSON_ERROR_SYNTAX: - return 'Syntax error, malformed JSON'; - case JSON_ERROR_UTF8: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - default: - return 'Unknown error'; - } - } } diff --git a/src/Matcher/Pattern/Assert/Json.php b/src/Matcher/Pattern/Assert/Json.php index 2e5303cb..f610fde8 100644 --- a/src/Matcher/Pattern/Assert/Json.php +++ b/src/Matcher/Pattern/Assert/Json.php @@ -44,4 +44,22 @@ public static function transformPattern(string $pattern) : string ) ); } + + public static function getErrorMessage() + { + switch (\json_last_error()) { + case JSON_ERROR_DEPTH: + return 'Maximum stack depth exceeded'; + case JSON_ERROR_STATE_MISMATCH: + return 'Underflow or the modes mismatch'; + case JSON_ERROR_CTRL_CHAR: + return 'Unexpected control character found'; + case JSON_ERROR_SYNTAX: + return 'Syntax error, malformed JSON'; + case JSON_ERROR_UTF8: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + default: + return 'Unknown error'; + } + } } diff --git a/src/Matcher/Pattern/Expander/Repeat.php b/src/Matcher/Pattern/Expander/Repeat.php index 837898aa..a5658d7d 100644 --- a/src/Matcher/Pattern/Expander/Repeat.php +++ b/src/Matcher/Pattern/Expander/Repeat.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\Matcher\Pattern\Expander; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\Matcher\Pattern\PatternExpander; use Coduo\ToString\StringConverter; @@ -55,7 +55,7 @@ public function match($values) : bool return false; } - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $matcher = $factory->createMatcher(); if ($this->isScalar) { diff --git a/src/Matcher/XmlMatcher.php b/src/Matcher/XmlMatcher.php index 90802d2c..4824f2e9 100644 --- a/src/Matcher/XmlMatcher.php +++ b/src/Matcher/XmlMatcher.php @@ -5,15 +5,16 @@ namespace Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\Matcher\Pattern\Assert\Xml; +use Coduo\ToString\StringConverter; use LSS\XML2Array; final class XmlMatcher extends Matcher { - private $matcher; + private $arrayMatcher; - public function __construct(ValueMatcher $matcher) + public function __construct(ArrayMatcher $arrayMatcher) { - $this->matcher = $matcher; + $this->arrayMatcher = $arrayMatcher; } public function match($value, $pattern) : bool @@ -29,9 +30,14 @@ public function match($value, $pattern) : bool $arrayValue = XML2Array::createArray($value); $arrayPattern = XML2Array::createArray($pattern); - $match = $this->matcher->match($arrayValue, $arrayPattern); + $match = $this->arrayMatcher->match($arrayValue, $arrayPattern); if (!$match) { - $this->error = $this->matcher->getError(); + $this->error = \sprintf( + 'Value %s does not match pattern %s', + new StringConverter($value), + new StringConverter($pattern) + ); + return false; } diff --git a/src/PHPMatcher.php b/src/PHPMatcher.php index 9b24e288..4088cb80 100644 --- a/src/PHPMatcher.php +++ b/src/PHPMatcher.php @@ -4,13 +4,13 @@ namespace Coduo\PHPMatcher; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; final class PHPMatcher { public static function match($value, $pattern, string &$error = null) : bool { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $matcher = $factory->createMatcher(); if (!$matcher->match($value, $pattern)) { diff --git a/src/PHPUnit/PHPMatcherConstraint.php b/src/PHPUnit/PHPMatcherConstraint.php index 235f755d..caf76cd6 100644 --- a/src/PHPUnit/PHPMatcherConstraint.php +++ b/src/PHPUnit/PHPMatcherConstraint.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\PHPUnit; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Util\Json; @@ -54,7 +54,7 @@ protected function matches($value) : bool private function createMatcher() : Matcher { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); return $factory->createMatcher(); } diff --git a/tests/EmptyPatternsTest.php b/tests/EmptyPatternsTest.php index bca7cc45..dc652874 100644 --- a/tests/EmptyPatternsTest.php +++ b/tests/EmptyPatternsTest.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\Tests; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\PHPMatcher; use PHPUnit\Framework\TestCase; @@ -18,7 +18,7 @@ final class EmptyPatternsTest extends TestCase public function setUp() : void { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $this->matcher = $factory->createMatcher(); } diff --git a/tests/ExpandersTest.php b/tests/ExpandersTest.php index e37edc03..7dd8871d 100644 --- a/tests/ExpandersTest.php +++ b/tests/ExpandersTest.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\Tests; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\PHPMatcher; use PHPUnit\Framework\TestCase; @@ -18,7 +18,7 @@ final class ExpandersTest extends TestCase public function setUp() : void { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $this->matcher = $factory->createMatcher(); } diff --git a/tests/Matcher/JsonMatcherTest.php b/tests/Matcher/JsonMatcherTest.php index 692984ef..d727e23d 100644 --- a/tests/Matcher/JsonMatcherTest.php +++ b/tests/Matcher/JsonMatcherTest.php @@ -31,10 +31,9 @@ public function setUp() : void new Matcher\ScalarMatcher(), new Matcher\WildcardMatcher(), ]); - $this->matcher = new Matcher\JsonMatcher(new Matcher\ChainMatcher([ - $scalarMatchers, + $this->matcher = new Matcher\JsonMatcher( new Matcher\ArrayMatcher($scalarMatchers, $parser) - ])); + ); } /** @@ -93,7 +92,7 @@ public function test_error_when_matching_fail() ]); $this->assertFalse($this->matcher->match($value, $pattern)); - $this->assertEquals($this->matcher->getError(), '"MichaƂ" does not match "@boolean@".'); + $this->assertEquals($this->matcher->getError(), 'Value {"users":[{"name":"Norbert"},{"name":"Micha\u0142"}]} does not match pattern {"users":[{"name":"@string@"},{"name":"@boolean@"}]}'); } public function test_error_when_path_in_nested_pattern_does_not_exist() @@ -103,7 +102,7 @@ public function test_error_when_path_in_nested_pattern_does_not_exist() $this->assertFalse($this->matcher->match($value, $pattern)); - $this->assertEquals($this->matcher->getError(), 'There is no element under path [foo][bar][baz] in pattern.'); + $this->assertEquals($this->matcher->getError(), 'Value {"foo":{"bar":{"baz":"bar value"}}} does not match pattern {"foo":{"bar":{"faz":"faz value"}}}'); } public function test_error_when_path_in_nested_value_does_not_exist() @@ -113,7 +112,7 @@ public function test_error_when_path_in_nested_value_does_not_exist() $this->assertFalse($this->matcher->match($value, $pattern)); - $this->assertEquals($this->matcher->getError(), 'There is no element under path [foo][bar][faz] in value.'); + $this->assertEquals($this->matcher->getError(), 'Value {"foo":{"bar":[]}} does not match pattern {"foo":{"bar":{"faz":"faz value"}}}'); } public function test_error_when_json_pattern_is_invalid() diff --git a/tests/Matcher/OrMatcherTest.php b/tests/Matcher/OrMatcherTest.php index ec9b5964..4c472b00 100644 --- a/tests/Matcher/OrMatcherTest.php +++ b/tests/Matcher/OrMatcherTest.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\Tests\Matcher; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use PHPUnit\Framework\TestCase; @@ -17,7 +17,7 @@ class OrMatcherTest extends TestCase public function setUp() : void { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $this->matcher = $factory->createMatcher(); } diff --git a/tests/Matcher/XmlMatcherTest.php b/tests/Matcher/XmlMatcherTest.php index bd62e7f2..88234b3f 100644 --- a/tests/Matcher/XmlMatcherTest.php +++ b/tests/Matcher/XmlMatcherTest.php @@ -33,12 +33,7 @@ public function setUp() : void ]); $this->matcher = new Matcher\XmlMatcher( - new Matcher\ChainMatcher( - [ - $scalarMatchers, - new Matcher\ArrayMatcher($scalarMatchers, $parser) - ] - ) + new Matcher\ArrayMatcher($scalarMatchers, $parser) ); } diff --git a/tests/OrMatcherTest.php b/tests/OrMatcherTest.php index 605fb978..5b7b1cd3 100644 --- a/tests/OrMatcherTest.php +++ b/tests/OrMatcherTest.php @@ -4,7 +4,7 @@ namespace Coduo\PHPMatcher\Tests; -use Coduo\PHPMatcher\Factory\SimpleFactory; +use Coduo\PHPMatcher\Factory\MatcherFactory; use Coduo\PHPMatcher\Matcher; use Coduo\PHPMatcher\PHPMatcher; use PHPUnit\Framework\TestCase; @@ -18,7 +18,7 @@ final class OrMatcherTest extends TestCase public function setUp() : void { - $factory = new SimpleFactory(); + $factory = new MatcherFactory(); $this->matcher = $factory->createMatcher(); }