Completed
Push — master ( d794c4...a065cf )
by Vasily
05:01
created

Pool::sasl_scrum_sha1_step()   C

Complexity

Conditions 16
Paths 19

Size

Total Lines 77
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 77
rs 5.1945
cc 16
eloc 53
nc 19
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace PHPDaemon\Clients\Mongo;
3
4
use PHPDaemon\Clients\Mongo\Collection;
5
use PHPDaemon\Clients\Mongo\Connection;
6
use PHPDaemon\Clients\Mongo\ConnectionFinished;
7
use PHPDaemon\Network\Client;
8
use PHPDaemon\Core\CallbackWrapper;
9
use PHPDaemon\Core\Daemon;
10
use PHPDaemon\Core\Debug;
11
12
/**
13
 * @package    Applications
14
 * @subpackage MongoClientAsync
15
 * @author     Vasily Zorin <[email protected]>
16
 */
17
class Pool extends Client {
18
	use \PHPDaemon\Traits\StaticObjectWatchdog;
19
20
	/* Codes of operations */
21
22
	/**
23
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
24
	 */
25
	const OP_REPLY        = 1;
26
	
27
	/**
28
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
29
	 */
30
	const OP_MSG          = 1000;
31
	
32
	/**
33
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
34
	 */
35
	const OP_UPDATE       = 2001;
36
	
37
	/**
38
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
39
	 */
40
	const OP_INSERT       = 2002;
41
	
42
	/**
43
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
44
	 */
45
	const OP_QUERY        = 2004;
46
	
47
	/**
48
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
49
	 */
50
	const OP_GETMORE      = 2005;
51
	
52
	/**
53
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
54
	 */
55
	const OP_DELETE       = 2006;
56
	
57
	/**
58
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
59
	 */
60
	const OP_KILL_CURSORS = 2007;
61
62
	/**
63
	 * @var array Objects of MongoClientAsyncCollection
64
	 */
65
	public $collections = [];
66
67
	/**
68
	 * @var string Current database
69
	 */
70
	public $dbname = '';
71
72
	/**
73
	 * @var Connection Holds last used MongoClientAsyncConnection object
74
	 */
75
	public $lastRequestConnection;
76
77
	/**
78
	 * @var object Object of MemcacheClient
79
	 */
80
	public $cache;
81
82
	protected $safeMode = true;
83
84
	/**
85
	 * Setting default config options
86
	 * Overriden from AppInstance::getConfigDefaults
87
	 * @return array|bool
88
	 */
89
	protected function getConfigDefaults() {
90
		return [
91
			/* [string|array] default server list */
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
92
			'servers'        => 'tcp://127.0.0.1',
93
94
			/* [integer] default port */
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
95
			'port'           => 27017,
96
			
97
			/* [integer] maxconnperserv */
98
			'maxconnperserv' => 32,
99
		];
100
	}
101
102
	/**
103
	 * @TODO
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
104
	 * @param  array $o
105
	 * @return void
106
	 */
107
	public static function safeModeEnc(&$o) {
108
		foreach ($o as &$v) {
109
			if (is_array($v)) {
110
				static::safeModeEnc($v);
111
			} elseif ($v instanceof MongoId) {
112
				$v = $v->getPlainObject();
113
			}
114
		}
115
116
	}
117
118
	/**
119
	 * Sets default database name
120
	 * @param  string  $name Database name
121
	 * @return boolean       Success
122
	 */
123
	public function selectDB($name) {
124
		$this->dbname = $name;
125
126
		return true;
127
	}
128
129
	/**
130
	 * Generates auth. key
131
	 * @param  string $username Username
132
	 * @param  string $password Password
133
	 * @param  string $nonce    Nonce
134
	 * @return string           MD5 hash
135
	 */
136
	public static function getAuthKey($username, $password, $nonce) {
137
		return md5($nonce . $username . md5($username . ':mongo:' . $password));
138
	}
139
140
	/**
141
	 * Adds mongo server
142
	 * @param string  $url    URL
143
	 * @param integer $weight Weight
0 ignored issues
show
Documentation introduced by
Should the type for parameter $weight not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
144
	 * @param mixed   $mock   @deprecated
145
	 * @return void
146
	 */
147
	public function addServer($url, $weight = NULL, $mock = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $mock 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...
148
		$this->servers[$url] = $weight;
149
	}
150
151
	/**
152
	 * Gets the key
153
	 * @param  integer    $opcode Opcode (see constants above)
154
	 * @param  string     $data   Data
155
	 * @param  boolean    $reply  Is an answer expected?
156
	 * @param  Connection $conn   Connection. Optional
0 ignored issues
show
Documentation introduced by
Should the type for parameter $conn not be Connection|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
157
	 * @param  callable   $sentcb Sent callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $sentcb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
158
	 * @callback $sentcb ( )
159
	 * @throws ConnectionFinished
160
	 * @return void
161
	 */
162
	public function request($opcode, $data, $reply = false, $conn = null, $sentcb = null) {
163
		$cb = $this->requestCbProducer($opcode, $data, $reply, $sentcb);
164
		if (is_object($conn) && ($conn instanceof Connection)) {
165
			if ($conn->isFinished()) {
166
				throw new ConnectionFinished;
167
			}
168
			$cb($conn);
169
		}
170
		elseif ($this->finished) {
171
			call_user_func($cb, false);
172
		}
173
		else {
174
			$this->getConnectionRR($cb);
175
		}
176
	}
177
178
	/**
179
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
180
	 * @param  integer  $opcode Opcode (see constants above)
181
	 * @param  string   $data   Data
182
	 * @param  boolean  $reply  Is an answer expected?
183
	 * @param  callable $sentcb Sent callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $sentcb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
184
	 * @callback $sentcb ( )
185
	 * @return callable
186
	 */
187
	protected function requestCbProducer($opcode, $data, $reply = false, $sentcb = null) {
188
		return function ($conn) use ($opcode, $data, $reply, $sentcb) {
189
			if (!$conn || $conn->isFinished()) {
190
				if ($this->finished) {
191
					if ($sentcb !== null) {
192
						call_user_func($sentcb, false);
193
					}
194
				} else {
195
					$this->getConnectionRR($this->requestCbProducer($opcode, $data, $reply, $sentcb));
196
				}
197
				return;
198
			}
199
			$reqId = ++$conn->lastReqId;
200
			$this->lastRequestConnection = $conn;
201
			$conn->write(pack('VVVV', strlen($data) + 16, $reqId, 0, $opcode));
202
			$conn->write($data);
203
			if ($reply) {
204
				$conn->setFree(false);
205
			}
206
			if ($sentcb !== null) {
207
				call_user_func($sentcb, $conn, $reqId);
208
			}
209
		};
210
	}
211
212
	/**
213
	 * Finds objects in collection and fires callback when got all objects
214
	 * @param  array    $p  Hash of properties (offset, limit, opts, tailable, await, where, col, fields, sort, hint, explain, snapshot, orderby, parse_oplog)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 155 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
215
	 * @param  callable $cb Callback called when response received
216
	 * @callback $cb ( )
217
	 * @return void
218
	 */
219
	public function findAll($p, $cb) {
220
		$this->find($p, function($cursor) use ($cb) {
221
			if (!$cursor->isFinished()) {
222
				$cursor->getMore();
223
			} else {
224
				call_user_func($cb, $cursor);
225
			}
226
		});
227
	}
228
229
	/**
230
	 * Finds objects in collection
231
	 * @param  array    $p  Hash of properties (offset, limit, opts, tailable, await, where, col, fields, sort, hint, explain, snapshot, orderby, parse_oplog)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 155 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
232
	 * @param  callable $cb Callback called when response received
233
	 * @callback $cb ( )
234
	 * @return void
235
	 */
236
	public function find($p, $cb) {
237
		if (!isset($p['offset'])) {
238
			$p['offset'] = 0;
239
		}
240
241
		if (!isset($p['limit'])) {
242
			$p['limit'] = 0;
243
		}
244
245
		if (!isset($p['opts'])) {
246
			$p['opts'] = '0';
247
		}
248
249
		if (isset($p['tailable']) && $p['tailable']) {
250
			$p['opts'] = '01000'.(isset($p['await']) && $p['await']?'1':'0').'00';
251
		}
252
253
		if (!isset($p['where'])) {
254
			$p['where'] = [];
255
		}
256
257
		$this->_params($p);
258
259
		$o = [];
260
		$s = false;
261
262 View Code Duplication
		foreach ($p as $k => $v) {
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...
263
			if (
264
					($k === 'sort')
265
					|| ($k === 'hint')
266
					|| ($k === 'explain')
267
					|| ($k === 'snapshot')
268
			) {
269
				if (!$s) {
270
					$s = true;
271
				}
272
273
				if ($k === 'sort') {
274
					$o['orderby'] = $v;
275
				}
276
				elseif ($k === 'parse_oplog') {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
277
				}
278
				elseif ($k === 'rp') {
279
					$o['$readPreference'] = $v;
280
				}
281
				else {
282
					$o[$k] = $v;
283
				}
284
			}
285
		}
286
287
		if ($s) {
288
			$o['query'] = $p['where'];
289
		}
290
		else {
291
			$o = $p['where'];
292
		}
293
294
		if (empty($o['orderby'])) {
295
			unset($o['orderby']);
296
		}
297
298
		if ($this->safeMode) {
299
			static::safeModeEnc($o);
300
		}
301
		try {
302
			$bson = bson_encode($o);
303
304
			if (isset($p['parse_oplog'])) {
305
				$bson = str_replace("\x11\$gt", "\x09\$gt", $bson);
306
			}
307
			$cb = CallbackWrapper::wrap($cb);
308
			$this->request(self::OP_QUERY,
309
									chr(bindec(strrev($p['opts']))) . "\x00\x00\x00"
310
									. $p['col'] . "\x00"
311
									. pack('VV', $p['offset'], $p['limit'])
312
									. $bson
313
									. (isset($p['fields']) ? bson_encode($p['fields']) : '')
314
				, true, null, function ($conn, $reqId = null) use ($p, $cb) {
315
					if (!$conn) {
316
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
317
						return;
318
					}
319
					$conn->requests[$reqId] = [$p['col'], $cb, false, isset($p['parse_oplog']), isset($p['tailable'])];
320
				});
321
		} catch (\MongoException $e) {
322
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
323 View Code Duplication
			if ($cb !== null) {
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...
324
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $o, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
325
			}
326
		} 
327
	}
328
329
	/**
330
	 * Finds one object in collection
331
	 * @param  array    $p  Hash of properties (offset,  opts, where, col, fields, sort, hint, explain, snapshot, orderby, parse_oplog)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 132 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
332
	 * @param  callable $cb Callback called when response received
333
	 * @callback $cb ( )
334
	 * @return void
335
	 */
336
	public function findOne($p, $cb) {
337
		if (isset($p['cachekey'])) {
338
			$db = $this;
339
			$this->cache->get($p['cachekey'], function ($r) use ($db, $p, $cb) {
340
				if ($r->result !== NULL) {
341
					call_user_func($cb, bson_decode($r->result));
342
				}
343
				else {
344
					unset($p['cachekey']);
345
					$db->findOne($p, $cb);
346
				}
347
			});
348
349
			return;
350
		}
351
		if (!isset($p['where'])) {
352
			$p['where'] = [];
353
		}
354
355
		$this->_params($p);
356
357
		$o = [];
358
		$s = false;
359
360 View Code Duplication
		foreach ($p as $k => $v) {
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...
361
			if (
362
					($k === 'sort')
363
					|| ($k === 'hint')
364
					|| ($k === 'explain')
365
					|| ($k === 'snapshot')
366
			) {
367
				if (!$s) {
368
					$s = true;
369
				}
370
371
				if ($k === 'sort') {
372
					$o['orderby'] = $v;
373
				}
374
				elseif ($k === 'parse_oplog') {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
375
				}
376
				elseif ($k === 'rp') {
377
					$o['$readPreference'] = $v;
378
				}
379
				else {
380
					$o[$k] = $v;
381
				}
382
			}
383
		}
384
		if (empty($o['orderby'])) {
385
			unset($o['orderby']);
386
		}
387
388
		if ($s) {
389
			$o['query'] = $p['where'];
390
		}
391
		else {
392
			$o = $p['where'];
393
		}
394
		$cb = CallbackWrapper::wrap($cb);
395
		if ($this->safeMode) {
396
			static::safeModeEnc($o);
397
		}
398
		try {
399
			$this->request(self::OP_QUERY,
400
									pack('V', $p['opts'])
401
									. $p['col'] . "\x00"
402
									. pack('VV', $p['offset'], -1)
403
									. bson_encode($o)
404
									. (isset($p['fields']) ? bson_encode($p['fields']) : '')
405 View Code Duplication
				, true, null, function($conn, $reqId = null) use ($p, $cb) {
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...
406
					if (!$conn) {
407
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
408
						return;
409
					}
410
					$conn->requests[$reqId] = [$p['col'], $cb, true];
411
				});
412
		} catch (\MongoException $e) {
413
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
414 View Code Duplication
			if ($cb !== null) {
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...
415
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $o, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
416
			}
417
		} 
418
	}
419
420
	/**
421
	 * Counts objects in collection
422
	 * @param  array    $p  Hash of properties (offset, limit, opts, where, col)
423
	 * @param  callable $cb Callback called when response received
424
	 * @callback $cb ( )
425
	 * @return void
426
	 */
427
	public function findCount($p, $cb) {
428
		if (!isset($p['offset'])) {
429
			$p['offset'] = 0;
430
		}
431
432
		if (!isset($p['limit'])) {
433
			$p['limit'] = -1;
434
		}
435
436
		if (!isset($p['opts'])) {
437
			$p['opts'] = 0;
438
		}
439
440
		if (!isset($p['where'])) {
441
			$p['where'] = [];
442
		}
443
444 View Code Duplication
		if (strpos($p['col'], '.') === false) {
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...
445
			$p['col'] = $this->dbname . '.' . $p['col'];
446
		}
447
448
		$e = explode('.', $p['col'], 2);
449
450
		$query = [
451
			'count'  => $e[1],
452
			'query'  => $p['where'],
453
			'fields' => ['_id' => 1],
454
		];
455
456 View Code Duplication
		if (isset($p[$k = 'rp'])) {
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...
457
			$v = $p[$k];
458
			if (is_string($v)) {
459
				$v = ['mode' => $v];
460
			}
461
			$query['$readPreference'] = $v;
462
		}
463
464 View Code Duplication
		if (is_string($p['where'])) {
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...
465
			$query['where'] = new \MongoCode($p['where']);
466
		}
467
		elseif (
468
				is_object($p['where'])
469
				|| sizeof($p['where'])
470
		) {
471
			$query['query'] = $p['where'];
472
		}
473
		$cb = CallbackWrapper::wrap($cb);
474
		if ($this->safeMode) {
475
			static::safeModeEnc($query);
476
		}
477
		try {
478
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
479
				. $e[0] . '.$cmd' . "\x00"
480
				. pack('VV', $p['offset'], $p['limit'])
481
				. bson_encode($query)
482 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
483
					if (!$conn) {
484
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
485
						return;
486
					}
487
					$conn->requests[$reqId] = [$p['col'], $cb, true];
488
			});
489
		} catch (\MongoException $e) {
490
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
491 View Code Duplication
			if ($cb !== null) {
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...
492
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
493
			}
494
		} 
