Skip to content

Commit 300c41a

Browse files
JarJaknorberttech
authored andcommitted
Array universal key (#143)
* Array universal key * Remove unwanted Exception * add test and remove dump * revert invalid array key check * remove not needed code samples * Add more tests * Update Readme with Universal Array Key example
1 parent 44ba53e commit 300c41a

File tree

6 files changed

+129
-6
lines changed

6 files changed

+129
-6
lines changed

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,64 @@ $matcher->match(
334334
);
335335
```
336336

337+
### Json matching with unbounded arrays and objects
338+
339+
```php
340+
<?php
341+
342+
use Coduo\PHPMatcher\Factory\SimpleFactory;
343+
344+
$factory = new SimpleFactory();
345+
$matcher = $factory->createMatcher();
346+
347+
$matcher->match(
348+
'{
349+
"users":[
350+
{
351+
"firstName": "Norbert",
352+
"lastName": "Orzechowicz",
353+
"created": "2014-01-01",
354+
"roles":["ROLE_USER", "ROLE_DEVELOPER"]},
355+
"attributes": {
356+
"isAdmin": false,
357+
"dateOfBirth" null,
358+
"hasEmailVerified": true
359+
}
360+
},
361+
{
362+
"firstName": "Michał",
363+
"lastName": "Dąbrowski",
364+
"created": "2014-01-01",
365+
"roles":["ROLE_USER", "ROLE_DEVELOPER", "ROLE_ADMIN"]},
366+
"attributes": {
367+
"isAdmin": true,
368+
"dateOfBirth" null,
369+
"hasEmailVerified": true
370+
}
371+
}
372+
]
373+
}',
374+
'{
375+
"users":[
376+
{
377+
"firstName": @string@,
378+
"lastName": @string@,
379+
"created": "@[email protected]()",
380+
"roles": [
381+
"ROLE_USER",
382+
@...@
383+
],
384+
"attributes": {
385+
"isAdmin": @boolean@,
386+
"@*@": "@*@"
387+
}
388+
}
389+
],
390+
@...@
391+
}'
392+
);
393+
```
394+
337395
### Xml matching
338396

339397
```php

src/Lexer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected function getCatchablePatterns() : array
3232
'\\-?[0-9]*\\.?[0-9]*', // numbers
3333
"'(?:[^']|'')*'", // string between ' character
3434
'"(?:[^"]|"")*"', // string between " character,
35-
'@[a-zA-Z0-9\\*]+@', // type pattern
35+
'@[a-zA-Z0-9\\*.]+@', // type pattern
3636
];
3737
}
3838

