Completed
Push — master ( d5605a...029d32 )
by Vasily
04:09
created

Connection::commit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
namespace PHPDaemon\Clients\MySQL;
3
4
use PHPDaemon\Core\Daemon;
5
use PHPDaemon\Network\ClientConnection;
6
use PHPDaemon\Structures\StackCallbacks;
7
use PHPDaemon\Utils\Binary;
8
9
class Connection extends ClientConnection {
10
11
	/**
12
	 * @var integer Sequence. Pointer of packet sequence
13
	 */
14
	public $seq = 0;
15
16
	/**
17
	 * @var integer Client flags
18
	 */
19
	public $clientFlags = 239237;
20
21
	/**
22
	 * @var integer
23
	 */
24
	public $threadId;
25
26
	/**
27
	 * @var string
28
	 */
29
	public $scramble;
30
31
	/**
32
	 * @var string
33
	 */
34
	public $serverver;
35
36
	/**
37
	 * @var integer
38
	 */
39
	public $serverCaps;
40
41
	/**
42
	 * @var integer
43
	 */
44
	public $serverLang;
45
	
46
	/**
47
	 * @var integer Server flags: http://dev.mysql.com/doc/internals/en/status-flags.html
48
	 */
49
	public $serverStatus;
50
	
51
	/**
52
	 * @var integer Number of warnings generated by the command
53
	 */
54
	public $warnCount;
55
	
56
	/**
57
	 * @var string
58
	 */
59
	public $message;
60
61
	/**
62
	 * @var integer Charset number (see MySQL charset list)
63
	 */
64
	public $charsetNumber = 0x21;
65
66
	/**
67
	 * @var string User name
68
	 */
69
	protected $user = 'root';
70
71
	/**
72
	 * @var string Password
73
	 */
74
	protected $password = '';
75
76
	/**
77
	 * @var string Database name
78
	 */
79
	public $dbname = '';
80
81
	/**
82
	 * @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...
83
	 */
84
	const STATE_STANDBY = 0;
85
86
	/**
87
	 * @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...
88
	 */
89
	const STATE_BODY    = 1;
90
91
	/**
92
	 * @var string Phase
93
	 */
94
	protected $phase = 0;
95
96
	/**
97
	 * @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...
98
	 */
99
	const PHASE_GOT_INIT   = 1;
100
101
	/**
102
	 * @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...
103
	 */
104
	const PHASE_AUTH_SENT  = 2;
105
106
	/**
107
	 * @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...
108
	 */
109
	const PHASE_AUTH_ERR   = 3;
110
111
	/**
112
	 * @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...
113
	 */
114
	const PHASE_HANDSHAKED = 4;
115
116
	/**
117
	 * @var integer State of pointer of incoming data. 0 - Result Set Header Packet, 1 - Field Packet, 2 - Row Packet
118
	 */
119
	protected $rsState = 0;
120
121
	/**
122
	 * @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...
123
	 */
124
	const RS_STATE_HEADER = 0;
125
126
	/**
127
	 * @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...
128
	 */
129
	const RS_STATE_FIELD  = 1;
130
131
	/**
132
	 * @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...
133
	 */
134
	const RS_STATE_ROW    = 2;
135
136
	/**
137
	 * @var integer Packet size
138
	 */
139
	protected $pctSize = 0;
140
141
	/**
142
	 * @var array Result rows
143
	 */
144
	public $resultRows = [];
145
146
	/**
147
	 * @var array Result fields
148
	 */
149
	public $resultFields = [];
150
151
	/**
152
	 * @var object Property holds a reference to user's object
153
	 */
154
	public $context;
155
156
	/**
157
	 * @var integer INSERT_ID()
158
	 */
159
	public $insertId;
160
161
	/**
162
	 * @var integer Affected rows
163
	 */
164
	public $affectedRows;
165
166
	/**
167
	 * @var integer Protocol version
168
	 */
169
	public $protover = 0;
170
171
	/**
172
	 * @var integer Timeout
173
	 */
174
	public $timeout = 120;
175
176
	/**
177
	 * @var integer Error number
178
	 */
179
	public $errno = 0;
180
181
	/**
182
	 * @var string Error message
183
	 */
184
	public $errmsg = '';
185
186
	/**
187
	 * @var integer Low mark
188
	 */
189
	protected $lowMark = 4;
190
191
	/**
192
	 * Executes the given callback when/if the connection is handshaked
193
	 * @param  callable $cb Callback
194
	 * @callback $cb ( Connection $conn, boolean $success )
195
	 * @return void
196
	 */
197
	public function onConnected($cb) {
198 View Code Duplication
		if ($this->phase === self::PHASE_AUTH_ERR) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_AUTH_ERR (integer) can never be identical. Maybe you want to use a loose comparison == instead?
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...
199
			$cb($this, false);
200
		}
201
		elseif ($this->phase === self::PHASE_HANDSHAKED) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_HANDSHAKED (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
202
			$cb($this, true);
203
		}
204
		else {
205
			if (!$this->onConnected) {
206
				$this->onConnected = new StackCallbacks();
207
			}
208
			$this->onConnected->push($cb);
209
		}
210
	}
