Browse files

Suport for

 - $expr->like()
 - $expr->descendant()
 - $expr->textSearch()
  • Loading branch information...
1 parent 43643f2 commit 00ca5eaedf3160e2913e772f835c1522a465d7fd @dantleech dantleech committed Jan 15, 2013
View
16 lib/Doctrine/ODM/PHPCR/Query/Expression/Comparison.php
@@ -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';
+}
View
4 ...Query/Expression/DescendantExpression.php → ...ODM/PHPCR/Query/Expression/Descendant.php
@@ -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;
@@ -21,6 +21,6 @@ public function getPath()
public function visit(ExpressionVisitor $visitor)
{
- return $visitor->walkCompositeExpression($this);
+ return $visitor->walkDescendantExpression($this);
}
}
View
33 lib/Doctrine/ODM/PHPCR/Query/Expression/TextSearch.php
@@ -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);
+ }
+}
View
16 lib/Doctrine/ODM/PHPCR/Query/ExpressionBuilder.php
@@ -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);
}
}
View
62 lib/Doctrine/ODM/PHPCR/Query/PhpcrExpressionVisitor.php
@@ -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;
@@ -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");
}
@@ -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));
+ }
+ }
}
View
45 tests/Doctrine/Tests/ODM/PHPCR/Functional/QueryBuilderTest.php
@@ -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);
+ }
}
View
41 tests/Doctrine/Tests/ODM/PHPCR/Query/PhpcrExpressionVisitorTest.php
@@ -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),
@@ -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)
{
@@ -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'),
@@ -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.