Skip to content

Aggregate expanders #31

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

Merged
merged 2 commits into from
Oct 18, 2014
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ $match = $matcher->match("lorem ipsum dolor", "@string@")
* ``lowerThan($boundry)``
* ``greaterThan($boundry)``
* ``inArray($value)``
* ``oneOf(...$expanders)`` - example usage ``"@[email protected](contains('foo'), contains('bar'), contains('baz'))"``

##Example usage

Expand Down
7 changes: 7 additions & 0 deletions src/Coduo/PHPMatcher/Exception/InvalidArgumentException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Coduo\PHPMatcher\Exception;

class InvalidArgumentException extends Exception
{
}
2 changes: 1 addition & 1 deletion src/Coduo/PHPMatcher/Factory/SimpleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ protected function buildScalarMatchers()
*/
protected function buildParser()
{
return new Parser(new Lexer());
return new Parser(new Lexer(), new Parser\ExpanderInitializer());
}
}
54 changes: 54 additions & 0 deletions src/Coduo/PHPMatcher/Matcher/Pattern/Expander/OneOf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Coduo\PHPMatcher\Matcher\Pattern\Expander;

use Coduo\PHPMatcher\Matcher\Pattern\PatternExpander;
use Coduo\ToString\String;

class OneOf implements PatternExpander
{
/**
* @var PatternExpander[]
*/
protected $expanders;

protected $error;

public function __construct()
{
if (func_num_args() < 2) {
throw new \InvalidArgumentException("OneOf expander require at least two expanders.");
}
foreach (func_get_args() as $argument) {
if (!$argument instanceof PatternExpander) {
throw new \InvalidArgumentException("OneOf expander require each argument to be a valid PatternExpander.");
}

$this->expanders[] = $argument;
}
}

/**
* @param $value
* @return boolean
*/
public function match($value)
{
foreach ($this->expanders as $expander) {
if ($expander->match($value)) {
return true;
}
}

$this->error = sprintf("Any expander available in OneOf expander does not match \"%s\".", new String($value));
return false;
}

/**
* @return string|null
*/
public function getError()
{
return $this->error;
}
}
61 changes: 10 additions & 51 deletions src/Coduo/PHPMatcher/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

use Coduo\PHPMatcher\AST;
use Coduo\PHPMatcher\Exception\Exception;
use Coduo\PHPMatcher\Exception\InvalidExpanderTypeException;
use Coduo\PHPMatcher\Exception\PatternException;
use Coduo\PHPMatcher\Exception\UnknownExpanderClassException;
use Coduo\PHPMatcher\Exception\UnknownExpanderException;
use Coduo\PHPMatcher\Matcher\Pattern;
use Coduo\PHPMatcher\Parser\ExpanderInitializer;

