GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 089298...c05766 )
by De
02:17
created

Cursor::fields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the PHPMongo package.
5
 *
6
 * (c) Dmytro Sokil <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sokil\Mongo;
13
14
use Sokil\Mongo\Exception\CursorException;
15
use Sokil\Mongo\Exception\FeatureNotSupportedException;
16
use Sokil\Mongo\Exception\WriteException;
17
18
/**
19
 * @mixin Expression
20
 */
21
class Cursor implements
22
    \Iterator,
23
    \Countable
24
{
25
    /**
26
     *
27
     * @var \Sokil\Mongo\Client
28
     */
29
    private $client;
30
31
    /**
32
     *
33
     * @var \Sokil\Mongo\Collection
34
     */
35
    private $collection;
36
37
    /**
38
     *
39
     * @var array
40
     */
41
    private $fields = array();
42
43
    /**
44
     *
45
     * @var \MongoCursor
46
     */
47
    private $cursor;
48
    /**
49
     *
50
     * @var Expression
51
     */
52
    private $expression;
53
54
    /**
55
     * Offset
56
     * @var int
57
     */
58
    private $skip = 0;
59
60
    /**
61
     * Limit
62
     * @var int
63
     */
64
    private $limit = 0;
65
66
    /**
67
     * Definition of sort
68
     * @var array
69
     */
70
    private $sort = array();
71
72
    /**
73
     * Definition of read preference
74
     * @var array
75
     */
76
    private $readPreference = array();
77
78
    /**
79
     * Return result as array or as Document instance
80
     * @var boolean
81
     */
82
    private $isResultAsArray = false;
83
84
    /**
85
     * Cursor options
86
     * @var array
87
     */
88
    private $options = array(
89
        'expressionClass' => '\Sokil\Mongo\Expression',
90
        /**
91
         * @link http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
92
         * @var int number of documents to return in each batch of the response from the MongoDB instance
93
         */
94
        'batchSize' => null,
95
        // client timeout
96
        'clientTimeout' => null,
97
        // Specifies a cumulative time limit in milliseconds to be allowed by the server for processing operations on the cursor.
98
        'serverTimeout' => null,
99
    );
100
101
    /**
102
     * Use document pool to create Document object from array
103
     * @var bool
104
     */
105
    private $isDocumentPoolUsed = true;
106
107
    /**
108
     * Index hinting
109
     * @param \Sokil\Mongo\Collection $collection
110
     * @param array $options
111
     */
112
    private $hint;
113
114
    public function __construct(Collection $collection, array $options = null)
115
    {
116
        $this->collection = $collection;
117
118
        $this->client = $this->collection->getDatabase()->getClient();
119
120
        if (!empty($options)) {
121
            $this->options = $options + $this->options;
122
        }
123
124
        // expression
125
        $this->expression = $this->expression();
126
    }
127
128
    public function __call($name, $arguments)
129
    {
130
        call_user_func_array(
131
            array($this->expression, $name),
132
            $arguments
133
        );
134
135
        return $this;
136
    }
137
138
    /**
139
     * Get option
140
     *
141
     * @param string|int $name
142
     * @param mixed $default
143
     *
144
     * @return mixed
145
     */
146
    public function getOption($name, $default = null)
147
    {
148
        return isset($this->options[$name]) ? $this->options[$name] : $default;
149
    }
150
151
    /**
152
     * Get result as array
153
     *
154
     * @return $this
155
     */
156
    public function asArray()
157
    {
158
        $this->isResultAsArray = true;
159
        return $this;
160
    }
161
162
    /**
163
     * Get result as object
164
     * @return $this
165
     */
166
    public function asObject()
167
    {
168
        $this->isResultAsArray = false;
169
        return $this;
170
    }
171
172
    /**
173
     * Check if result returned as array
174
     * @return bool
175
     */
176
    public function isResultAsArray()
177
    {
178
        return $this->isResultAsArray;
179
    }
180
181
    /**
182
     * Return only specified fields
183
     *
184
     * @param array $fields
185
     * @return Cursor
186
     */
187
    public function fields(array $fields)
188
    {
189
        $this->fields = array_fill_keys($fields, 1);
190
        $this->skipDocumentPool();
191
        return $this;
192
    }
193
194
    /**
195
     * Append field to accept list
196
     *
197
     * @param string $field field name
198
     *
199
     * @return Cursor
200
     */
201
    public function field($field)
202
    {
203
        $this->fields[$field] = 1;
204
        $this->skipDocumentPool();
205
        return $this;
206
    }
207
    /**
208
     * Return all fields except specified
209
     *
210
     * @param array $fields
211
     * @return \Sokil\Mongo\Cursor
212
     */
213
    public function skipFields(array $fields)
214
    {
215
        $this->fields = array_fill_keys($fields, 0);
216
        $this->skipDocumentPool();
217
        return $this;
218
    }
219
220
    /**
221
     * Append field to skip list
222
     *
223
     * @param string $field field name
224
     * @return Cursor
225
     */
226
    public function skipField($field)
227
    {
228
        $this->fields[$field] = 0;
229
        $this->skipDocumentPool();
230
        return $this;
231
    }
232
233
    /**
234
     * Paginate list of sub-documents
235
     *
236
     * @param string $field
237
     * @param integer $limit
238
     * @param integer $skip
239
     * @return \Sokil\Mongo\Cursor
240
     * @throws Exception
241
     */
242
    public function slice($field, $limit, $skip = null)
243
    {
244
        $limit  = (int) $limit;
245
        $skip   = (int) $skip;
246
247
        if ($skip) {
248
            $this->fields[$field] = array('$slice' => array($skip, $limit));
249
        } else {
250
            $this->fields[$field] = array('$slice' => $limit);
251
        }
252
253
        $this->skipDocumentPool();
254
255
        return $this;
256
    }
257
258
    /**
259
     * Merge expression
260
     * @param \Sokil\Mongo\Expression $expression
261
     * @return \Sokil\Mongo\Cursor
262
     */
263
    public function query(Expression $expression)
264
    {
265
        $this->expression->merge($expression);
266
        return $this;
267
    }
268
269
    /**
270
     * Helper to create new expression
271
     *
272
     * @return \Sokil\Mongo\Expression
273
     */
274
    public function expression()
275
    {
276
        return new $this->options['expressionClass'];
277
    }
278
279
    /**
280
     * Filter by list of \MongoId
281
     *
282
     * @param array $idList list of ids
283
     * @return \Sokil\Mongo\Cursor
284
     */
285
    public function byIdList(array $idList)
286
    {
287
        $this->expression->whereIn('_id', self::mixedToMongoIdList($idList));
288
        return $this;
289
    }
290
291
    /**
292
     * Filter by id
293
     *
294
     * @param string|\MongoId $id id of document
295
     * @return \Sokil\Mongo\Cursor
296
     */
297
    public function byId($id)
298
    {
299
        if ($id instanceof \MongoId) {
300
            $this->expression->where('_id', $id);
301
        } else {
302
            try {
303
                $this->expression->where('_id', new \MongoId($id));
304
            } catch (\MongoException $e) {
305
                $this->expression->where('_id', $id);
306
            }
307
        }
308
309
        return $this;
310
    }
311
312
    /**
313
     * Skip defined number of documents
314
     *
315
     * @param int $skip number of documents to skip
316
     * @return \Sokil\Mongo\Cursor
317
     */
318
    public function skip($skip)
319
    {
320
        $this->skip = (int) $skip;
321
322
        return $this;
323
    }
324
325
    /**
326
     * Limit result set to specified number of elements
327
     *
328
     * @param int $limit number of elements in result set
329
     * @param int|null $offset number of elements to skip
330
     * @return \Sokil\Mongo\Cursor
331
     */
332
    public function limit($limit, $offset = null)
333
    {
334
        $this->limit = (int) $limit;
335
336
        if (null !== $offset) {
337
            $this->skip($offset);
338
        }
339
340
        return $this;
341
    }
342
343
    /**
344
     * Specifies the number of documents to return in each batch of the response from the MongoDB instance.
345
     *
346
     * @param int $size number of documents
347
     * @link http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
348
     * @return \Sokil\Mongo\Cursor
349
     */
350
    public function setBatchSize($size)
351
    {
352
        $this->options['batchSize'] = (int) $size;
353
354
        return $this;
355
    }
356
357
    /**
358
     * Instructs the driver to stop waiting for a response and throw a
359
     * MongoCursorTimeoutException after a set time.
360
     * A timeout can be set at any time and will affect subsequent queries on
361
     * the cursor, including fetching more results from the database.
362
     *
363
     * @param int $ms
364
     * @return Cursor
365
     */
366
    public function setClientTimeout($ms)
367
    {
368
        $this->options['clientTimeout'] = (int) $ms;
369
        return $this;
370
    }
371
372
    /**
373
     * Server-side timeout for a query,
374
     * Specifies a cumulative time limit in milliseconds to be allowed
375
     * by the server for processing operations on the cursor.
376
     *
377
     * @param int $ms
378
     * @return \Sokil\Mongo\Cursor
379
     */
380
    public function setServerTimeout($ms)
381
    {
382
        $this->options['serverTimeout'] = (int) $ms;
383
        return $this;
384
    }
385
386
    /**
387
     * Sort result by specified keys and directions
388
     *
389
     *  An array of fields by which to sort. Each element in the array has as key the field name, and as value either
390
     * 1 for ascending sort, or -1 for descending sort. Each result is first sorted on the first field in the array,
391
     * then (if it exists) on the second field in the array, etc. This means that the order of the fields in the
392
     * fields array is important. See also the examples section.
393
     *
394
     * @param array $sort
395
     * @return Cursor
396
     */
397
    public function sort(array $sort)
398
    {
399
        $this->sort = $sort;
400
        return $this;
401
    }
402
403
    /**
404
     * Count documents in result without applying limit and offset
405
     * @return int count
406
     */
407
    public function count()
408
    {
409
        return (int) $this->collection
410
            ->getMongoCollection()
411
            ->count($this->expression->toArray());
412
    }
413
414
    /**
415
     * Explain expression
416
     *
417
     * @return array
418
     *
419
     * @throws FeatureNotSupportedException
420
     */
421
    public function explain()
422
    {
423
        if (Client::isEmulationMode()) {
424
            throw new FeatureNotSupportedException('Feature not implemented in emulation mode');
425
        }
426
427
        $this->rewind();
428
429
        return $this->cursor->explain();
430
    }
431
432
    /**
433
     * Count documents in result with applying limit and offset
434
     *
435
     * ext-mongo:1.0.7  Added limit and skip as second and third parameters, respectively.
436
     * ext-mongo:1.6.0  The second parameter is now an options array. Passing limit and skip as the second and third
437
     *                  parameters, respectively, is deprecated.
438
     *
439
     * @return int
440
     *
441
     * @throws FeatureNotSupportedException
442
     */
443
    public function limitedCount()
444
    {
445
        if (version_compare(\MongoClient::VERSION, '1.0.7', '<')) {
446
            throw new FeatureNotSupportedException('Limit and skip not supported in ext-mongo versions prior to 1.0.7');
447
        }
448
449
        return (int) $this->collection
450
            ->getMongoCollection()
451
            ->count(
452
                $this->expression->toArray(),
453
                $this->limit,
454
                $this->skip
455
            );
456
    }
457
458
459
    /**
460
     * Gte list of \MongoId of current search query
461
     * @return array
462
     */
463
    public function getIdList()
464
    {
465
        return self::mixedToMongoIdList($this->findAll());
466
    }
467
468
    /**
469
     * Find one document which correspond to expression
470
     *
471
     * @return Document|array|null
472
     *
473
     * @throws CursorException
474
     */
475
    public function findOne()
476
    {
477
        try {
478
            $mongoDocument = $this->collection
479
                ->getMongoCollection()
480
                ->findOne(
481
                    $this->expression->toArray(),
482
                    $this->fields
483
                );
484
        } catch (\Exception $e) {
485
            throw new CursorException(
486
                $e->getMessage(),
487
                $e->getCode(),
488
                $e
489
            );
490
        }
491
492
        if (empty($mongoDocument)) {
493
            return null;
494
        }
495
496
        if (true === $this->isResultAsArray) {
497
            return $mongoDocument;
498
        }
499
500
        return $this->collection->hydrate(
501
            $mongoDocument,
502
            $this->isDocumentPoolUsed()
503
        );
504
    }
505
506
    /**
507
     * Get result of searching
508
     *
509
     * @return array
510
     */
511
    public function findAll()
512
    {
513
        return iterator_to_array($this);
514
    }
515
516
    /**
517
     * Get random document
518
     *
519
     * @return Document|null
520
     */
521
    public function findRandom()
522
    {
523
        $count = $this->count();
524
        switch ($count) {
525
            case 0:
526
                return null;
527
            case 1:
528
                return $this->findOne();
529
            default:
530
                $cursor = $this->skip(mt_rand(0, $count - 1))->limit(1);
531
                $cursor->rewind();
532
                return $cursor->current();
533
        }
534
    }
535
536
    /**
537
     * Get query builder's expression
538
     *
539
     * @return Expression
540
     */
541
    public function getExpression()
542
    {
543
        return $this->expression;
544
    }
545
546
    /**
547
     * Get MongoDB query array
548
     *
549
     * @return array
550
     */
551
    public function getMongoQuery()
552
    {
553
        return $this->expression->toArray();
554
    }
555
    
556
    /**
557
     * Return the values from a single field in the result set of documents
558
     *
559
     * @param string $fieldName
560
     * @return array
561
     */
562
    public function pluck($fieldName)
563
    {
564
        $isEmbeddedDocumentField = false !== strpos($fieldName, '.');
565
566
        $valueList = array();
567
568
        if ($isEmbeddedDocumentField) {
569
            // get result
570
            if ($this->isResultAsArray) {
571
                $cursor = clone $this;
572
                $documentObjectList = $cursor->asObject()->findAll();
573
                unset($cursor);
574
            } else {
575
                $documentObjectList = $this->findAll();
576
            }
577
            // get value of field
578
            foreach ($documentObjectList as $key => $documentObject) {
579
                $valueList[$key] = $documentObject->get($fieldName);
580
            }
581
        } else {
582
            // get result
583
            if ($this->isResultAsArray) {
584
                $documentArrayList = $this->findAll();
585
            } else {
586
                $cursor = clone $this;
587
                $documentArrayList = $cursor->asArray()->findAll();
588
                unset($cursor);
589
            }
590
            // get values of field
591
            $valueList = array_column($documentArrayList, $fieldName, '_id');
592
        }
593
594
        return $valueList;
595
    }
596
597
    /**
598
     * Get document instance and remove it from collection
599
     *
600
     * @return \Sokil\Mongo\Document
601
     */
602
    public function findAndRemove()
603
    {
604
        $mongoDocument = $this->collection->getMongoCollection()->findAndModify(
605
            $this->expression->toArray(),
606
            null,
607
            $this->fields,
608
            array(
609
                'remove' => true,
610
                'sort' => $this->sort,
611
            )
612
        );
613
614
        if (empty($mongoDocument)) {
615
            return null;
616
        }
617
618
        return $this->collection->hydrate(
619
            $mongoDocument,
620
            $this->isDocumentPoolUsed()
621
        );
622
    }
623
624
    /**
625
     * Find first document and update it
626
     *
627
     * @param Operator $operator operations with document to update
628
     * @param bool $upsert if document not found - create
629
     * @param bool $returnUpdated if true - return updated document
630
     *
631
     * @return null|Document
632
     */
633
    public function findAndUpdate(Operator $operator, $upsert = false, $returnUpdated = true)
634
    {
635
        $mongoDocument = $this->collection
636
            ->getMongoCollection()
637
            ->findAndModify(
638
                $this->expression->toArray(),
639
                $operator ? $operator->toArray() : null,
640
                $this->fields,
641
                array(
642
                    'new' => $returnUpdated,
643
                    'sort' => $this->sort,
644
                    'upsert' => $upsert,
645
                )
646
            );
647
648
        if (empty($mongoDocument)) {
649
            return null;
650
        }
651
652
        return $this->collection->hydrate($mongoDocument, $this->isDocumentPoolUsed());
653
    }
654
655
    /**
656
     * Apply callable to all documents in cursor
657
     *
658
     * @param callable $handler
659
     * @return array
660
     */
661 View Code Duplication
    public function map($handler)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
662
    {
663
        $result = array();
664
665
        foreach ($this as $id => $document) {
666
            $result[$id] = $handler($document);
667
        }
668
669
        return $result;
670
    }
671
672
    /**
673
     * Filter documents in cursor by condition in callable
674
     *
675
     * @param callable $handler
676
     * @return array
677
     */
678 View Code Duplication
    public function filter($handler)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
679
    {
680
        $result = array();
681
682
        foreach ($this as $id => $document) {
683
            if (!$handler($document)) {
684
                continue;
685
            }
686
687
            $result[$id] = $document;
688
        }
689
690
        return $result;
691
    }
692
693
    /**
694
     * Get result set of documents.
695
     *
696
     * @return \Sokil\Mongo\ResultSet
697
     */
698
    public function getResultSet()
699
    {
700
        return new ResultSet($this->findAll());
701
    }
702
703
    /**
704
     * Get paginator
705
     *
706
     * @param int $page page number
707
     * @param int $itemsOnPage number of items on page
708
     * @return Paginator
709
     */
710
    public function paginate($page, $itemsOnPage = 30)
711
    {
712
        $paginator = new Paginator($this);
713
714
        return $paginator
715
            ->setCurrentPage($page)
716
            ->setItemsOnPage($itemsOnPage);
717
    }
718
719
    /**
720
     * Clears the cursor
721
     */
722
    public function reset()
723
    {
724
        if ($this->cursor !== null) {
725
            $this->cursor->reset();
726
        }
727
728
        return $this;
729
    }
730
731
    /**
732
     * Returns the cursor to the beginning of the result set.
733
     * This is identical to call reset() && next().
734
     * @return void
735
     */
736
    public function rewind()
737
    {
738
        if ($this->cursor !== null) {
739
            $this->cursor->rewind();
740
            return;
741
        }
742
743
        $this->cursor = $this->collection
744
            ->getMongoCollection()
745
            ->find(
746
                $this->expression->toArray(),
747
                $this->fields
748
            );
749
750
        if ($this->skip) {
751
            $this->cursor->skip($this->skip);
752
        }
753
754
        if ($this->limit) {
755
            $this->cursor->limit($this->limit);
756
        }
757
758
        if ($this->options['batchSize']) {
759
            $this->cursor->batchSize($this->options['batchSize']);
760
        }
761
762
        if ($this->options['clientTimeout']) {
763
            $this->cursor->timeout($this->options['clientTimeout']);
764
        }
765
766
        if ($this->options['serverTimeout']) {
767
            $this->cursor->maxTimeMS($this->options['clientTimeout']);
768
        }
769
770
        if (!empty($this->sort)) {
771
            $this->cursor->sort($this->sort);
772
        }
773
774
        if ($this->hint) {
775
            $this->cursor->hint($this->hint);
776
        }
777
778
        // define read preferences
779
        if (!empty($this->readPreference)) {
780
            $this->cursor->setReadPreference(
781
                $this->readPreference['type'],
782
                $this->readPreference['tagsets']
783
            );
784
        }
785
786
        // init cursor state
787
        $this->cursor->rewind();
788
    }
789
790
    /**
791
     * @return bool
792
     */
793
    public function valid()
794
    {
795
        return $this->cursor->valid();
796
    }
797
798
    /**
799
     * @return Document|array|null
800
     */
801
    public function current()
802
    {
803
        $mongoDocument = $this->cursor->current();
804
        if (empty($mongoDocument)) {
805
            return null;
806
        }
807
808
        if ($this->isResultAsArray) {
809
            return $mongoDocument;
810
        }
811
812
        return $this->collection->hydrate(
813
            $mongoDocument,
814
            $this->isDocumentPoolUsed
815
        );
816
    }
817
818
    /**
819
     * @return string
820
     */
821
    public function key()
822
    {
823
        return $this->cursor->key();
824
    }
825
826
    /**
827
     * @return void
828
     */
829
    public function next()
830
    {
831
        $this->cursor->next();
832
    }
833
834
    public function readPrimaryOnly()
835
    {
836
        $this->readPreference = array(
837
            'type'      => \MongoClient::RP_PRIMARY,
838
            'tagsets'   => array(),
839
        );
840
841
        return $this;
842
    }
843
844
    public function readPrimaryPreferred(array $tags = null)
845
    {
846
        $this->readPreference = array(
847
            'type'      => \MongoClient::RP_PRIMARY_PREFERRED,
848
            'tagsets'   => $tags,
849
        );
850
851
        return $this;
852
    }
853
854
    public function readSecondaryOnly(array $tags = null)
855
    {
856
        $this->readPreference = array(
857
            'type'      => \MongoClient::RP_SECONDARY,
858
            'tagsets'   => $tags,
859
        );
860
861
        return $this;
862
    }
863
864
    public function readSecondaryPreferred(array $tags = null)
865
    {
866
        $this->readPreference = array(
867
            'type'      => \MongoClient::RP_SECONDARY_PREFERRED,
868
            'tagsets'   => $tags,
869
        );
870
871
        return $this;
872
    }
873
874
    public function readNearest(array $tags = null)
875
    {
876
        $this->readPreference = array(
877
            'type'      => \MongoClient::RP_NEAREST,
878
            'tagsets'   => $tags,
879
        );
880
881
        return $this;
882
    }
883
884
    /**
885
     * @return array
886
     */
887
    public function getReadPreference()
888
    {
889
        if ($this->cursor) {
890
            return $this->cursor->getReadPreference();
891
        }
892
893
        return $this->readPreference;
894
    }
895
896
    public function isDocumentPoolUsed()
897
    {
898
        return $this->isDocumentPoolUsed;
899
    }
900
901
    public function useDocumentPool()
902
    {
903
        $this->isDocumentPoolUsed = true;
904
        return $this;
905
    }
906
907
    public function skipDocumentPool()
908
    {
909
        $this->isDocumentPoolUsed = false;
910
        return $this;
911
    }
912
913
    /**
914
     * Specify index to use
915
     *
916
     * @link http://docs.mongodb.org/manual/reference/operator/meta/hint/
917
     * @param array|string $specification Specify the index either by the index name or by document
918
     * @return \Sokil\Mongo\Cursor
919
     */
920
    public function hint($specification)
921
    {
922
        $this->hint = $specification;
923
        return $this;
924
    }
925
926
    /**
927
     * Copy selected documents to another collection
928
     *
929
     * @param string $targetCollectionName
930
     * @param string|null $targetDatabaseName Target database name. If not specified - use current
931
     * @param int $batchLimit count of documents to get from old and insert to new collection per time
932
     *
933
     * @return Cursor
934
     *
935
     * @throws WriteException
936
     */
937
    public function copyToCollection(
938
        $targetCollectionName,
939
        $targetDatabaseName = null,
940
        $batchLimit = 100
941
    ) {
942
        // target database
943
        if (empty($targetDatabaseName)) {
944
            $database = $this->collection->getDatabase();
945
        } else {
946
            $database = $this->client->getDatabase($targetDatabaseName);
947
        }
948
949
        // target collection
950
        $targetMongoCollection = $database
951
            ->getCollection($targetCollectionName)
952
            ->getMongoCollection();
953
954
        // cursor
955
        $this->rewind();
956
957
        // copy data
958
        $inProgress = true;
959
        while ($inProgress) {
960
            // get next pack of documents
961
            $documentList = array();
962
            for ($i = 0; $i < $batchLimit; $i++) {
963
                if (!$this->cursor->valid()) {
964
                    $inProgress = false;
965
966
                    if (!empty($documentList)) {
967
                        // still need batch insert
968
                        break;
969
                    } else {
970
                        // no documents to insert - just exit
971
                        break(2);
972
                    }
973
                }
974
975
                $documentList[] = $this->cursor->current();
976
                $this->cursor->next();
977
            }
978
979
            // insert
980
            $result = $targetMongoCollection->batchInsert($documentList);
981
982
            // With passed write concern, returns an associative array with the status of the inserts ("ok")
983
            // and any error that may have occurred ("err").
984
            // Otherwise, returns TRUE if the batch insert was successfully sent, FALSE otherwise.
985
            if (is_array($result)) {
986
                if ($result['ok'] != 1) {
987
                    throw new WriteException('Batch insert error: ' . $result['err']);
988
                }
989
            } elseif (false === $result) {
990
                throw new WriteException('Batch insert error');
991
            }
992
        }
993
994
        return $this;
995
    }
996
997
    /**
998
     * Move selected documents to another collection.
999
     * Documents will be removed from source collection only after
1000
     * copying them to target collection.
1001
     *
1002
     * @param string $targetCollectionName
1003
     * @param string|null $targetDatabaseName Target database name. If not specified - use current
1004
     * @param int $batchLimit count of documents to get from old and insert to new collection per time
1005
     */
1006
    public function moveToCollection(
1007
        $targetCollectionName,
1008
        $targetDatabaseName = null,
1009
        $batchLimit = 100
1010
    ) {
1011
        // copy to target
1012
        $this->copyToCollection($targetCollectionName, $targetDatabaseName, $batchLimit);
1013
1014
        // remove from source
1015
        $this->collection->batchDelete($this->expression);
0 ignored issues
show
Documentation introduced by
$this->expression is of type object<Sokil\Mongo\Expression>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1016
    }
1017
1018
    /**
1019
     * Used to get hash that uniquely identifies current query
1020
     *
1021
     * @return string
1022
     */
1023
    public function getHash()
1024
    {
1025
        $hash = array();
1026
1027
        // expression
1028
        $hash[] = json_encode($this->expression->toArray());
1029
1030
        // sorts
1031 View Code Duplication
        if (!empty($this->sort)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1032
            $sort = $this->sort;
1033
            ksort($sort);
1034
            $hash[] = implode('', array_merge(array_keys($sort), array_values($sort)));
1035
        }
1036
1037
        // fields
1038 View Code Duplication
        if (!empty($this->fields)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1039
            $fields = $this->fields;
1040
            ksort($fields);
1041
            $hash[] = implode('', array_merge(array_keys($fields), array_values($fields)));
1042
        }
1043
1044
        // skip and limit
1045
        $hash[] = $this->skip;
1046
        $hash[] = $this->limit;
1047
1048
        // get hash
1049
        return md5(implode(':', $hash));
1050
    }
1051
1052
    /**
1053
     * Get list of MongoId objects from array of strings, MongoId's and Document's
1054
     *
1055
     * @param array $list
1056
     * @return array list of \MongoId
1057
     */
1058
    public static function mixedToMongoIdList(array $list)
1059
    {
1060
        return array_map(function ($element) {
1061
            // MongoId
1062
            if ($element instanceof \MongoId) {
1063
                return $element;
1064
            }
1065
1066
            // \Sokil\Mongo\Document
1067
            if ($element instanceof Document) {
1068
                return $element->getId();
1069
            }
1070
1071
            // array with id key
1072
            if (is_array($element)) {
1073
                if (!isset($element['_id'])) {
1074
                    throw new \InvalidArgumentException('Array must have _id key');
1075
                }
1076
                return $element['_id'];
1077
            }
1078
1079
            // string
1080
            if (is_string($element)) {
1081
                try {
1082
                    return new \MongoId($element);
1083
                } catch (\MongoException $e) {
1084
                    return $element;
1085
                }
1086
            }
1087
1088
            // int
1089
            if (is_int($element)) {
1090
                return $element;
1091
            }
1092
1093
            throw new \InvalidArgumentException('Must be \MongoId, \Sokil\Mongo\Document, array with _id key, string or integer');
1094
        }, array_values($list));
1095
    }
1096
}
1097