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 ( 8481f6...51fc84 )
by De
02:25
created

Cursor::skipField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
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
17
/**
18
 * @mixin Expression
19
 */
20
class Cursor implements
21
    \Iterator,
22
    \Countable
23
{
24
    /**
25
     *
26
     * @var \Sokil\Mongo\Client
27
     */
28
    private $client;
29
30
    /**
31
     *
32
     * @var \Sokil\Mongo\Collection
33
     */
34
    private $collection;
35
36
    /**
37
     *
38
     * @var array
39
     */
40
    private $fields = array();
41
42
    /**
43
     *
44
     * @var \MongoCursor
45
     */
46
    private $cursor;
47
    /**
48
     *
49
     * @var Expression
50
     */
51
    private $expression;
52
53
    /**
54
     * Offset
55
     * @var int
56
     */
57
    private $skip = 0;
58
59
    /**
60
     * Limit
61
     * @var int
62
     */
63
    private $limit = 0;
64
65
    /**
66
     * Definition of sort
67
     * @var array
68
     */
69
    private $sort = array();
70
71
    /**
72
     * Definition of read preference
73
     * @var array
74
     */
75
    private $readPreference = array();
76
77
    /**
78
     * Return result as array or as Document instance
79
     * @var boolean 
80
     */
81
    private $isResultAsArray = false;
82
83
    /**
84
     * Cursor options
85
     * @var array
86
     */
87
    private $options = array(
88
        'expressionClass' => '\Sokil\Mongo\Expression',
89
        /**
90
         * @link http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
91
         * @var int number of documents to return in each batch of the response from the MongoDB instance
92
         */
93
        'batchSize' => null,
94
        // client timeout
95
        'clientTimeout' => null,
96
        // Specifies a cumulative time limit in milliseconds to be allowed by the server for processing operations on the cursor.
97
        'serverTimeout' => null,
98
    );
99
100
    /**
101
     * Use document pool to create Document object from array
102
     * @var bool
103
     */
104
    private $isDocumentPoolUsed = true;
105
106
    /**
107
     * Index hinting
108
     * @param \Sokil\Mongo\Collection $collection
109
     * @param array $options
110
     */
111
    private $hint;
112
113
    public function __construct(Collection $collection, array $options = null)
114
    {
115
        $this->collection = $collection;
116
117
        $this->client = $this->collection->getDatabase()->getClient();
118
119
        if ($options) {
120
            $this->options = $options + $this->options;
121
        }
122
123
        // expression
124
        $this->expression = $this->expression();
125
    }
126
127
    public function __call($name, $arguments)
128
    {
129
        call_user_func_array(
130
            array($this->expression, $name),
131
            $arguments
132
        );
133
134
        return $this;
135
    }
136
137
    /**
138
     * Get option
139
     *
140
     * @param string|int $name
141
     * @return mixed
142
     */
143
    public function getOption($name, $default = null)
144
    {
145
        return isset($this->options[$name]) ? $this->options[$name] : $default;
146
    }
147
148
    /**
149
     * Get result as array
150
     * @return $this
151
     */
152
    public function asArray()
153
    {
154
        $this->isResultAsArray = true;
155
        return $this;
156
    }
157
158
    /**
159
     * Get result as object
160
     * @return $this
161
     */
162
    public function asObject()
163
    {
164
        $this->isResultAsArray = false;
165
        return $this;
166
    }
167
168
    /**
169
     * Check if result returned as array
170
     * @return bool
171
     */
172
    public function isResultAsArray()
173
    {
174
        return $this->isResultAsArray;
175
    }
176
177
    /**
178
     * Return only specified fields
179
     *
180
     * @param array $fields
181
     * @return \Sokil\Mongo\Cursor
182
     */
183
    public function fields(array $fields)
184
    {
185
        $this->fields = array_fill_keys($fields, 1);
186
187
        $this->skipDocumentPool();
188
189
        return $this;
190
    }
191
192
    /**
193
     * Return all fields except specified
194
     *
195
     * @param array $fields
196
     * @return \Sokil\Mongo\Cursor
197
     */
198
    public function skipFields(array $fields)
199
    {
200
        $this->fields = array_fill_keys($fields, 0);
201
202
        $this->skipDocumentPool();
203
204
        return $this;
205
    }
206
207
    /**
208
     * Append field to accept list
209
     *
210
     * @param string $field field name
211
     * @return \Sokil\Mongo\Cursor
212
     */
213
    public function field($field)
214
    {
215
        $this->fields[$field] = 1;
216
217
        $this->skipDocumentPool();
218
219
        return $this;
220
    }
221
222
    /**
223
     * Append field to skip list
224
     *
225
     * @param string $field field name
226
     * @return Cursor
227
     */
228
    public function skipField($field)
229
    {
230
        $this->fields[$field] = 0;
231
232
        $this->skipDocumentPool();
233
234
        return $this;
235
    }
236
237
    /**
238
     * Paginate list of sub-documents
239
     *
240
     * @param string $field
241
     * @param integer $limit
242
     * @param integer $skip
243
     * @return \Sokil\Mongo\Cursor
244
     * @throws Exception
245
     */
246
    public function slice($field, $limit, $skip = null)
247
    {
248
        $limit  = (int) $limit;
249
        $skip   = (int) $skip;
250
251
        if($skip) {
252
            $this->fields[$field] = array('$slice' => array($skip, $limit));
253
        }
254
        else {
255
            $this->fields[$field] = array('$slice' => $limit);
256
        }
257
258
        $this->skipDocumentPool();
259
260
        return $this;
261
    }
262
263
    /**
264
     * Merge expression
265
     * @param \Sokil\Mongo\Expression $expression
266
     * @return \Sokil\Mongo\Cursor
267
     */
268
    public function query(Expression $expression)
269
    {
270
        $this->expression->merge($expression);
271
        return $this;
272
    }
273
274
    /**
275
     * Helper to create new expression
276
     *
277
     * @return \Sokil\Mongo\Expression
278
     */
279
    public function expression()
280
    {
281
        return new $this->options['expressionClass'];
282
    }
283
284
    /**
285
     * Filter by list of \MongoId
286
     *
287
     * @param array $idList list of ids
288
     * @return \Sokil\Mongo\Cursor
289
     */
290
    public function byIdList(array $idList)
291
    {
292
        $this->expression->whereIn('_id', self::mixedToMongoIdList($idList));
293
        return $this;
294
    }
295
296
    /**
297
     * Filter by id
298
     *
299
     * @param string|\MongoId $id id of document
300
     * @return \Sokil\Mongo\Cursor
301
     */
302
    public function byId($id)
303
    {
304
        if($id instanceof \MongoId) {
305
            $this->expression->where('_id', $id);
306
        } else {
307
            try {
308
                $this->expression->where('_id', new \MongoId($id));
309
            } catch (\MongoException $e) {
310
                $this->expression->where('_id', $id);
311
            }
312
        }
313
314
        return $this;
315
    }
316
317
    /**
318
     * Skip defined number of documents
319
     *
320
     * @param int $skip number of documents to skip
321
     * @return \Sokil\Mongo\Cursor
322
     */
323
    public function skip($skip)
324
    {
325
        $this->skip = (int) $skip;
326
327
        return $this;
328
    }
329
330
    /**
331
     * Limit result set to specified number of elements
332
     *
333
     * @param int $limit number of elements in result set
334
     * @param int|null $offset number of elements to skip
335
     * @return \Sokil\Mongo\Cursor
336
     */
337
    public function limit($limit, $offset = null)
338
    {
339
        $this->limit = (int) $limit;
340
341
        if(null !== $offset) {
342
            $this->skip($offset);
343
        }
344
345
        return $this;
346
    }
347
348
    /**
349
     * Specifies the number of documents to return in each batch of the response from the MongoDB instance.
350
     *
351
     * @param int $size number of documents
352
     * @link http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
353
     * @return \Sokil\Mongo\Cursor
354
     */
355
    public function setBatchSize($size)
356
    {
357
        $this->options['batchSize'] = (int) $size;
358
359
        return $this;
360
    }
361
362
    /**
363
     * Instructs the driver to stop waiting for a response and throw a
364
     * MongoCursorTimeoutException after a set time,
365
     * A timeout can be set at any time and will affect subsequent queries on
366
     * the cursor, including fetching more results from the database.
367
     * @param type $ms
368
     * @return \Sokil\Mongo\Cursor
369
     */
370
    public function setClientTimeout($ms)
371
    {
372
        $this->options['clientTimeout'] = (int) $ms;
373
374
        return $this;
375
    }
376
377
    /**
378
     * Server-side timeout for a query,
379
     * Specifies a cumulative time limit in milliseconds to be allowed
380
     * by the server for processing operations on the cursor.
381
     * @param type $ms
382
     * @return \Sokil\Mongo\Cursor
383
     */
384
    public function setServerTimeout($ms)
385
    {
386
        $this->options['serverTimeout'] = (int) $ms;
387
388
        return $this;
389
    }
390
391
    /**
392
     * Sort result by specified keys and directions
393
     *
394
     *  An array of fields by which to sort. Each element in the array has as key the field name, and as value either
395
     * 1 for ascending sort, or -1 for descending sort. Each result is first sorted on the first field in the array,
396
     * then (if it exists) on the second field in the array, etc. This means that the order of the fields in the
397
     * fields array is important. See also the examples section.
398
     *
399
     * @param array $sort
400
     * @return \Sokil\Mongo\Cursor
401
     */
402
    public function sort(array $sort)
403
    {
404
        $this->sort = $sort;
405
        return $this;
406
    }
407
408
    /**
409
     *
410
     * @return \MongoCursor
411
     */
412
    private function getCursor()
413
    {
414
        if($this->cursor) {
415
            return $this->cursor;
416
        }
417
418
        $this->cursor = $this->collection
419
            ->getMongoCollection()
420
            ->find($this->expression->toArray(), $this->fields);
421
422
        if($this->skip) {
423
            $this->cursor->skip($this->skip);
424
        }
425
426
        if($this->limit) {
427
            $this->cursor->limit($this->limit);
428
        }
429
430
        if($this->options['batchSize']) {
431
            $this->cursor->batchSize($this->options['batchSize']);
432
        }
433
434
        if($this->options['clientTimeout']) {
435
            $this->cursor->timeout($this->options['clientTimeout']);
436
        }
437
438
        if($this->options['serverTimeout']) {
439
            $this->cursor->maxTimeMS($this->options['clientTimeout']);
440
        }
441
442
        if (!empty($this->sort)) {
443
            $this->cursor->sort($this->sort);
444
        }
445
446
        if($this->hint) {
447
            $this->cursor->hint($this->hint);
448
        }
449
450
        // log request
451
        if($this->client->hasLogger()) {
452
            $this->client->getLogger()->debug(get_called_class() . ': ' . json_encode(array(
453
                'collection' => $this->collection->getName(),
454
                'query' => $this->expression->toArray(),
455
                'project' => $this->fields,
456
                'sort' => $this->sort,
457
            )));
458
        }
459
460
        $this->cursor->rewind();
461
462
        // define read preferences
463
        if (!empty($this->readPreference)) {
464
            $this->cursor->setReadPreference(
465
                $this->readPreference['type'],
466
                $this->readPreference['tagsets']
467
            );
468
        }
469
470
        return $this->cursor;
471
    }
472
473
    /**
474
     * Count documents in result without applying limit and offset
475
     * @return int count
476
     */
477
    public function count()
478
    {
479
        return (int) $this->collection
480
            ->getMongoCollection()
481
            ->count($this->expression->toArray());
482
    }
483
484
    public function explain()
485
    {
486
        if (Client::isEmulationMode()) {
487
            throw new FeatureNotSupportedException('Feature not implemented in emulation mode');
488
        }
489
490
        return $this->getCursor()->explain();
491
    }
492
493
    /**
494
     * Count documents in result with applying limit and offset
495
     * @return int count
496
     */
497
    public function limitedCount()
498
    {
499
        return (int) $this->collection
500
            ->getMongoCollection()
501
            ->count($this->expression->toArray(), $this->limit, $this->skip);
502
    }
503
504
505
    /**
506
     * Gte list of \MongoId of current search query
507
     * @return array
508
     */
509
    public function getIdList()
510
    {
511
        return self::mixedToMongoIdList($this->findAll());
512
    }
513
514
    /**
515
     * Find one document which correspond to expression
516
     * 
517
     * @return \Sokil\Mongo\Document|array|null
518
     */
519
    public function findOne()
520
    {
521
        try {
522
            $mongoDocument = $this->collection
523
                ->getMongoCollection()
524
                ->findOne(
525
                    $this->expression->toArray(),
526
                    $this->fields
527
                );
528
        } catch (\Exception $e) {
529
            throw new CursorException(
530
                $e->getMessage(),
531
                $e->getCode(),
532
                $e
533
            );
534
        }
535
536
        if (empty($mongoDocument)) {
537
            return null;
538
        }
539
540
        if (true === $this->isResultAsArray) {
541
            return $mongoDocument;
542
        }
543
544
        return $this->collection->hydrate(
545
            $mongoDocument,
546
            $this->isDocumentPoolUsed()
547
        );
548
    }
549
550
    /**
551
     *
552
     * @return array result of searching
553
     */
554
    public function findAll()
555
    {
556
        return iterator_to_array($this);
557
    }
558
559
    /**
560
     * Get random document
561
     * @return
562
     */
563
    public function findRandom()
564
    {
565
        $count = $this->count();
566
567
        if(!$count) {
568
            return null;
569
        }
570
571
        if(1 === $count) {
572
            return $this->findOne();
573
        }
574
575
        return $this
576
            ->skip(mt_rand(0, $count - 1))
577
            ->limit(1)
578
            ->current();
579
    }
580
581
    /**
582
     * Get query builder's expression
583
     *
584
     * @return Expression
585
     */
586
    public function getExpression()
587
    {
588
        return $this->expression;
589
    }
590
591
    /**
592
     * Get MongoDB query array
593
     * 
594
     * @return array
595
     */
596
    public function getMongoQuery()
597
    {
598
        return $this->expression->toArray();
599
    }
600
    
601
    /**
602
     * Return the values from a single field in the result set of documents
603
     *
604
     * @param string $fieldName
605
     * @return array
606
     */
607
    public function pluck($fieldName)
608
    {
609
        // if field with embedded document or native php function not exists
610
        if (false !== strpos($fieldName, '.') || !function_exists('array_column')) {
611
            return $this->pluckDotNotated($fieldName);
612
        }
613
614
        // use native php function if field without embedded document
615 View Code Duplication
        if ($this->isResultAsArray) {
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...
616
            $result = $this->findAll();
617
        } else {
618
            $cursor = clone $this;
619
            $result = $cursor->asArray()->findAll();
620
            unset($cursor);
621
        }
622
623
        return array_column($result, $fieldName, '_id');
624
625
    }
626
627
    /**
628
     * Pluck by dot-notated field name
629
     * 
630
     * @param string $fieldName field name
631
     * @return array
632
     */
633
    private function pluckDotNotated($fieldName)
634
    {
635 View Code Duplication
        if ($this->isResultAsArray) {
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...
636
            $cursor = clone $this;
637
            $result = $cursor->asObject()->findAll();
638
            unset($cursor);
639
        } else {
640
            $result = $this->findAll();
641
        }
642
643
        $list = array();
644
        foreach($result as $key => $document) {
645
            $list[$key] = $document->get($fieldName);
646
        }
647
648
        return $list;
649
    }
650
651
    /**
652
     * Get document instance and remove it from collection
653
     *
654
     * @return \Sokil\Mongo\Document
655
     */
656
    public function findAndRemove()
657
    {
658
        $mongoDocument = $this->collection->getMongoCollection()->findAndModify(
659
            $this->expression->toArray(),
660
            null,
661
            $this->fields,
662
            array(
663
                'remove' => true,
664
                'sort' => $this->sort,
665
            )
666
        );
667
668
        if (empty($mongoDocument)) {
669
            return null;
670
        }
671
672
        return $this->collection->hydrate(
673
            $mongoDocument,
674
            $this->isDocumentPoolUsed()
675
        );
676
    }
677
678
    /**
679
     * Find first document and update it
680
     *
681
     * @param Operator $operator operations with document to update
682
     * @param bool $upsert if document not found - create
683
     * @param bool $returnUpdated if true - return updated document
684
     *
685
     * @return null|Document
686
     */
687
    public function findAndUpdate(Operator $operator, $upsert = false, $returnUpdated = true)
688
    {
689
        $mongoDocument = $this->collection
690
            ->getMongoCollection()
691
            ->findAndModify(
692
                $this->expression->toArray(),
693
                $operator ? $operator->toArray() : null,
694
                $this->fields,
695
                array(
696
                    'new' => $returnUpdated,
697
                    'sort' => $this->sort,
698
                    'upsert' => $upsert,
699
                )
700
            );
701
702
        if (empty($mongoDocument)) {
703
            return null;
704
        }
705
706
        return $this->collection->hydrate($mongoDocument, $this->isDocumentPoolUsed());
707
    }
708
709 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...
710
    {
711
        $result = array();
712
713
        foreach($this as $id => $document) {
714
            $result[$id] = $handler($document);
715
        }
716
717
        return $result;
718
    }
719
720 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...
721
    {
722
        $result = array();
723
724
        foreach($this as $id => $document) {
725
            if(!$handler($document)) {
726
                continue;
727
            }
728
729
            $result[$id] = $document;
730
        }
731
732
        return $result;
733
    }
734
735
    /**
736
     * Get result set of documents.
737
     * 
738
     * @return \Sokil\Mongo\ResultSet
739
     */
740
    public function getResultSet()
741
    {
742
        return new ResultSet($this->findAll());
743
    }
744
745
    /**
746
     * Get paginator
747
     *
748
     * @param int $page page number
749
     * @param int $itemsOnPage number of items on page
750
     * @return \Sokil\Mongo\Paginator
751
     */
752
    public function paginate($page, $itemsOnPage = 30)
753
    {
754
        $paginator = new Paginator($this);
755
756
        return $paginator
757
            ->setCurrentPage($page)
758
            ->setItemsOnPage($itemsOnPage);
759
760
    }
761
762
    public function current()
763
    {
764
        $mongoDocument = $this->getCursor()->current();
765
        if (empty($mongoDocument)) {
766
            return null;
767
        }
768
769
        if ($this->isResultAsArray) {
770
            return $mongoDocument;
771
        }
772
773
        return $this->collection->hydrate(
774
            $mongoDocument,
775
            $this->isDocumentPoolUsed()
776
        );
777
    }
778
779
    public function key()
780
    {
781
        return $this->getCursor()->key();
782
    }
783
784
    public function next()
785
    {
786
        $this->getCursor()->next();
787
        return $this;
788
    }
789
790
    public function rewind()
791
    {
792
        $this->getCursor()->rewind();
793
        return $this;
794
    }
795
796
    public function valid()
797
    {
798
        return $this->getCursor()->valid();
799
    }
800
801
    public function readPrimaryOnly()
802
    {
803
        $this->readPreference = array(
804
            'type'      => \MongoClient::RP_PRIMARY,
805
            'tagsets'   => array(),
806
        );
807
808
        return $this;
809
    }
810
811
    public function readPrimaryPreferred(array $tags = null)
812
    {
813
        $this->readPreference = array(
814
            'type'      => \MongoClient::RP_PRIMARY_PREFERRED,
815
            'tagsets'   => $tags,
816
        );
817
818
        return $this;
819
    }
820
821
    public function readSecondaryOnly(array $tags = null)
822
    {
823
        $this->readPreference = array(
824
            'type'      => \MongoClient::RP_SECONDARY,
825
            'tagsets'   => $tags,
826
        );
827
828
        return $this;
829
    }
830
831
    public function readSecondaryPreferred(array $tags = null)
832
    {
833
        $this->readPreference = array(
834
            'type'      => \MongoClient::RP_SECONDARY_PREFERRED,
835
            'tagsets'   => $tags,
836
        );
837
838
        return $this;
839
    }
840
841
    public function readNearest(array $tags = null)
842
    {
843
        $this->readPreference = array(
844
            'type'      => \MongoClient::RP_NEAREST,
845
            'tagsets'   => $tags,
846
        );
847
848
        return $this;
849
    }
850
851
    /**
852
     * @return array
853
     */
854
    public function getReadPreference()
855
    {
856
        if($this->cursor) {
857
            return $this->cursor->getReadPreference();
858
        }
859
860
        return $this->readPreference;
861
    }
862
863
    public function isDocumentPoolUsed()
864
    {
865
        return $this->isDocumentPoolUsed;
866
    }
867
868
    public function useDocumentPool()
869
    {
870
        $this->isDocumentPoolUsed = true;
871
        return $this;
872
    }
873
874
    public function skipDocumentPool()
875
    {
876
        $this->isDocumentPoolUsed = false;
877
        return $this;
878
    }
879
880
    /**
881
     * Specify index to use
882
     *
883
     * @link http://docs.mongodb.org/manual/reference/operator/meta/hint/
884
     * @param array|string $specification Specify the index either by the index name or by document
885
     * @return \Sokil\Mongo\Cursor
886
     */
887
    public function hint($specification)
888
    {
889
        $this->hint = $specification;
890
        return $this;
891
    }
892
893
    /**
894
     * Copy selected documents to another collection
895
     *
896
     * @param type $targetCollectionName
897
     * @param type $targetDatabaseName Target database name. If not specified - use current
898
     */
899
    public function copyToCollection($targetCollectionName, $targetDatabaseName = null)
900
    {
901
        // target database
902
        if(!$targetDatabaseName) {
903
            $database = $this->collection->getDatabase();
904
        } else {
905
            $database = $this->client->getDatabase($targetDatabaseName);
906
        }
907
908
        // target collection
909
        $targetMongoCollection = $database
910
            ->getCollection($targetCollectionName)
911
            ->getMongoCollection();
912
913
        // cursor
914
        $cursor = $this->getCursor();
915
916
        $batchLimit = 100;
917
        $inProgress = true;
918
919
        // copy data
920
        while($inProgress) {
921
            // get next pack of documents
922
            $documentList = array();
923
            for($i = 0; $i < $batchLimit; $i++) {
924
                if(!$cursor->valid()) {
925
                    $inProgress = false;
926
927
                    if($documentList) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $documentList of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
928
                        // still need batch insert
929
                        break;
930
                    } else {
931
                        // no documents to insert - just exit
932
                        break(2);
933
                    }
934
                }
935
936
                $documentList[] = $cursor->current();
937
                $cursor->next();
938
            }
939
940
            // insert
941
            $result = $targetMongoCollection->batchInsert($documentList);
942
943
            // check result
944 View Code Duplication
            if(is_array($result)) {
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...
945
                if($result['ok'] != 1) {
946
                    throw new Exception('Batch insert error: ' . $result['err']);
947
                }
948
            } elseif(!$result) {
949
                throw new Exception('Batch insert error');
950
            }
951
        }
952
953
        return $this;
954
    }