class Parser
{
Expand All @@ -20,24 +19,17 @@ class Parser
private $lexer;

/**
* @var array
* @var ExpanderInitializer
*/
private $expanderDefinitions = array(
"startsWith" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\StartsWith",
"endsWith" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\EndsWith",
"notEmpty" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\NotEmpty",
"lowerThan" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\LowerThan",
"greaterThan" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\GreaterThan",
"inArray" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\InArray",
"contains" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\Contains"
);
private $expanderInitializer;

/**
* @param Lexer $lexer
*/
public function __construct(Lexer $lexer)
public function __construct(Lexer $lexer, ExpanderInitializer $expanderInitializer)
{
$this->lexer = $lexer;
$this->expanderInitializer = $expanderInitializer;
}

/**
Expand All @@ -64,11 +56,7 @@ public function parse($pattern)
$AST = $this->getAST($pattern);
$pattern = new Pattern\TypePattern((string) $AST->getType());
foreach ($AST->getExpanders() as $expander) {
if (!array_key_exists($expander->getName(), $this->expanderDefinitions)) {
throw new UnknownExpanderException(sprintf("Unknown expander \"%s\"", $expander->getName()));
}

$pattern->addExpander($this->initializeExpander($expander));
$pattern->addExpander($this->expanderInitializer->initialize($expander));
}

return $pattern;
Expand All @@ -84,20 +72,6 @@ public function getAST($pattern)
return $this->getPattern();
}

/**
* @param $expanderName
* @param $expanderFQCN Fully-Qualified Class Name that implements PatternExpander interface
* @throws UnknownExpanderClassException
*/
public function addExpanderDefinition($expanderName, $expanderFQCN)
{
if (!class_exists($expanderFQCN)) {
throw new UnknownExpanderClassException(sprintf("Class \"%s\" does not exists.", $expanderFQCN));
}

$this->expanderDefinitions[$expanderName] = $expanderFQCN;
}

/**
* Create AST root
*
Expand Down Expand Up @@ -222,6 +196,10 @@ private function getNextArgumentValue()
return $this->getArrayArgument();
}

if ($this->lexer->isNextToken(Lexer::T_EXPANDER_NAME)) {
return $this->getNextExpanderNode();
}

if (!$this->lexer->isNextTokenAny($validArgumentTypes)) {
$this->unexpectedSyntaxError($this->lexer->lookahead, "string, number, boolean or null argument");
}
Expand Down Expand Up @@ -341,23 +319,4 @@ private function endOfPattern()
{
return is_null($this->lexer->lookahead);
}

/**
* @param AST\Expander $expander
* @throws InvalidExpanderTypeException
* @return Pattern\PatternExpander
*/
private function initializeExpander(AST\Expander $expander)
{
$reflection = new \ReflectionClass($this->expanderDefinitions[$expander->getName()]);
$expander = !$expander->hasArguments()
? $reflection->newInstance()
: $reflection->newInstanceArgs($expander->getArguments());

if (!$expander instanceof Pattern\PatternExpander) {
throw new InvalidExpanderTypeException();
}

return $expander;
}
}
99 changes: 99 additions & 0 deletions src/Coduo/PHPMatcher/Parser/ExpanderInitializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Coduo\PHPMatcher\Parser;

use Coduo\PHPMatcher\AST\Expander;
use Coduo\PHPMatcher\Exception\InvalidArgumentException;
use Coduo\PHPMatcher\Exception\InvalidExpanderTypeException;
use Coduo\PHPMatcher\Exception\UnknownExpanderClassException;
use Coduo\PHPMatcher\Exception\UnknownExpanderException;
use Coduo\PHPMatcher\Matcher\Pattern\PatternExpander;