211
212
	/**
213
	 * Called when the connection is handshaked (at low-level), and peer is ready to recv. data
214
	 * @return void
215
	 */
216
	public function onReady() {
217
		if (strlen($this->path) && !strlen($this->dbname)) {
218
			$this->dbname = $this->path;
219
		}
220
	}
221
222
	/**
223
	 * Sends a packet
224
	 * @param  string  $packet Data
225
	 * @return boolean         Success
226
	 */
227
	public function sendPacket($packet) {
228
		//Daemon::log('Client --> Server: ' . Debug::exportBytes($packet) . "\n\n");
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...
229
		return $this->write(Binary::int2bytes(3, strlen($packet), true) . chr($this->seq++) . $packet);
230
	}
231
232
	/**
233
	 * Builds length-encoded binary string
234
	 * @param  string $s String
235
	 * @return string    Resulting binary string
236
	 */
237
	public function buildLenEncodedBinary($s) {
238
		if ($s === NULL) {
239
			return "\251";
240
		}
241
242
		$l = strlen($s);
243
244
		if ($l <= 250) {
245
			return chr($l) . $s;
246
		}
247
248
		if ($l <= 0xFFFF) {
249
			return "\252" . Binary::int2bytes(2, true) . $s;
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
250
		}
251
252
		if ($l <= 0xFFFFFF) {
253
			return "\254" . Binary::int2bytes(3, true) . $s;
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
254
		}
255
256
		return Binary::int2bytes(8, $l, true) . $s;
257
	}
258
259
	/**
260
	 * Parses length-encoded binary integer
261
	 * @return integer Result
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|null|false|double?

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...
262
	 */
