Skip to content

Commit 272f536

Browse files
author
Norbert Orzechowicz
committed
Merge pull request #49 from norzechowicz/fix-text-matcher-null
Ignore strings that can be matched by other matchers in TextMatcher
2 parents cb81445 + abdf429 commit 272f536

File tree

9 files changed

+172
-52
lines changed

9 files changed

+172
-52
lines changed

src/Coduo/PHPMatcher/Exception/UnknownTypeException.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,19 @@
44

55
class UnknownTypeException extends Exception
66
{
7+
private $type;
8+
9+
public function __construct($type)
10+
{
11+
$this->type = "@" . $type . "@";
12+
parent::__construct(sprintf("Type pattern \"%s\" is not supported.", $this->type), 0, null);
13+
}
14+
15+
/**
16+
* @return mixed
17+
*/
18+
public function getType()
19+
{
20+
return $this->type;
21+
}
722
}

src/Coduo/PHPMatcher/Matcher/JsonMatcher.php

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
namespace Coduo\PHPMatcher\Matcher;
44

5+
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Json;
6+
57
class JsonMatcher extends Matcher
68
{
7-
const TRANSFORM_QUOTATION_PATTERN = '/([^"])@([a-zA-Z0-9\.]+)@([^"])/';
8-
const TRANSFORM_QUOTATION_REPLACEMENT = '$1"@$2@"$3';
9-
109
/**
1110
* @var
1211
*/
@@ -25,12 +24,12 @@ public function __construct(ValueMatcher $matcher)
2524
*/
2625
public function match($value, $pattern)
2726
{
28-
if (!is_string($value) || !$this->isValidJson($value)) {
27+
if (!Json::isValid($value)) {
2928
return false;
3029
}
3130

32-
$pattern = $this->transformPattern($pattern);
33-
$match = $this->matcher->match(json_decode($value, true), json_decode($pattern, true));
31+
$transformedPattern = Json::transformPattern($pattern);
32+
$match = $this->matcher->match(json_decode($value, true), json_decode($transformedPattern, true));
3433
if (!$match) {
3534
$this->error = $this->matcher->getError();
3635
return false;
@@ -44,29 +43,6 @@ public function match($value, $pattern)
4443
*/
4544
public function canMatch($pattern)
4645
{
47-
if (!is_string($pattern)) {
48-
return false;
49-
}
50-
51-
return $this->isValidJson($this->transformPattern($pattern));
46+
return Json::isValidPattern($pattern);
5247
}
53-
54-
private function isValidJson($string)
55-
{
56-
@json_decode($string, true);
57-
58-
return (json_last_error() === JSON_ERROR_NONE);
59-
}
60-
61-
/**
62-
* Wraps placeholders which arent wrapped with quotes yet
63-
*
64-
* @param $pattern
65-
* @return mixed
66-
*/
67-
private function transformPattern($pattern)
68-
{
69-
return preg_replace(self::TRANSFORM_QUOTATION_PATTERN, self::TRANSFORM_QUOTATION_REPLACEMENT, $pattern);
70-
}
71-
7248
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Coduo\PHPMatcher\Matcher\Pattern\Assert;
4+
5+
class Json
6+
{
7+
const TRANSFORM_QUOTATION_PATTERN = '/([^"])@([a-zA-Z0-9\.]+)@([^"])/';
8+
const TRANSFORM_QUOTATION_REPLACEMENT = '$1"@$2@"$3';
9+
10+
/**
11+
* @param string $value
12+
* @return bool
13+
*/
14+
public static function isValid($value)
15+
{
16+
if (!is_string($value)) {
17+
return false;
18+
}
19+
20+
if (null === json_decode($value) && JSON_ERROR_NONE !== json_last_error()) {
21+
return false;
22+
}
23+
24+
return true;
25+
}
26+
27+
/**
28+
* Before checking json it wraps type patterns (@type@) with quotes ("@type@")
29+
*
30+
* @param string $value
31+
* @return bool
32+
*/
33+
public static function isValidPattern($value)
34+
{
35+
if (!is_string($value)) {
36+
return false;
37+
}
38+
39+
return self::isValid(self::transformPattern($value));
40+
}
41+
42+
/**
43+
* Wraps placeholders which arent wrapped with quotes yet
44+
*
45+
* @param $pattern
46+
* @return mixed
47+
*/
48+
public static function transformPattern($pattern)
49+
{
50+
return preg_replace(self::TRANSFORM_QUOTATION_PATTERN, self::TRANSFORM_QUOTATION_REPLACEMENT, $pattern);
51+
}
52+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Coduo\PHPMatcher\Matcher\Pattern\Assert;
4+
5+
class Xml
6+
{
7+
/**
8+
* @param $value
9+
* @return bool
10+
*/
11+
public static function isValid($value)
12+
{
13+
if (!is_string($value)) {
14+
return false;
15+
16+
}
17+
$xml = @simplexml_load_string($value);
18+
if (!$xml instanceof \SimpleXMLElement) {
19+
return false;
20+
}
21+
22+
return true;
23+
}
24+
}

src/Coduo/PHPMatcher/Matcher/Pattern/RegexConverter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
class RegexConverter
88
{
9-
public function toRegex(TypePattern $type)
9+
public function toRegex(TypePattern $typePattern)
1010
{
11-
switch ($type->getType()) {
11+
switch ($typePattern->getType()) {
1212
case 'string':
1313
case 'wildcard':
1414
case '*':
@@ -20,7 +20,7 @@ public function toRegex(TypePattern $type)
2020
case 'double':
2121
return "(\\-?[0-9]*[\\.|\\,][0-9]*)";
2222
default:
23-
throw new UnknownTypeException();
23+
throw new UnknownTypeException($typePattern->getType());
2424
}
2525
}
2626
}

src/Coduo/PHPMatcher/Matcher/TextMatcher.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Coduo\PHPMatcher\Matcher;
44

5+
use Coduo\PHPMatcher\Exception\UnknownTypeException;
6+
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Json;
7+
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Xml;
58
use Coduo\PHPMatcher\Matcher\Pattern\TypePattern;
69
use Coduo\PHPMatcher\Parser;
710
use Coduo\PHPMatcher\Matcher\Pattern\RegexConverter;
@@ -46,7 +49,12 @@ public function match($value, $pattern)
4649
$patternRegex = $pattern;
4750
$patternsReplacedWithRegex = $this->replaceTypePatternsWithPlaceholders($patternRegex);
4851
$patternRegex = $this->prepareRegex($patternRegex);
49-
$patternRegex = $this->replacePlaceholderWithPatternRegexes($patternRegex, $patternsReplacedWithRegex);
52+
try {
53+
$patternRegex = $this->replacePlaceholderWithPatternRegexes($patternRegex, $patternsReplacedWithRegex);
54+
} catch (UnknownTypeException $exception) {
55+
$this->error = sprintf(sprintf("Type pattern \"%s\" is not supported by TextMatcher.", $exception->getType()));
56+
return false;
57+
}
5058

5159
if (!preg_match($patternRegex, $value, $matchedValues)) {
5260
$this->error = sprintf("\"%s\" does not match \"%s\" pattern", $value, $pattern);
@@ -79,6 +87,14 @@ public function canMatch($pattern)
7987
return false;
8088
}
8189

90+
if (Json::isValidPattern($pattern)) {
91+
return false;
92+
}
93+
94+
if (Xml::isValid($pattern)) {
95+
return false;
96+
}
97+
8298
return true;
8399
}
84100

src/Coduo/PHPMatcher/Matcher/XmlMatcher.php

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Coduo\PHPMatcher\Matcher;
44

5+
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Xml;
56
use LSS\XML2Array;
67

78
class XmlMatcher extends Matcher
@@ -24,7 +25,7 @@ public function __construct(ValueMatcher $matcher)
2425
*/
2526
public function match($value, $pattern)
2627
{
27-
if (!is_string($value) || !$this->isValidXml($value) || !$this->isValidXml($pattern)) {
28+
if (!Xml::isValid($value) || !Xml::isValid($pattern)) {
2829
return false;
2930
}
3031

@@ -45,22 +46,6 @@ public function match($value, $pattern)
4546
*/
4647
public function canMatch($pattern)
4748
{
48-
if (!is_string($pattern)) {
49-
return false;
50-
}
51-
52-
return $this->isValidXml($pattern);
53-
}
54-
55-
private function isValidXml($string)
56-
{
57-
$xml = @simplexml_load_string($string);
58-
59-
if (!$xml instanceof \SimpleXMLElement) {
60-
61-
return false;
62-
}
63-
64-
return true;
49+
return Xml::isValid($pattern);
6550
}
6651
}

tests/Coduo/PHPMatcher/Matcher/TextMatcherTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,48 @@ public function test_positive_matches($value, $pattern, $expectedResult)
4545
$this->assertEquals($expectedResult, $this->matcher->match($value, $pattern));
4646
}
4747

48+
public function test_ignore_valid_json_patterns()
49+
{
50+
$jsonPattern = json_encode(array(
51+
'users' => array(
52+
array('id' => '@number@', 'name' => 'Norbert'),
53+
array('id' => '@number@', 'name' => 'Michal')
54+
)
55+
));
56+
57+
$this->assertFalse($this->matcher->canMatch($jsonPattern));
58+
}
59+
60+
public function test_ignore_valid_xml_patterns()
61+
{
62+
$xmlPattern = <<<XML
63+
<?xml version="1.0"?>
64+
<soap:Envelope
65+
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
66+
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
67+
68+
<soap:Body xmlns:m="http://www.example.org/stock">
69+
<m:GetStockPrice>
70+
<m:StockName>@string@</m:StockName>
71+
<m:StockValue>Any Value</m:StockValue>
72+
</m:GetStockPrice>
73+
</soap:Body>
74+
75+
</soap:Envelope>
76+
XML;
77+
78+
$this->assertFalse($this->matcher->canMatch($xmlPattern));
79+
}
80+
81+
public function test_error_when_unsupported_type_pattern_used()
82+
{
83+
$pattern = "lorem ipsum @null@ bla bla";
84+
$value = "lorem ipsum bla bla";
85+
86+
$this->assertFalse($this->matcher->match($value, $pattern));
87+
$this->assertSame("Type pattern \"@null@\" is not supported by TextMatcher.", $this->matcher->getError());
88+
}
89+
4890
public function matchingData()
4991
{
5092
return array(

tests/Coduo/PHPMatcher/MatcherTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,16 @@ public function test_text_matcher()
203203
$this->assertTrue(match($value, $pattern));
204204
}
205205

206+
207+
public function test_error_when_json_value_does_not_match_json_pattern()
208+
{
209+
$pattern = '{"a": @null@, "b": 4}';
210+
$value = '{"a": null, "b": 5}';
211+
212+
$this->assertFalse($this->matcher->match($value, $pattern));
213+
$this->assertSame('"5" does not match "4".', $this->matcher->getError());
214+
}
215+
206216
public function test_matcher_with_captures()
207217
{
208218
$this->assertTrue($this->matcher->match(

0 commit comments

Comments
 (0)