class ExpanderInitializer
{
/**
* @var array
*/
private $expanderDefinitions = array(
"startsWith" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\StartsWith",
"endsWith" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\EndsWith",
"notEmpty" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\NotEmpty",
"lowerThan" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\LowerThan",
"greaterThan" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\GreaterThan",
"inArray" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\InArray",
"contains" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\Contains",

"oneOf" => "Coduo\\PHPMatcher\\Matcher\\Pattern\\Expander\\OneOf"
);

/**
* @param string $expanderName
* @param string $expanderFQCN Fully-Qualified Class Name that implements PatternExpander interface
* @throws UnknownExpanderClassException
*/
public function setExpanderDefinition($expanderName, $expanderFQCN)
{
if (!class_exists($expanderFQCN)) {
throw new UnknownExpanderClassException(sprintf("Class \"%s\" does not exists.", $expanderFQCN));
}

$this->expanderDefinitions[$expanderName] = $expanderFQCN;
}

/**
* @param $expanderName
* @return bool
*/
public function hasExpanderDefinition($expanderName)
{
return array_key_exists($expanderName, $this->expanderDefinitions);
}

/**
* @param $expanderName
* @return string
* @throws InvalidArgumentException
*/
public function getExpanderDefinition($expanderName)
{
if (!$this->hasExpanderDefinition($expanderName)) {
throw new InvalidArgumentException(sprintf("Definition for \"%s\" expander does not exists.", $expanderName));
}

return $this->expanderDefinitions[$expanderName];
}

/**
* @param Expander $expanderNode
* @throws InvalidExpanderTypeException
* @throws UnknownExpanderException
* @return PatternExpander
*/
public function initialize(Expander $expanderNode)
{
if (!array_key_exists($expanderNode->getName(), $this->expanderDefinitions)) {
throw new UnknownExpanderException(sprintf("Unknown expander \"%s\"", $expanderNode->getName()));
}

$reflection = new \ReflectionClass($this->expanderDefinitions[$expanderNode->getName()]);

if ($expanderNode->hasArguments()) {
$arguments = array();
foreach ($expanderNode->getArguments() as $argument) {
$arguments[] = ($argument instanceof Expander)
? $this->initialize($argument)
: $argument;
}

$expander = $reflection->newInstanceArgs($arguments);
} else {
$expander = $reflection->newInstance();
}

if (!$expander instanceof PatternExpander) {
throw new InvalidExpanderTypeException();
}

return $expander;
}
}
4 changes: 2 additions & 2 deletions tests/Coduo/PHPMatcher/Matcher/ArrayMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ArrayMatcherTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
$parser = new Parser(new Lexer());
$parser = new Parser(new Lexer(), new Parser\ExpanderInitializer());
$this->matcher = new Matcher\ArrayMatcher(
new Matcher\ChainMatcher(array(
new Matcher\CallbackMatcher(),
Expand Down Expand Up @@ -55,7 +55,7 @@ public function test_negative_match_when_cant_find_matcher_that_can_match_array_
new Matcher\ChainMatcher(array(
new Matcher\WildcardMatcher()
)),
$parser = new Parser(new Lexer())
$parser = new Parser(new Lexer(), new Parser\ExpanderInitializer())
);

$this->assertFalse($matcher->match(array('test' => 1), array('test' => 1)));
Expand Down
2 changes: 1 addition & 1 deletion tests/Coduo/PHPMatcher/Matcher/DoubleMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DoubleMatcherTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
$this->matcher = new DoubleMatcher(new Parser(new Lexer()));
$this->matcher = new DoubleMatcher(new Parser(new Lexer(), new Parser\ExpanderInitializer()));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/Coduo/PHPMatcher/Matcher/IntegerMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class IntegerMatcherTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
$this->matcher = new IntegerMatcher(new Parser(new Lexer()));
$this->matcher = new IntegerMatcher(new Parser(new Lexer(), new Parser\ExpanderInitializer()));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/Coduo/PHPMatcher/Matcher/JsonMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class JsonMatcherTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
$parser = new Parser(new Lexer());
$parser = new Parser(new Lexer(), new Parser\ExpanderInitializer());
$scalarMatchers = new Matcher\ChainMatcher(array(
new Matcher\CallbackMatcher(),
new Matcher\ExpressionMatcher(),
Expand Down
51 changes: 51 additions & 0 deletions tests/Coduo/PHPMatcher/Matcher/Pattern/Expander/OneOfTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Coduo\PHPMatcher\Tests\Matcher\Pattern\Expander;

use Coduo\PHPMatcher\Matcher\Pattern\Expander\Contains;
use Coduo\PHPMatcher\Matcher\Pattern\Expander\OneOf;

class OneOfTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage OneOf expander require at least two expanders.
*/
public function test_not_enough_arguments()
{
$expander = new OneOf();
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage OneOf expander require each argument to be a valid PatternExpander.
*/
public function test_invalid_argument_types()
{
$expander = new OneOf("arg1", array("test"));
}

public function test_positive_match()
{
$expander = new OneOf(
new Contains("lorem"),
new Contains("test")
);

$this->assertTrue($expander->match("lorem ipsum"));
}

public function test_negative_match()
{
$expander = new OneOf(
new Contains("lorem"),
new Contains("test")
);

$this->assertFalse($expander->match("this is random stiring"));
$this->assertSame(
"Any expander available in OneOf expander does not match \"this is random stiring\".",
$expander->getError()
);
}
}
2 changes: 1 addition & 1 deletion tests/Coduo/PHPMatcher/Matcher/StringMatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class StringMatcherTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
$parser = new Parser(new Lexer());
$parser = new Parser(new Lexer(), new Parser\ExpanderInitializer());
$this->matcher = new StringMatcher($parser);
}
/**
Expand Down
Loading