263
	public function parseEncodedBinary() {
264
		$f = ord($this->read(1));
265
		if ($f <= 250) {
266
			return $f;
267
		}
268
		if ($f === 251) {
269
			return null;
270
		}
271
		if ($f === 255) {
272
			return false;
273
		}
274
		if ($f === 252) {
275
			return Binary::bytes2int($this->read(2), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
276
		}
277
		if ($f === 253) {
278
			return Binary::bytes2int($this->read(3), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(3) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
279
		}
280
		return Binary::bytes2int($this->read(8), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(8) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
281
	}
282
283
	/**
284
	 * Parse length-encoded string
285
	 * @return integer Result
0 ignored issues
show
Documentation introduced by
Should the return type not be null|false|string?

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...
286
	 */
287
	public function parseEncodedString() {
288
		$l = $this->parseEncodedBinary();
289
		if (($l === null) || ($l === false)) {
290
			return $l;
291
		}
292
		return $this->read($l);
293
	}
294
295
	/**
296
	 * Generates auth. token
297
	 * @param  string $scramble Scramble string
298
	 * @param  string $password Password
299
	 * @return string           Result
300
	 */
301
	public function getAuthToken($scramble, $password) {
302
		return sha1($scramble . sha1($hash1 = sha1($password, true), true), true) ^ $hash1;
303
	}
304
305
	/**
306
	 * Sends auth. packet
307
	 * @return void
308
	 */
309
	public function auth() {
310
		if ($this->phase !== self::PHASE_GOT_INIT) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
311
			return;
312
		}
313
		$this->phase = self::PHASE_AUTH_SENT;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_AUTH_SENT is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
314 View Code Duplication
		$this->onResponse->push(function ($conn, $result) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
315
			if ($conn->onConnected) {
316
				$conn->connected = true;
317
				$conn->onConnected->executeAll($conn, $result);
318
				$conn->onConnected = null;
319
			}
320
		});
321
		$this->clientFlags =
322
				Pool::CLIENT_LONG_PASSWORD |
323
				Pool::CLIENT_LONG_FLAG |
324
				Pool::CLIENT_LOCAL_FILES |
325
				Pool::CLIENT_PROTOCOL_41 |
326
				Pool::CLIENT_INTERACTIVE |
327
				Pool::CLIENT_TRANSACTIONS |
328
				Pool::CLIENT_SECURE_CONNECTION |
329
				Pool::CLIENT_MULTI_STATEMENTS |
330
				Pool::CLIENT_MULTI_RESULTS;
331
332
		$this->sendPacket(
333
			$packet = pack('VVc', $this->clientFlags, $this->pool->maxAllowedPacket, $this->charsetNumber)
334
					. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
335
					. $this->user . "\x00"
336
					. ($this->password === '' ? "\x00" : $this->buildLenEncodedBinary(
337
						$this->getAuthToken($this->scramble, $this->password)
338
					))
339
					. ($this->path !== '' ? $this->path . "\x00" : '')
340
		);
341
	}
342
343
	/**
344
	 * Sends SQL-query
345
	 * @param  string   $q        Query
346
	 * @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...
347
	 * @callback $cb ( Connection $conn, boolean $success )
348
	 * @return boolean            Success
349
	 */
350
	public function query($q, $cb = null) {
351
		if ($this->finished) {
352
			throw new ConnectionFinished;
353
		}
354
		return $this->command(Pool::COM_QUERY, $q, $cb);
355
	}
356
357
	/**
358
	 * Begins a transaction
359
	 * @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...
360
	 * @throws ConnectionFinished
361
	 */
362
	public function begin($cb = null) {
363
		$this->query('BEGIN', $cb);
364
		$this->acquire();
365
	}
366
367
	/**
368
	 * Commit a transaction
369
	 * @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...
370
	 * @throws ConnectionFinished
371
	 */
372
	public function commit($cb = null) {
373
		$this->query('COMMIT', $cb);
374
		$this->release();
375
	}
376
377
	/**
378
	 * Rollback a transaction
379
	 * @throws ConnectionFinished
380
	 */
381
	public function rollback($cb = null) {
382
		$this->query('ROLLBACK', $cb);
383
		$this->release();
384
	}
385
386
	/**
387
	 * Sends echo-request
388
	 * @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...
389
	 * @callback $cb ( Connection $conn, boolean $success )
390
	 * @return boolean            Success
391
	 */
392
	public function ping($cb = NULL) {
393
		return $this->command(Pool::COM_PING, '', $cb);
394
	}
395
396
	/**
397
	 * Sends arbitrary command
398
	 * @param  string   $cmd      Command
399
	 * @param  string   $q        Data
400
	 * @param  callable $cb Optional
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...
401
	 * @throws ConnectionFinished
402
	 * @callback $cb ( Connection $conn, boolean $success )
403
	 * @return boolean            Success
404
	 */
405 View Code Duplication
	public function command($cmd, $q = '', $cb = NULL) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
406
		if ($this->phase !== self::PHASE_HANDSHAKED) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_HANDSHAKED (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
407
			return false;
408
		}
409
410
		$this->onResponse->push($cb);
0 ignored issues
show
Bug introduced by
It seems like $cb defined by parameter $cb on line 405 can also be of type null; however, PHPDaemon\Structures\StackCallbacks::push() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
411
		$this->seq = 0;
412
		$this->sendPacket(chr($cmd) . $q);
413
414
		return TRUE;
415
	}
416
417
	/**
418
	 * Sets default database name
419
	 * @param  string  $name   Database name
420
	 * @return boolean         Success
421
	 */