495
	}
496
497
	/**
498
	 * Sends authenciation packet
499
	 * @param  array    $p  Hash of properties (dbname, user, password, nonce)
500
	 * @param  callable $cb Callback called when response received
501
	 * @callback $cb ( )
502
	 * @return void
503
	 */
504
	public function auth($p, $cb) {
505
		if (!isset($p['opts'])) {
506
			$p['opts'] = 0;
507
		}
508
509
		$query = [
510
			'authenticate' => 1,
511
			'user'         => $p['user'],
512
			'nonce'        => $p['nonce'],
513
			'key'          => self::getAuthKey($p['user'], $p['password'], $p['nonce']),
514
		];
515
		if ($this->safeMode) {
516
			static::safeModeEnc($query);
517
		}
518
		try {
519
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
520
				. $p['dbname'] . '.$cmd' . "\x00"
521
				. pack('VV', 0, -1)
522
				. bson_encode($query)
523 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
524
					if (!$conn) {
525
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
526
						return;
527
					}
528
					$conn->requests[$reqId] = [$p['dbname'], $cb, true];
529
			});
530
		} catch (\MongoException $e) {
531
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
532 View Code Duplication
			if ($cb !== null) {
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...
533
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
534
			}
535
		} 
536
	}
537
538
	/**
539
	 * Sends request of nonce
540
	 * @param  array    $p  Hash of properties
541
	 * @param  callable $cb Callback called when response received
542
	 * @callback $cb ( )
543
	 * @return void
544
	 */
