Completed
Pull Request — master (#20)
by
unknown
02:47
created

MongoCursor::sort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4286
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 */
15
16
use Alcaeus\MongoDbAdapter\AbstractCursor;
17
use Alcaeus\MongoDbAdapter\TypeConverter;
18
use Alcaeus\MongoDbAdapter\ExceptionConverter;
19
use MongoDB\Driver\Cursor;
20
use MongoDB\Driver\ReadPreference;
21
use MongoDB\Operation\Find;
22
23
/**
24
 * Result object for database query.
25
 * @link http://www.php.net/manual/en/class.mongocursor.php
26
 */
27
class MongoCursor extends AbstractCursor implements Iterator
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
28
{
29
    /**
30
     * @var bool
31
     */
32
    public static $slaveOkay = false;
33
34
    /**
35
     * @var int
36
     */
37
    public static $timeout = 30000;
38
39
    /**
40
     * @var array
41
     */
42
    protected $optionNames = [
43
        'allowPartialResults',
44
        'batchSize',
45
        'cursorType',
46
        'limit',
47
        'maxTimeMS',
48
        'modifiers',
49
        'noCursorTimeout',
50
        'projection',
51
        'readPreference',
52
        'skip',
53
        'sort',
54
    ];
55
56
    /**
57
     * @var array
58
     */
59
    protected $projection;
60
61
    /**
62
     * @var array
63
     */
64
    protected $query;
65
66
    protected $allowPartialResults;
67
    protected $awaitData;
68
    protected $flags = 0;
69
    protected $hint;
70
    protected $limit;
71
    protected $maxTimeMS;
72
    protected $noCursorTimeout;
73
    protected $options = [];
74
    protected $skip;
75
    protected $snapshot;
76
    protected $sort;
77
    protected $tailable;
78
79
    /**
80
     * Create a new cursor
81
     * @link http://www.php.net/manual/en/mongocursor.construct.php
82
     * @param MongoClient $connection Database connection.
83
     * @param string $ns Full name of database and collection.
84
     * @param array $query Database query.
85
     * @param array $fields Fields to return.
86
     */
87
    public function __construct(MongoClient $connection, $ns, array $query = array(), array $fields = array())
88
    {
89
        parent::__construct($connection, $ns);
90
91
        $this->query = $query;
92
        $this->projection = $fields;
93
    }
94
95
    /**
96
     * Adds a top-level key/value pair to a query
97
     * @link http://www.php.net/manual/en/mongocursor.addoption.php
98
     * @param string $key Fieldname to add.
99
     * @param mixed $value Value to add.
100
     * @throws MongoCursorException
101
     * @return MongoCursor Returns this cursor
102
     */
103
    public function addOption($key, $value)
104
    {
105
        $this->errorIfOpened();
106
        $this->options[$key] = $value;
107
108
        return $this;
109
    }
110
111
    /**
112
     * (PECL mongo &gt;= 1.2.11)<br/>
113
     * Sets whether this cursor will wait for a while for a tailable cursor to return more data
114
     * @param bool $wait [optional] <p>If the cursor should wait for more data to become available.</p>
115
     * @return MongoCursor Returns this cursor.
116
     */
117
    public function awaitData($wait = true)
118
    {
119
        $this->errorIfOpened();
120
        $this->awaitData = $wait;
121
122
        return $this;
123
    }
124
125
126
    /**
127
     * Counts the number of results for this query
128
     * @link http://www.php.net/manual/en/mongocursor.count.php
129
     * @param bool $foundOnly Send cursor limit and skip information to the count function, if applicable.
130
     * @return int The number of documents returned by this cursor's query.
131
     */
132
    public function count($foundOnly = false)
133
    {
134
        if ($foundOnly && $this->cursor !== null) {
135
            return iterator_count($this->ensureIterator());
136
        }
137
138
        $optionNames = ['hint', 'maxTimeMS'];
139
        if ($foundOnly) {
140
            $optionNames = array_merge($optionNames, ['limit', 'skip']);
141
        }
142
143
        $options = $this->getOptions($optionNames) + $this->options;
144
        try {
145
            $count = $this->collection->count(TypeConverter::fromLegacy($this->query), $options);
146
        } catch (\MongoDB\Driver\Exception\Exception $e) {
1 ignored issue
show
Bug introduced by
The class MongoDB\Driver\Exception\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
147
            ExceptionConverter::toLegacy($e);
148
        }
149
150
        return $count;
151
    }
152
153
    /**
154
     * Execute the query
155
     * @link http://www.php.net/manual/en/mongocursor.doquery.php
156
     * @throws MongoConnectionException if it cannot reach the database.
157
     * @return void
158
     */
159
    protected function doQuery()
160
    {
161
        $options = $this->getOptions() + $this->options;
162
163
        try {
164
            $this->cursor = $this->collection->find(TypeConverter::fromLegacy($this->query), $options);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->collection->find(...this->query), $options) of type object<MongoDB\Operation\Cursor> is incompatible with the declared type object<MongoDB\Driver\Cursor> of property $cursor.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
165
        } catch (\MongoDB\Driver\Exception\Exception $e) {
1 ignored issue
show
Bug introduced by
The class MongoDB\Driver\Exception\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
166
            ExceptionConverter::toLegacy($e);
167
        }
168
    }
169
170
    /**
171
     * Return an explanation of the query, often useful for optimization and debugging
172
     * @link http://www.php.net/manual/en/mongocursor.explain.php
173
     * @return array Returns an explanation of the query.
174
     */
175
    public function explain()
176
    {
177
        $this->notImplemented();
178
    }
179
180
    /**
181
     * Sets the fields for a query
182
     * @link http://www.php.net/manual/en/mongocursor.fields.php
183
     * @param array $f Fields to return (or not return).
184
     * @throws MongoCursorException
185
     * @return MongoCursor
186
     */
187
    public function fields(array $f)
188
    {
189
        $this->errorIfOpened();
190
        $this->projection = $f;
191
192
        return $this;
193
    }
194
195
    /**
196
     * Return the next object to which this cursor points, and advance the cursor
197
     * @link http://www.php.net/manual/en/mongocursor.getnext.php
198
     * @throws MongoConnectionException
199
     * @throws MongoCursorTimeoutException
200
     * @return array Returns the next object
201
     */
202
    public function getNext()
203
    {
204
        $this->next();
205
206
        return $this->current();
207
    }
208
209
    /**
210
     * Checks if there are any more elements in this cursor
211
     * @link http://www.php.net/manual/en/mongocursor.hasnext.php
212
     * @throws MongoConnectionException
213
     * @throws MongoCursorTimeoutException
214
     * @return bool Returns true if there is another element
215
     */
216
    public function hasNext()
217
    {
218
        $this->errorIfOpened();
219
        $this->notImplemented();
220
    }
221
222
    /**
223
     * Gives the database a hint about the query
224
     * @link http://www.php.net/manual/en/mongocursor.hint.php
225
     * @param array|string $keyPattern Indexes to use for the query.
226
     * @throws MongoCursorException
227
     * @return MongoCursor Returns this cursor
228
     */
229
    public function hint($keyPattern)
230
    {
231
        $this->errorIfOpened();
232
        $this->hint = $keyPattern;
233
234
        return $this;
235
    }
236
237
    /**
238
     * Sets whether this cursor will timeout
239
     * @link http://www.php.net/manual/en/mongocursor.immortal.php
240
     * @param bool $liveForever If the cursor should be immortal.
241
     * @throws MongoCursorException
242
     * @return MongoCursor Returns this cursor
243
     */
244
    public function immortal($liveForever = true)
245
    {
246
        $this->errorIfOpened();
247
        $this->noCursorTimeout = $liveForever;
248
249
        return $this;
250
    }
251
252
    /**
253
     * Limits the number of results returned
254
     * @link http://www.php.net/manual/en/mongocursor.limit.php
255
     * @param int $num The number of results to return.
256
     * @throws MongoCursorException
257
     * @return MongoCursor Returns this cursor
258
     */
259
    public function limit($num)
260
    {
261
        $this->errorIfOpened();
262
        $this->limit = $num;
263
264
        return $this;
265
    }
266
267
    /**
268
     * @param int $ms
269
     * @return $this
270
     * @throws MongoCursorException
271
     */
272
    public function maxTimeMS($ms)
273
    {
274
        $this->errorIfOpened();
275
        $this->maxTimeMS = $ms;
276
277
        return $this;
278
    }
279
280
    /**
281
     * @link http://www.php.net/manual/en/mongocursor.partial.php
282
     * @param bool $okay [optional] <p>If receiving partial results is okay.</p>
283
     * @return MongoCursor Returns this cursor.
284
     */
285
    public function partial($okay = true)
286
    {
287
        $this->allowPartialResults = $okay;
288
289
        return $this;
290
    }
291
292
    /**
293
     * Clears the cursor
294
     * @link http://www.php.net/manual/en/mongocursor.reset.php
295
     * @return void
296
     */
297
    public function reset()
298
    {
299
        parent::reset();
300
    }
301
302
    /**
303
     * @link http://www.php.net/manual/en/mongocursor.setflag.php
304
     * @param int $flag
305
     * @param bool $set
306
     * @return MongoCursor
307
     */
308
    public function setFlag($flag, $set = true)
0 ignored issues
show
Unused Code introduced by
The parameter $flag is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $set is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
309
    {
310
        $this->notImplemented();
311
    }
312
313
    /**
314
     * Skips a number of results
315
     * @link http://www.php.net/manual/en/mongocursor.skip.php
316
     * @param int $num The number of results to skip.
317
     * @throws MongoCursorException
318
     * @return MongoCursor Returns this cursor
319
     */
320
    public function skip($num)
321
    {
322
        $this->errorIfOpened();
323
        $this->skip = $num;
324
325
        return $this;
326
    }
327
328
    /**
329
     * Sets whether this query can be done on a slave
330
     * This method will override the static class variable slaveOkay.
331
     * @link http://www.php.net/manual/en/mongocursor.slaveOkay.php
332
     * @param boolean $okay If it is okay to query the slave.
333
     * @throws MongoCursorException
334
     * @return MongoCursor Returns this cursor
335
     */
336
    public function slaveOkay($okay = true)
337
    {
338
        $this->errorIfOpened();
339
340
        $this->setReadPreferenceFromSlaveOkay($okay);
341
342
        return $this;
343
    }
344
345
    /**
346
     * Use snapshot mode for the query
347
     * @link http://www.php.net/manual/en/mongocursor.snapshot.php
348
     * @throws MongoCursorException
349
     * @return MongoCursor Returns this cursor
350
     */
351
    public function snapshot()
352
    {
353
        $this->errorIfOpened();
354
        $this->snapshot = true;
355
356
        return $this;
357
    }
358
359
    /**
360
     * Sorts the results by given fields
361
     * @link http://www.php.net/manual/en/mongocursor.sort.php
362
     * @param array $fields An array of fields by which to sort. Each element in the array has as key the field name, and as value either 1 for ascending sort, or -1 for descending sort
363
     * @throws MongoCursorException
364
     * @return MongoCursor Returns the same cursor that this method was called on
365
     */
366
    public function sort(array $fields)
367
    {
368
        $this->errorIfOpened();
369
        $this->sort = $fields;
370
371
        return $this;
372
    }
373
374
    /**
375
     * Sets whether this cursor will be left open after fetching the last results
376
     * @link http://www.php.net/manual/en/mongocursor.tailable.php
377
     * @param bool $tail If the cursor should be tailable.
378
     * @return MongoCursor Returns this cursor
379
     */
380
    public function tailable($tail = true)
381
    {
382
        $this->errorIfOpened();
383
        $this->tailable = $tail;
384
385
        return $this;
386
    }
387
388
    /**
389
     * @return int|null
390
     */
391
    protected function convertCursorType()
392
    {
393
        if (! $this->tailable) {
394
            return null;
395
        }
396
397
        return $this->awaitData ? Find::TAILABLE_AWAIT : Find::TAILABLE;
398
    }
399
400
    protected function convertModifiers()
401
    {
402
        $modifiers = array_key_exists('modifiers', $this->options) ? $this->options['modifiers'] : [];
403
404
        foreach (['hint', 'snapshot'] as $modifier) {
405
            if ($this->$modifier === null) {
406
                continue;
407
            }
408
409
            $modifiers['$' . $modifier] = $this->$modifier;
410
        }
411
412
        return $modifiers;
413
    }
414
415
    /**
416
     * @return Cursor
417
     */
418
    protected function ensureCursor()
419
    {
420
        if ($this->cursor === null) {
421
            $this->doQuery();
422
        }
423
424
        return $this->cursor;
425
    }
426
427
    /**
428
     * @return array
429
     */
430
    protected function getCursorInfo()
431
    {
432
        return [
433
            'ns' => $this->ns,
434
            'limit' => $this->limit,
435
            'batchSize' => $this->batchSize,
436
            'skip' => $this->skip,
437
            'flags' => $this->flags,
438
            'query' => $this->query,
439
            'fields' => $this->projection,
440
        ];
441
    }
442
}
443