955
956
    /**
957
     * Move selected documents to another collection.
958
     * Dociuments will be removed from source collection only after
959
     * copying them to target collection.
960
     *
961
     * @param type $targetCollectionName
962
     * @param type $targetDatabaseName Target database name. If not specified - use current
963
     */
964
    public function moveToCollection($targetCollectionName, $targetDatabaseName = null)
965
    {
966
        // copy to target
967
        $this->copyToCollection($targetCollectionName, $targetDatabaseName);
968
969
        // remove from source
970
        $this->collection->deleteDocuments($this->expression);
0 ignored issues
show
Documentation introduced by
$this->expression is of type object<Sokil\Mongo\Expression>, but the function expects a array.

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...
Deprecated Code introduced by
The method Sokil\Mongo\Collection::deleteDocuments() has been deprecated with message: since 1.13. Use Collection::batchDelete();

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
971
    }
972
973
    /**
974
     * Used to get hash that uniquely identifies current query
975
     */
976
    public function getHash()
977
    {
978
        $hash = array();
979
980
        // expression
981
        $hash[] = json_encode($this->expression->toArray());
982
983
        // sorts
984 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...
985
            $sort = $this->sort;
986
            ksort($sort);
987
            $hash[] = implode('', array_merge(array_keys($sort), array_values($sort)));
988
        }