545
	public function getNonce($p, $cb) {
546
		if (!isset($p['opts'])) {
547
			$p['opts'] = 0;
548
		}
549
550
		$query = [
551
			'getnonce' => 1,
552
		];
553
		$cb = CallbackWrapper::wrap($cb);
554
		try {
555
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
556
				. $p['dbname'] . '.$cmd' . "\x00"
557
				. pack('VV', 0, -1)
558
				. bson_encode($query)
559 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
560
					if (!$conn) {
561
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
562
						return;
563
					}
564
					$conn->requests[$reqId] = [$p['dbname'], $cb, true];
565
				});
566
		} catch (\MongoException $e) {
567
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
568 View Code Duplication
			if ($cb !== null) {
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...
569
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
570
			}
571
		} 
572
	}
573
574
	/**
575
	 * @TODO DESCR
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
576
	 * @param  array  $keys
577
	 * @return string
578
	 */
579
	public function getIndexName($keys) {
580
		$name  = '';
581
		$first = true;
582
		foreach ($keys as $k => $v) {
583
			$name .= ($first ? '_' : '') . $k . '_' . $v;
584
			$first = false;
585
		}
586
		return $name;
587
	}
588
589
	/**
590
	 * Ensure index
591
	 * @param  string   $ns      Collection
592
	 * @param  array    $keys    Keys
593
	 * @param  array    $options Optional. Options
594
	 * @param  callable $cb      Optional. Callback called when response received
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
595
	 * @callback $cb ( )
596
	 * @return void
597
	 */
598
	public function ensureIndex($ns, $keys, $options = [], $cb = null) {
599
		$e   = explode('.', $ns, 2);
600
		$doc = [
601
			'ns'   => $ns,
602
			'key'  => $keys,
603
			'name' => isset($options['name']) ? $options['name'] : $this->getIndexName($keys),
604
		];
605
		if (isset($options['unique'])) {
606
			$doc['unique'] = $options['unique'];
607
		}
608
		if (isset($options['sparse'])) {
609
			$doc['sparse'] = $options['sparse'];
610
		}
611
		if (isset($options['version'])) {
612
			$doc['v'] = $options['version'];
613
		}
614
		if (isset($options['background'])) {
615
			$doc['background'] = $options['background'];
616
		}
617
		if (isset($options['ttl'])) {
618
			$doc['expireAfterSeconds'] = $options['ttl'];
619
		}
620
		$this->getCollection($e[0] . '.system.indexes')->insert($doc, $cb);
621
	}