src/Matcher/ArrayMatcher.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ final class ArrayMatcher extends Matcher
1515
{
1616
const PATTERN = 'array';
1717
const UNBOUNDED_PATTERN = '@...@';
18+
const UNIVERSAL_KEY = '@*@';
1819

1920
private $propertyMatcher;
2021

@@ -70,18 +71,20 @@ private function iterateMatch(array $values, array $patterns, string $parentPath
7071
foreach ($values as $key => $value) {
7172
$path = $this->formatAccessPath($key);
7273

73-
if ($this->shouldSkippValueMatchingFor($pattern)) {
74+
if ($this->shouldSkipValueMatchingFor($pattern)) {
7475
continue;
7576
}
7677

7778
if ($this->valueExist($path, $patterns)) {
7879
$pattern = $this->getValueByPath($patterns, $path);
80+
} elseif (isset($patterns[self::UNIVERSAL_KEY])) {
81+
$pattern = $patterns[self::UNIVERSAL_KEY];
7982
} else {
8083
$this->setMissingElementInError('pattern', $this->formatFullPath($parentPath, $path));
8184
return false;
8285
}
8386

84-
if ($this->shouldSkippValueMatchingFor($pattern)) {
87+
if ($this->shouldSkipValueMatchingFor($pattern)) {
8588
continue;
8689
}
8790

@@ -138,9 +141,13 @@ function ($item) use ($skipPattern) {
138141
return true;
139142
}
140143

141-
private function findNotExistingKeys(array $pattern, array $values) : array
144+
private function findNotExistingKeys(array $patterns, array $values) : array
142145
{
143-
$notExistingKeys = \array_diff_key($pattern, $values);
146+
if (isset($patterns[self::UNIVERSAL_KEY])) {
147+
return [];
148+
}
149+
150+
$notExistingKeys = \array_diff_key($patterns, $values);
144151

145152
return \array_filter($notExistingKeys, function ($pattern) use ($values) {
146153
if (\is_array($pattern)) {
@@ -230,7 +237,7 @@ private function formatFullPath(string $parentPath, string $path) : string
230237
return \sprintf('%s%s', $parentPath, $path);
231238
}
232239

233-
private function shouldSkippValueMatchingFor($lastPattern) : bool
240+
private function shouldSkipValueMatchingFor($lastPattern) : bool
234241
{
235242
return $lastPattern === self::UNBOUNDED_PATTERN;
236243
}

tests/LexerTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public static function validMatcherTypePatterns()
181181
['@integer@'],
182182
['@number@'],
183183
['@*@'],
184+
['@...@'],
184185
['@wildcard@']
185186
];
186187
}

tests/Matcher/ArrayMatcherTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,39 @@ public static function positiveMatchData()
158158
6.66
159159
];
160160

161+
$simpleArrPatternWithUniversalKey = [
162+
'users' => [
163+
[
164+
'firstName' => '@string@',
165+
Matcher\ArrayMatcher::UNIVERSAL_KEY => '@*@'
166+
],
167+
Matcher\ArrayMatcher::UNBOUNDED_PATTERN
168+
],
169+
true,
170+
false,
171+
1,
172+
6.66
173+
];
174+
175+
$simpleArrPatternWithUniversalKeyAndStringValue = [
176+
'users' => [
177+
[
178+
'firstName' => '@string@',
179+
Matcher\ArrayMatcher::UNIVERSAL_KEY => '@string@'
180+
],
181+
Matcher\ArrayMatcher::UNBOUNDED_PATTERN
182+
],
183+
true,
184+
false,
185+
1,
186+
6.66
187+
];
188+
161189
return [
162190
[$simpleArr, $simpleArr],
163191
[$simpleArr, $simpleArrPattern],
192+
[$simpleArr, $simpleArrPatternWithUniversalKey],
193+
[$simpleArr, $simpleArrPatternWithUniversalKeyAndStringValue],
164194
[[], []],
165195
[['foo' => null], ['foo' => null]],
166196
[['foo' => null], ['foo' => '@null@']],
@@ -224,8 +254,23 @@ public static function negativeMatchData()
224254
6.66
225255
];
226256

257+
$simpleArrPatternWithUniversalKeyAndIntegerValue = [
258+
'users' => [
259+
[
260+
'firstName' => '@string@',
261+
Matcher\ArrayMatcher::UNIVERSAL_KEY => '@integer@'
262+
],
263+
Matcher\ArrayMatcher::UNBOUNDED_PATTERN
264+
],
265+
true,
266+
false,
267+
1,
268+
6.66
269+
];
270+
227271
return [
228272
[$simpleArr, $simpleDiff],
273+
[$simpleArr, $simpleArrPatternWithUniversalKeyAndIntegerValue],
229274
[['status' => 'ok', 'data' => [['foo']]], ['status' => 'ok', 'data' => []]],
230275
[[1], []],
231276
[['key' => 'val'], ['key' => 'val2']],

tests/Matcher/JsonMatcherTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,21 @@ public static function positiveMatches()
200200
'{"users":[{"firstName":"Norbert","lastName":"Orzechowicz","roles":["ROLE_USER", "ROLE_DEVELOPER"]}]}',
201201
'{"users":[{"firstName":"Norbert","lastName":"Orzechowicz","roles":"@wildcard@"}]}'
202202
],
203+
[
204+
'{"users":[{"firstName":"Norbert","lastName":"Orzechowicz","roles":["ROLE_USER", "ROLE_DEVELOPER"]}]}',
205+
'{"users":[{"firstName":"Norbert","@*@":"@*@"}]}'
206+
],
207+
[
208+
'{"users":[{"firstName":"Norbert","lastName":"Orzechowicz","roles":["ROLE_USER", "ROLE_DEVELOPER"]},{}]}',
209+
'{"users":[{"firstName":"Norbert","@*@":"@*@"},@...@]}'
210+
],
203211
[
204212
'[{"name": "Norbert"},{"name":"Michał"},{"name":"Bob"},{"name":"Martin"}]',
205213
'[{"name": "Norbert"},@...@]'
214+
],
215+
[
216+
'[{"name": "Norbert","lastName":"Orzechowicz"},{"name":"Michał"},{"name":"Bob"},{"name":"Martin"}]',
217+
'[{"name": "Norbert","@*@":"@*@"},@...@]'
206218
]
207219
];
208220
}

0 commit comments

Comments
 (0)