Skip to content

Commit c7b1ab7

Browse files
committed
Revamped subquery scoping:
- scope() method is now deprecated - where clauses and query() method have been fixed - whereIn() and whereNotIn() (from recent Scout versions) are now supported - support of soft delete has been refactored
1 parent b60d44c commit c7b1ab7

File tree

6 files changed

+102
-77
lines changed

6 files changed

+102
-77
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,12 @@ $results = Post::search('you see what happens larry')
170170
> any effect. See below for the proper way to order results.
171171
172172
If the name of your scope collides with the name of a method of the
173-
`Baril\Sqlout\Builder` object, you can wrap your scope into the `scope` method:
173+
`Baril\Sqlout\Builder` object, you still have the option to use Scout's
174+
`query` method:
174175

175176
```php
176177
$results = Post::search('ve vant ze money lebowski')
177-
->scope(function ($query) {
178+
->query(function ($query) {
178179
$query->within('something');
179180
})
180181
->get();

src/Builder.php

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,6 @@ class Builder extends ScoutBuilder
2525
*/
2626
public $scopes = [];
2727

28-
/**
29-
* Create a new search builder instance.
30-
*
31-
* @param \Illuminate\Database\Eloquent\Model $model
32-
* @param string $query
33-
* @param \Closure $callback
34-
* @param bool $softDelete
35-
* @return void
36-
*/
37-
public function __construct($model, $query, $callback = null, $softDelete = false)
38-
{
39-
parent::__construct($model, $query, $callback, $softDelete);
40-
if ($softDelete) {
41-
unset($this->wheres['__soft_deleted']);
42-
}
43-
}
44-
4528
public function __call($method, $parameters)
4629
{
4730
if (static::hasMacro($method)) {
@@ -52,45 +35,12 @@ public function __call($method, $parameters)
5235
return $this;
5336
}
5437

55-
public function scope(Closure $callback)
56-
{
57-
$this->scopes[] = $callback;
58-
return $this;
59-
}
60-
6138
/**
62-
* Add a constraint to the search query.
63-
*
64-
* @param string $field
65-
* @param mixed $value
66-
* @return $this
39+
* @deprecated Will be removed in next major version, use Scout's $builder->query($callback) instead.
6740
*/
68-
public function where($field, $value)
69-
{
70-
$args = func_get_args();
71-
$this->scopes[] = ['where', $args];
72-
return $this;
73-
}
74-
75-
/**
76-
* Include soft deleted records in the results.
77-
*
78-
* @return $this
79-
*/
80-
public function withTrashed()
81-
{
82-
$this->scopes[] = ['withTrashed', []];
83-
return $this;
84-
}
85-
86-
/**
87-
* Include only soft deleted records in the results.
88-
*
89-
* @return $this
90-
*/
91-
public function onlyTrashed()
41+
public function scope(Closure $callback)
9242
{
93-
$this->scopes[] = ['onlyTrashed', []];
43+
$this->scopes[] = $callback;
9444
return $this;
9545
}
9646

src/Engine.php

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,6 @@ protected function performSearch(Builder $builder, array $options = [])
162162
->groupBy('record_id')
163163
->selectRaw("sum(weight * (match(content) against (? $mode))) as _score", [$terms])
164164
->addSelect(['record_type', 'record_id']);
165-
foreach ($builder->wheres as $field => $value) {
166-
if (is_array($value) || $value instanceof Arrayable) {
167-
$query->whereIn($field, $value);
168-
} else {
169-
$query->where($field, $value);
170-
}
171-
}
172165

173166
// Order clauses:
174167
if (!$builder->orders) {
@@ -193,16 +186,8 @@ protected function performSearch(Builder $builder, array $options = [])
193186
}
194187
}
195188

196-
// Applying scopes to the model query:
197189
$query->whereHasMorph('record', get_class($builder->model), function ($query) use ($builder) {
198-
foreach ($builder->scopes as $scope) {
199-
if ($scope instanceof Closure) {
200-
$scope($query);
201-
} else {
202-
list($method, $parameters) = $scope;
203-
$query->$method(...$parameters);
204-
}
205-
}
190+
$this->applyQueryScopes($builder, $query);
206191
});
207192

208193
// Applying limit/offset:
@@ -226,6 +211,51 @@ protected function performSearch(Builder $builder, array $options = [])
226211
return $results;
227212
}
228213

214+
/**
215+
* @param \Baril\Sqlout\Builder $builder
216+
* @param \Illuminate\Database\Eloquent\Query\Builder $query
217+
* @return void
218+
*/
219+
protected function applyQueryScopes($builder, $query)
220+
{
221+
$softDeleted = $builder->wheres['__soft_deleted'] ?? null;
222+
if (!method_exists($builder->model, 'bootSoftDeletes')) {
223+
// Model is not soft deletable
224+
} elseif (is_null($softDeleted)) {
225+
$query->withTrashed();
226+
} elseif ($softDeleted) {
227+
$query->onlyTrashed();
228+
} else {
229+
$query->withoutTrashed();
230+
}
231+
unset($builder->wheres['__soft_deleted']);
232+
foreach ($builder->wheres as $field => $value) {
233+
if (is_array($value) || $value instanceof Arrayable) {
234+
$query->whereIn($field, $value);
235+
} else {
236+
$query->where($field, $value);
237+
}
238+
}
239+
foreach ($builder->whereIns ?? [] as $field => $values) {
240+
$query->whereIn($field, $values);
241+
}
242+
foreach ($builder->whereNotIns ?? [] as $field => $values) {
243+
$query->whereNotIn($field, $values);
244+
}
245+
foreach ($builder->scopes as $scope) {
246+
if ($scope instanceof Closure) {
247+
$scope($query);
248+
} else {
249+
list($method, $parameters) = $scope;
250+
$query->$method(...$parameters);
251+
}
252+
}
253+
if ($builder->queryCallback) {
254+
$callback = $builder->queryCallback;
255+
$callback($query);
256+
}
257+
}
258+
229259
/**
230260
* Pluck and return the primary keys of the given results.
231261
*

tests/Models/Comment.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class Comment extends Model
1212
use HasFactory;
1313
use Searchable;
1414

15+
protected $guarded = [];
16+
1517
public function post()
1618
{
1719
return $this->belongsTo(Post::class);

tests/Models/Post.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class Post extends Model
1414
use SoftDeletes;
1515
use Searchable;
1616

17+
protected $guarded = [];
18+
1719
protected $weights = [
1820
'title' => 4,
1921
];

tests/SearchTest.php

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,51 @@ public function test_restricted_search()
107107
$this->assertEquals($posts[2]->id, $results[0]->id);
108108
}
109109

110-
public function test_where_and_forwarded_scope()
110+
public function test_wheres()
111+
{
112+
Comment::query()->update([
113+
'author' => 'kiki',
114+
'text' => 'kuku',
115+
'post_id' => 1,
116+
]);
117+
Comment::all()->searchable();
118+
$comments = Comment::all();
119+
$comments[0]->update([
120+
'author' => 'toto',
121+
'post_id' => 2,
122+
]);
123+
$comments[1]->update([
124+
'author' => 'toto',
125+
]);
126+
$comments[2]->update([
127+
'author' => 'tutu',
128+
'post_id' => 2,
129+
]);
130+
131+
$search = Comment::search('kuku')->where('author', 'toto');
132+
$this->assertEquals(2, $search->count());
133+
$this->assertEquals(2, $search->get()->count());
134+
135+
if (method_exists(Builder::class, 'whereIn')) {
136+
$search = Comment::search('kuku')->whereIn('author', ['toto', 'tutu']);
137+
$this->assertEquals(3, $search->count());
138+
$this->assertEquals(3, $search->get()->count());
139+
140+
$search = Comment::search('kuku')
141+
->whereIn('author', ['toto', 'kiki'])
142+
->where('post_id', 1);
143+
$this->assertEquals(3, $search->count());
144+
$this->assertEquals(3, $search->get()->count());
145+
}
146+
147+
if (method_exists(Builder::class, 'whereNotIn')) {
148+
$search = Comment::search('kuku')->whereNotIn('author', ['toto', 'tutu']);
149+
$this->assertEquals(2, $search->count());
150+
$this->assertEquals(2, $search->get()->count());
151+
}
152+
}
153+
154+
public function test_forwarded_scope()
111155
{
112156
Comment::query()->update(['text' => 'schtroumpf']);
113157
Comment::all()->searchable();
@@ -117,15 +161,11 @@ public function test_where_and_forwarded_scope()
117161

118162
$this->assertEquals(5, Comment::search('schtroumpf')->count());
119163

120-
$results = Comment::search('schtroumpf')->where('author', 'gargamel')->get();
121-
$this->assertCount(1, $results);
122-
$this->assertEquals($comment->id, $results[0]->id);
123-
124164
$results = Comment::search('schtroumpf')->author('gargamel')->get();
125165
$this->assertCount(1, $results);
126166
$this->assertEquals($comment->id, $results[0]->id);
127167

128-
$results = Comment::search('schtroumpf')->scope(function ($builder) {
168+
$results = Comment::search('schtroumpf')->query(function ($builder) {
129169
$builder->author('gargamel');
130170
})->get();
131171
$this->assertCount(1, $results);

0 commit comments

Comments
 (0)