Skip to content

Commit b817283

Browse files
committed
Merge pull request #2 from norzechowicz/dev
JsonMatcher and some smaller fixes
2 parents 0ea5895 + a5c3914 commit b817283

File tree

10 files changed

+280
-71
lines changed

10 files changed

+280
-71
lines changed

src/JsonMatcher/Matcher/ArrayMatcher.php

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Symfony\Component\PropertyAccess\PropertyAccess;
66
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
7+
use Symfony\Component\PropertyAccess\PropertyAccessor;
78

89
class ArrayMatcher implements PropertyMatcher
910
{
@@ -14,6 +15,11 @@ class ArrayMatcher implements PropertyMatcher
1415

1516
private $paths;
1617

18+
/**
19+
* @var PropertyAccessor
20+
*/
21+
private $accessor;
22+
1723
public function __construct(PropertyMatcher $propertyMatcher)
1824
{
1925
$this->propertyMatcher = $propertyMatcher;
@@ -24,60 +30,94 @@ public function __construct(PropertyMatcher $propertyMatcher)
2430
*/
2531
public function match($value, $pattern)
2632
{
27-
$accessorBuilder = PropertyAccess::createPropertyAccessorBuilder();
28-
$accessorBuilder->enableExceptionOnInvalidIndex();
29-
$accessor = $accessorBuilder->getPropertyAccessor();
33+
if (!is_array($value)) {
34+
return false;
35+
}
36+
37+
if (false === $this->iterateMatch($value, $pattern)) {
38+
return false;
39+
}
40+
41+
return true;
42+
}
3043

31-
$this->paths = array();
44+
/**
45+
* {@inheritDoc}
46+
*/
47+
public function canMatch($pattern)
48+
{
49+
return is_array($pattern);
50+
}
51+
52+
/**
53+
* @param array $value
54+
* @param array $pattern
55+
* @return bool
56+
*/
57+
private function iterateMatch(array $value, array $pattern)
58+
{
3259
foreach ($value as $key => $element) {
3360
$path = sprintf("[%s]", $key);
3461

35-
if (is_array($element)) {
36-
$this->buildPath($element, $path);
37-
continue;
62+
if (!$this->hasValue($pattern, $path)) {
63+
return false;
64+
}
65+
$elementPattern = $this->getValue($pattern, $path);
66+
if ($this->propertyMatcher->canMatch($elementPattern)) {
67+
if (true === $this->propertyMatcher->match($element, $elementPattern)) {
68+
continue;
69+
}
3870
}
3971

40-
$this->paths[] = $path;
41-
}
42-
43-
foreach ($this->paths as $path) {
44-
$elementValue = $accessor->getValue($value, $path);
45-
try {
46-
$patternValue = $accessor->getValue($pattern, $path);
47-
} catch (NoSuchIndexException $e) {
72+
if (!is_array($element)) {
4873
return false;
4974
}
5075

51-
if ($this->propertyMatcher->canMatch($patternValue)) {
52-
if (false === $this->propertyMatcher->match($elementValue, $patternValue)) {
53-
return false;
54-
}
76+
if (false === $this->iterateMatch($element, $elementPattern)) {
77+
return false;
5578
}
79+
}
80+
}
5681

82+
/**
83+
* @param $array
84+
* @param $path
85+
* @return bool
86+
*/
87+
private function hasValue($array, $path)
88+
{
89+
try {
90+
$this->getPropertyAccessor()->getValue($array, $path);
91+
} catch (NoSuchIndexException $e) {
92+
return false;
5793
}
5894

5995
return true;
6096
}
6197

6298
/**
63-
* {@inheritDoc}
99+
* @param $array
100+
* @param $path
101+
* @return mixed
64102
*/
65-
public function canMatch($pattern)
103+
private function getValue($array, $path)
66104
{
67-
return is_array($pattern);
105+
return $this->getPropertyAccessor()->getValue($array, $path);
68106
}
69107

70-
private function buildPath(array $array, $parentPath)
108+
/**
109+
* @return \Symfony\Component\PropertyAccess\PropertyAccessorInterface
110+
*/
111+
private function getPropertyAccessor()
71112
{
72-
foreach ($array as $key => $element) {
73-
$path = sprintf("%s[%s]", $parentPath, $key);
113+
if (isset($this->accessor)) {
114+
return $this->accessor;
115+
}
74116

75-
if (is_array($element)) {
76-
$this->buildPath($element, $path);
77-
continue;
78-
}
117+
$accessorBuilder = PropertyAccess::createPropertyAccessorBuilder();
118+
$accessorBuilder->enableExceptionOnInvalidIndex();
119+
$this->accessor = $accessorBuilder->getPropertyAccessor();
79120

80-
$this->paths[] = $path;
81-
}
121+
return $this->accessor;
82122
}
83123
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace JsonMatcher\Matcher;
4+
5+
class JsonMatcher implements PropertyMatcher
6+
{
7+
/**
8+
* @var
9+
*/
10+
private $matcher;
11+
12+
/**
13+
* @param PropertyMatcher $matcher
14+
*/
15+
public function __construct(PropertyMatcher $matcher)
16+
{
17+
$this->matcher = $matcher;
18+
}
19+
20+
/**
21+
* {@inheritDoc}
22+
*/
23+
public function match($value, $pattern)
24+
{
25+
if (!is_string($value) || !$this->isValidJson($value)) {
26+
return false;
27+
}
28+
29+
return $this->matcher->match(json_decode($value, true), json_decode($pattern, true));
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
public function canMatch($pattern)
36+
{
37+
return is_string($pattern) && $this->isValidJson($pattern);
38+
}
39+
40+
private function isValidJson($string)
41+
{
42+
@json_decode($string, true);
43+
return (json_last_error() == JSON_ERROR_NONE);
44+
}
45+
}

src/JsonMatcher/Matcher/TypeMatcher.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
class TypeMatcher implements PropertyMatcher
66
{
7-
87
/**
98
* {@inheritDoc}
109
*/
@@ -18,12 +17,11 @@ public function match($value, $pattern)
1817
*/
1918
public function canMatch($pattern)
2019
{
21-
return is_string($pattern) && 0 !== preg_match("/^@(string|integer|boolean|double)@$/", $pattern);
20+
return is_string($pattern) && 0 !== preg_match("/^@(string|integer|boolean|double|array)@$/", $pattern);
2221
}
2322

2423
private function extractType($pattern)
2524
{
2625
return str_replace("@", "", $pattern);
2726
}
28-
2927
}

src/JsonMatcher/Matcher/WildcardMatcher.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function match($matcher, $pattern)
1717
*/
1818
public function canMatch($pattern)
1919
{
20-
return '*' === $pattern;
20+
return is_string($pattern) && 0 !== preg_match("/^@(\*|wildcard)@$/", $pattern);
2121
}
2222

2323
}

src/autoload.php

Lines changed: 0 additions & 26 deletions
This file was deleted.

tests/JsonMatcher/Matcher/ArrayMatcherTest.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,39 @@
44
use JsonMatcher\Matcher\ArrayMatcher;
55
use JsonMatcher\Matcher\ChainMatcher;
66
use JsonMatcher\Matcher\ScalarMatcher;
7+
use JsonMatcher\Matcher\WildcardMatcher;
78

89
class ArrayMatcherTest extends \PHPUnit_Framework_TestCase
910
{
11+
/**
12+
* @var ArrayMatcher
13+
*/
14+
private $matcher;
15+
16+
public function setUp()
17+
{
18+
$this->matcher = new ArrayMatcher(
19+
new ChainMatcher(array(
20+
new ScalarMatcher(),
21+
new WildcardMatcher()
22+
))
23+
);
24+
}
25+
1026
/**
1127
* @dataProvider positiveMatchData
1228
*/
1329
public function test_positive_match_arrays($value, $pattern)
1430
{
15-
$matcher = new ArrayMatcher(new ScalarMatcher());
16-
$this->assertTrue($matcher->match($value, $pattern));
31+
$this->assertTrue($this->matcher->match($value, $pattern));
1732
}
1833

1934
/**
2035
* @dataProvider negativeMatchData
2136
*/
2237
public function test_negative_match_arrays($value, $pattern)
2338
{
24-
$matcher = new ArrayMatcher(new ScalarMatcher());
25-
$this->assertFalse($matcher->match($value, $pattern));
39+
$this->assertFalse($this->matcher->match($value, $pattern));
2640
}
2741

2842
public static function positiveMatchData()
@@ -48,7 +62,8 @@ public static function positiveMatchData()
4862
array($simpleArr, $simpleArr),
4963
array(array(), array()),
5064
array(array('key' => 'val'), array('key' => 'val')),
51-
array(array(1), array(1))
65+
array(array(1), array(1)),
66+
array(array('roles' => array('ROLE_ADMIN', 'ROLE_DEVELOPER')), array('roles' => '@wildcard@'))
5267
);
5368
}
5469

0 commit comments

Comments
 (0)