Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Match expander #35 #101

Closed
wants to merge 3 commits into from
Closed
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
67 changes: 57 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ $matcher->getError(); // returns null or error message
* ``inArray($value)``
* ``oneOf(...$expanders)`` - example usage ``"@[email protected](contains('foo'), contains('bar'), contains('baz'))"``
* ``matchRegex($regex)`` - example usage ``"@[email protected]('/^lorem.+/')"``
* ``match($subPattern)`` - example usage ``"@[email protected]({"id": "@integer@"})"``

##Example usage

Expand All @@ -97,7 +98,7 @@ $factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$matcher->match(1, 1);
$matcher->match('string', 'string')
$matcher->match('string', 'string');
```

### String matching
Expand All @@ -111,7 +112,7 @@ $factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$matcher->match('Norbert', '@string@');
$matcher->match("lorem ipsum dolor", "@[email protected]('lorem').contains('ipsum').endsWith('dolor')")
$matcher->match("lorem ipsum dolor", "@[email protected]('lorem').contains('ipsum').endsWith('dolor')");

```

Expand Down Expand Up @@ -185,12 +186,12 @@ use Coduo\PHPMatcher\Factory\SimpleFactory;
$factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$matcher->match("@integer@", "@*@"),
$matcher->match("foobar", "@*@"),
$matcher->match(true, "@*@"),
$matcher->match(6.66, "@*@"),
$matcher->match(array("bar"), "@wildcard@"),
$matcher->match(new \stdClass, "@wildcard@"),
$matcher->match("@integer@", "@*@");
$matcher->match("foobar", "@*@");
$matcher->match(true, "@*@");
$matcher->match(6.66, "@*@");
$matcher->match(array("bar"), "@wildcard@");
$matcher->match(new \stdClass, "@wildcard@");
```

### Expression matching
Expand Down Expand Up @@ -274,7 +275,7 @@ $matcher->match(
'@boolean@',
'@double@'
)
)
);
```

### Json matching
Expand Down Expand Up @@ -307,7 +308,7 @@ $matcher->match(
}
]
}'
)
);

```

Expand Down Expand Up @@ -355,6 +356,52 @@ XML
);
```

### Nested Object matching

```php

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$matcher->match(<<<JSON
{
"id": 1,
"galleries": [
[
"id": 1,
"cover": null,
"images": [['id': 1], ['id': 2]],
],
[
"id": 1,
"cover": null,
"images": [['id': 1], ['id': 2]],
]
]
}
JSON, <<<JSON
{
"id": "@integer@",
"galleries": '
@[email protected]({
"id": "@integer@",
"cover": \'
@null@||@[email protected]({
"id": "@integer@"
})
\',
"images": \'
@[email protected]({
"id": "@integer@"
})
\'
})
'
}
JSON);

```

