diff --git a/composer.json b/composer.json index 9d7d90398..e45d32eb6 100644 --- a/composer.json +++ b/composer.json @@ -32,5 +32,8 @@ "branch-alias": { "dev-master": "1.6.x-dev" } + }, + "suggest": { + "ext-mbstring": "Only required when ICONTAINS comparison is used" } } diff --git a/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php index cd99e2f10..56ca30978 100644 --- a/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php +++ b/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php @@ -163,6 +163,11 @@ public function walkComparison(Comparison $comparison) return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false; }; + case Comparison::ICONTAINS: + return function ($object) use ($field, $value) { + return false !== strpos(mb_strtolower(ClosureExpressionVisitor::getObjectFieldValue($object, $field)), mb_strtolower($value)); + }; + case Comparison::MEMBER_OF: return function ($object) use ($field, $value) : bool { $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field); diff --git a/lib/Doctrine/Common/Collections/Expr/Comparison.php b/lib/Doctrine/Common/Collections/Expr/Comparison.php index d93687086..4f7110eee 100644 --- a/lib/Doctrine/Common/Collections/Expr/Comparison.php +++ b/lib/Doctrine/Common/Collections/Expr/Comparison.php @@ -7,19 +7,20 @@ */ class Comparison implements Expression { - public const EQ = '='; - public const NEQ = '<>'; - public const LT = '<'; - public const LTE = '<='; - public const GT = '>'; - public const GTE = '>='; - public const IS = '='; // no difference with EQ - public const IN = 'IN'; - public const NIN = 'NIN'; - public const CONTAINS = 'CONTAINS'; - public const MEMBER_OF = 'MEMBER_OF'; - public const STARTS_WITH = 'STARTS_WITH'; - public const ENDS_WITH = 'ENDS_WITH'; + public const EQ = '='; + public const NEQ = '<>'; + public const LT = '<'; + public const LTE = '<='; + public const GT = '>'; + public const GTE = '>='; + public const IS = '='; // no difference with EQ + public const IN = 'IN'; + public const NIN = 'NIN'; + public const CONTAINS = 'CONTAINS'; + public const ICONTAINS = 'ICONTAINS'; + public const MEMBER_OF = 'MEMBER_OF'; + public const STARTS_WITH = 'STARTS_WITH'; + public const ENDS_WITH = 'ENDS_WITH'; /** * @var string diff --git a/lib/Doctrine/Common/Collections/ExpressionBuilder.php b/lib/Doctrine/Common/Collections/ExpressionBuilder.php index 55a95e6b6..a0669e57d 100644 --- a/lib/Doctrine/Common/Collections/ExpressionBuilder.php +++ b/lib/Doctrine/Common/Collections/ExpressionBuilder.php @@ -145,6 +145,17 @@ public function contains($field, $value) return new Comparison($field, Comparison::CONTAINS, new Value($value)); } + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function iContains($field, $value) + { + return new Comparison($field, Comparison::ICONTAINS, new Value($value)); + } + /** * @param string $field * @param mixed $value diff --git a/tests/Doctrine/Tests/Common/Collections/ExpressionBuilderTest.php b/tests/Doctrine/Tests/Common/Collections/ExpressionBuilderTest.php index eba0a97ab..86e812103 100644 --- a/tests/Doctrine/Tests/Common/Collections/ExpressionBuilderTest.php +++ b/tests/Doctrine/Tests/Common/Collections/ExpressionBuilderTest.php @@ -124,6 +124,14 @@ public function testContains() : void self::assertEquals(Comparison::CONTAINS, $expr->getOperator()); } + public function testIContains() : void + { + $expr = $this->builder->iContains("a", "b"); + + $this->assertInstanceOf(Comparison::class, $expr); + $this->assertEquals(Comparison::ICONTAINS, $expr->getOperator()); + } + public function testMemberOf() : void { $expr = $this->builder->memberOf('b', ['a']);