989
990
        // fields
991 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...
992
            $fields = $this->fields;
993
            ksort($fields);
994
            $hash[] = implode('', array_merge(array_keys($fields), array_values($fields)));
995
        }
996
997
        // skip and limit
998
        $hash[] = $this->skip;
999
        $hash[] = $this->limit;
1000
1001
        // get hash
1002
        return md5(implode(':', $hash));
1003
    }
1004
1005
    /**
1006
     * Get list of MongoId objects from array of strings, MongoId's and Document's
1007
     *
1008
     * @param array $list
1009
     * @return array list of \MongoId
1010
     */
1011
    public static function mixedToMongoIdList(array $list)
1012
    {
1013
        return array_map(function($element) {
1014
            // MongoId
1015
            if($element instanceof \MongoId) {
1016
                return $element;
1017
            }
1018
1019
            // \Sokil\Mongo\Document
1020
            if($element instanceof Document) {
1021
                return $element->getId();
1022
            }
1023
1024
            // array with id key
1025
            if(is_array($element)) {
1026
                if(!isset($element['_id'])) {
1027
                    throw new \InvalidArgumentException('Array must have _id key');
1028
                }
1029
                return $element['_id'];
1030
            }
1031
1032
            // string
1033
            if(is_string($element)) {
1034
                try {
1035
                    return new \MongoId($element);
1036
                } catch (\MongoException $e) {
1037
                    return $element;
1038
                }
1039
            }
1040
1041
            // int
1042
            if(is_int($element)) {
1043
                return $element;
1044
            }
1045
1046
            throw new \InvalidArgumentException('Must be \MongoId, \Sokil\Mongo\Document, array with _id key, string or integer');
1047
1048
        }, array_values($list));
1049
    }
1050
}
1051