622
623
	/**
624
	 * Gets last error
625
	 * @param  string     $db     Dbname
626
	 * @param  callable   $cb     Callback called when response received
627
	 * @param  array      $params Parameters.
628
	 * @param  Connection $conn   Connection. Optional
0 ignored issues
show
Documentation introduced by
Should the type for parameter $conn not be Connection|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
629
	 * @callback $cb ( )
630
	 * @return void
631
	 */
632
	public function lastError($db, $cb, $params = [], $conn = null) {
633
		$e                      = explode('.', $db, 2);
634
		$params['getlasterror'] = 1;
635
		$cb = CallbackWrapper::wrap($cb);
636
		try {
637
			$this->request(self::OP_QUERY,
638
				pack('V', 0)
639
				. $e[0] . '.$cmd' . "\x00"
640
				. pack('VV', 0, -1)
641
				. bson_encode($params)
642 View Code Duplication
				, true, $conn, function ($conn, $reqId = null) use ($db, $cb) {
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...
643
					if (!$conn) {
644
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
645
						return;
646
					}
647
					$conn->requests[$reqId] = [$db, $cb, true];
648
			});
649
		} catch (\MongoException $e) {
650
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
651
			if ($cb !== null) {
652
				call_user_func($cb, ['$err' => $e->getMessage()]);
653
			}
654
		} 
655
	}
656
657
	/**
658
	 * Find objects in collection using min/max specifiers
659
	 * @param  array    $p  Hash of properties (offset, limit, opts, where, col, min, max)
660
	 * @param  callable $cb Callback called when response received
661
	 * @callback $cb ( )
662
	 * @return void
663
	 */
664
	public function range($p, $cb) {
665
		if (!isset($p['offset'])) {
666
			$p['offset'] = 0;
667
		}
668
669
		if (!isset($p['limit'])) {
670
			$p['limit'] = -1;
671
		}
672
673
		if (!isset($p['opts'])) {
674
			$p['opts'] = 0;
675
		}
676
677
		if (!isset($p['where'])) {
678
			$p['where'] = [];
679
		}
680
681
		if (!isset($p['min'])) {
682
			$p['min'] = [];
683
		}
684
685
		if (!isset($p['max'])) {
686
			$p['max'] = [];
687
		}
688
689 View Code Duplication
		if (strpos($p['col'], '.') === false) {
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...
690
			$p['col'] = $this->dbname . '.' . $p['col'];
691
		}
692
693
		$e = explode('.', $p['col'], 2);
694
695
		$query = [
696
			'$query' => $p['where'],
697
		];
698
699
		if (sizeof($p['min'])) {
700
			$query['$min'] = $p['min'];
701
		}
702
703
		if (sizeof($p['max'])) {
704
			$query['$max'] = $p['max'];
705
		}
706
707 View Code Duplication
		if (is_string($p['where'])) {
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...
708
			$query['where'] = new \MongoCode($p['where']);
709
		}
710
		elseif (
711
				is_object($p['where'])
712
				|| sizeof($p['where'])
713
		) {
714
			$query['query'] = $p['where'];
715
		}
716
717
		$cb = CallbackWrapper::wrap($cb);
718
		if ($this->safeMode) {
719
			static::safeModeEnc($query);
720
		}
721
		try {
722
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
723
				. $e[0] . '.$cmd' . "\x00"
724
				. pack('VV', $p['offset'], $p['limit'])
725
				. bson_encode($query)
726 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
727
					if (!$conn) {
728
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
729
						return;
730
					}
731
					$conn->requests[$reqId] = [$p['col'], $cb, true];
732
			});
733
		} catch (\MongoException $e) {
734
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
735 View Code Duplication
			if ($cb !== null) {
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...
736
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
737
			}
738
		} 
739
	}
740
741
	/**
742
	 * Evaluates a code on the server side
743
	 * @param  string   $code Code
744
	 * @param  callable $cb   Callback called when response received
745
	 * @callback $cb ( )
746
	 * @return void
747
	 */
748
	public function evaluate($code, $cb) {
749
		$p = [];
750
751
		if (!isset($p['offset'])) {
752
			$p['offset'] = 0;
753
		}
754
755
		if (!isset($p['limit'])) {
756
			$p['limit'] = -1;
757
		}
758
759
		if (!isset($p['opts'])) {
760
			$p['opts'] = 0;
761
		}
762
763
		if (!isset($p['db'])) {
764
			$p['db'] = $this->dbname;
765
		}
766
767
		$cb = CallbackWrapper::wrap($cb);
768
		try {
769
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
770
				. $p['db'] . '.$cmd' . "\x00"
771
				. pack('VV', $p['offset'], $p['limit'])
772
				. bson_encode(['$eval' => new \MongoCode($code)])
773 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
774
					if (!$conn) {
775
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
776
						return;
777
					}
778
					$conn->requests[$reqId] = [$p['db'], $cb, true];
779
				});
780
		} catch (\MongoException $e) {
781
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
782 View Code Duplication
			if ($cb !== null) {
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...
783
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Bug introduced by
The variable $query does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
784
			}
785
		} 
786
	}
787
788
	/**
789
	 * Returns distinct values of the property
790
	 * @param  array    $p  Hash of properties (offset, limit, opts, key, col, where)
791
	 * @param  callable $cb Callback called when response received
792
	 * @callback $cb ( )
793
	 * @return void
794
	 */
795
	public function distinct($p, $cb) {
796
		$this->_params($p);
797
		$e = explode('.', $p['col'], 2);
798
799
		$query = [
800
			'distinct' => $e[1],
801
			'key'      => $p['key'],
802
		];
803
804 View Code Duplication
		if (isset($p[$k = 'rp'])) {
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...
805
			$v = $p[$k];
806
			if (is_string($v)) {
807
				$v = ['mode' => $v];
808
			}
809
			$query['$readPreference'] = $v;
810
		}
811
812
		if (isset($p['where'])) {
813
			$query['query'] = $p['where'];
814
		}
815
		$cb = CallbackWrapper::wrap($cb);
816
		$this->request(self::OP_QUERY, pack('V', $p['opts'])
817
			. $e[0] . '.$cmd' . "\x00"
818
			. pack('VV', $p['offset'], $p['limit'])
819
			. bson_encode($query)
820 View Code Duplication
			. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
821
				if (!$conn) {
822
					!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
823
					return;
824
				}
825
				$conn->requests[$reqId] = [$p['col'], $cb, true];
826
		});
827
	}
828
829
	/**
830
	 * [_paramFields description]
831
	 * @param  mixed $f
832
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be null|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
833
	 */
