Skip to content

Commit b7aeb2e

Browse files
committed
Use factory to create filters
1 parent a3e6151 commit b7aeb2e

File tree

5 files changed

+130
-68
lines changed

5 files changed

+130
-68
lines changed

src/Criteria.php

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@
1414
class Criteria implements Countable, Filter
1515
{
1616
protected $currentIndex = null;
17+
protected $factory;
1718
protected $filters = array();
1819

20+
public function __construct(Factory $factory)
21+
{
22+
$this->factory = $factory;
23+
}
24+
1925
public function getFilters()
2026
{
2127
return $this->filters;
@@ -38,35 +44,13 @@ public function __get($index)
3844
return $this;
3945
}
4046

41-
protected function newFilterInstance($shortName, array $arguments = array())
42-
{
43-
$reflection = new ReflectionClass('PHPFluent\\ArrayStorage\\Filter\\' . ucfirst($shortName));
44-
if (! $reflection->isSubclassOf('PHPFluent\\ArrayStorage\\Filter\\Filter')) {
45-
throw new BadMethodCallException(sprintf('"%s" is not a valid filter name', $shortName));
46-
}
47-
48-
return $reflection->newInstanceArgs($arguments);
49-
}
50-
5147
public function __call($methodName, array $arguments = array())
5248
{
5349
if (null === $this->currentIndex) {
5450
throw new UnexpectedValueException('You first need to call a property for this filter');
5551
}
5652

57-
if (0 === strpos($methodName, 'not')) {
58-
$shortName = substr($methodName, 3);
59-
$filter = new Not($this->newFilterInstance($shortName, $arguments));
60-
} elseif (false !== strpos($methodName, 'Or')) {
61-
$pieces = explode('Or', $methodName);
62-
$filters = array();
63-
foreach ($pieces as $shortName) {
64-
$filters[] = $this->newFilterInstance($shortName, $arguments);
65-
}
66-
$filter = new OneOf($filters);
67-
} else {
68-
$filter = $this->newFilterInstance($methodName, $arguments);
69-
}
53+
$filter = $this->factory->filter($methodName, $arguments);
7054

7155
$this->addFilter($this->currentIndex, $filter);
7256

src/Factory.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
namespace PHPFluent\ArrayStorage;
44

5-
use PHPFluent\ArrayStorage\Filter\Filter;
5+
use InvalidArgumentException;
66
use PHPFluent\ArrayStorage\Filter\EqualTo;
7+
use PHPFluent\ArrayStorage\Filter\Filter;
8+
use PHPFluent\ArrayStorage\Filter\Not;
9+
use PHPFluent\ArrayStorage\Filter\OneOf;
10+
use ReflectionClass;
711

812
class Factory
913
{
@@ -30,7 +34,7 @@ public function criteria($criteria = null)
3034
{
3135
if (! $criteria instanceof Criteria) {
3236
$filters = (array) $criteria;
33-
$criteria = new Criteria();
37+
$criteria = new Criteria($this);
3438
foreach ($filters as $key => $value) {
3539
if ($value instanceof Filter) {
3640
$criteria->addFilter($key, $value);
@@ -43,4 +47,35 @@ public function criteria($criteria = null)
4347

4448
return $criteria;
4549
}
50+
51+
public function filter($filter, array $arguments = array())
52+
{
53+
if (! $filter instanceof Filter) {
54+
if (0 === strpos($filter, 'not')) {
55+
$filterName = substr($filter, 3);
56+
$filter = $this->filter($filterName, $arguments);
57+
58+
return new Not($filter);
59+
}
60+
61+
if (false !== strpos($filter, 'Or')) {
62+
$filtersNames = explode('Or', $filter);
63+
$filters = array();
64+
foreach ($filtersNames as $filterName) {
65+
$filters[] = $this->filter($filterName, $arguments);
66+
}
67+
68+
return new OneOf($filters);
69+
}
70+
71+
$reflectionClass = new ReflectionClass(__NAMESPACE__ . '\\Filter\\' . ucfirst($filter));
72+
if (! $reflectionClass->isSubclassOf(__NAMESPACE__ . '\\Filter\\Filter')) {
73+
throw new InvalidArgumentException(sprintf('"%s" is not a valid filter name', $filter));
74+
}
75+
76+
return $reflectionClass->newInstanceArgs($arguments);
77+
}
78+
79+
return $filter;
80+
}
4681
}

tests/CollectionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function testShouldUseFactoryToCreateCriteria()
4545

4646
$filters = array('foo' => $this->getMock('PHPFluent\\ArrayStorage\\Filter\\Filter'));
4747

48-
$criteria = new Criteria();
48+
$criteria = new Criteria($factory);
4949
$criteria->addFilter('foo', $filters['foo']);
5050

5151
$factory

tests/CriteriaTest.php

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,30 @@ protected function filter()
1212
return $this->getMock('PHPFluent\ArrayStorage\Filter\Filter');
1313
}
1414

15+
public function testShouldAcceptFactoryOnConstructor()
16+
{
17+
$factory = new Factory();
18+
$criteria = new Criteria($factory);
19+
}
20+
1521
public function testShouldAddFilter()
1622
{
17-
$criteria = new Criteria();
23+
$criteria = new Criteria(new Factory());
1824
$criteria->addFilter('foo', $this->filter());
1925

2026
$this->assertCount(1, $criteria);
2127
}
2228

2329
public function testShouldReturnSelfWhenGettingANonExistentProperty()
2430
{
25-
$criteria = new Criteria();
31+
$criteria = new Criteria(new Factory());
2632

2733
$this->assertSame($criteria, $criteria->foo);
2834
}
2935

30-
public function testShouldReturnAddFilterUsingMethodOverload()
36+
public function testShouldAddFilterUsingMethodOverload()
3137
{
32-
$criteria = new Criteria();
38+
$criteria = new Criteria(new Factory());
3339
$criteria->foo->equalTo(2);
3440
$filters = $criteria->getFilters();
3541
list($index, $filter) = $filters[0];
@@ -38,29 +44,34 @@ public function testShouldReturnAddFilterUsingMethodOverload()
3844
$this->assertInstanceOf('PHPFluent\\ArrayStorage\\Filter\\EqualTo', $filter);
3945
}
4046

41-
/**
42-
* @expectedException UnexpectedValueException
43-
* @expectedExceptionMessage You first need to call a property for this filter
44-
*/
45-
public function testShouldThrowExceptionWhenCallingAMethodBeforeCallAProperty()
47+
public function testShouldUseFactoryToCreateFilters()
4648
{
47-
$criteria = new Criteria();
48-
$criteria->equalTo(2);
49+
$filter = $this->getMock('PHPFluent\\ArrayStorage\\Filter\\Filter');
50+
51+
$factory = $this->getMock('PHPFluent\\ArrayStorage\\Factory');
52+
$factory
53+
->expects($this->once())
54+
->method('filter')
55+
->with('someFilter')
56+
->will($this->returnValue($filter));
57+
58+
$criteria = new Criteria($factory);
59+
$criteria->foo->someFilter(2);
4960
}
5061

5162
/**
52-
* @expectedException BadMethodCallException
53-
* @expectedExceptionMessage "filter" is not a valid filter name
63+
* @expectedException UnexpectedValueException
64+
* @expectedExceptionMessage You first need to call a property for this filter
5465
*/
55-
public function testShouldThrowExceptionWhenCallingMethodDoesNotRefersToAValidFilter()
66+
public function testShouldThrowExceptionWhenCallingAFilterBeforeCallAProperty()
5667
{
57-
$criteria = new Criteria();
58-
$criteria->foo->filter(2);
68+
$criteria = new Criteria(new Factory());
69+
$criteria->equalTo(2);
5970
}
6071

6172
public function testShouldValidateUsingFiltersWhenRecordIsValid()
6273
{
63-
$criteria = new Criteria();
74+
$criteria = new Criteria(new Factory());
6475
$criteria->foo->equalTo(2);
6576
$criteria->bar->equalTo(false);
6677

@@ -74,7 +85,7 @@ public function testShouldValidateUsingFiltersWhenRecordIsValid()
7485

7586
public function testShouldValidateUsingFiltersWhenRecordIsInvalid()
7687
{
77-
$criteria = new Criteria();
88+
$criteria = new Criteria(new Factory());
7889
$criteria->foo->equalTo(2);
7990
$criteria->bar->equalTo(true);
8091

@@ -85,26 +96,4 @@ public function testShouldValidateUsingFiltersWhenRecordIsInvalid()
8596

8697
$this->assertFalse($criteria->isValid($record));
8798
}
88-
89-
public function testShouldUseNotFilterWhenUsingTheWordNotInTheFilterName()
90-
{
91-
$criteria = new Criteria();
92-
$criteria->foo->notEqualTo(42);
93-
94-
$record = new Record();
95-
$record->foo = 42;
96-
97-
$this->assertFalse($criteria->isValid($record));
98-
}
99-
100-
public function testShouldUseOneOfFilterWhenUsingTheWordOrInTheFilterName()
101-
{
102-
$criteria = new Criteria();
103-
$criteria->foo->greaterThanOrEqualTo(42);
104-
105-
$record = new Record();
106-
$record->foo = 42;
107-
108-
$this->assertTrue($criteria->isValid($record));
109-
}
11099
}

tests/FactoryTest.php

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

33
namespace PHPFluent\ArrayStorage;
44

5-
use PHPFluent\ArrayStorage\Filter\EqualTo;
5+
use PHPFluent\ArrayStorage\Filter;
66

77
/**
88
* @covers PHPFluent\ArrayStorage\Factory
@@ -92,9 +92,63 @@ public function testShouldCreateACriteriaFromAKeyValueArrayOfNonFilters()
9292
$factory = new Factory();
9393
$criteria = $factory->criteria($inputFilters);
9494
$actualFilters = $criteria->getFilters();
95-
$expectedFilter = new EqualTo($inputFilters['foo']);
95+
$expectedFilter = new Filter\EqualTo($inputFilters['foo']);
9696

9797
$this->assertEquals('foo', $actualFilters[0][0]);
9898
$this->assertEquals($expectedFilter, $actualFilters[0][1]);
9999
}
100+
101+
public function testShouldReturnInputIfInputIsAlreadyAFilter()
102+
{
103+
$filter = new Filter\EqualTo(42, 'identical');
104+
105+
$factory = new Factory();
106+
107+
$this->assertSame($filter, $factory->filter($filter));
108+
}
109+
110+
public function testShouldCreateAFilterByNameAndArguments()
111+
{
112+
$expectedFilter = new Filter\EqualTo(42, 'identical');
113+
114+
$factory = new Factory();
115+
$actualFilter = $factory->filter('equalTo', array(42, 'identical'));
116+
117+
$this->assertEquals($expectedFilter, $actualFilter);
118+
}
119+
120+
/**
121+
* @expectedException InvalidArgumentException
122+
* @expectedExceptionMessage "filter" is not a valid filter name
123+
*/
124+
public function testShouldThrowExceptionWhenCallingMethodDoesNotRefersToAValidFilter()
125+
{
126+
$factory = new Factory();
127+
$factory->filter('filter');
128+
}
129+
130+
public function testShouldUseNotFilterWhenInputHasNotAsPrefix()
131+
{
132+
$expectedFilter = new Filter\Not(new Filter\EqualTo(42));
133+
134+
$factory = new Factory();
135+
$actualFilter = $factory->filter('notEqualTo', array(42));
136+
137+
$this->assertEquals($expectedFilter, $actualFilter);
138+
}
139+
140+
public function testShouldUseOneOfFilterWhenInputHasContainsTheWordOr()
141+
{
142+
$expectedFilter = new Filter\OneOf(
143+
array(
144+
new Filter\GreaterThan(42),
145+
new Filter\EqualTo(42),
146+
)
147+
);
148+
149+
$factory = new Factory();
150+
$actualFilter = $factory->filter('greaterThanOrEqualTo', array(42));
151+
152+
$this->assertEquals($expectedFilter, $actualFilter);
153+
}
100154
}

0 commit comments

Comments
 (0)