Skip to content

Commit

Permalink
Suport for
Browse files Browse the repository at this point in the history
 - $expr->like()
 - $expr->descendant()
 - $expr->textSearch()
  • Loading branch information
dantleech committed Jan 15, 2013
1 parent 43643f2 commit 00ca5ea
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 14 deletions.
16 changes: 16 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Query/Expression/Comparison.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Doctrine\ODM\PHPCR\Query\Expression;

use Doctrine\Common\Collections\Expr\Comparison as BaseComparison;
use Doctrine\Common\Collections\Expr\ExpressionVisitor;

/**
* This class purpose is to provide provide a place
* for the LIKE constant. Everything else is handled
* in Doctrine\Common\Collections\Expr\Comparison
*/
class Comparison extends BaseComparison
{
const LIKE = 'like';
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Doctrine\Common\Collections\Expr\Expression;
use Doctrine\Common\Collections\Expr\ExpressionVisitor;

class DescendantExpression implements Expression
class Descendant implements Expression
{
protected $path;

Expand All @@ -21,6 +21,6 @@ public function getPath()

public function visit(ExpressionVisitor $visitor)
{
return $visitor->walkCompositeExpression($this);
return $visitor->walkDescendantExpression($this);
}
}
33 changes: 33 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Query/Expression/TextSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Doctrine\ODM\PHPCR\Query\Expression;

use Doctrine\Common\Collections\Expr\Expression;
use Doctrine\Common\Collections\Expr\ExpressionVisitor;

class TextSearch implements Expression
{
protected $field;
protected $search;

public function __construct($field, $search)
{
$this->field = $field;
$this->search = $search;
}

public function getField()
{
return $this->field;
}

public function getSearch()
{
return $this->search;
}

public function visit(ExpressionVisitor $visitor)
{
return $visitor->walkTextSearchExpression($this);
}
}
16 changes: 14 additions & 2 deletions lib/Doctrine/ODM/PHPCR/Query/ExpressionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@
namespace Doctrine\ODM\PHPCR\Query;

use Doctrine\Common\Collections\ExpressionBuilder as BaseExpressionBuilder;
use Doctrine\ODM\PHPCR\Query\Expression\DescendantExpression;
use Doctrine\ODM\PHPCR\Query\Expression\Descendant;
use Doctrine\ODM\PHPCR\Query\Expression\Comparison;
use Doctrine\ODM\PHPCR\Query\Expression\TextSearch;

class ExpressionBuilder extends BaseExpressionBuilder
{
public function descendant($path)
{
return new DescendantExpression($path);
return new Descendant($path);
}

public function like($field, $value)
{
return new Comparison($field, Comparison::LIKE, $value);
}

public function textSearch($field, $search)
{
return new TextSearch($field, $search);
}
}
62 changes: 59 additions & 3 deletions lib/Doctrine/ODM/PHPCR/Query/PhpcrExpressionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace Doctrine\ODM\PHPCR\Query;
use Doctrine\Common\Collections\Expr\ExpressionVisitor;
use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\Value;
use Doctrine\Common\Collections\Expr\CompositeExpression;
use Doctrine\ODM\PHPCR\Query\Expression\DescendantExpression;
use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\Expression;
use Doctrine\ODM\PHPCR\Query\Expression\Descendant;
use Doctrine\ODM\PHPCR\Query\Expression\TextSearch;
use Doctrine\ODM\PHPCR\Query\Expression\Comparison as ODMComparison;

use PHPCR\Query\QOM\DynamicOperandInterface;
use PHPCR\Query\QOM\QueryObjectModelFactoryInterface;
Expand Down Expand Up @@ -59,6 +62,9 @@ public function walkComparison(Comparison $comparison)
case Comparison::GT:
$qomOperator = QOMConstant::JCR_OPERATOR_GREATER_THAN;
break;
case ODMComparison::LIKE:
$qomOperator = QOMConstant::JCR_OPERATOR_LIKE;
break;
default:
throw new \InvalidArgumentException("Unsupported operator $operator");
}
Expand Down Expand Up @@ -127,8 +133,58 @@ public function walkValue(Value $value)
return $this->qomf->literal($value->getValue());
}

public function walkDescendant(DescendantExpression $expr)
/**
* Convert a descendant expression to its PHPCR counterpart.
*
* @param \Doctrine\ODM\PHPCR\Query\Expression\Descendant
*
* @return \PHPCR\Query\QOM\DescendantNodeInterface
*/
public function walkDescendant(Descendant $expr)
{
return $this->qomf->descendantNode($expr->getPath());
}


/**
* Convert a testSearch expression to its PHPCR counterpart.
*
* @param \Doctrine\ODM\PHPCR\Query\Expression\TextSearch
*
* @return \PHPCR\Query\QOM\FullTextSearchInterface
*/
public function walkTextSearch(TextSearch $expr)
{
return $this->qomf->fullTextSearch($expr->getField(), $expr->getSearch());
}

