Completed
Pull Request — master (#10)
by Andreas
02:41
created

MongoCursor::applyOptions()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 32
rs 8.439
cc 5
eloc 22
nc 10
nop 2
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 MongoDB\Driver\Cursor;
18
use MongoDB\Driver\ReadPreference;
19
use MongoDB\Operation\Find;
20
21
/**
22
 * Result object for database query.
23
 * @link http://www.php.net/manual/en/class.mongocursor.php
24
 */
25
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...
26
{
27
    /**
28
     * @var bool
29
     */
30
    public static $slaveOkay = false;
31
32
    /**
33
     * @var int
34
     */
35
    public static $timeout = 30000;
36
37
    /**
38
     * @var array
39
     */
40
    protected $optionNames = [
41
        'allowPartialResults',
42
        'batchSize',
43
        'cursorType',
44
        'limit',
45
        'maxTimeMS',
46
        'modifiers',
47
        'noCursorTimeout',
48
        'projection',
49
        'readPreference',
50
        'skip',
51
        'sort',
52
    ];
53
54
    /**
55
     * @var array
56
     */
57
    protected $projection;
58
59
    /**
60
     * @var array
61
     */
62
    protected $query;
63
64
    protected $allowPartialResults;
65
    protected $awaitData;
66
    protected $flags;
67
    protected $hint;
68
    protected $limit;
69
    protected $maxTimeMS;
70
    protected $noCursorTimeout;
71
    protected $options = [];
72
    protected $skip;
73
    protected $snapshot;
74
    protected $sort;
75
    protected $tailable;
76
77
    /**
78
     * Create a new cursor
79
     * @link http://www.php.net/manual/en/mongocursor.construct.php
80
     * @param MongoClient $connection Database connection.
81
     * @param string $ns Full name of database and collection.
82
     * @param array $query Database query.
83
     * @param array $fields Fields to return.
84
     */
85
    public function __construct(MongoClient $connection, $ns, array $query = array(), array $fields = array())
86
    {
87
        parent::__construct($connection, $ns);
88
89
        $this->query = $query;
90
        $this->projection = $fields;
91
    }
92
93
    /**
94
     * Adds a top-level key/value pair to a query
95
     * @link http://www.php.net/manual/en/mongocursor.addoption.php
96
     * @param string $key Fieldname to add.
97
     * @param mixed $value Value to add.
98
     * @throws MongoCursorException
99
     * @return MongoCursor Returns this cursor
100
     */
101
    public function addOption($key, $value)
102
    {
103
        $this->errorIfOpened();
104
        $this->options[$key] = $value;
105
106
        return $this;
107
    }
108
109
    /**
110
     * (PECL mongo &gt;= 1.2.11)<br/>
111
     * Sets whether this cursor will wait for a while for a tailable cursor to return more data
112
     * @param bool $wait [optional] <p>If the cursor should wait for more data to become available.</p>
113
     * @return MongoCursor Returns this cursor.
114
     */
115
    public function awaitData($wait = true)
116
    {
117
        $this->errorIfOpened();
118
        $this->awaitData = $wait;
119
120
        return $this;
121
    }
122
123
124
    /**
125
     * Counts the number of results for this query
126
     * @link http://www.php.net/manual/en/mongocursor.count.php
127
     * @param bool $foundOnly Send cursor limit and skip information to the count function, if applicable.
128
     * @return int The number of documents returned by this cursor's query.
129
     */
130
    public function count($foundOnly = false)
131
    {
132
        if ($foundOnly && $this->cursor !== null) {
133
            return iterator_count($this->ensureIterator());
134
        }
135
136
        $optionNames = ['hint', 'maxTimeMS'];
137
        if ($foundOnly) {
138
            $optionNames = array_merge($optionNames, ['limit', 'skip']);
139
        }
140
141
        $options = $this->getOptions($optionNames) + $this->options;
142
143
        $count = $this->collection->count($this->query, $options);
144
        return $count;
145
    }
146
147
148
    /**
149
     * Execute the query
150
     * @link http://www.php.net/manual/en/mongocursor.doquery.php
151
     * @throws MongoConnectionException if it cannot reach the database.
152
     * @return void
153
     */
154
    protected function doQuery()
155
    {
156
        $options = $this->getOptions() + $this->options;
157
158
        $this->cursor = $this->collection->find($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...
159
    }
160
161
    /**
162
     * Return an explanation of the query, often useful for optimization and debugging
163
     * @link http://www.php.net/manual/en/mongocursor.explain.php
164
     * @return array Returns an explanation of the query.
165
     */
166
    public function explain()
167
    {
168
        $this->notImplemented();
169
    }
170
171
    /**
172
     * Sets the fields for a query
173
     * @link http://www.php.net/manual/en/mongocursor.fields.php
174
     * @param array $f Fields to return (or not return).
175
     * @throws MongoCursorException
176
     * @return MongoCursor
177
     */
178
    public function fields(array $f)
179
    {
180
        $this->errorIfOpened();
181
        $this->projection = $f;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Return the next object to which this cursor points, and advance the cursor
188
     * @link http://www.php.net/manual/en/mongocursor.getnext.php
189
     * @throws MongoConnectionException
190
     * @throws MongoCursorTimeoutException
191
     * @return array Returns the next object
192
     */
193
    public function getNext()
194
    {
195
        $this->next();
196
197
        return $this->current();
198
    }
199
200
    /**
201
     * Checks if there are any more elements in this cursor
202
     * @link http://www.php.net/manual/en/mongocursor.hasnext.php
203
     * @throws MongoConnectionException
204
     * @throws MongoCursorTimeoutException
205
     * @return bool Returns true if there is another element
206
     */
207
    public function hasNext()
208
    {
209
        $this->errorIfOpened();
210
        $this->notImplemented();
211
    }
212
213
    /**
214
     * Gives the database a hint about the query
215
     * @link http://www.php.net/manual/en/mongocursor.hint.php
216
     * @param array|string $keyPattern Indexes to use for the query.
217
     * @throws MongoCursorException
218
     * @return MongoCursor Returns this cursor
219
     */
220
    public function hint($keyPattern)
221
    {
222
        $this->errorIfOpened();
223
        $this->hint = $keyPattern;
224
225
        return $this;
226
    }
227
228
    /**
229
     * Sets whether this cursor will timeout
230
     * @link http://www.php.net/manual/en/mongocursor.immortal.php
231
     * @param bool $liveForever If the cursor should be immortal.
232
     * @throws MongoCursorException
233
     * @return MongoCursor Returns this cursor
234
     */
235
    public function immortal($liveForever = true)
236
    {
237
        $this->errorIfOpened();
238
        $this->noCursorTimeout = $liveForever;
239
240
        return $this;
241
    }
242
243
    /**
244
     * Limits the number of results returned
245
     * @link http://www.php.net/manual/en/mongocursor.limit.php
246
     * @param int $num The number of results to return.
247
     * @throws MongoCursorException
248
     * @return MongoCursor Returns this cursor
249
     */
250
    public function limit($num)
251
    {
252
        $this->errorIfOpened();
253
        $this->limit = $num;
254
255
        return $this;
256
    }
257
258
    /**
259
     * @param int $ms
260
     * @return $this
261
     * @throws MongoCursorException
262
     */
263
    public function maxTimeMS($ms)
264
    {
265
        $this->errorIfOpened();
266
        $this->maxTimeMS = $ms;
267
268
        return $this;
269
    }
270
271
    /**
272
     * @link http://www.php.net/manual/en/mongocursor.partial.php
273
     * @param bool $okay [optional] <p>If receiving partial results is okay.</p>
274
     * @return MongoCursor Returns this cursor.
275
     */
276
    public function partial($okay = true)
277
    {
278
        $this->allowPartialResults = $okay;
279
280
        return $this;
281
    }
282
283
    /**
284
     * Clears the cursor
285
     * @link http://www.php.net/manual/en/mongocursor.reset.php
286
     * @return void
287
     */
288
    public function reset()
289
    {
290
        parent::reset();
291
    }
292
293
    /**
294
     * @link http://www.php.net/manual/en/mongocursor.setflag.php
295
     * @param int $flag
296
     * @param bool $set
297
     * @return MongoCursor
298
     */
299
    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...
300
    {
301
        $this->notImplemented();
302
    }
303
304
    /**
305
     * Skips a number of results
306
     * @link http://www.php.net/manual/en/mongocursor.skip.php
307
     * @param int $num The number of results to skip.
308
     * @throws MongoCursorException
309
     * @return MongoCursor Returns this cursor
310
     */
311
    public function skip($num)
312
    {
313
        $this->errorIfOpened();
314
        $this->skip = $num;
315
316
        return $this;
317
    }
318
319
    /**
320
     * Sets whether this query can be done on a slave
321
     * This method will override the static class variable slaveOkay.
322
     * @link http://www.php.net/manual/en/mongocursor.slaveOkay.php
323
     * @param boolean $okay If it is okay to query the slave.
324
     * @throws MongoCursorException
325
     * @return MongoCursor Returns this cursor
326
     */
327
    public function slaveOkay($okay = true)
328
    {
329
        $this->errorIfOpened();
330
        static::$slaveOkay = $okay;
331
    }
332
333
    /**
334
     * Use snapshot mode for the query
335
     * @link http://www.php.net/manual/en/mongocursor.snapshot.php
336
     * @throws MongoCursorException
337
     * @return MongoCursor Returns this cursor
338
     */
339
    public function snapshot()
340
    {
341
        $this->errorIfOpened();
342
        $this->snapshot = true;
343
344
        return $this;
345
    }
346
347
    /**
348
     * Sorts the results by given fields
349
     * @link http://www.php.net/manual/en/mongocursor.sort.php
350
     * @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
351
     * @throws MongoCursorException
352
     * @return MongoCursor Returns the same cursor that this method was called on
353
     */
354
    public function sort(array $fields)
355
    {
356
        $this->errorIfOpened();
357
        $this->sort = $fields;
358
359
        return $this;
360
    }
361
362
    /**
363
     * Sets whether this cursor will be left open after fetching the last results
364
     * @link http://www.php.net/manual/en/mongocursor.tailable.php
365
     * @param bool $tail If the cursor should be tailable.
366
     * @return MongoCursor Returns this cursor
367
     */
368
    public function tailable($tail = true)
369
    {
370
        $this->errorIfOpened();
371
        $this->tailable = $tail;
372
373
        return $this;
374
    }
375
376
    /**
377
     * @return int|null
378
     */
379
    protected function convertCursorType()
380
    {
381
        if (! $this->tailable) {
382
            return null;
383
        }
384
385
        return $this->awaitData ? Find::TAILABLE_AWAIT : Find::TAILABLE;
386
    }
387
388
    protected function convertModifiers()
389
    {
390
        $modifiers = array_key_exists('modifiers', $this->options) ? $this->options['modifiers'] : [];
391
392
        foreach (['hint', 'snapshot'] as $modifier) {
393
            if ($this->$modifier === null) {
394
                continue;
395
            }
396
397
            $modifiers['$' . $modifier] = $this->$modifier;
398
        }
399
400
        return $modifiers;
401
    }
402
403
    /**
404
     * {@inheritdoc}
405
     */
406
    protected function convertReadPreference()
407
    {
408
        $readPreference = parent::convertReadPreference();
409
        if ($readPreference === null && static::$slaveOkay) {
410
            $readPreference = new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED);
411
        }
412
413
        return $readPreference;
414
    }
415
416
    /**
417
     * @return Cursor
418
     */
419
    protected function ensureCursor()
420
    {
421
        if ($this->cursor === null) {
422
            $this->doQuery();
423
        }
424
425
        return $this->cursor;
426
    }
427
428
    /**
429
     * @return array
430
     */
431
    protected function getCursorInfo()
432
    {
433
        return [
434
            'ns' => $this->ns,
435
            'limit' => $this->limit,
436
            'batchSize' => $this->batchSize,
437
            'skip' => $this->skip,
438
            'flags' => $this->flags,
439
            'query' => $this->query,
440
            'fields' => $this->projection,
441
        ];
442
    }
443
}
444