diff --git a/src/ElasticaSpecification/ExpressionBuilder/NotBuilder.php b/src/ElasticaSpecification/ExpressionBuilder/NotBuilder.php new file mode 100644 index 0000000..9d2cca4 --- /dev/null +++ b/src/ElasticaSpecification/ExpressionBuilder/NotBuilder.php @@ -0,0 +1,45 @@ + + */ +class NotBuilder implements Builder +{ + /** + * @var Registry + */ + private $registry; + + /** + * @param Registry $registry + */ + public function __construct(Registry $registry) + { + $this->registry = $registry; + } + + /** + * {inheritdoc} + */ + public function build(Specification $spec, QueryBuilder $qb) + { + if (!$spec instanceof Not) { + throw new \InvalidArgumentException(); + } + + $firstPartBuilder = $this->registry->getBuilder($spec->getWrappedSpecification()); + + return $qb->query()->bool() + ->addMustNot($firstPartBuilder->build($spec->getWrappedSpecification(), $qb)) + ; + } +} diff --git a/tests/ElasticaSpecification/ExpressionBuilder/NotBuilderTest.php b/tests/ElasticaSpecification/ExpressionBuilder/NotBuilderTest.php new file mode 100644 index 0000000..c294e0f --- /dev/null +++ b/tests/ElasticaSpecification/ExpressionBuilder/NotBuilderTest.php @@ -0,0 +1,81 @@ +assertInstanceOf(NotBuilder::class, $builder); + } + + public function testBuildReturnsNotExpression() + { + $not = $this->createNot(); + $registry = $this->createRegistry($not); + + $builder = new NotBuilder($registry); + + $query = $builder->build($not, new QueryBuilder()); + + $this->assertInstanceOf(BoolQuery::class, $query); + + $this->assertArrayHasKey('bool', $query->toArray()); + $this->assertArrayHasKey('must_not', $query->toArray()['bool']); + $this->assertCount(1, $query->toArray()['bool']['must_not']); + } + + /** + * @return Not + */ + private function createNot() + { + return new Not( + $this->createMock(Specification::class) + ); + } + + /** + * @param Not $not + * + * @return Registry + */ + private function createRegistry($not) + { + $builder = $this->createMock(Builder::class); + $builder + ->expects($this->any()) + ->method('build') + ->willReturn($this->createMock(AbstractQuery::class)) + ; + + $registry = new Registry(); + + $registry->register(get_class($not->getWrappedSpecification()), $builder); + + return $registry; + } + + + public function testBuildThrowExceptionIfNotNotSpecification() + { + $spec = $this->createMock(Specification::class); + $registry = new Registry(); + $builder = new NotBuilder($registry); + + $this->setExpectedException(\InvalidArgumentException::class); + + $expr = $builder->build($spec, new QueryBuilder()); + } +}