Skip to content

Commit

Permalink
Merge pull request #49 from norzechowicz/fix-text-matcher-null
Browse files Browse the repository at this point in the history
Ignore strings that can be matched by other matchers in TextMatcher
  • Loading branch information
Norbert Orzechowicz committed Jan 26, 2015
2 parents cb81445 + abdf429 commit 272f536
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 52 deletions.
15 changes: 15 additions & 0 deletions src/Coduo/PHPMatcher/Exception/UnknownTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,19 @@

class UnknownTypeException extends Exception
{
private $type;

public function __construct($type)
{
$this->type = "@" . $type . "@";
parent::__construct(sprintf("Type pattern \"%s\" is not supported.", $this->type), 0, null);
}

/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
}
36 changes: 6 additions & 30 deletions src/Coduo/PHPMatcher/Matcher/JsonMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

namespace Coduo\PHPMatcher\Matcher;

use Coduo\PHPMatcher\Matcher\Pattern\Assert\Json;

class JsonMatcher extends Matcher
{
const TRANSFORM_QUOTATION_PATTERN = '/([^"])@([a-zA-Z0-9\.]+)@([^"])/';
const TRANSFORM_QUOTATION_REPLACEMENT = '$1"@$2@"$3';

/**
* @var
*/
Expand All @@ -25,12 +24,12 @@ public function __construct(ValueMatcher $matcher)
*/
public function match($value, $pattern)
{
if (!is_string($value) || !$this->isValidJson($value)) {
if (!Json::isValid($value)) {
return false;
}

$pattern = $this->transformPattern($pattern);
$match = $this->matcher->match(json_decode($value, true), json_decode($pattern, true));
$transformedPattern = Json::transformPattern($pattern);
$match = $this->matcher->match(json_decode($value, true), json_decode($transformedPattern, true));
if (!$match) {
$this->error = $this->matcher->getError();
return false;
Expand All @@ -44,29 +43,6 @@ public function match($value, $pattern)
*/
public function canMatch($pattern)
{
if (!is_string($pattern)) {
return false;
}

return $this->isValidJson($this->transformPattern($pattern));
return Json::isValidPattern($pattern);
}

private function isValidJson($string)
{
@json_decode($string, true);

return (json_last_error() === JSON_ERROR_NONE);
}

/**
* Wraps placeholders which arent wrapped with quotes yet
*
* @param $pattern
* @return mixed
*/
private function transformPattern($pattern)
{
return preg_replace(self::TRANSFORM_QUOTATION_PATTERN, self::TRANSFORM_QUOTATION_REPLACEMENT, $pattern);
}

}
52 changes: 52 additions & 0 deletions src/Coduo/PHPMatcher/Matcher/Pattern/Assert/Json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Coduo\PHPMatcher\Matcher\Pattern\Assert;

class Json
{
const TRANSFORM_QUOTATION_PATTERN = '/([^"])@([a-zA-Z0-9\.]+)@([^"])/';
const TRANSFORM_QUOTATION_REPLACEMENT = '$1"@$2@"$3';

/**
* @param string $value
* @return bool
*/
public static function isValid($value)
{
if (!is_string($value)) {
return false;
}

if (null === json_decode($value) && JSON_ERROR_NONE !== json_last_error()) {
return false;
}

return true;
}

/**
* Before checking json it wraps type patterns (@type@) with quotes ("@type@")
*
* @param string $value
* @return bool
*/
public static function isValidPattern($value)
{
if (!is_string($value)) {
return false;
}

return self::isValid(self::transformPattern($value));
}

/**
* Wraps placeholders which arent wrapped with quotes yet
*
* @param $pattern
* @return mixed
*/
public static function transformPattern($pattern)
{
return preg_replace(self::TRANSFORM_QUOTATION_PATTERN, self::TRANSFORM_QUOTATION_REPLACEMENT, $pattern);
}
}
24 changes: 24 additions & 0 deletions src/Coduo/PHPMatcher/Matcher/Pattern/Assert/Xml.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Coduo\PHPMatcher\Matcher\Pattern\Assert;

class Xml
{
/**
* @param $value
* @return bool
*/
public static function isValid($value)
{
if (!is_string($value)) {
return false;

}
$xml = @simplexml_load_string($value);
if (!$xml instanceof \SimpleXMLElement) {
return false;
}

return true;
}
}
6 changes: 3 additions & 3 deletions src/Coduo/PHPMatcher/Matcher/Pattern/RegexConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

class RegexConverter
{
public function toRegex(TypePattern $type)
public function toRegex(TypePattern $typePattern)
{
switch ($type->getType()) {
switch ($typePattern->getType()) {
case 'string':
case 'wildcard':
case '*':
Expand All @@ -20,7 +20,7 @@ public function toRegex(TypePattern $type)
case 'double':
return "(\\-?[0-9]*[\\.|\\,][0-9]*)";
default:
throw new UnknownTypeException();
throw new UnknownTypeException($typePattern->getType());
}
}
}
18 changes: 17 additions & 1 deletion src/Coduo/PHPMatcher/Matcher/TextMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Coduo\PHPMatcher\Matcher;

use Coduo\PHPMatcher\Exception\UnknownTypeException;
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Json;
use Coduo\PHPMatcher\Matcher\Pattern\Assert\Xml;
use Coduo\PHPMatcher\Matcher\Pattern\TypePattern;
use Coduo\PHPMatcher\Parser;
use Coduo\PHPMatcher\Matcher\Pattern\RegexConverter;
Expand Down Expand Up @@ -46,7 +49,12 @@ public function match($value, $pattern)
$patternRegex = $pattern;
$patternsReplacedWithRegex = $this->replaceTypePatternsWithPlaceholders($patternRegex);
$patternRegex = $this->prepareRegex($patternRegex);
$patternRegex = $this->replacePlaceholderWithPatternRegexes($patternRegex, $patternsReplacedWithRegex);
try {
$patternRegex = $this->replacePlaceholderWithPatternRegexes($patternRegex, $patternsReplacedWithRegex);
} catch (UnknownTypeException $exception) {
$this->error = sprintf(sprintf("Type pattern \"%s\" is not supported by TextMatcher.", $exception->getType()));
return false;
}

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

if (Json::isValidPattern($pattern)) {
return false;
}

if (Xml::isValid($pattern)) {
return false;
}

return true;
}

Expand Down
21 changes: 3 additions & 18 deletions src/Coduo/PHPMatcher/Matcher/XmlMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Coduo\PHPMatcher\Matcher;

use Coduo\PHPMatcher\Matcher\Pattern\Assert\Xml;
use LSS\XML2Array;

class XmlMatcher extends Matcher
Expand All @@ -24,7 +25,7 @@ public function __construct(ValueMatcher $matcher)
*/
public function match($value, $pattern)
{
if (!is_string($value) || !$this->isValidXml($value) || !$this->isValidXml($pattern)) {
if (!Xml::isValid($value) || !Xml::isValid($pattern)) {
return false;
}

Expand All @@ -45,22 +46,6 @@ public function match($value, $pattern)
*/
public function canMatch($pattern)
{
if (!is_string($pattern)) {
return false;
}

return $this->isValidXml($pattern);
}

private function isValidXml($string)
{
$xml = @simplexml_load_string($string);

if (!$xml instanceof \SimpleXMLElement) {

return false;
}

return true;
return Xml::isValid($pattern);
}
}
42 changes: 42 additions & 0 deletions tests/Coduo/PHPMatcher/Matcher/TextMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,48 @@ public function test_positive_matches($value, $pattern, $expectedResult)
$this->assertEquals($expectedResult, $this->matcher->match($value, $pattern));
}

public function test_ignore_valid_json_patterns()
{
$jsonPattern = json_encode(array(
'users' => array(
array('id' => '@number@', 'name' => 'Norbert'),
array('id' => '@number@', 'name' => 'Michal')
)
));

$this->assertFalse($this->matcher->canMatch($jsonPattern));
}

public function test_ignore_valid_xml_patterns()
{
$xmlPattern = <<<XML
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:GetStockPrice>
<m:StockName>@string@</m:StockName>
<m:StockValue>Any Value</m:StockValue>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
XML;

$this->assertFalse($this->matcher->canMatch($xmlPattern));
}

public function test_error_when_unsupported_type_pattern_used()
{
$pattern = "lorem ipsum @null@ bla bla";
$value = "lorem ipsum bla bla";

$this->assertFalse($this->matcher->match($value, $pattern));
$this->assertSame("Type pattern \"@null@\" is not supported by TextMatcher.", $this->matcher->getError());
}

public function matchingData()
{
return array(
Expand Down
10 changes: 10 additions & 0 deletions tests/Coduo/PHPMatcher/MatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ public function test_text_matcher()
$this->assertTrue(match($value, $pattern));
}


public function test_error_when_json_value_does_not_match_json_pattern()
{
$pattern = '{"a": @null@, "b": 4}';
$value = '{"a": null, "b": 5}';

$this->assertFalse($this->matcher->match($value, $pattern));
$this->assertSame('"5" does not match "4".', $this->matcher->getError());
}

public function test_matcher_with_captures()
{
$this->assertTrue($this->matcher->match(
Expand Down

0 comments on commit 272f536

Please sign in to comment.