/**
* Dispatch walking an expression to the appropriate handler.
*
* @param Expression
*
* @return mixed
*/
public function dispatch(Expression $expr)
{
switch (true) {
case ($expr instanceof Comparison):
return $this->walkComparison($expr);

case ($expr instanceof Value):
return $this->walkValue($expr);

case ($expr instanceof CompositeExpression):
return $this->walkCompositeExpression($expr);

case ($expr instanceof Descendant):
return $this->walkDescendant($expr);

case ($expr instanceof TextSearch):
return $this->walkTextSearch($expr);

default:
throw new \RuntimeException("Unknown Expression " . get_class($expr));
}
}
}
45 changes: 45 additions & 0 deletions tests/Doctrine/Tests/ODM/PHPCR/Functional/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,49 @@ public function testFrom_all()
$this->assertContains('Doctrine\Tests\Models\CMS\CmsUser', $fqns);
$this->assertContains('Doctrine\Tests\Models\CMS\CmsItem', $fqns);
}

/**
* I don't think this test has much value, but will commit it at
* least once as it took a few minutes to write...
*/
public function getTextSearches()
{
return array(
array('name', 'johnsmith',
null, null,
"SELECT s FROM nt:base WHERE CONTAINS(name, 'johnsmith')",
),
array('name', 'johnsmith',
'from', 'Doctrine\Tests\Models\CMS\CmsUser',
"SELECT s FROM nt:unstructured WHERE (CONTAINS(name, 'johnsmith') AND phpcr:class = 'Doctrine\Tests\Models\CMS\CmsUser')",
),
array('name', 'johnsmith',
'nodeType', 'nt:unstructured',
"SELECT s FROM nt:unstructured WHERE CONTAINS(name, 'johnsmith')",
),
);
}

/**
* @dataProvider getTextSearches
*/
public function testTextSearch($field, $search, $sourceMethod = null, $source = null, $expectedStatement)
{
$qb = $this->createQb();
if ($sourceMethod) {
$qb->$sourceMethod($source);
}
$qb->where($qb->expr()->textSearch($field, $search));
$res = $qb->getQuery()->execute();
$statement = $qb->getQuery()->getStatement();
$this->assertEquals($expectedStatement, $statement);
}

public function testDescendant()
{
$qb = $this->createQb();
$qb->where($qb->expr()->descendant('/functional'));
$statement = $qb->getQuery()->getStatement();
$this->assertEquals("SELECT s FROM nt:base WHERE jcr:path LIKE '/functional[%]/%'", $statement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function setUp()
$this->visitor = new PhpcrExpressionVisitor($this->qomf);
}

public function getExpressions()
public function getComparisonExpressions()
{
return array(
array('foobar', 'eq', 123, QOMConstant::JCR_OPERATOR_EQUAL_TO),
Expand All @@ -28,11 +28,12 @@ public function getExpressions()
array('foobar', 'lte', 123, QOMConstant::JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO),
array('foobar', 'gte', 123, QOMConstant::JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO),
array('foobar', 'gt', 123, QOMConstant::JCR_OPERATOR_GREATER_THAN),
array('foobar', 'like', 123, QOMConstant::JCR_OPERATOR_LIKE),
);
}

/**
* @dataProvider getExpressions
* @dataProvider getComparisonExpressions
*/
public function testWalkComparison($field, $exprMethod, $value, $expectedJcrOperator)
{
Expand Down Expand Up @@ -78,9 +79,8 @@ public function testWalkCompositeExpression_two()
public function testWalkCompositeExpression_three()
{
// Should be equivilent to
// ("foo" == "bar" AND bar = "foo") AND "bar" > $foo
// ("foo" == "bar" AND bar == "foo") AND "bar" > $foo

// NOTE: I wonder if we should just now allow composites of more than two
$expr = $this->expr->andx(
$this->expr->eq('foo', 'bar'),
$this->expr->eq('bar', 'foo'),
Expand All @@ -101,9 +101,36 @@ public function testWalkValue()
$this->assertEquals('test', $res->getLiteralValue());
}

public function testDescendant()
public function getDispatchExpressions()
{
$expr = $this->expr->descendant('/foo/bar');
$res = $this->visitor->walkDescendant($expr);
$eb = new ExpressionBuilder;
return array(
array(
$eb->descendant('/foo/bar'),
'PHPCR\Query\QOM\DescendantNodeInterface', array(
'getAncestorPath' => '/foo/bar',
)
),
array(
$eb->textSearch('foobar', 'barfoo'),
'PHPCR\Query\QOM\FullTextSearchInterface', array(
'getPropertyName' => 'foobar',
'getFullTextSearchExpression' => 'barfoo',
)
)
);
}

/**
* @dataProvider getDispatchExpressions
*/
public function testDispatch($expression, $expectedQOMFClass, $methodAssertions)
{
$res = $this->visitor->dispatch($expression);
$this->assertInstanceOf($expectedQOMFClass, $res);

foreach ($methodAssertions as $method => $expected) {
$this->assertEquals($expected, $res->$method());
}
}
}

0 comments on commit 00ca5ea

Please sign in to comment.