Completed
Push — master ( 1e1f46...8a29e8 )
by Vasily
04:50
created

Connection::onFinish()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
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 View Code Duplication
	public function onConnected($cb) {
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...
198
		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...
199
			call_user_func($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
			call_user_func($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 $callback Optional. Callback called when response received
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback 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 $callback ( Connection $conn, boolean $success )
348
	 * @return boolean            Success
349
	 */
350
	public function query($q, $callback = NULL) {
351
		return $this->command(Pool::COM_QUERY, $q, $callback);
352
	}
353
354
	/**
355
	 * Sends echo-request
356
	 * @param  callable $callback Optional. Callback called when response received
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback 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...
357
	 * @callback $callback ( Connection $conn, boolean $success )
358
	 * @return boolean            Success
359
	 */
360
	public function ping($callback = NULL) {
361
		return $this->command(Pool::COM_PING, '', $callback);
362
	}
363
364
	/**
365
	 * Sends arbitrary command
366
	 * @param  string   $cmd      Command
367
	 * @param  string   $q        Data
368
	 * @param  callable $callback Optional
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback 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...
369
	 * @throws ConnectionFinished
370
	 * @callback $callback ( Connection $conn, boolean $success )
371
	 * @return boolean            Success
372
	 */
373
	public function command($cmd, $q = '', $callback = NULL) {
374
		if ($this->finished) {
375
			throw new ConnectionFinished;
376
		}
377
378
		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...
379
			return false;
380
		}
381
382
		$this->onResponse->push($callback);
0 ignored issues
show
Bug introduced by
It seems like $callback defined by parameter $callback on line 373 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...
383
		$this->seq = 0;
384
		$this->sendPacket(chr($cmd) . $q);
385
386
		return TRUE;
387
	}
388
389
	/**
390
	 * Sets default database name
391
	 * @param  string  $name   Database name
392
	 * @return boolean         Success
393
	 */
394
	public function selectDB($name) {
395
		$this->dbname = $name;
396
397
		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...
398
			return $this->query('USE `' . $name . '`');
399
		}
400
401
		return TRUE;
402
	}
403
404
	/**
405
	 * Called when new data received
406
	 * @return void
407
	 */
408
	public function onRead() {
409
		packet:
410
		if ($this->state === self::STATE_STANDBY) {
411
			if ($this->bev->input->length < 4) {
412
				return;
413
			}
414
			$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...
415
			$this->setWatermark($this->pctSize, $this->pctSize);
416
			$this->state = self::STATE_BODY;
417
			$this->seq   = ord($this->read(1)) + 1;
418
		}
419
		/* STATE_BODY */
420
		$l = $this->bev->input->length;
421
		if ($l < $this->pctSize) {
422
			return;
423
		}
424
		$this->state = self::STATE_STANDBY;
425
		$this->setWatermark(4);
426
		if ($this->phase === 0) {
427
			$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...
428
			$this->protover = ord($this->read(1));
429
			if ($this->protover === 0xFF) { // error
430
				$fieldCount     = $this->protover;
431
				$this->protover = 0;
432 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...
433
					if ($conn->onConnected) {
434
						$conn->connected = true;
435
						$conn->onConnected->executeAll($conn, $result);
436
						$conn->onConnected = null;
437
					}
438
				});
439
				goto field;
440
			}
441
			if (($p = $this->search("\x00")) === false) {
442
				$this->log('nul-terminator of \'serverver\' is not found');
443
				$this->finish();
444
				return;
445
			}
446
			$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...
447
			$this->drain(1); // drain nul-byte
448
			$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...
449
			$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...
450
			$this->drain(1); // ????
451
452
			$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...
453
			$this->serverLang   = ord($this->read(1));
454
			$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...
455
			$this->drain(13);
456
			$restScramble = $this->read(12);
457
			$this->scramble .= $restScramble;
458
			$this->drain(1);
459
460
			$this->auth();
461
		}
