Skip to content
This repository was archived by the owner on Aug 22, 2023. It is now read-only.

Commit 491e96d

Browse files
committed
Restore ilike & regexp for compatibility with Eloquent
1 parent c18e814 commit 491e96d

File tree

3 files changed

+44
-54
lines changed

3 files changed

+44
-54
lines changed

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ All notable changes to this project will be documented in this file.
1515
- Accept operators prefixed by `$` in `Query\Builder::orWhere` [#20](https://github.com/GromNaN/laravel-mongodb-private/pull/20) by [@GromNaN](https://github.com/GromNaN).
1616
- Remove `Query\Builder::whereAll($column, $values)`. Use `Query\Builder::where($column, 'all', $values)` instead. [#16](https://github.com/GromNaN/laravel-mongodb-private/pull/16) by [@GromNaN](https://github.com/GromNaN).
1717
- Fix validation of unique values when the validated value is found as part of an existing value. [#21](https://github.com/GromNaN/laravel-mongodb-private/pull/21) by [@GromNaN](https://github.com/GromNaN).
18-
- Fix support for `%` and `_` in `like` expression [#17](https://github.com/GromNaN/laravel-mongodb-private/pull/17) by [@GromNaN](https://github.com/GromNaN).
19-
- Remove `ilike` and `regexp` operators, use `like` and `regex` instead [#17](https://github.com/GromNaN/laravel-mongodb-private/pull/17) by [@GromNaN](https://github.com/GromNaN).
18+
- Support `%` and `_` in `like` expression [#17](https://github.com/GromNaN/laravel-mongodb-private/pull/17) by [@GromNaN](https://github.com/GromNaN).
2019

2120
## [3.9.2] - 2022-09-01
2221

src/Query/Builder.php

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
class Builder extends BaseBuilder
2626
{
27+
private const REGEX_DELIMITERS = ['/', '#', '~'];
28+
2729
/**
2830
* The database collection.
2931
*
@@ -112,19 +114,23 @@ class Builder extends BaseBuilder
112114
*/
113115
protected $conversion = [
114116
'=' => '=',
115-
'!=' => '$ne',
116-
'<>' => '$ne',
117-
'<' => '$lt',
118-
'<=' => '$lte',
119-
'>' => '$gt',
120-
'>=' => '$gte',
121-
];
122-
123-
private $replacementOperators = [
117+
'!=' => 'ne',
118+
'<>' => 'ne',
119+
'<' => 'lt',
120+
'<=' => 'lte',
121+
'>' => 'gt',
122+
'>=' => 'gte',
124123
'regexp' => 'regex',
125124
'not regexp' => 'not regex',
126125
'ilike' => 'like',
127126
'not ilike' => 'not like',
127+
'elemmatch' => 'elemMatch',
128+
'geointersects' => 'geoIntersects',
129+
'geowithin' => 'geoWithin',
130+
'nearsphere' => 'nearSphere',
131+
'maxdistance' => 'maxDistance',
132+
'centersphere' => 'centerSphere',
133+
'uniquedocs' => 'uniqueDocs',
128134
];
129135

130136
/**
@@ -937,19 +943,9 @@ protected function compileWheres(): array
937943
if (isset($where['operator'])) {
938944
$where['operator'] = strtolower($where['operator']);
939945

940-
// Operator conversions
941-
$convert = [
942-
'elemmatch' => 'elemMatch',
943-
'geointersects' => 'geoIntersects',
944-
'geowithin' => 'geoWithin',
945-
'nearsphere' => 'nearSphere',
946-
'maxdistance' => 'maxDistance',
947-
'centersphere' => 'centerSphere',
948-
'uniquedocs' => 'uniqueDocs',
949-
];
950-
951-
if (array_key_exists($where['operator'], $convert)) {
952-
$where['operator'] = $convert[$where['operator']];
946+
// Convert aliased operators
947+
if (array_key_exists($where['operator'], $this->conversion)) {
948+
$where['operator'] = $this->conversion[$where['operator']];
953949
}
954950
}
955951

@@ -1057,12 +1053,12 @@ protected function compileWhereBasic(array $where): array
10571053
// Automatically convert regular expression strings to Regex objects.
10581054
if (is_string($value)) {
10591055
$delimiter = substr($value, 0, 1);
1060-
if (! in_array($delimiter, ['/', '#', '~'])) {
1061-
throw new \LogicException(sprintf('Regular expressions must be surrounded by delimiter "/". Got "%s"', $value));
1056+
if (! in_array($delimiter, self::REGEX_DELIMITERS)) {
1057+
throw new \LogicException(sprintf('Missing expected starting delimiter in regular expression "%s", supported delimiters are: %s', $value, implode(' ', self::REGEX_DELIMITERS)));
10621058
}
10631059
$e = explode($delimiter, $value);
10641060
if (count($e) < 3) {
1065-
throw new \LogicException(sprintf('Regular expressions must be surrounded by delimiter "%s". Got "%s"', $delimiter, $value));
1061+
throw new \LogicException(sprintf('Missing expected ending delimiter "%s" in regular expression "%s"', $delimiter, $value));
10661062
}
10671063
$flags = end($e);
10681064
$regstr = substr($value, 1, -1 - strlen($flags));
@@ -1075,8 +1071,6 @@ protected function compileWhereBasic(array $where): array
10751071

10761072
if (! isset($operator) || $operator == '=') {
10771073
$query = [$column => $value];
1078-
} elseif (array_key_exists($operator, $this->conversion)) {
1079-
$query = [$column => [$this->conversion[$operator] => $value]];
10801074
} else {
10811075
$query = [$column => ['$'.$operator => $value]];
10821076
}
@@ -1135,7 +1129,7 @@ protected function compileWhereNull(array $where): array
11351129
*/
11361130
protected function compileWhereNotNull(array $where): array
11371131
{
1138-
$where['operator'] = '!=';
1132+
$where['operator'] = 'ne';
11391133
$where['value'] = null;
11401134

11411135
return $this->compileWhereBasic($where);
@@ -1255,8 +1249,14 @@ protected function compileWhereRaw(array $where): mixed
12551249

12561250
protected function invalidOperator($operator)
12571251
{
1258-
if (is_string($operator) && isset($this->replacementOperators[$operator = strtolower($operator)])) {
1259-
throw new \InvalidArgumentException(sprintf('Operator "%s" is not supported. Use "%s" instead.', $operator, $this->replacementOperators[$operator]));
1252+
if (! is_string($operator)) {
1253+
return true;
1254+
}
1255+
1256+
$operator = strtolower($operator);
1257+
1258+
if (isset($this->conversion[$operator])) {
1259+
return false;
12601260
}
12611261

12621262
return parent::invalidOperator($operator);

tests/Query/BuilderTest.php

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,11 @@ function (Builder $builder) {
584584
fn (Builder $builder) => $builder->where('name', 'like', 'acme'),
585585
];
586586

587+
yield 'where ilike' => [ // Alias for like
588+
['find' => [['name' => new Regex('^acme$', 'i')], []]],
589+
fn (Builder $builder) => $builder->where('name', 'ilike', 'acme'),
590+
];
591+
587592
yield 'where like escape' => [
588593
['find' => [['name' => new Regex('^\^ac\.me\$$', 'i')], []]],
589594
fn (Builder $builder) => $builder->where('name', 'like', '^ac.me$'),
@@ -610,6 +615,11 @@ function (Builder $builder) {
610615
fn (Builder $builder) => $builder->where('name', 'regex', $regex),
611616
];
612617

618+
yield 'where regexp' => [ // Alias for regex
619+
['find' => [['name' => $regex], []]],
620+
fn (Builder $builder) => $builder->where('name', 'regex', '/^acme$/si'),
621+
];
622+
613623
yield 'where regex delimiter /' => [
614624
['find' => [['name' => $regex], []]],
615625
fn (Builder $builder) => $builder->where('name', 'regex', '/^acme$/si'),
@@ -746,7 +756,6 @@ public static function provideExceptions(): iterable
746756
fn (Builder $builder) => $builder->whereBetween('id', ['min' => 1, 'max' => 2]),
747757
];
748758

749-
750759
yield 'find with single string argument' => [
751760
\ArgumentCountError::class,
752761
'Too few arguments to function Jenssegers\Mongodb\Query\Builder::where("foo"), 1 passed and at least 2 expected when the 1st is a string',
@@ -755,32 +764,14 @@ public static function provideExceptions(): iterable
755764

756765
yield 'where regex not starting with /' => [
757766
\LogicException::class,
758-
'Regular expressions must be surrounded by delimiter "/". Got "^ac/me$"',
767+
'Missing expected starting delimiter in regular expression "^ac/me$", supported delimiters are: / # ~',
759768
fn (Builder $builder) => $builder->where('name', 'regex', '^ac/me$'),
760769
];
761770

762771
yield 'where regex not ending with /' => [
763772
\LogicException::class,
764-
'Regular expressions must be surrounded by delimiter "/". Got "/^acme$"',
765-
fn (Builder $builder) => $builder->where('name', 'regex', '/^acme$'),
766-
];
767-
768-
yield 'where regex not ending with #' => [
769-
\LogicException::class,
770-
'Regular expressions must be surrounded by delimiter "#". Got "#^acme$"',
771-
fn (Builder $builder) => $builder->where('name', 'regex', '#^acme$'),
772-
];
773-
774-
yield 'where regexp not supported' => [
775-
\LogicException::class,
776-
'Operator "regexp" is not supported. Use "regex" instead.',
777-
fn (Builder $builder) => $builder->where('name', 'regexp', '/^acme$/'),
778-
];
779-
780-
yield 'where ilike not supported' => [
781-
\LogicException::class,
782-
'Operator "ilike" is not supported. Use "like" instead.',
783-
fn (Builder $builder) => $builder->where('name', 'ilike', 'acme'),
773+
'Missing expected ending delimiter "/" in regular expression "/foo#bar"',
774+
fn (Builder $builder) => $builder->where('name', 'regex', '/foo#bar'),
784775
];
785776
}
786777

0 commit comments

Comments
 (0)