834
	protected function _paramFields($f) {
835
		if (is_string($f)) {
836
			$f = array_map('trim', explode(',', $f));
837
		}
838
		if (!is_array($f) || sizeof($f) === 0) {
839
			return null;
840
		}
841
		if (!isset($f[0])) {
842
			return $f;
843
		}
844
		$p = [];
845
		foreach ($f as $k) {
846
			$p[$k] = 1;
847
		}
848
		return $p;
849
	}
850
851
	/**
852
	 * [_params description]
853
	 * @param  array &$p
854
	 * @return void
855
	 */
856
	protected function _params(&$p) {
857
		foreach ($p as $k => &$v) {
858
			if ($k === 'fields' || $k === 'sort') {
859
				$v = $this->_paramFields($v);
860
			} elseif ($k === 'where') {
861
				if (is_string($v)) {
862
					$v = new \MongoCode($v);
863
				}
864
			}
865
			elseif ($k === 'reduce') {
866
				if (is_string($v)) {
867
					$v = new \MongoCode($v);
868
				}
869
			}
870
			elseif ($k === 'rp') {
871
				if (is_string($v)) {
872
					$v = ['mode' => $v];
873
				}
874
			}
875
		}
876
877
		if (!isset($p['offset'])) {
878
			$p['offset'] = 0;
879
		}
880
881
		if (!isset($p['limit'])) {
882
			$p['limit'] = -1;
883
		}
884
885
		if (!isset($p['opts'])) {
886
			$p['opts'] = 0;
887
		}
888
889
		if (!isset($p['key'])) {
890
			$p['key'] = '';
891
		}
892
893 View Code Duplication
		if (strpos($p['col'], '.') === false) {
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...
894
			$p['col'] = $this->dbname . '.' . $p['col'];
895
		}
896
	}
897
898
	/**
899
	 * Find and modify
900
	 * @param  array    $p  Hash of properties
901
	 * @param  callable $cb Callback called when response received
902
	 * @callback $cb ( )
903
	 * @return void
904
	 */
905
	public function findAndModify($p, $cb) {
906
		$this->_params($p);
907
		$e = explode('.', $p['col'], 2);
908
		$query = [
909
			'findAndModify' => $e[1],
910
		];
911
912 View Code Duplication
		if (isset($p[$k = 'rp'])) {
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...
913
			$v = $p[$k];
914
			if (is_string($v)) {
915
				$v = ['mode' => $v];
916
			}
917
			$query['$readPreference'] = $v;
918
		}
919
920
		if (isset($p['sort'])) {
921
			$query['sort'] = $p['sort'];
922
		}
923
		if (isset($p['update'])) {
924
			$query['update'] = $p['update'];
925
		}
926
		if (isset($p['new'])) {
927
			$query['new'] = (boolean) $p['new'];
928
		}
929
		if (isset($p['remove'])) {
930
			$query['remove'] = (boolean) $p['remove'];
931
		}
932
		if (isset($p['upsert'])) {
933
			$query['upsert'] = (boolean) $p['upsert'];
934
		}
935
		if (isset($p['where'])) {
936
			$query['query'] = $p['where'];
937
		}
938
		elseif (isset($p['query'])) {
939
			$query['query'] = $p['query'];
940
		}
941
		if ($this->safeMode) {
942
			static::safeModeEnc($query);
943
		}
944
		$cb = CallbackWrapper::wrap($cb);
945
		try {
946
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
947
				. $e[0] . '.$cmd' . "\x00"
948
				. pack('VV', $p['offset'], $p['limit'])
949
				. bson_encode($query)
950 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
951
					if (!$conn) {
952
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
953
						return;
954
					}
955
					$conn->requests[$reqId] = [$p['col'], $cb, true];
956
			});
957
		} catch (\MongoException $e) {
958
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
959 View Code Duplication
			if ($cb !== null) {
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...
960
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
961
			}
962
		} 
963
	}
964
965
	/**
966
	 * Groupping function
967
	 * @param  array    $p  Hash of properties (offset, limit, opts, key, col, reduce, initial)
968
	 * @param  callable $cb Callback called when response received
969
	 * @callback $cb ( )
970
	 * @return void
971
	 */
972
	public function group($p, $cb) {
973
		if (!isset($p['reduce'])) {
974
			$p['reduce'] = '';
975
		}
976
		$this->_params($p);
977
978
		$e = explode('.', $p['col'], 2);
979
980
		$query = [
981
			'group' => [
982
				'ns'      => $e[1],
983
				'key'     => $p['key'],
984
				'$reduce' => $p['reduce'],
985
				'initial' => $p['initial'],
986
			]
987
		];
988
989
		if (isset($p[$k = 'cond'])) {
990
			$query['group'][$k] = $p[$k];
991
		}
992
993
		if (isset($p['rp'])) {
994
			$query['$readPreference'] = $p['rp'];
995
		}
996
997
		if (isset($p[$k = 'finalize'])) {
998
			if (is_string($p[$k])) {
999
				$p[$k] = new \MongoCode($p[$k]);
1000
			}
1001
1002
			$query['group'][$k] = $p[$k];
1003
		}
1004
1005
		if (isset($p[$k = 'keyf'])) {
1006
			$query[$k] = $p[$k];
1007
		}
1008
		if ($this->safeMode) {
1009
			static::safeModeEnc($query);
1010
		}
1011
		$cb = CallbackWrapper::wrap($cb);
1012
		try {
1013
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
1014
				. $e[0] . '.$cmd' . "\x00"
1015
				. pack('VV', $p['offset'], $p['limit'])
1016
				. bson_encode($query)
1017 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1018
					if (!$conn) {
1019
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
1020
						return;
1021
					}
1022
					$conn->requests[$reqId] = [$p['col'], $cb, false];
1023
				});
1024
		} catch (\MongoException $e) {
1025
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1026 View Code Duplication
			if ($cb !== null) {
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...
1027
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1028
			}
1029
		} 
1030
	}
1031
1032
	/**
1033
	 * Aggregate function
1034
	 * @param  array    $p  Hash of properties (offset, limit, opts, key, col)
1035
	 * @param  callable $cb Callback called when response received
1036
	 * @callback $cb ( )
1037
	 * @return void
1038
	 */