462
		else {
463
			$fieldCount = ord($this->read(1));
464
			field:
465
			if ($fieldCount === 0xFF) {
466
				// Error packet
467
				$u            = unpack('v', $this->read(2));
468
				$this->errno  = $u[1];
469
				$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...
470
				$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...
471
				$this->onError();
472
				$this->errno  = 0;
473
				$this->errmsg = '';
474
			}
475
			elseif ($fieldCount === 0x00) {
476
				// OK Packet Empty
477
				if ($this->phase === self::PHASE_AUTH_SENT) {
478
					$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...
479
480
					if ($this->dbname !== '') {
481
						$this->query('USE `' . $this->dbname . '`');
482
					}
483
				}
484
485
				$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...
486
487
				$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...
488
489
				$u                  = unpack('v', $this->read(2));
490
				$this->serverStatus = $u[1];
491
492
				$u               = unpack('v', $this->read(2));
493
				$this->warnCount = $u[1];
494
495
				$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...
496
				$this->onResultDone();
497
			}
498
			elseif ($fieldCount === 0xFE) {
499
				// EOF Packet
500
				if ($this->rsState === self::RS_STATE_ROW) {
501
					$this->onResultDone();
502
				}
503
				else {
504
					++$this->rsState;
505
				}
506
			}
507
			else {
508
				// Data packet
509
				$this->prependInput(chr($fieldCount));
510
511
				if ($this->rsState === self::RS_STATE_HEADER) {
512
					// Result Set Header Packet
513
					$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...
514
					$this->rsState = self::RS_STATE_FIELD;
515
				}
516
				elseif ($this->rsState === self::RS_STATE_FIELD) {
517
					// Field Packet
518
					$field = [
519
						'catalog'   => $this->parseEncodedString(),
520
						'db'        => $this->parseEncodedString(),
521
						'table'     => $this->parseEncodedString(),
522
						'org_table' => $this->parseEncodedString(),
523
						'name'      => $this->parseEncodedString(),
524
						'org_name'  => $this->parseEncodedString()
525
					];
526
527
					$this->drain(1); // filler
528
529
					$u = unpack('v', $this->read(2));
530
531
					$field['charset'] = $u[1];
532
					$u                = unpack('V', $this->read(4));
533
					$field['length']  = $u[1];
534
535
					$field['type'] = ord($this->read(1));
536
537
					$u              = unpack('v', $this->read(2));
538
					$field['flags'] = $u[1];
539
540
					$field['decimals'] = ord($this->read(1));
541
542
					$this->resultFields[] = $field;
543
				}
544
				elseif ($this->rsState === self::RS_STATE_ROW) {
545
					// Row Packet
546
					$row = [];
547
548
					for ($i = 0, $nf = sizeof($this->resultFields); $i < $nf; ++$i) {
549
						$row[$this->resultFields[$i]['name']] = $this->parseEncodedString();
550
					}
551
552
					$this->resultRows[] = $row;
553
				}
554
			}
555
		}
556
		$this->drain($this->pctSize - $l + $this->bev->input->length); // drain the rest of packet
557
		goto packet;
558
	}
559
560
	/**
561
	 * Called when connection finishes
562
	 * @return void
563
	 */
564
	public function onFinish()
565
	{
566
		$this->command(Pool::COM_QUIT);
567
		parent::onFinish();
568
	}
569
570
	/**
571
	 * Called when the whole result received
572
	 * @return void
573
	 */
574
	public function onResultDone() {
575
		$this->rsState = self::RS_STATE_HEADER;
576
		$this->onResponse->executeOne($this, true);
577
		$this->checkFree();
578
		$this->resultRows   = [];
579
		$this->resultFields = [];
580
	}
581
582
	/**
583
	 * Called when error occured
584
	 * @return void
585
	 */
586
	public function onError() {
587
		$this->rsState = self::RS_STATE_HEADER;
588
		$this->onResponse->executeOne($this, false);
589
		$this->checkFree();
590
		$this->resultRows   = [];
591
		$this->resultFields = [];
592
593
		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...
594
			// in case of auth error
595
			$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...
596
			$this->finish();
597
		}
598
599
		Daemon::log(__METHOD__ . ' #' . $this->errno . ': ' . $this->errmsg);
600
	}
601
}
602