17
17
18
18
namespace MongoDB \GridFS ;
19
19
20
+ use ArrayIterator ;
20
21
use MongoDB \Collection ;
21
22
use MongoDB \Driver \Cursor ;
22
23
use MongoDB \Driver \Manager ;
23
24
use MongoDB \Driver \ReadPreference ;
24
25
use MongoDB \Exception \InvalidArgumentException ;
25
26
use MongoDB \UpdateResult ;
27
+ use MultipleIterator ;
26
28
use stdClass ;
27
29
use function abs ;
30
+ use function count ;
31
+ use function is_numeric ;
28
32
use function sprintf ;
29
33
30
34
/**
@@ -289,27 +293,31 @@ public function updateFilenameForId($id, $filename)
289
293
*/
290
294
private function ensureChunksIndex ()
291
295
{
296
+ $ expectedIndex = ['files_id ' => 1 , 'n ' => 1 ];
297
+
292
298
foreach ($ this ->chunksCollection ->listIndexes () as $ index ) {
293
- if ($ index ->isUnique () && $ index -> getKey () === [ ' files_id ' => 1 , ' n ' => 1 ] ) {
299
+ if ($ index ->isUnique () && $ this -> indexKeysMatch ( $ expectedIndex , $ index -> getKey ()) ) {
294
300
return ;
295
301
}
296
302
}
297
303
298
- $ this ->chunksCollection ->createIndex ([ ' files_id ' => 1 , ' n ' => 1 ] , ['unique ' => true ]);
304
+ $ this ->chunksCollection ->createIndex ($ expectedIndex , ['unique ' => true ]);
299
305
}
300
306
301
307
/**
302
308
* Create an index on the files collection if it does not already exist.
303
309
*/
304
310
private function ensureFilesIndex ()
305
311
{
312
+ $ expectedIndex = ['filename ' => 1 , 'uploadDate ' => 1 ];
313
+
306
314
foreach ($ this ->filesCollection ->listIndexes () as $ index ) {
307
- if ($ index -> getKey () === [ ' filename ' => 1 , ' uploadDate ' => 1 ] ) {
315
+ if ($ this -> indexKeysMatch ( $ expectedIndex , $ index -> getKey ()) ) {
308
316
return ;
309
317
}
310
318
}
311
319
312
- $ this ->filesCollection ->createIndex ([ ' filename ' => 1 , ' uploadDate ' => 1 ] );
320
+ $ this ->filesCollection ->createIndex ($ expectedIndex );
313
321
}
314
322
315
323
/**
@@ -334,6 +342,36 @@ private function ensureIndexes()
334
342
$ this ->ensureChunksIndex ();
335
343
}
336
344
345
+ private function indexKeysMatch (array $ expectedKeys , array $ actualKeys ) : bool
346
+ {
347
+ if (count ($ expectedKeys ) !== count ($ actualKeys )) {
348
+ return false ;
349
+ }
350
+
351
+ $ iterator = new MultipleIterator (MultipleIterator::MIT_NEED_ANY );
352
+ $ iterator ->attachIterator (new ArrayIterator ($ expectedKeys ));
353
+ $ iterator ->attachIterator (new ArrayIterator ($ actualKeys ));
354
+
355
+ foreach ($ iterator as $ key => $ value ) {
356
+ list ($ expectedKey , $ actualKey ) = $ key ;
357
+ list ($ expectedValue , $ actualValue ) = $ value ;
358
+
359
+ if ($ expectedKey !== $ actualKey ) {
360
+ return false ;
361
+ }
362
+
363
+ /* Since we don't expect special indexes (e.g. text), we mark any
364
+ * index with a non-numeric definition as unequal. All others are
365
+ * compared against their int value to avoid differences due to
366
+ * some drivers using float values in the key specification. */
367
+ if (! is_numeric ($ actualValue ) || (int ) $ expectedValue !== (int ) $ actualValue ) {
368
+ return false ;
369
+ }
370
+ }
371
+
372
+ return true ;
373
+ }
374
+
337
375
/**
338
376
* Returns whether the files collection is empty.
339
377
*
0 commit comments