422
	public function selectDB($name) {
423
		$this->dbname = $name;
424
425
		if ($this->phase !== self::PHASE_GOT_INIT) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
426
			return $this->query('USE `' . $name . '`');
427
		}
428
429
		return TRUE;
430
	}
431
432
	/**
433
	 * Called when new data received
434
	 * @return void
435
	 */
436
	public function onRead() {
437
		packet:
438
		if ($this->state === self::STATE_STANDBY) {
439
			if ($this->bev->input->length < 4) {
440
				return;
441
			}
442
			$this->pctSize = Binary::bytes2int($this->read(3), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(3) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(3), true) can also be of type double. However, the property $pctSize is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
443
			$this->setWatermark($this->pctSize, $this->pctSize);
444
			$this->state = self::STATE_BODY;
445
			$this->seq   = ord($this->read(1)) + 1;
446
		}
447
		/* STATE_BODY */
448
		$l = $this->bev->input->length;
449
		if ($l < $this->pctSize) {
450
			return;
451
		}
452
		$this->state = self::STATE_STANDBY;
453
		$this->setWatermark(4);
454
		if ($this->phase === 0) {
455
			$this->phase    = self::PHASE_GOT_INIT;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_GOT_INIT is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
456
			$this->protover = ord($this->read(1));
457
			if ($this->protover === 0xFF) { // error
458
				$fieldCount     = $this->protover;
459
				$this->protover = 0;
460 View Code Duplication
				$this->onResponse->push(function ($conn, $result) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
461
					if ($conn->onConnected) {
462
						$conn->connected = true;
463
						$conn->onConnected->executeAll($conn, $result);
464
						$conn->onConnected = null;
465
					}
466
				});
467
				goto field;
468
			}
469
			if (($p = $this->search("\x00")) === false) {
470
				$this->log('nul-terminator of \'serverver\' is not found');
471
				$this->finish();
472
				return;
473
			}
474
			$this->serverver = $this->read($p);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($p) can also be of type false. However, the property $serverver is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
475
			$this->drain(1); // drain nul-byte
476
			$this->threadId = Binary::bytes2int($this->read(4), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(4) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(4), true) can also be of type double. However, the property $threadId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
477
			$this->scramble = $this->read(8);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read(8) can also be of type false. However, the property $scramble is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
478
			$this->drain(1); // ????
479
480
			$this->serverCaps   = Binary::bytes2int($this->read(2), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(2), true) can also be of type double. However, the property $serverCaps is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
481
			$this->serverLang   = ord($this->read(1));
482
			$this->serverStatus = Binary::bytes2int($this->read(2), true);
0 ignored issues
show
Security Bug introduced by
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(2), true) can also be of type double. However, the property $serverStatus is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
483
			$this->drain(13);
484
			$restScramble = $this->read(12);
485
			$this->scramble .= $restScramble;
486
			$this->drain(1);
487
488
			$this->auth();
489
		}
