Skip to content

Commit 3938058

Browse files
committed
Support where expression (instead of criteria)
1 parent e92eb23 commit 3938058

7 files changed

Lines changed: 46 additions & 89 deletions

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
],
1414
"require": {
1515
"php": ">=7.0",
16-
"doctrine/common": "^2.9"
16+
"doctrine/common": "^2.9",
17+
"doctrine/orm": "^2.5"
1718
},
1819
"require-dev": {
1920
"phpunit/phpunit": "^6.4",

src/AndSpecification.php

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

33
namespace Tanigami\Specification;
44

5-
use Doctrine\Common\Collections\Criteria;
6-
75
class AndSpecification extends Specification
86
{
97
/**
@@ -37,9 +35,15 @@ public function isSatisfiedBy($object): bool
3735
/**
3836
* {@inheritdoc}
3937
*/
40-
public function criteria(): Criteria
38+
public function whereExpression(string $alias): string
4139
{
42-
return $this->one->criteria()->andWhere($this->other->criteria()->getWhereExpression());
40+
return sprintf(
41+
sprintf(
42+
'(%s) AND (%s)',
43+
$this->one()->whereExpression($alias),
44+
$this->other()->whereExpression($alias)
45+
)
46+
);
4347
}
4448

4549
/**

src/AnyOfSpecification.php

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

33
namespace Tanigami\Specification;
44

5-
use Doctrine\Common\Collections\Criteria;
6-
75
class AnyOfSpecification extends Specification
86
{
97
/**
@@ -36,19 +34,14 @@ public function isSatisfiedBy($object): bool
3634
/**
3735
* {@inheritdoc}
3836
*/
39-
public function criteria(): Criteria
37+
public function whereExpression(string $alias): string
4038
{
41-
/** @var Criteria $criteria */
42-
$criteria = null;
43-
foreach ($this->specifications as $specification) {
44-
if (is_null($criteria)) {
45-
$criteria = $specification->criteria();
46-
} else {
47-
$criteria = $criteria->andWhere($specification->criteria()->getWhereExpression());
48-
}
49-
}
50-
51-
return $criteria;
39+
return implode(' AND ', array_map(
40+
function (Specification $specification) use ($alias) {
41+
return '(' . $specification->whereExpression($alias) . ')';
42+
},
43+
$this->specifications
44+
));
5245
}
5346

5447
/**

src/OneOfSpecification.php

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

33
namespace Tanigami\Specification;
44

5-
use Doctrine\Common\Collections\Criteria;
6-
75
class OneOfSpecification extends Specification
86
{
97
/**
@@ -22,33 +20,28 @@ public function __construct(Specification ...$specifications)
2220
/**
2321
* {@inheritdoc}
2422
*/
25-
public function criteria(): Criteria
23+
public function isSatisfiedBy($object): bool
2624
{
27-
/** @var Criteria $criteria */
28-
$criteria = null;
2925
foreach ($this->specifications as $specification) {
30-
if (is_null($criteria)) {
31-
$criteria = $specification->criteria();
32-
} else {
33-
$criteria = $criteria->orWhere($specification->criteria()->getWhereExpression());
26+
if ($specification->isSatisfiedBy($object)) {
27+
return true;
3428
}
3529
}
3630

37-
return $criteria;
31+
return false;
3832
}
3933

4034
/**
4135
* {@inheritdoc}
4236
*/
43-
public function isSatisfiedBy($object): bool
37+
public function whereExpression(string $alias): string
4438
{
45-
foreach ($this->specifications as $specification) {
46-
if ($specification->isSatisfiedBy($object)) {
47-
return true;
48-
}
49-
}
50-
51-
return false;
39+
return implode(' OR ', array_map(
40+
function (Specification $specification) use ($alias) {
41+
return '(' . $specification->whereExpression($alias) . ')';
42+
},
43+
$this->specifications
44+
));
5245
}
5346

5447
/**

src/OrSpecification.php

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

33
namespace Tanigami\Specification;
44

5-
use Doctrine\Common\Collections\Criteria;
6-
75
class OrSpecification extends Specification
86
{
97
/**
@@ -37,9 +35,15 @@ public function isSatisfiedBy($object): bool
3735
/**
3836
* {@inheritdoc}
3937
*/
40-
public function criteria(): Criteria
38+
public function whereExpression(string $alias): string
4139
{
42-
return $this->one->criteria()->orWhere($this->other->criteria()->getWhereExpression());
40+
return sprintf(
41+
sprintf(
42+
'(%s) OR (%s)',
43+
$this->one()->whereExpression($alias),
44+
$this->other()->whereExpression($alias)
45+
)
46+
);
4347
}
4448

4549
/**

src/Specification.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Tanigami\Specification;
44

55
use BadMethodCallException;
6-
use Doctrine\Common\Collections\Criteria;
76

87
abstract class Specification
98
{
@@ -14,11 +13,12 @@ abstract class Specification
1413
abstract public function isSatisfiedBy($object): bool;
1514

1615
/**
17-
* @return Criteria
16+
* @param string $alias
17+
* @return string
1818
*/
19-
public function criteria()
19+
public function whereExpression(string $alias): string
2020
{
21-
throw new BadMethodCallException('Criteria is not supported.');
21+
throw new BadMethodCallException('Where expression is not supported');
2222
}
2323

2424
/**

tests/SpecificationTest.php

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,18 @@ public function testCriteriaComposition()
8585
new OneOfSpecification($trueSpec, $falseSpec, $trueSpec),
8686
$trueSpec
8787
);
88-
$visitor = new Visitor();
89-
$compositeSpec->criteria()->getWhereExpression()->visit($visitor);
9088
$this->assertSame(
91-
'((((((bool = 1) AND (bool = 0)) OR (bool = 1)) AND (bool = 0)) AND (((bool = 1) OR (bool = 0)) OR (bool = 1))) AND (bool = 1))',
92-
$visitor->trace()
89+
'((((1) AND (0)) OR (1)) AND (0)) AND ((1) OR (0) OR (1)) AND (1)',
90+
$compositeSpec->whereExpression('a')
9391
);
9492
}
9593

9694
/**
9795
* @expectedException \BadMethodCallException
9896
*/
99-
public function testCriteriaIsNotSupported()
97+
public function testWhereExpressionIsNotSupported()
10098
{
101-
(new BoolSpecification(true))->not()->criteria();
99+
(new BoolSpecification(true))->not()->whereExpression('a');
102100
}
103101
}
104102

@@ -116,44 +114,8 @@ public function isSatisfiedBy($object): bool
116114
return $this->bool;
117115
}
118116

119-
public function criteria(): Criteria
117+
public function whereExpression(string $alias): string
120118
{
121-
return new Criteria(Criteria::expr()->eq('bool', $this->bool));
122-
}
123-
}
124-
125-
class Visitor extends ExpressionVisitor
126-
{
127-
private $trace;
128-
129-
public function walkComparison(Comparison $comparison)
130-
{
131-
$this->trace .= '(';
132-
$this->trace .= $comparison->getField();
133-
$this->trace .= ' ' . $comparison->getOperator() . ' ';
134-
$this->trace .= $this->walkValue($comparison->getValue());
135-
$this->trace .= ')';
136-
}
137-
138-
public function walkCompositeExpression(CompositeExpression $expr)
139-
{
140-
$this->trace .= '(';
141-
foreach ($expr->getExpressionList() as $i => $child) {
142-
if ($i !== 0) {
143-
$this->trace .= (' ' . $expr->getType() . ' ');
144-
}
145-
$expressionList[] = $this->dispatch($child);
146-
}
147-
$this->trace .= ')';
148-
}
149-
150-
public function walkValue(Value $value)
151-
{
152-
return $value->getValue() ? '1' : '0';
153-
}
154-
155-
public function trace()
156-
{
157-
return $this->trace;
119+
return $this->bool ? '1' : '0';
158120
}
159121
}

0 commit comments

Comments
 (0)