1717
1818namespace MongoDB \GridFS ;
1919
20+ use ArrayIterator ;
2021use MongoDB \Collection ;
2122use MongoDB \Driver \Cursor ;
2223use MongoDB \Driver \Manager ;
2324use MongoDB \Driver \ReadPreference ;
2425use MongoDB \Exception \InvalidArgumentException ;
2526use MongoDB \UpdateResult ;
27+ use MultipleIterator ;
2628use stdClass ;
2729use function abs ;
30+ use function count ;
31+ use function is_numeric ;
2832use function sprintf ;
2933
3034/**
@@ -289,27 +293,31 @@ public function updateFilenameForId($id, $filename)
289293 */
290294 private function ensureChunksIndex ()
291295 {
296+ $ expectedIndex = ['files_id ' => 1 , 'n ' => 1 ];
297+
292298 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 ()) ) {
294300 return ;
295301 }
296302 }
297303
298- $ this ->chunksCollection ->createIndex ([ ' files_id ' => 1 , ' n ' => 1 ] , ['unique ' => true ]);
304+ $ this ->chunksCollection ->createIndex ($ expectedIndex , ['unique ' => true ]);
299305 }
300306
301307 /**
302308 * Create an index on the files collection if it does not already exist.
303309 */
304310 private function ensureFilesIndex ()
305311 {
312+ $ expectedIndex = ['filename ' => 1 , 'uploadDate ' => 1 ];
313+
306314 foreach ($ this ->filesCollection ->listIndexes () as $ index ) {
307- if ($ index -> getKey () === [ ' filename ' => 1 , ' uploadDate ' => 1 ] ) {
315+ if ($ this -> indexKeysMatch ( $ expectedIndex , $ index -> getKey ()) ) {
308316 return ;
309317 }
310318 }
311319
312- $ this ->filesCollection ->createIndex ([ ' filename ' => 1 , ' uploadDate ' => 1 ] );
320+ $ this ->filesCollection ->createIndex ($ expectedIndex );
313321 }
314322
315323 /**
@@ -334,6 +342,36 @@ private function ensureIndexes()
334342 $ this ->ensureChunksIndex ();
335343 }
336344
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+
337375 /**
338376 * Returns whether the files collection is empty.
339377 *
0 commit comments