1039
	public function aggregate($p, $cb) {
1040
		$this->_params($p);
1041
1042
		$e = explode('.', $p['col'], 2);
1043
		$query = [
1044
			'aggregate' => $e[1]
1045
		];
1046
1047
		if (isset($p['rp'])) {
1048
			$query['$readPreference'] = $p['rp'];
1049
			unset($p['rp']);
1050
		}
1051
		foreach ($p as $k => $v) {
1052
			if (substr($k, 0, 1) === '$' || $k === 'pipeline') {
1053
				$query[$k] = $v;
1054
			}
1055
		}
1056
		$cb = CallbackWrapper::wrap($cb);
1057
		try {
1058
			$this->request(self::OP_QUERY, pack('V', $p['opts'])
1059
				. $e[0] . '.$cmd' . "\x00"
1060
				. pack('VV', $p['offset'], $p['limit'])
1061
				. bson_encode($query)
1062 View Code Duplication
				. (isset($p['fields']) ? bson_encode($p['fields']) : ''), true, null, function ($conn, $reqId = null) use ($p, $cb) {
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...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1063
					if (!$conn) {
1064
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
1065
						return;
1066
					}
1067
					$conn->requests[$reqId] = [$p['col'], $cb, false];
1068
				});
1069
		} catch (\MongoException $e) {
1070
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1071 View Code Duplication
			if ($cb !== null) {
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...
1072
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1073
			}
1074
		} 
1075
	}
1076
1077
	/**
1078
	 * Updates one object in collection
1079
	 * @param  string   $col    Collection's name
1080
	 * @param  array    $cond   Conditions
1081
	 * @param  array    $data   Data
1082
	 * @param  integer  $flags  Optional. Flags
1083
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1084
	 * @param  array    $params Optional. Parameters
1085
	 * @callback $cb ( )
1086
	 * @return void
1087
	 */
1088
	public function update($col, $cond, $data, $flags = 0, $cb = NULL, $params = []) {
1089 View Code Duplication
		if (strpos($col, '.') === false) {
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...
1090
			$col = $this->dbname . '.' . $col;
1091
		}
1092
1093
		if (is_string($cond)) {
1094
			$cond = new \MongoCode($cond);
1095
		}
1096
1097
		if ($flags) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1098
			//if (!isset($data['_id'])) {$data['_id'] = new MongoId();}
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1099
		}
1100
		if ($this->safeMode) {
1101
			static::safeModeEnc($cond);
0 ignored issues
show
Bug introduced by
It seems like $cond defined by new \MongoCode($cond) on line 1094 can also be of type object<MongoCode>; however, PHPDaemon\Clients\Mongo\Pool::safeModeEnc() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1102
			static::safeModeEnc($data);
1103
		}
1104
		$this->request(self::OP_UPDATE,
1105
			"\x00\x00\x00\x00"
1106
			. $col . "\x00"
1107
			. pack('V', $flags)
1108
			. bson_encode($cond)
1109
			. bson_encode($data)
1110 View Code Duplication
		, false, null, function ($conn, $reqId = null) use ($cb, $col, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $reqId 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...
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...
1111
			if (!$conn) {
1112
				!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
1113
				return;
1114
			}
1115
			if ($cb !== NULL) {
1116
				$this->lastError($col, $cb, $params, $conn);
1117
			}
1118
		});
1119
	}
1120
1121
	/**
1122
	 * Updates one object in collection
1123
	 * @param  string   $col    Collection's name
1124
	 * @param  array    $cond   Conditions
1125
	 * @param  array    $data   Data
1126
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1127
	 * @param  array    $params Optional. Parameters
1128
	 * @callback $cb ( )
1129
	 * @return void
1130
	 */
1131
	public function updateOne($col, $cond, $data, $cb = NULL, $params = []) {
1132
		$this->update($col, $cond, $data, 0, $cb, $params);	
1133
	}
1134
1135
	/**
1136
	 * Updates several objects in collection
1137
	 * @param  string   $col    Collection's name
1138
	 * @param  array    $cond   Conditions
1139
	 * @param  array    $data   Data
1140
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1141
	 * @param  array    $params Optional. Parameters
1142
	 * @callback $cb ( )
1143
	 * @return void
1144
	 */
1145
	public function updateMulti($col, $cond, $data, $cb = NULL, $params = []) {
1146
		$this->update($col, $cond, $data, 2, $cb, $params);
1147
	}
1148
1149
	/**
1150
	 * Upserts an object (updates if exists, insert if not exists)
1151
	 * @param  string   $col    Collection's name
1152
	 * @param  array    $cond   Conditions
1153
	 * @param  array    $data   Data
1154
	 * @param  boolean  $multi  Optional. Multi
1155
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1156
	 * @param  array    $params Optional. Parameters
1157
	 * @callback $cb ( )
1158
	 * @return void
1159
	 */
1160
	public function upsert($col, $cond, $data, $multi = false, $cb = NULL, $params = []) {
1161
		$this->update($col, $cond, $data, $multi ? 3 : 1, $cb, $params);
1162
	}
1163
1164
	/**
1165
	 * Upserts an object (updates if exists, insert if not exists)
1166
	 * @param  string   $col    Collection's name
1167
	 * @param  array    $cond   Conditions
1168
	 * @param  array    $data   Data
1169
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1170
	 * @param  array    $params Optional. Parameters
1171
	 * @callback $cb ( )
1172
	 * @return void
1173
	 */
1174
	public function upsertOne($col, $cond, $data, $cb = NULL, $params = []) {
1175
		$this->update($col, $cond, $data, 1, $cb, $params);
1176
	}
1177
1178
	/**
1179
	 * Upserts an object (updates if exists, insert if not exists)
1180
	 * @param  string   $col    Collection's name
1181
	 * @param  array    $cond   Conditions
1182
	 * @param  array    $data   Data
1183
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1184
	 * @param  array    $params Optional. Parameters
1185
	 * @callback $cb ( )
1186
	 * @return void
1187
	 */
1188
	public function upsertMulti($col, $cond, $data, $cb = NULL, $params = []) {
1189
		$this->update($col, $cond, $data, 3, $cb, $params);
1190
	}
1191
1192
	/**
1193
	 * Inserts an object
1194
	 * @param  string   $col    Collection's name
1195
	 * @param  array    $doc    Document
1196
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1197
	 * @param  array    $params Optional. Parameters
1198
	 * @callback $cb ( )
1199
	 * @return MongoId
1200
	 */
