Completed
Push — master ( 3fcc00...26959a )
by Vasily
04:27
created

Application::beginRequest()   D

Complexity

Conditions 20
Paths 245

Size

Total Lines 61
Code Lines 41

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 61
rs 4.6788
cc 20
eloc 41
nc 245
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\SockJS;
3
4
use PHPDaemon\HTTPRequest\Generic;
5
use PHPDaemon\Core\Daemon;
6
use PHPDaemon\Structures\ObjectStorage;
7
use PHPDaemon\Core\Debug;
8
use PHPDaemon\Servers\WebSocket\Pool as WebSocketPool;
9
10
/**
11
 * @package    Libraries
12
 * @subpackage SockJS
13
 * @author     Vasily Zorin <[email protected]>
14
 */
15
class Application extends \PHPDaemon\Core\AppInstance {
16
	protected $redis;
17
	protected $sessions;
18
19
	public $wss;
20
21
	/**
22
	 * Setting default config options
23
	 * @return array|bool
24
	 */
25
	protected function getConfigDefaults() {
26
		return [
27
			/* [string] @todo redis-name */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
28
			'redis-name' => '',
29
30
			/* [string] @todo redis-prefix */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
31
			'redis-prefix' => 'sockjs:',
32
33
			/* [string] @todo wss-name */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
34
			'wss-name' => '',
35
			
36
			/* [Double] @todo batch-delay */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
37
			'batch-delay' => new \PHPDaemon\Config\Entry\Double('0.05'),
38
			
39
			/* [Double] @todo heartbeat-interval */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
40
			'heartbeat-interval' => new \PHPDaemon\Config\Entry\Double('25'),
41
			
42
			/* [Time] @todo dead-session-timeout */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
43
			'dead-session-timeout' => new \PHPDaemon\Config\Entry\Time('1h'),
44
			
45
			/* [Size] @todo gc-max-response-size */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
46
			'gc-max-response-size' => new \PHPDaemon\Config\Entry\Size('128k'),
47
			
48
			/* [Time] @todo network-timeout-read */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
49
			'network-timeout-read' => new \PHPDaemon\Config\Entry\Time('2h'),
50
			
51
			/* [Time] @todo network-timeout-write */
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
52
			'network-timeout-write' => new \PHPDaemon\Config\Entry\Time('120s'),
53
		];
54
	}
55
56
	/**
57
	 * Set Redis instance
58
	 * @param \PHPDaemon\Clients\Redis\Pool $redis
59
	 * @return $this
60
	 */
61
	public function setRedis(\PHPDaemon\Clients\Redis\Pool $redis) {
62
		$this->redis = $redis;
63
		return $this;
64
	}
65
66
	/**
67
	 * getLocalSubscribersCount
68
	 * @param  string $chan
69
	 * @return integer
70
	 */
71
	public function getLocalSubscribersCount($chan) {
72
		return $this->redis->getLocalSubscribersCount($this->config->redisprefix->value . $chan);
73
	}
74
75
	/**
76
	 * subscribe
77
	 * @param  string   $chan [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
78
	 * @param  callable $cb   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
79
	 * @param  callable $opcb [@todo description]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $opcb 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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
80
	 * @callback $cb ( )
81
	 * @callback $opcb ( )
82
	 * @return void
83
	 */
84
	public function subscribe($chan, $cb, $opcb = null) {
85
		$this->redis->subscribe($this->config->redisprefix->value . $chan, $cb, $opcb);
0 ignored issues
show
Bug introduced by
The method subscribe() does not exist on PHPDaemon\Clients\Redis\Pool. Did you maybe mean getLocalSubscribersCount()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
86
	}
87
88
	/**
89
	 * setnx
90
	 * @param  string   $key   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
91
	 * @param  mixed    $value [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
92
	 * @param  callable $cb    [@todo description]
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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
93
	 * @callback $cb ( )
94
	 * @return void
95
	 */
96
	public function setnx($key, $value, $cb = null) {
97
		$this->redis->setnx($this->config->redisprefix->value . $key, $value, $cb);
0 ignored issues
show
Documentation Bug introduced by
The method setnx does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
98
	}
99
100
	/**
101
	 * setkey
102
	 * @param  string   $key   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
103
	 * @param  mixed    $value [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
104
	 * @param  callable $cb    [@todo description]
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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
105
	 * @callback $cb ( )
106
	 * @return void
107
	 */
108
	public function setkey($key, $value, $cb = null) {
109
		$this->redis->set($this->config->redisprefix->value . $key, $value, $cb);
0 ignored issues
show
Documentation Bug introduced by
The method set does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
110
	}
111
112
	/**
113
	 * getkey
114
	 * @param  string   $key   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
115
	 * @param  callable $cb    [@todo description]
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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
116
	 * @callback $cb ( )
117
	 * @return void
118
	 */
119
	public function getkey($key, $cb = null) {
120
		$this->redis->get($this->config->redisprefix->value . $key, $cb);
0 ignored issues
show
Documentation Bug introduced by
The method get does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
121
	}
122
123
	/**
124
	 * expire
125
	 * @param  string   $key     [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
126
	 * @param  integer  $seconds [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
127
	 * @param  callable $cb      [@todo description]
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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
128
	 * @callback $cb ( )
129
	 * @return void
130
	 */
131
	public function expire($key, $seconds, $cb = null) {
132
		$this->redis->expire($this->config->redisprefix->value . $key, $seconds, $cb);
0 ignored issues
show
Documentation Bug introduced by
The method expire does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
133
	}
134
135
	/**
136
	 * unsubscribe
137
	 * @param  string   $chan [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
138
	 * @param  callable $cb   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
139
	 * @param  callable $opcb [@todo description]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $opcb 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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
140
	 * @callback $cb ( )
141
	 * @callback $opcb ( )
142
	 * @return void
143
	 */
144
	public function unsubscribe($chan, $cb, $opcb = null) {
145
		$this->redis->unsubscribe($this->config->redisprefix->value . $chan, $cb, $opcb);
0 ignored issues
show
Documentation Bug introduced by
The method unsubscribe does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
146
	}
147
148
	/**
149
	 * unsubscribeReal
150
	 * @param  string   $chan [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
151
	 * @param  callable $opcb [@todo description]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $opcb 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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
152
	 * @callback $opcb ( )
153
	 * @return void
154
	 */
155
	public function unsubscribeReal($chan, $opcb = null) {
156
		$this->redis->unsubscribeReal($this->config->redisprefix->value . $chan, $opcb);
0 ignored issues
show
Documentation Bug introduced by
The method unsubscribeReal does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
157
	}
158
159
	/**
160
	 * publish
161
	 * @param  string   $chan [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
162
	 * @param  callable $cb   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
163
	 * @param  callable $opcb [@todo description]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $opcb 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...
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
164
	 * @callback $cb ( )
165
	 * @callback $opcb ( )
166
	 * @return void
167
	 */
168
	public function publish($chan, $cb, $opcb = null) {
169
		$this->redis->publish($this->config->redisprefix->value . $chan, $cb, $opcb);
0 ignored issues
show
Documentation Bug introduced by
The method publish does not exist on object<PHPDaemon\Clients\Redis\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
170
	}
171
172
	/**
173
	 * Called when the worker is ready to go
174
	 * @return void
175
	 */
176
	public function onReady() {
177
		$this->redis = \PHPDaemon\Clients\Redis\Pool::getInstance($this->config->redisname->value);
178
		$this->sessions = new ObjectStorage;
179
		$this->wss = new ObjectStorage;
180
		foreach (preg_split('~\s*;\s*~', $this->config->wssname->value) as $wssname) {
181
			$this->attachWss(WebSocketPool::getInstance(trim($wssname)));
182
		}
183
	}
184
185
	/**
186
	 * onFinish
187
	 * @return void
188
	 */
189
	public function onFinish() {
190
		foreach ($this->attachedTo as $wss) {
0 ignored issues
show
Bug introduced by
The property attachedTo does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
191
			$this->detachWss($wss);
192
		}
193
		parent::onFinish();
194
	}
195
196
	/**
197
	 * attachWss
198
	 * @param \PHPDaemon\Network\Pool $wss
199
	 * @return boolean
200
	 */
201
	public function attachWss($wss) {
202
		if ($this->wss->contains($wss)) {
203
			return false;
204
		}
205
		$this->wss->attach($wss);
206
		$wss->bind('customTransport', [$this, 'wsHandler']);
0 ignored issues
show
Documentation Bug introduced by
The method bind does not exist on object<PHPDaemon\Network\Pool>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
207
		return true;
208
	}
209
210
	/**
211
	 * wsHandler
212
	 * @param  object   $ws     [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
213
	 * @param  string   $path   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
214
	 * @param  object   $client [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
215
	 * @param  callable $state  [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
216
	 * @callback $state ( object $route )
217
	 * @return boolean
218
	 */
219
	public function wsHandler($ws, $path, $client, $state) {
220
		$e = explode('/', $path);
221
		$method = array_pop($e);
222
		$serverId = null;
0 ignored issues
show
Unused Code introduced by
$serverId 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...
223
		$sessId = null;
0 ignored issues
show
Unused Code introduced by
$sessId 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...
224
		if ($method !== 'websocket') {
225
			return false;
226
		}
227
		if (sizeof($e) < 3 || !isset($e[sizeof($e) - 2]) || !ctype_digit($e[sizeof($e) - 2])) {
228
			return false;
229
		}
230
		$sessId = array_pop($e);
0 ignored issues
show
Unused Code introduced by
$sessId 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...
231
		$serverId = array_pop($e);
0 ignored issues
show
Unused Code introduced by
$serverId 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...
232
		$path = implode('/', $e);
233
		$client = new WebSocketConnectionProxy($this, $client);
234
		$route = $ws->getRoute($path, $client, true);
235
		if (!$route) {
236
			$state($route);
237
			return false;
238
		}
239
		$route = new WebSocketRouteProxy($this, $route);
240
		$state($route);
241
		return true;
242
	}
243
244
	/**
245
	 * detachWss
246
	 * @param  object $wss [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
247
	 * @return boolean
248
	 */
249
	public function detachWss($wss) {
250
		if (!$this->wss->contains($wss)) {
251
			return false;
252
		}
253
		$this->wss->detach($wss);
254
		$wss->unbind('transport', [$this, 'wsHandler']);
255
		return true;
256
	}
257
258
	/**
259
	 * beginSession
260
	 * @param  string $path   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
261
	 * @param  string $sessId [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
262
	 * @param  string $server [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
263
	 * @return object
0 ignored issues
show
Documentation introduced by
Should the return type not be false|Session?

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...
264
	 */
265
	public function beginSession($path, $sessId, $server) {
266
		$session = new Session($this, $sessId, $server);
0 ignored issues
show
Documentation introduced by
$server is of type string, but the function expects a array.

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...
267
		foreach ($this->wss as $wss) {
268
			if ($session->route = $wss->getRoute($path, $session)) {
269
				break;
270
			}
271
		}
272
		if (!$session->route) {
273
			return false;
274
		}
275
		$this->sessions->attach($session);
276
		$session->onHandshake();
277
		return $session;
278
	}
279
280
	/**
281
	 * getRouteOptions
282
	 * @param  string $path [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
283
	 * @return array
284
	 */
285
	public function getRouteOptions($path) {
286
		$opts = [
287
			'websocket' => true,
288
			'origins' => ['*:*'],
289
			'cookie_needed' => false,
290
		];
291
		foreach ($this->wss as $wss) {
292
			if ($wss->routeExists($path)) {
293
				foreach ($wss->getRouteOptions($path) as $k => $v) {
294
					$opts[$k] = $v;
295
				}
296
				break;
297
			}
298
		}
299
		return $opts;
300
	}
301
302
	/**
303
	 * endSession
304
	 * @param Session $session
305
	 * @return void
306
	 */
307
	public function endSession($session) {
308
		$this->sessions->detach($session);
309
	}
310
311
	/**
312
	 * Creates Request.
313
	 * @param  object $req      Request.
314
	 * @param  object $upstream Upstream application instance.
315
	 * @return object           Request.
316
	 */
317
	public function beginRequest($req, $upstream) {
318
		$e = array_map('rawurldecode', explode('/', $req->attrs->server['DOCUMENT_URI']));
319
		
320
		$serverId = null;
321
		$sessId = null;
322
323
		/* Route discovery */
324
		$path = null;
325
		$extra = [];
326
		do {
327
			foreach ($this->wss as $wss) {
328
				$try = implode('/', $e);
329
				if ($try === '') {
330
					$try = '/';
331
				}
332
				if ($wss->routeExists($try)) {
333
					$path = $try;
334
					break 2;
335
				}
336
			}
337
		 	array_unshift($extra, array_pop($e));
338
		} while (sizeof($e) > 0);
339
340
		if ($path === null) {
341
			return $this->callMethod('NotFound', $req, $upstream);
342
		}
343
344
		if (sizeof($extra) > 0 && end($extra) === '') {
345
			array_pop($extra);
346
		}
347
348
		$method = sizeof($extra) ? array_pop($extra) : null;
349
		
350
		if ($method === null) {
351
			$method = 'Welcome';
352
		}
353
		elseif ($method === 'info') {
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...
354
355
		}
356
		elseif (preg_match('~^iframe(?:-([^/]*))?\.html$~', $method, $m)) {
357
			$method = 'Iframe';
358
			$version = isset($m[1]) ? $m[1] : null;
359
		} else {
360
			if (sizeof($extra) < 2) {
361
				return $this->callMethod('NotFound', $req, $upstream);	
362
			}
363
			$sessId = array_pop($extra);
364
			$serverId = array_pop($extra);
365
			if ($sessId === '' || $serverId === '' || strpos($sessId, '.') !== false || strpos($serverId, '.') !== false) {
366
				return $this->callMethod('NotFound', $req, $upstream);	
367
			}
368
		}
369
		$req->attrs->sessId = $sessId;
370
		$req->attrs->serverId = $serverId;
371
		$req->attrs->path = $path;
372
		$req = $this->callMethod($method, $req, $upstream);
373
		if ($req instanceof Methods\Iframe && strlen($version)) {
374
			$req->attrs->version = $version;
0 ignored issues
show
Bug introduced by
The variable $version does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
375
		}
376
		return $req;
377
	}
378
379
	/**
380
	 * callMethod
381
	 * @param  string $method   [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
382
	 * @param  object $req      [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
383
	 * @param  object $upstream [@todo description]
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
384
	 * @return object
385
	 */
386
	public function callMethod($method, $req, $upstream) {
387
		$method = strtr(ucwords(strtr($method, ['_' => ' '])), [' ' => '']);
388
		if (strtolower($method) === 'generic') {
389
			$method = 'NotFound';
390
		}
391
		$class = __NAMESPACE__ . '\\Methods\\' . $method;
392
		if (!class_exists($class)) {
393
			$class = __NAMESPACE__ . '\\Methods\\NotFound'; 
394
		}
395
		return new $class($this, $upstream, $req);
396
	}
397
}
398