Skip to content

Commit f8a4ace

Browse files
committed
WIP tests
1 parent c777096 commit f8a4ace

File tree

4 files changed

+390
-40
lines changed

4 files changed

+390
-40
lines changed

src/Scout/ScoutEngine.php

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use MongoDB\Exception\Exception;
2323
use MongoDB\Exception\RuntimeException;
2424
use Traversable;
25+
use TypeError;
2526

2627
use function array_column;
2728
use function array_filter;
@@ -32,9 +33,13 @@
3233
use function assert;
3334
use function call_user_func;
3435
use function class_uses_recursive;
36+
use function get_debug_type;
3537
use function hrtime;
3638
use function in_array;
39+
use function is_array;
40+
use function is_int;
3741
use function is_iterable;
42+
use function is_string;
3843
use function iterator_to_array;
3944
use function preg_quote;
4045
use function sleep;
@@ -84,7 +89,7 @@ public function update($models)
8489
return;
8590
}
8691

87-
$collection = $this->getCollection($models);
92+
$collection = $this->getIndexableCollection($models);
8893

8994
if ($this->softDelete && $this->usesSoftDelete($models)) {
9095
$models->each->pushSoftDeleteMetadata();
@@ -102,8 +107,8 @@ public function update($models)
102107
'updateOne' => [
103108
['_id' => $model->getScoutKey()],
104109
[
105-
'$set' => array_merge($searchableData, $model->scoutMetadata()),
106110
'$setOnInsert' => ['_id' => $model->getScoutKey()],
111+
'$set' => array_merge($searchableData, $model->scoutMetadata()),
107112
],
108113
['upsert' => true],
109114
],
@@ -123,15 +128,15 @@ public function update($models)
123128
*/
124129
public function delete($models): void
125130
{
131+
assert($models instanceof Collection, new TypeError(sprintf('Argument #1 ($models) must be of type %s, %s given', Collection::class, get_debug_type($models))));
132+
126133
if ($models->isEmpty()) {
127134
return;
128135
}
129136

130-
$collection = $this->mongodb->getCollection($models);
131-
$ids = array_map(fn (Model $model) => $model->getScoutKey(), $models->toArray());
132-
$collection->deleteMany([
133-
'_id' => ['$in' => $ids],
134-
]);
137+
$collection = $this->getIndexableCollection($models);
138+
$ids = $models->map(fn (Model $model) => $model->getScoutKey())->all();
139+
$collection->deleteMany(['_id' => ['$in' => $ids]]);
135140
}
136141

137142
/**
@@ -157,6 +162,9 @@ public function search(Builder $builder)
157162
*/
158163
public function paginate(Builder $builder, $perPage, $page)
159164
{
165+
assert(is_int($perPage), new TypeError(sprintf('Argument #2 ($perPage) must be of type int, %s given', get_debug_type($perPage))));
166+
assert(is_int($page), new TypeError(sprintf('Argument #3 ($page) must be of type int, %s given', get_debug_type($page))));
167+
160168
return $this->performSearch($builder, array_filter([
161169
'filters' => $this->filters($builder),
162170
'limit' => (int) $perPage,
@@ -169,7 +177,7 @@ public function paginate(Builder $builder, $perPage, $page)
169177
*/
170178
protected function performSearch(Builder $builder, array $searchParams = []): array
171179
{
172-
$collection = $this->getCollection($builder->model);
180+
$collection = $this->getSearchableCollection($builder->model);
173181

174182
if ($builder->callback) {
175183
$result = call_user_func(
@@ -242,6 +250,8 @@ protected function filters(Builder $builder): array
242250
*/
243251
public function mapIds($results): Collection
244252
{
253+
assert(is_array($results), new TypeError(sprintf('Argument #1 ($results) must be of type array, %s given', get_debug_type($results))));
254+
245255
return new Collection(array_column($results, '_id'));
246256
}
247257

@@ -253,6 +263,9 @@ public function mapIds($results): Collection
253263
*/
254264
public function map(Builder $builder, $results, $model): Collection
255265
{
266+
assert(is_array($results), new TypeError(sprintf('Argument #2 ($results) must be of type array, %s given', get_debug_type($results))));
267+
assert($model instanceof Model, new TypeError(sprintf('Argument #3 ($model) must be of type %s, %s given', Model::class, get_debug_type($model))));
268+
256269
if (! $results) {
257270
return $model->newCollection();
258271
}
@@ -287,22 +300,27 @@ public function getTotalCount($results): int
287300
*/
288301
public function flush($model): void
289302
{
290-
$collection = $this->getCollection($model);
303+
assert($model instanceof Model, new TypeError(sprintf('Argument #1 ($model) must be of type %s, %s given', Model::class, get_debug_type($model))));
304+
305+
$collection = $this->getIndexableCollection($model);
291306

292307
$collection->deleteMany([]);
293308
}
294309

295310
/**
296311
* Map the given results to instances of the given model via a lazy collection.
297312
*
298-
* @param Builder $builder
299-
* @param mixed $results
300-
* @param Model $model
313+
* @param Builder $builder
314+
* @param array|Cursor $results
315+
* @param Model $model
301316
*
302317
* @return LazyCollection
303318
*/
304-
public function lazyMap(Builder $builder, $results, $model)
319+
public function lazyMap(Builder $builder, $results, $model): LazyCollection
305320
{
321+
assert($results instanceof Cursor || is_array($results), new TypeError(sprintf('Argument #2 ($results) must be of type %s|array, %s given', Cursor::class, get_debug_type($results))));
322+
assert($model instanceof Model, new TypeError(sprintf('Argument #3 ($model) must be of type %s, %s given', Model::class, get_debug_type($model))));
323+
306324
if (! $results) {
307325
return LazyCollection::make($model->newCollection());
308326
}
@@ -341,6 +359,8 @@ public function lazyMap(Builder $builder, $results, $model)
341359
*/
342360
public function createIndex($name, array $options = []): void
343361
{
362+
assert(is_string($name), new TypeError(sprintf('Argument #1 ($name) must be of type string, %s given', get_debug_type($name))));
363+
344364
$this->performSearchIndexOperation(function () use ($name, $options) {
345365
$this->mongodb->createCollection($name);
346366
$collection = $this->mongodb->selectCollection($name);
@@ -375,6 +395,8 @@ public function createIndex($name, array $options = []): void
375395
*/
376396
public function deleteIndex($name): void
377397
{
398+
assert(is_string($name), new TypeError(sprintf('Argument #1 ($name) must be of type string, %s given', get_debug_type($name))));
399+
378400
$this->mongodb->selectCollection($name)->drop();
379401
}
380402

@@ -394,8 +416,8 @@ public function deleteAllIndexes()
394416
}
395417
}
396418

397-
/** Get the MongoDB collection used as search index for the provided model */
398-
private function getCollection(Model|EloquentCollection $model): MongoDBCollection
419+
/** Get the MongoDB collection used to search for the provided model */
420+
private function getSearchableCollection(Model|EloquentCollection $model): MongoDBCollection
399421
{
400422
if ($model instanceof EloquentCollection) {
401423
$model = $model->first();
@@ -406,6 +428,18 @@ private function getCollection(Model|EloquentCollection $model): MongoDBCollecti
406428
return $this->mongodb->selectCollection($model->searchableAs());
407429
}
408430

431+
/** Get the MongoDB collection used to index the provided model */
432+
private function getIndexableCollection(Model|EloquentCollection $model): MongoDBCollection
433+
{
434+
if ($model instanceof EloquentCollection) {
435+
$model = $model->first();
436+
}
437+
438+
assert(in_array(Searchable::class, class_uses_recursive($model)), sprintf('Model "%s" must use "%s" trait', $model::class, Searchable::class));
439+
440+
return $this->mongodb->selectCollection($model->indexableAs());
441+
}
442+
409443
private static function serialize(mixed $value): mixed
410444
{
411445
if ($value instanceof DateTimeInterface) {

tests/Models/SearchableModel.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MongoDB\Laravel\Tests\Models;
6+
7+
use Laravel\Scout\Searchable;
8+
use MongoDB\Laravel\Eloquent\Model as Eloquent;
9+
use MongoDB\Laravel\Eloquent\SoftDeletes;
10+
11+
class SearchableModel extends Eloquent
12+
{
13+
use Searchable;
14+
use SoftDeletes;
15+
16+
protected $connection = 'sqlite';
17+
protected $table = 'searchable';
18+
protected static $unguarded = true;
19+
20+
public function searchableAs(): string
21+
{
22+
return 'table_searchable';
23+
}
24+
25+
public function indexableAs(): string
26+
{
27+
return 'table_indexable';
28+
}
29+
30+
public function getScoutKey(): string
31+
{
32+
return 'key_' . $this->id;
33+
}
34+
}

0 commit comments

Comments
 (0)