1201
	public function insert($col, $doc = [], $cb = NULL, $params = []) {
1202 View Code Duplication
		if (strpos($col, '.') === false) {
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...
1203
			$col = $this->dbname . '.' . $col;
1204
		}
1205
1206
		if (!isset($doc['_id'])) {
1207
			$doc['_id'] = new \MongoId;
1208
		}
1209
		if ($this->safeMode) {
1210
			static::safeModeEnc($doc);
1211
		}
1212
		try {
1213
			$this->request(self::OP_INSERT,
1214
									"\x00\x00\x00\x00"
1215
									. $col . "\x00"
1216
									. bson_encode($doc)
1217 View Code Duplication
			, false, null, function ($conn, $reqId = null) use ($cb, $col, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $reqId 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...
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...
1218
				if ($cb !== NULL) {
1219
					$this->lastError($col, $cb, $params, $conn);
1220
				}
1221
			});
1222
1223
			return $doc['_id'];
1224
		} catch (\MongoException $e) {
1225
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1226 View Code Duplication
			if ($cb !== null) {
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...
1227
				if ($cb !== null) {
1228
					call_user_func($cb, ['$err' => $e->getMessage(), '$doc' => $doc]);
1229
				}
1230
			}
1231
		} 
1232
	}
1233
1234
	/**
1235
	 * Sends a request to kill certain cursors on the server side
1236
	 * @param  array      $cursors Array of cursors
1237
	 * @param  Connection $conn    Connection
1238
	 * @return void
1239
	 */
1240
	public function killCursors($cursors = [], $conn) {
1241
		$this->request(self::OP_KILL_CURSORS,
1242
					   "\x00\x00\x00\x00"
1243
					   . pack('V', sizeof($cursors))
1244
					   . implode('', $cursors)
1245
		, false, $conn);
1246
	}
1247
1248
	/**
1249
	 * Inserts several documents
1250
	 * @param  string   $col    Collection's name
1251
	 * @param  array    $docs   Array of docs
1252
	 * @param  callable $cb     Optional. Callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1253
	 * @param  array    $params Optional. Parameters
1254
	 * @callback $cb ( )
1255
	 * @return array IDs
1256
	 */
1257
	public function insertMulti($col, $docs = [], $cb = NULL, $params = []) {
1258 View Code Duplication
		if (strpos($col, '.') === false) {
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...
1259
			$col = $this->dbname . '.' . $col;
1260
		}
1261
1262
		$ids  = [];
1263
		$bson = '';
1264
1265
		foreach ($docs as &$doc) {
1266
			if (!isset($doc['_id'])) {
1267
				$doc['_id'] = new MongoId();
1268
			}
1269
			try {
1270
				$bson .= bson_encode($doc);
1271
			} catch (\MongoException $e) {
1272
				Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1273 View Code Duplication
				if ($cb !== null) {
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...
1274
					call_user_func($cb, ['$err' => $e->getMessage(), '$doc' => $doc]);
1275
				}
1276
			} 
1277
1278
			$ids[] = $doc['_id'];
1279
		}
1280
1281
		$this->request(self::OP_INSERT,
1282
					   "\x00\x00\x00\x00"
1283
					   . $col . "\x00"
1284
					   . $bson
1285 View Code Duplication
		, false, null, function ($conn, $reqId = null) use ($cb, $col, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $reqId 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...
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...
1286
			if ($cb !== NULL) {
1287
				$this->lastError($col, $cb, $params, $conn);
1288
			}
1289
		});
1290
		return $ids;
1291
	}
1292
1293
	/**
1294
	 * Remove objects from collection
1295
	 * @param  string   $col    Collection's name
1296
	 * @param  array    $cond   Conditions
1297
	 * @param  callable $cb     Optional. Callback called when response received
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1298
	 * @param  array    $params Optional. Parameters
1299
	 * @callback $cb ( )
1300
	 * @return void
1301
	 */
1302
	public function remove($col, $cond = [], $cb = NULL, $params = []) {
1303 View Code Duplication
		if (strpos($col, '.') === false) {
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...
1304
			$col = $this->dbname . '.' . $col;
1305
		}
1306
1307
		if (is_string($cond)) {
1308
			$cond = new \MongoCode($cond);
1309
		}
1310
1311
		if ($this->safeMode && is_array($cond)) {
1312
			static::safeModeEnc($cond);
1313
		}
1314
		try {
1315
			$this->request(self::OP_DELETE,
1316
						   "\x00\x00\x00\x00"
1317
						   . $col . "\x00"
1318
						   . "\x00\x00\x00\x00"
1319
						   . bson_encode($cond)
1320 View Code Duplication
			, false, null, function ($conn, $reqId = null) use ($col, $cb, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $reqId 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...
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...
1321
				if (!$conn) {
1322
					!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
1323
					return;
1324
				}
1325
				if ($cb !== NULL) {
1326
					$this->lastError($col, $cb, $params, $conn);
1327
				}
1328
			});
1329
		} catch (\MongoException $e) {
1330
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1331 View Code Duplication
			if ($cb !== null) {
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...
1332
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $cond]);
1333
			}
1334
		} 
1335
	}
1336
1337
	/**
1338
	 * Asks for more objects
1339
	 * @param  string     $col    Collection's name
1340
	 * @param  string     $id     Cursor's ID
1341
	 * @param  integer    $number Number of objects
1342
	 * @param  Connection $conn   Connection
1343
	 * @return void
1344
	 */
1345
	public function getMore($col, $id, $number, $conn) {
1346 View Code Duplication
		if (strpos($col, '.') === false) {
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...
1347
			$col = $this->dbname . '.' . $col;
1348
		}
1349
1350
		$this->request(self::OP_GETMORE,
1351
			 "\x00\x00\x00\x00"
1352
			. $col . "\x00"
1353
			. pack('V', $number)
1354
			. $id, false, $conn, function ($conn, $reqId = null) use ($id) {
1355
				if (!$conn) {
1356
					!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
0 ignored issues
show
Bug introduced by
The variable $cb does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1357
					return;
1358
				}
1359
				$conn->requests[$reqId] = [$id];
1360
			}
1361
		);
1362
	}
1363
1364
	/**
1365
	 * Returns an object of collection
1366
	 * @param  string $col Collection's name
1367
	 * @return Collection
1368
	 */
1369
	public function getCollection($col) {
1370
		if (strpos($col, '.') === false) {
1371
			$col = $this->dbname . '.' . $col;
1372
		}
1373
		else {
1374
			$collName = explode('.', $col, 2);
0 ignored issues
show
Unused Code introduced by
$collName is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1375
		}
1376
1377
		if (isset($this->collections[$col])) {
1378
			return $this->collections[$col];
1379
		}
1380
1381
		return $this->collections[$col] = new Collection($col, $this);
1382
	}
1383
1384
	/**
1385
	 * Magic getter-method. Proxy for getCollection
1386
	 * @param  string $name Collection's name
1387
	 * @return Collection
1388
	 */
1389
	public function __get($name) {
1390
		return $this->getCollection($name);
1391
	}
1392
1393
	public function sasl_scrum_sha1_auth($p, $cb)
