22
22
use MongoDB \Exception \Exception ;
23
23
use MongoDB \Exception \RuntimeException ;
24
24
use Traversable ;
25
+ use TypeError ;
25
26
26
27
use function array_column ;
27
28
use function array_filter ;
32
33
use function assert ;
33
34
use function call_user_func ;
34
35
use function class_uses_recursive ;
36
+ use function get_debug_type ;
35
37
use function hrtime ;
36
38
use function in_array ;
39
+ use function is_array ;
40
+ use function is_int ;
37
41
use function is_iterable ;
42
+ use function is_string ;
38
43
use function iterator_to_array ;
39
44
use function preg_quote ;
40
45
use function sleep ;
@@ -84,7 +89,7 @@ public function update($models)
84
89
return ;
85
90
}
86
91
87
- $ collection = $ this ->getCollection ($ models );
92
+ $ collection = $ this ->getIndexableCollection ($ models );
88
93
89
94
if ($ this ->softDelete && $ this ->usesSoftDelete ($ models )) {
90
95
$ models ->each ->pushSoftDeleteMetadata ();
@@ -102,8 +107,8 @@ public function update($models)
102
107
'updateOne ' => [
103
108
['_id ' => $ model ->getScoutKey ()],
104
109
[
105
- '$set ' => array_merge ($ searchableData , $ model ->scoutMetadata ()),
106
110
'$setOnInsert ' => ['_id ' => $ model ->getScoutKey ()],
111
+ '$set ' => array_merge ($ searchableData , $ model ->scoutMetadata ()),
107
112
],
108
113
['upsert ' => true ],
109
114
],
@@ -123,15 +128,15 @@ public function update($models)
123
128
*/
124
129
public function delete ($ models ): void
125
130
{
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
+
126
133
if ($ models ->isEmpty ()) {
127
134
return ;
128
135
}
129
136
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 ]]);
135
140
}
136
141
137
142
/**
@@ -157,6 +162,9 @@ public function search(Builder $builder)
157
162
*/
158
163
public function paginate (Builder $ builder , $ perPage , $ page )
159
164
{
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
+
160
168
return $ this ->performSearch ($ builder , array_filter ([
161
169
'filters ' => $ this ->filters ($ builder ),
162
170
'limit ' => (int ) $ perPage ,
@@ -169,7 +177,7 @@ public function paginate(Builder $builder, $perPage, $page)
169
177
*/
170
178
protected function performSearch (Builder $ builder , array $ searchParams = []): array
171
179
{
172
- $ collection = $ this ->getCollection ($ builder ->model );
180
+ $ collection = $ this ->getSearchableCollection ($ builder ->model );
173
181
174
182
if ($ builder ->callback ) {
175
183
$ result = call_user_func (
@@ -242,6 +250,8 @@ protected function filters(Builder $builder): array
242
250
*/
243
251
public function mapIds ($ results ): Collection
244
252
{
253
+ assert (is_array ($ results ), new TypeError (sprintf ('Argument #1 ($results) must be of type array, %s given ' , get_debug_type ($ results ))));
254
+
245
255
return new Collection (array_column ($ results , '_id ' ));
246
256
}
247
257
@@ -253,6 +263,9 @@ public function mapIds($results): Collection
253
263
*/
254
264
public function map (Builder $ builder , $ results , $ model ): Collection
255
265
{
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
+
256
269
if (! $ results ) {
257
270
return $ model ->newCollection ();
258
271
}
@@ -287,22 +300,27 @@ public function getTotalCount($results): int
287
300
*/
288
301
public function flush ($ model ): void
289
302
{
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 );
291
306
292
307
$ collection ->deleteMany ([]);
293
308
}
294
309
295
310
/**
296
311
* Map the given results to instances of the given model via a lazy collection.
297
312
*
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
301
316
*
302
317
* @return LazyCollection
303
318
*/
304
- public function lazyMap (Builder $ builder , $ results , $ model )
319
+ public function lazyMap (Builder $ builder , $ results , $ model ): LazyCollection
305
320
{
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
+
306
324
if (! $ results ) {
307
325
return LazyCollection::make ($ model ->newCollection ());
308
326
}
@@ -341,6 +359,8 @@ public function lazyMap(Builder $builder, $results, $model)
341
359
*/
342
360
public function createIndex ($ name , array $ options = []): void
343
361
{
362
+ assert (is_string ($ name ), new TypeError (sprintf ('Argument #1 ($name) must be of type string, %s given ' , get_debug_type ($ name ))));
363
+
344
364
$ this ->performSearchIndexOperation (function () use ($ name , $ options ) {
345
365
$ this ->mongodb ->createCollection ($ name );
346
366
$ collection = $ this ->mongodb ->selectCollection ($ name );
@@ -375,6 +395,8 @@ public function createIndex($name, array $options = []): void
375
395
*/
376
396
public function deleteIndex ($ name ): void
377
397
{
398
+ assert (is_string ($ name ), new TypeError (sprintf ('Argument #1 ($name) must be of type string, %s given ' , get_debug_type ($ name ))));
399
+
378
400
$ this ->mongodb ->selectCollection ($ name )->drop ();
379
401
}
380
402
@@ -394,8 +416,8 @@ public function deleteAllIndexes()
394
416
}
395
417
}
396
418
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
399
421
{
400
422
if ($ model instanceof EloquentCollection) {
401
423
$ model = $ model ->first ();
@@ -406,6 +428,18 @@ private function getCollection(Model|EloquentCollection $model): MongoDBCollecti
406
428
return $ this ->mongodb ->selectCollection ($ model ->searchableAs ());
407
429
}
408
430
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
+
409
443
private static function serialize (mixed $ value ): mixed
410
444
{
411
445
if ($ value instanceof DateTimeInterface) {
0 commit comments