Example scenario for api in behat using mongo.
---
``` cucumber
Expand Down
1 change: 0 additions & 1 deletion src/AST/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@

interface Node
{

}
72 changes: 49 additions & 23 deletions src/Factory/SimpleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

class SimpleFactory implements Factory
{
private $parser;

/**
* @return Matcher
*/
Expand All @@ -22,41 +24,61 @@ public function createMatcher()
*/
protected function buildMatchers()
{
$parser = $this->buildParser();
$scalarMatchers = $this->buildScalarMatchers();
$orMatcher = $this->buildOrMatcher();
$orMatcher = $this->buildOrMatcher($scalarMatchers);
$jsonMatcher = $this->buildJsonObjectMatcher($scalarMatchers);
$arrayMatcher = $this->buildArrayMatcher($scalarMatchers, $orMatcher, $jsonMatcher, $parser);

$chainMatcher = new Matcher\ChainMatcher(array(
$scalarMatchers,
$orMatcher,
new Matcher\JsonMatcher($orMatcher),
new Matcher\XmlMatcher($orMatcher),
new Matcher\TextMatcher($scalarMatchers, $this->buildParser())
$jsonMatcher,
$scalarMatchers,
$arrayMatcher,
));

return $chainMatcher;
$decoratedMatcher = new Matcher\ChainMatcher([
$chainMatcher,
new Matcher\JsonMatcher($chainMatcher),
new Matcher\XmlMatcher($chainMatcher),
new Matcher\TextMatcher($chainMatcher, $parser),
]);

return $decoratedMatcher;
}

protected function buildArrayMatcher(
Matcher\ValueMatcher $scalarMatchers,
Matcher\ValueMatcher $orMatcher,
Matcher\ValueMatcher $jsonMatcher,
Parser $parser
)
{
return new Matcher\ArrayMatcher(new Matcher\ChainMatcher([
$orMatcher,
$scalarMatchers,
$jsonMatcher
]), $parser);
}

/**
* @return Matcher\ChainMatcher
* @return Matcher\ValueMatcher
*/
protected function buildOrMatcher()
protected function buildOrMatcher(Matcher\ChainMatcher $scalarMatchers)
{
$scalarMatchers = $this->buildScalarMatchers();
$orMatcher = new Matcher\OrMatcher($scalarMatchers);
$arrayMatcher = new Matcher\ArrayMatcher(
new Matcher\ChainMatcher(array(
$orMatcher,
$scalarMatchers
)),
$this->buildParser()
);
$chainMatcher = new Matcher\ChainMatcher([
$scalarMatchers,
$this->buildJsonObjectMatcher($scalarMatchers)
]);

$chainMatcher = new Matcher\ChainMatcher(array(
$orMatcher,
$arrayMatcher,
));
return new Matcher\OrMatcher($chainMatcher);
}

return $chainMatcher;
protected function buildJsonObjectMatcher(Matcher\ValueMatcher $scalarMatchers)
{
$parser = $this->buildParser();

return new Matcher\JsonObjectMatcher($scalarMatchers, $parser);
}

/**
Expand Down Expand Up @@ -86,6 +108,10 @@ protected function buildScalarMatchers()
*/
protected function buildParser()
{
return new Parser(new Lexer(), new Parser\ExpanderInitializer());
if ($this->parser) {
return $this->parser;
}

return $this->parser = new Parser(new Lexer(), new Parser\ExpanderInitializer());
}
}
91 changes: 91 additions & 0 deletions src/Matcher/JsonObjectMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Coduo\PHPMatcher\Matcher;

use Coduo\PHPMatcher\Parser;
use Coduo\ToString\StringConverter;
use Symfony\Component\PropertyAccess\PropertyAccessor;

final class JsonObjectMatcher extends Matcher
{
const JSON_PATTERN = '@json@';

/**
* @var ValueMatcher
*/
private $propertyMatcher;

/**
* @var PropertyAccessor
*/
private $accessor;

/**
* @var Parser
*/
private $parser;

/**
* @param ValueMatcher $propertyMatcher
*/
public function __construct(ValueMatcher $propertyMatcher, Parser $parser)
{
$this->propertyMatcher = $propertyMatcher;
$this->parser = $parser;
}

/**
* {@inheritDoc}
*/
public function match($value, $pattern)
{
if (!$this->isJsonPattern($pattern)) {
return false;
}

if (!is_array($value)) {
$this->error = sprintf("%s \"%s\" is not a valid array.", gettype($value), new StringConverter($value));
return false;
}

if ($this->isJsonPattern($pattern)) {
return $this->allExpandersMatch($value, $pattern);
}

return true;
}

/**
* {@inheritDoc}
*/
public function canMatch($pattern)
{
return is_string($pattern) && $this->isJsonPattern($pattern);
}

private function isJsonPattern($pattern)
{
if (!is_string($pattern)) {
return false;
}

return $this->parser->hasValidSyntax($pattern) && $this->parser->parse($pattern)->is('json');
}

/**
* @param $value
* @param $pattern
* @return bool
* @throws \Coduo\PHPMatcher\Exception\UnknownExpanderException
*/
private function allExpandersMatch($value, $pattern)
{
$typePattern = $this->parser->parse($pattern);
if (!$typePattern->matchExpanders($value)) {
$this->error = $typePattern->getError();
return false;
}

return true;
}
}
4 changes: 3 additions & 1 deletion src/Matcher/OrMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ public function __construct(ChainMatcher $chainMatcher)
public function match($value, $pattern)
{
$patterns = explode('||', $pattern);
$patterns = array_map('trim', $patterns);

foreach ($patterns as $childPattern) {
if ($this->matchChild($value, $childPattern)){
if ($this->matchChild($value, $childPattern)) {
return true;
}
}
Expand Down
60 changes: 60 additions & 0 deletions src/Matcher/Pattern/Expander/Match.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Coduo\PHPMatcher\Matcher\Pattern\Expander;

use Coduo\PHPMatcher\Factory\SimpleFactory;
use Coduo\PHPMatcher\Matcher\Pattern\PatternExpander;
use Coduo\ToString\StringConverter;

final class Match implements PatternExpander
{
/**
* @var null|string
*/
private $error;

/**
* @var
*/
private $value;

/**
* @param $value
*/
public function __construct($value)
{
$this->value = $value;
}

/**
* @param $value
* @return boolean
*/
public function match($value)
{
if (!is_array($value)) {
$this->error = sprintf("Match expander require \"array\", got \"%s\".", new StringConverter($value));
return false;
}

$match = true;
$matcher = (new SimpleFactory)->createMatcher();
foreach ($value as $singleRowValue) {
if (!$matcher->match($singleRowValue, $this->value)) {
$match = false;
$this->error = $matcher->getError();
}
}
unset($matcher);

return $match;
}

/**
* @return string|null
*/
public function getError()
{
return $this->error;
}
}
Loading