1394
	{			
1395
		$session = [
1396
			'cb' => $cb,
1397
			'step' => 0,
1398
			'dbname' => $p['dbname'],
1399
			'user' => $p['user'],
1400
			'password' => $p['password'],
1401
			'auth_message' => '',
1402
			'conn' => array_key_exists('conn', $p) ? $p['conn'] : null,
1403
		];
1404
		$this->sasl_scrum_sha1_step($session);
1405
	}
1406
1407
	public function sasl_scrum_sha1_step($session, $input = null)
1408
	{
1409
		$session['step']++;
1410
		$query = [];
1411
1412
		if (!is_null($input) && (!empty($input['$err']) || !empty($input['errmsg']))) {			
1413
			call_user_func($session['cb'], $input);
1414
			return;
1415
		}
1416
1417
		if ($session['step'] == 1) {
1418
1419
			$session['nonce'] = base64_encode(openssl_random_pseudo_bytes(24));
1420
			$payload = 'n,,n=' . $session['user'] . ',r=' . $session['nonce'];
1421
			$query = ['saslStart' => 1, 'mechanism' => 'SCRAM-SHA-1', 'payload' => base64_encode($payload)];
1422
			$session['auth_message'] .= 'n=' . $session['user'] . ',r=' . $session['nonce'] . ',';
1423
1424
		} elseif ($session['step'] == 2) {
1425
			$in_payload = $this->sasl_scrum_sha1_extract_payload($input['payload']);
1426
1427
			$error = null;
1428
			if (count($in_payload) != 3) $error = 'Incorrect number of arguments for first SCRAM-SHA-1 server message, got ' . count($in_payload) . 'expected 3';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 152 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1429
			elseif (strlen($in_payload['r']) < 2) $error = 'Incorrect SCRAM-SHA-1 client|server nonce: ' . $in_payload['r'];
1430
			elseif (strlen($in_payload['s']) < 6) $error = 'Incorrect SCRAM-SHA-1 salt: ' . $in_payload['s'];
1431
			elseif (strlen($in_payload['i']) < 3) $error = 'Incorrect SCRAM-SHA-1 iteration count: ' . $in_payload['i'];
1432
			elseif (strpos($in_payload['r'], $session['nonce']) !== 0) $error = 'Server SCRAM-SHA-1 nonce does not match client nonce';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1433
			if (!empty($error)) {
1434
				call_user_func($session['cb'], ['ok' => 0, 'errmsg' => $error]);
1435
				return;
1436
			} else {
1437
				$session['conversation_id'] = $input['conversationId'];
1438
				$session['nonce'] = $in_payload['r'];
1439
			}
1440
1441
			$payload = 'c=biws,r=' . $session['nonce'];
1442
			$session['auth_message'] .= base64_decode($input['payload']) . ',' . $payload;
1443
1444
			$decoded_salt = base64_decode($in_payload['s']);
1445
			$password = md5($session['user'] . ':mongo:' . $session['password']);
1446
			$salted_password = hash_pbkdf2('sha1', $password, $decoded_salt, (int) $in_payload['i'], 0, TRUE);
1447
1448
			$client_key = hash_hmac('sha1', 'Client Key', $salted_password, true);
1449
			$stored_key = sha1($client_key, true);
1450
			$client_sign = hash_hmac('sha1', $session['auth_message'], $stored_key, true);			
1451
			$client_proof = $client_key ^ $client_sign;
1452
1453
			$payload .= ',p=' . base64_encode($client_proof);
1454
1455
			$query = ['saslContinue' => 1, 'conversationId' => $session['conversation_id'], 'payload' => base64_encode($payload)];
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1456
1457
		} elseif ($session['step'] == 3) {
1458
1459
			$in_payload = $this->sasl_scrum_sha1_extract_payload($input['payload']);
1460
			if (!empty($in_payload['v'])) {
1461
				$session['server_signature'] = $in_payload['v'];
1462
				$query = ['saslContinue' => 1, 'conversationId' => $session['conversation_id'], 'payload' => base64_encode('')];
1463
			}
1464
1465
		} elseif ($session['step'] == 4) {
1466
1467
			$in_payload = $this->sasl_scrum_sha1_extract_payload($input['payload']);
0 ignored issues
show
Unused Code introduced by
$in_payload is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1468
			$res = $input['done'] ? [
1469
				'ok' => 1, 
1470
				'server_signature' => $session['server_signature'],
1471
			] : [
1472
				'ok' => 0,
1473
				'errmsg' => 'Authentication failed.',
1474
			];
1475
			call_user_func($session['cb'], $res);
1476
			return;
1477
1478
		}
1479
1480
		$this->sasl_scrum_sha1_conversation($session['dbname'], $query, function($res) use ($session) {
1481
			$this->sasl_scrum_sha1_step($session, $res);
1482
		}, $session['conn']);
1483
	}
1484
1485
	public function sasl_scrum_sha1_conversation($dbname, $query, $cb, $conn = null)
1486
	{
1487
		if ($this->safeMode) {
1488
			static::safeModeEnc($query);
1489
		}
1490
1491
		try {			
1492
			$this->request(self::OP_QUERY, pack('V', 0)
1493
				. $dbname . '.$cmd' . "\x00"
1494
				. pack('VV', 0, -1)
1495
				. bson_encode($query), true, $conn, function ($conn, $reqId = null) use ($dbname, $cb) {
1496
					if (!$conn) {
1497
						!$cb || call_user_func($cb, ['$err' => 'Connection error.']);
1498
						return;
1499
					}
1500
					$conn->requests[$reqId] = [$dbname, $cb, true];
1501
				});
1502
		} catch (\MongoException $e) {
1503
			Daemon::log('MongoClient exception: '.$e->getMessage().': '.$e->getTraceAsString());
1504 View Code Duplication
			if ($cb !== null) {
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...
1505
				call_user_func($cb, ['$err' => $e->getMessage(), '$query' => $query, '$fields' => isset($p['fields']) ? $p['fields'] : null]);
0 ignored issues
show
Bug introduced by
The variable $p seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1506
			}
1507
		}
1508
	}
1509
1510
	public function sasl_scrum_sha1_extract_payload($payload)
1511
	{
1512
		$result = [];
1513
		$payload = base64_decode($payload);
1514
		foreach (explode(',', $payload) as $line) {
1515
			if (preg_match('/^([a-z]+)=(.*)/', $line, $ms)) {
1516
				$result[$ms[1]] = $ms[2];
1517
			}
1518
		}
1519
		return $result;
1520
	}
1521
}
1522