490
		else {
491
			$fieldCount = ord($this->read(1));
492
			field:
493
			if ($fieldCount === 0xFF) {
494
				// Error packet
495
				$u            = unpack('v', $this->read(2));
496
				$this->errno  = $u[1];
497
				$state        = $this->read(6);
0 ignored issues
show
Unused Code introduced by
$state 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...
498
				$this->errmsg = $this->read($this->pctSize - $l + $this->bev->input->length);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($this->pctSi...is->bev->input->length) can also be of type false. However, the property $errmsg is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
499
				$this->onError();
500
				$this->errno  = 0;
501
				$this->errmsg = '';
502
			}
503
			elseif ($fieldCount === 0x00) {
504
				// OK Packet Empty
505
				if ($this->phase === self::PHASE_AUTH_SENT) {
506
					$this->phase = self::PHASE_HANDSHAKED;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_HANDSHAKED is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
507
508
					if ($this->dbname !== '') {
509
						$this->query('USE `' . $this->dbname . '`');
510
					}
511
				}
512
513
				$this->affectedRows = $this->parseEncodedBinary();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parseEncodedBinary() can also be of type false or double. However, the property $affectedRows is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
514
515
				$this->insertId = $this->parseEncodedBinary();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parseEncodedBinary() can also be of type false or double. However, the property $insertId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
516
517
				$u                  = unpack('v', $this->read(2));
518
				$this->serverStatus = $u[1];
519
520
				$u               = unpack('v', $this->read(2));
521
				$this->warnCount = $u[1];
522
523
				$this->message = $this->read($this->pctSize - $l + $this->bev->input->length);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($this->pctSi...is->bev->input->length) can also be of type false. However, the property $message is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
524
				$this->onResultDone();
525
			}
526
			elseif ($fieldCount === 0xFE) {
527
				// EOF Packet
528
				if ($this->rsState === self::RS_STATE_ROW) {
529
					$this->onResultDone();
530
				}
531
				else {
532
					++$this->rsState;
533
				}
534
			}
535
			else {
536
				// Data packet
537
				$this->prependInput(chr($fieldCount));
538
539
				if ($this->rsState === self::RS_STATE_HEADER) {
540
					// Result Set Header Packet
541
					$extra         = $this->parseEncodedBinary();
0 ignored issues
show
Unused Code introduced by
$extra 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...
542
					$this->rsState = self::RS_STATE_FIELD;
543
				}
544
				elseif ($this->rsState === self::RS_STATE_FIELD) {
545
					// Field Packet
546
					$field = [
547
						'catalog'   => $this->parseEncodedString(),
548
						'db'        => $this->parseEncodedString(),
549
						'table'     => $this->parseEncodedString(),
550
						'org_table' => $this->parseEncodedString(),
551
						'name'      => $this->parseEncodedString(),
552
						'org_name'  => $this->parseEncodedString()
553
					];
554
555
					$this->drain(1); // filler
556
557
					$u = unpack('v', $this->read(2));
558
559
					$field['charset'] = $u[1];
560
					$u                = unpack('V', $this->read(4));
561
					$field['length']  = $u[1];
562
563
					$field['type'] = ord($this->read(1));
564
565
					$u              = unpack('v', $this->read(2));
566
					$field['flags'] = $u[1];
567
568
					$field['decimals'] = ord($this->read(1));
569
570
					$this->resultFields[] = $field;
571
				}
572
				elseif ($this->rsState === self::RS_STATE_ROW) {
573
					// Row Packet
574
					$row = [];
575
576
					for ($i = 0, $nf = sizeof($this->resultFields); $i < $nf; ++$i) {
577
						$row[$this->resultFields[$i]['name']] = $this->parseEncodedString();
578
					}
579
580
					$this->resultRows[] = $row;
581
				}
582
			}
583
		}
584
		if ($this->finished) {
585
			return;
586
		}
587
		$this->drain($this->pctSize - $l + $this->bev->input->length); // drain the rest of packet
588
		goto packet;
589
	}
590
591
	/**
592
	 * Called when connection finishes
593
	 * @return void
594
	 */
595
	public function onFinish()
596
	{
597
		$this->command(Pool::COM_QUIT);
598
		parent::onFinish();
599
	}
600
601
	/**
602
	 * Called when the whole result received
603
	 * @return void
604
	 */
605
	public function onResultDone() {
606
		$this->rsState = self::RS_STATE_HEADER;
607
		$this->onResponse->executeOne($this, true);
608
		$this->checkFree();
609
		$this->resultRows   = [];
610
		$this->resultFields = [];
611
	}
612
613
	/**
614
	 * Called when error occured
615
	 * @return void
616
	 */
617
	public function onError() {
618
		$this->rsState = self::RS_STATE_HEADER;
619
		$this->onResponse->executeOne($this, false);
620
		$this->checkFree();
621
		$this->resultRows   = [];
622
		$this->resultFields = [];
623
624
		if (($this->phase === self::PHASE_AUTH_SENT) || ($this->phase === self::PHASE_GOT_INIT)) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_AUTH_SENT (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
625
			// in case of auth error
626
			$this->phase = self::PHASE_AUTH_ERR;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_AUTH_ERR is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
627
			$this->finish();
628
		}
629
630
		Daemon::log(__METHOD__ . ' #' . $this->errno . ': ' . $this->errmsg);
631
	}
632
}
633