Passed
Push — master ( da3f2a...c03036 )
by Shahrad
01:59
created
src/Model/DownloadResult.php 2 patches
Indentation   +141 added lines, -141 removed lines patch added patch discarded remove patch
@@ -12,146 +12,146 @@
 block discarded – undo
12 12
 class DownloadResult
13 13
 {
14 14
 
15
-	/**
16
-	 * The unique identifier of the download
17
-	 *
18
-	 * @var string
19
-	 */
20
-	public string $id;
21
-
22
-	/**
23
-	 * The final size of the downloaded file
24
-	 *
25
-	 * @var int
26
-	 */
27
-	public int $fileSize;
28
-
29
-	/**
30
-	 * The path of the downloaded chunks
31
-	 *
32
-	 * @var string
33
-	 */
34
-	public string $chunksPath;
35
-
36
-	/**
37
-	 * The size of each chunk
38
-	 *
39
-	 * @var int
40
-	 */
41
-	public int $chunkSize;
42
-
43
-	/**
44
-	 * The count of chunks
45
-	 *
46
-	 * @var int
47
-	 */
48
-	public int $chunks;
49
-
50
-	/**
51
-	 * Start time of the download in timestamp.
52
-	 *
53
-	 * @var int
54
-	 */
55
-	public int $startTime;
56
-
57
-	/**
58
-	 * End time of the download in timestamp.
59
-	 *
60
-	 * @var int
61
-	 */
62
-	public int $endTime;
63
-
64
-	/**
65
-	 * The downloaded chunks
66
-	 *
67
-	 * @var array [{id, size, location, elapsedTime}, ...]
68
-	 */
69
-	public array $downloads;
70
-
71
-	/**
72
-	 * Add a chunk to the download result
73
-	 *
74
-	 * @param string $id The unique identifier of the chunk
75
-	 * @param ?string $body The chunk body
76
-	 * @param float $elapsedTime in microseconds
77
-	 * @return void
78
-	 */
79
-	public function addChunk(string $id, ?string $body, float $elapsedTime): void
80
-	{
81
-		$data = [
82
-			'id' => $id,
83
-			'location' => null,
84
-			'size' => 0,
85
-			'elapsed_time' => $elapsedTime,
86
-			'status' => 'failed',
87
-		];
88
-		if ($body !== null) {
89
-			$save = $this->saveChunk($id, $body);
90
-			$data = array_merge($data, [
91
-				'location' => $save ?? null,
92
-				'size' => strlen($body),
93
-				'status' => $save ? 'saved' : 'failed',
94
-			]);
95
-		}
96
-		$this->downloads[] = $data;
97
-	}
98
-
99
-	/**
100
-	 * Save the chunks to the temp directory
101
-	 *
102
-	 * @param string $id The unique identifier of the chunk
103
-	 * @param string $body The body of the chunk
104
-	 * @return string|bool
105
-	 */
106
-	private function saveChunk(string $id, string $body): string|bool
107
-	{
108
-		$path = $this->chunksPath . DIRECTORY_SEPARATOR . $id;
109
-		return file_put_contents($path, $body) ? $path : false;
110
-	}
111
-
112
-	/**
113
-	 * Merge the chunks into a single string
114
-	 *
115
-	 * @return string
116
-	 */
117
-	public function mergeChunks(): string
118
-	{
119
-		$result = '';
120
-		foreach ($this->downloads as $chunk) {
121
-			$result .= file_get_contents($chunk['location']);
122
-		}
123
-		return $result;
124
-	}
125
-
126
-	/**
127
-	 * Save the merged chunks to a file
128
-	 *
129
-	 * @param string $filePath The path/to/file.ext
130
-	 * @return bool
131
-	 */
132
-	public function save(string $filePath): bool
133
-	{
134
-		$pathInfo = pathinfo($filePath, PATHINFO_DIRNAME);
135
-		if (gettype($pathInfo) != "string") $pathInfo = $pathInfo['dirname'];
136
-		if (!file_exists($pathInfo)) {
137
-			throw new \InvalidArgumentException('The directory does not exist');
138
-		}
139
-		$result = $this->mergeChunks();
140
-		$this->cleanChunks();
141
-		return file_put_contents($filePath, $result) !== false;
142
-	}
143
-
144
-	/**
145
-	 * Clean the directory of the chunks
146
-	 *
147
-	 * @return void
148
-	 */
149
-	public function cleanChunks(): void
150
-	{
151
-		foreach (glob($this->chunksPath . DIRECTORY_SEPARATOR . '*') as $file) {
152
-			unlink($file);
153
-		}
154
-		rmdir($this->chunksPath);
155
-	}
15
+    /**
16
+     * The unique identifier of the download
17
+     *
18
+     * @var string
19
+     */
20
+    public string $id;
21
+
22
+    /**
23
+     * The final size of the downloaded file
24
+     *
25
+     * @var int
26
+     */
27
+    public int $fileSize;
28
+
29
+    /**
30
+     * The path of the downloaded chunks
31
+     *
32
+     * @var string
33
+     */
34
+    public string $chunksPath;
35
+
36
+    /**
37
+     * The size of each chunk
38
+     *
39
+     * @var int
40
+     */
41
+    public int $chunkSize;
42
+
43
+    /**
44
+     * The count of chunks
45
+     *
46
+     * @var int
47
+     */
48
+    public int $chunks;
49
+
50
+    /**
51
+     * Start time of the download in timestamp.
52
+     *
53
+     * @var int
54
+     */
55
+    public int $startTime;
56
+
57
+    /**
58
+     * End time of the download in timestamp.
59
+     *
60
+     * @var int
61
+     */
62
+    public int $endTime;
63
+
64
+    /**
65
+     * The downloaded chunks
66
+     *
67
+     * @var array [{id, size, location, elapsedTime}, ...]
68
+     */
69
+    public array $downloads;
70
+
71
+    /**
72
+     * Add a chunk to the download result
73
+     *
74
+     * @param string $id The unique identifier of the chunk
75
+     * @param ?string $body The chunk body
76
+     * @param float $elapsedTime in microseconds
77
+     * @return void
78
+     */
79
+    public function addChunk(string $id, ?string $body, float $elapsedTime): void
80
+    {
81
+        $data = [
82
+            'id' => $id,
83
+            'location' => null,
84
+            'size' => 0,
85
+            'elapsed_time' => $elapsedTime,
86
+            'status' => 'failed',
87
+        ];
88
+        if ($body !== null) {
89
+            $save = $this->saveChunk($id, $body);
90
+            $data = array_merge($data, [
91
+                'location' => $save ?? null,
92
+                'size' => strlen($body),
93
+                'status' => $save ? 'saved' : 'failed',
94
+            ]);
95
+        }
96
+        $this->downloads[] = $data;
97
+    }
98
+
99
+    /**
100
+     * Save the chunks to the temp directory
101
+     *
102
+     * @param string $id The unique identifier of the chunk
103
+     * @param string $body The body of the chunk
104
+     * @return string|bool
105
+     */
106
+    private function saveChunk(string $id, string $body): string|bool
107
+    {
108
+        $path = $this->chunksPath . DIRECTORY_SEPARATOR . $id;
109
+        return file_put_contents($path, $body) ? $path : false;
110
+    }
111
+
112
+    /**
113
+     * Merge the chunks into a single string
114
+     *
115
+     * @return string
116
+     */
117
+    public function mergeChunks(): string
118
+    {
119
+        $result = '';
120
+        foreach ($this->downloads as $chunk) {
121
+            $result .= file_get_contents($chunk['location']);
122
+        }
123
+        return $result;
124
+    }
125
+
126
+    /**
127
+     * Save the merged chunks to a file
128
+     *
129
+     * @param string $filePath The path/to/file.ext
130
+     * @return bool
131
+     */
132
+    public function save(string $filePath): bool
133
+    {
134
+        $pathInfo = pathinfo($filePath, PATHINFO_DIRNAME);
135
+        if (gettype($pathInfo) != "string") $pathInfo = $pathInfo['dirname'];
136
+        if (!file_exists($pathInfo)) {
137
+            throw new \InvalidArgumentException('The directory does not exist');
138
+        }
139
+        $result = $this->mergeChunks();
140
+        $this->cleanChunks();
141
+        return file_put_contents($filePath, $result) !== false;
142
+    }
143
+
144
+    /**
145
+     * Clean the directory of the chunks
146
+     *
147
+     * @return void
148
+     */
149
+    public function cleanChunks(): void
150
+    {
151
+        foreach (glob($this->chunksPath . DIRECTORY_SEPARATOR . '*') as $file) {
152
+            unlink($file);
153
+        }
154
+        rmdir($this->chunksPath);
155
+    }
156 156
 
157 157
 }
158 158
\ No newline at end of file
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -132,7 +132,9 @@
 block discarded – undo
132 132
 	public function save(string $filePath): bool
133 133
 	{
134 134
 		$pathInfo = pathinfo($filePath, PATHINFO_DIRNAME);
135
-		if (gettype($pathInfo) != "string") $pathInfo = $pathInfo['dirname'];
135
+		if (gettype($pathInfo) != "string") {
136
+		    $pathInfo = $pathInfo['dirname'];
137
+		}
136 138
 		if (!file_exists($pathInfo)) {
137 139
 			throw new \InvalidArgumentException('The directory does not exist');
138 140
 		}
Please login to merge, or discard this patch.
src/Model/HttpResponse.php 1 patch
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -35,90 +35,90 @@
 block discarded – undo
35 35
 class HttpResponse
36 36
 {
37 37
 
38
-	/**
39
-	 * Set the curl handle
40
-	 *
41
-	 * @param \CurlHandle $curlHandle
42
-	 * @return HttpResponse
43
-	 */
44
-	public function setCurlHandle(\CurlHandle $curlHandle): HttpResponse
45
-	{
46
-		$this->curlHandle = $curlHandle;
47
-		return $this;
48
-	}
38
+    /**
39
+     * Set the curl handle
40
+     *
41
+     * @param \CurlHandle $curlHandle
42
+     * @return HttpResponse
43
+     */
44
+    public function setCurlHandle(\CurlHandle $curlHandle): HttpResponse
45
+    {
46
+        $this->curlHandle = $curlHandle;
47
+        return $this;
48
+    }
49 49
 
50
-	/**
51
-	 * Get info from the curl handle
52
-	 *
53
-	 * @return CurlInfo|false
54
-	 */
55
-	public function getInfoFromCurl(): CurlInfo|false
56
-	{
57
-		if (empty($this->getCurlHandle())) {
58
-			return false;
59
-		}
50
+    /**
51
+     * Get info from the curl handle
52
+     *
53
+     * @return CurlInfo|false
54
+     */
55
+    public function getInfoFromCurl(): CurlInfo|false
56
+    {
57
+        if (empty($this->getCurlHandle())) {
58
+            return false;
59
+        }
60 60
 
61
-		return new CurlInfo(curl_getinfo($this->curlHandle));
62
-	}
61
+        return new CurlInfo(curl_getinfo($this->curlHandle));
62
+    }
63 63
 
64
-	/**
65
-	 * Set the headers of the response
66
-	 *
67
-	 * @param string $headers
68
-	 * @return HttpResponse
69
-	 */
70
-	public function setHeaders(string $headers): HttpResponse
71
-	{
72
-		$result = [];
73
-		$lines = explode("\r\n", $headers);
74
-		foreach ($lines as $line) {
75
-			if (str_contains($line, ':')) {
76
-				$parts = explode(':', $line);
77
-				$result[trim($parts[0])] = trim($parts[1]);
78
-			}
79
-		}
80
-		$this->headers = $result;
81
-		return $this;
82
-	}
64
+    /**
65
+     * Set the headers of the response
66
+     *
67
+     * @param string $headers
68
+     * @return HttpResponse
69
+     */
70
+    public function setHeaders(string $headers): HttpResponse
71
+    {
72
+        $result = [];
73
+        $lines = explode("\r\n", $headers);
74
+        foreach ($lines as $line) {
75
+            if (str_contains($line, ':')) {
76
+                $parts = explode(':', $line);
77
+                $result[trim($parts[0])] = trim($parts[1]);
78
+            }
79
+        }
80
+        $this->headers = $result;
81
+        return $this;
82
+    }
83 83
 
84
-	/**
85
-	 * Get a key from the response headers
86
-	 *
87
-	 * @param string $key
88
-	 * @return mixed
89
-	 */
90
-	public function getHeaderLine(string $key): mixed
91
-	{
92
-		return array_change_key_case($this->headers, CASE_LOWER)[strtolower($key)] ?? null;
93
-	}
84
+    /**
85
+     * Get a key from the response headers
86
+     *
87
+     * @param string $key
88
+     * @return mixed
89
+     */
90
+    public function getHeaderLine(string $key): mixed
91
+    {
92
+        return array_change_key_case($this->headers, CASE_LOWER)[strtolower($key)] ?? null;
93
+    }
94 94
 
95
-	/**
96
-	 * @param string $name
97
-	 * @param array $arguments
98
-	 * @return mixed
99
-	 */
100
-	public function __call(string $name, array $arguments): mixed
101
-	{
102
-		if (property_exists($this, $name)) {
103
-			return $this->{$name};
104
-		}
95
+    /**
96
+     * @param string $name
97
+     * @param array $arguments
98
+     * @return mixed
99
+     */
100
+    public function __call(string $name, array $arguments): mixed
101
+    {
102
+        if (property_exists($this, $name)) {
103
+            return $this->{$name};
104
+        }
105 105
 
106
-		if (method_exists($this, $name)) {
107
-			return $this->{$name}();
108
-		}
106
+        if (method_exists($this, $name)) {
107
+            return $this->{$name}();
108
+        }
109 109
 
110
-		if (str_starts_with($name, 'get')) {
111
-			$property = lcfirst(substr($name, 3));
112
-			return $this->{$property} ?? null;
113
-		}
110
+        if (str_starts_with($name, 'get')) {
111
+            $property = lcfirst(substr($name, 3));
112
+            return $this->{$property} ?? null;
113
+        }
114 114
 
115
-		if (str_starts_with($name, 'set')) {
116
-			$property = lcfirst(substr($name, 3));
117
-			$this->{$property} = $arguments[0] ?? null;
118
-			return $this;
119
-		}
115
+        if (str_starts_with($name, 'set')) {
116
+            $property = lcfirst(substr($name, 3));
117
+            $this->{$property} = $arguments[0] ?? null;
118
+            return $this;
119
+        }
120 120
 
121
-		throw new \BadMethodCallException("Method $name does not exist");
122
-	}
121
+        throw new \BadMethodCallException("Method $name does not exist");
122
+    }
123 123
 
124 124
 }
125 125
\ No newline at end of file
Please login to merge, or discard this patch.
examples/websocket/coinmarketcap-ticker.php 2 patches
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -13,41 +13,41 @@
 block discarded – undo
13 13
  */
14 14
 function startTicker(array $ids, callable $callback): void
15 15
 {
16
-	try {
17
-
18
-		$close_time = time() + 10;
19
-		$ClientConfig = (new WebSocketConfig())->setFragmentSize(8096)->setTimeout(15);
20
-		$WebSocketClient = new WebSocket('wss://stream.coinmarketcap.com/price/latest', $ClientConfig);
21
-
22
-		$WebSocketClient->send(json_encode([
23
-			'method' => 'subscribe',
24
-			'id' => 'price',
25
-			'data' => [
26
-				'cryptoIds' => $ids,
27
-				'index' => 'detail'
28
-			]
29
-		]));
30
-
31
-		while ($close_time > time()) {
32
-			if (($message = $WebSocketClient->receive()) != "") {
33
-				$json_response = json_decode($message, true);
34
-
35
-				if ($json_response['id'] == "price") {
36
-					$callback($json_response);
37
-				}
38
-			}
39
-		}
40
-
41
-	} catch (Exception $e) {
42
-		echo "<b>Error</b>: " . $e->getMessage();
43
-	}
16
+    try {
17
+
18
+        $close_time = time() + 10;
19
+        $ClientConfig = (new WebSocketConfig())->setFragmentSize(8096)->setTimeout(15);
20
+        $WebSocketClient = new WebSocket('wss://stream.coinmarketcap.com/price/latest', $ClientConfig);
21
+
22
+        $WebSocketClient->send(json_encode([
23
+            'method' => 'subscribe',
24
+            'id' => 'price',
25
+            'data' => [
26
+                'cryptoIds' => $ids,
27
+                'index' => 'detail'
28
+            ]
29
+        ]));
30
+
31
+        while ($close_time > time()) {
32
+            if (($message = $WebSocketClient->receive()) != "") {
33
+                $json_response = json_decode($message, true);
34
+
35
+                if ($json_response['id'] == "price") {
36
+                    $callback($json_response);
37
+                }
38
+            }
39
+        }
40
+
41
+    } catch (Exception $e) {
42
+        echo "<b>Error</b>: " . $e->getMessage();
43
+    }
44 44
 }
45 45
 
46 46
 echo "<pre>Start Tome: " . date('Y-m-d H:i:s') . "</pre><br/>";
47 47
 
48 48
 $responses = [];
49 49
 startTicker([1, 1027, 825, 3408, 1839, 4687, 52, 2010, 5426], function ($data) use (&$responses) {
50
-	$responses[] = $data;
50
+    $responses[] = $data;
51 51
 });
52 52
 
53 53
 echo "<pre>" . json_encode($responses, JSON_PRETTY_PRINT) . "</pre><br/>";
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -46,7 +46,7 @@
 block discarded – undo
46 46
 echo "<pre>Start Tome: " . date('Y-m-d H:i:s') . "</pre><br/>";
47 47
 
48 48
 $responses = [];
49
-startTicker([1, 1027, 825, 3408, 1839, 4687, 52, 2010, 5426], function ($data) use (&$responses) {
49
+startTicker([1, 1027, 825, 3408, 1839, 4687, 52, 2010, 5426], function($data) use (&$responses) {
50 50
 	$responses[] = $data;
51 51
 });
52 52
 
Please login to merge, or discard this patch.
src/Contracts/MessageContract.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -14,11 +14,11 @@
 block discarded – undo
14 14
 interface MessageContract
15 15
 {
16 16
 
17
-	/**
18
-	 * @param string $message
19
-	 * @return void
20
-	 * @throws WebSocketException
21
-	 */
22
-	public function onMessage(string $message): void;
17
+    /**
18
+     * @param string $message
19
+     * @return void
20
+     * @throws WebSocketException
21
+     */
22
+    public function onMessage(string $message): void;
23 23
 
24 24
 }
Please login to merge, or discard this patch.
src/Contracts/WebSocketContract.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -14,21 +14,21 @@
 block discarded – undo
14 14
 interface WebSocketContract
15 15
 {
16 16
 
17
-	/**
18
-	 * @return void
19
-	 */
20
-	public function onOpen(): void;
17
+    /**
18
+     * @return void
19
+     */
20
+    public function onOpen(): void;
21 21
 
22
-	/**
23
-	 * @param int $closeStatus
24
-	 * @return void
25
-	 */
26
-	public function onClose(int $closeStatus): void;
22
+    /**
23
+     * @param int $closeStatus
24
+     * @return void
25
+     */
26
+    public function onClose(int $closeStatus): void;
27 27
 
28
-	/**
29
-	 * @param WebSocketException $exception
30
-	 * @return void
31
-	 */
32
-	public function onError(WebSocketException $exception): void;
28
+    /**
29
+     * @param WebSocketException $exception
30
+     * @return void
31
+     */
32
+    public function onError(WebSocketException $exception): void;
33 33
 
34 34
 }
Please login to merge, or discard this patch.
src/WebSocket.php 2 patches
Indentation   +412 added lines, -412 removed lines patch added patch discarded remove patch
@@ -19,417 +19,417 @@
 block discarded – undo
19 19
 class WebSocket implements WscCommonsContract
20 20
 {
21 21
 
22
-	use WSClientTrait;
23
-
24
-	/**
25
-	 * App version
26
-	 *
27
-	 * @var string
28
-	 */
29
-	public const VERSION = 'v1.0.0';
30
-
31
-	/**
32
-	 * @var resource|bool
33
-	 */
34
-	private $socket;
35
-
36
-	/**
37
-	 * @var bool
38
-	 */
39
-	private bool $isConnected = false;
40
-
41
-	/**
42
-	 * @var bool
43
-	 */
44
-	private bool $isClosing = false;
45
-
46
-	/**
47
-	 * @var string
48
-	 */
49
-	private string $lastOpcode;
50
-
51
-	/**
52
-	 * @var float|int
53
-	 */
54
-	private float|int $closeStatus;
55
-
56
-	/**
57
-	 * @var string|null
58
-	 */
59
-	private ?string $hugePayload;
60
-
61
-	/**
62
-	 * @var array|int[]
63
-	 */
64
-	private static array $opcodes = [
65
-		CommonsContract::EVENT_TYPE_CONTINUATION => 0,
66
-		CommonsContract::EVENT_TYPE_TEXT => 1,
67
-		CommonsContract::EVENT_TYPE_BINARY => 2,
68
-		CommonsContract::EVENT_TYPE_CLOSE => 8,
69
-		CommonsContract::EVENT_TYPE_PING => 9,
70
-		CommonsContract::EVENT_TYPE_PONG => 10,
71
-	];
72
-
73
-	/**
74
-	 * @var WebSocketConfig
75
-	 */
76
-	protected WebSocketConfig $config;
77
-
78
-	/**
79
-	 * @var string
80
-	 */
81
-	protected string $socketUrl;
82
-
83
-	/**
84
-	 * @var ?SocketClient
85
-	 */
86
-	protected ?SocketClient $client = null;
87
-
88
-	/**
89
-	 * Sets parameters for Web Socket Client intercommunication
90
-	 *
91
-	 * @param SocketClient|string $clientOrUri pass the SocketClient object or the URI of the server
92
-	 * @param ?WebSocketConfig $config if you're passing the URI, you can pass the config object
93
-	 */
94
-	public function __construct(SocketClient|string $clientOrUri, ?WebSocketConfig $config = null)
95
-	{
96
-		if ($clientOrUri instanceof SocketClient) {
97
-			$this->client = $clientOrUri;
98
-		} else {
99
-			$this->connect($clientOrUri, $config === null ? new WebSocketConfig() : $config);
100
-		}
101
-	}
102
-
103
-	/**
104
-	 * @param string $socketUrl string that represents the URL of the Web Socket server. e.g. ws://localhost:1337 or wss://localhost:1337
105
-	 * @param WebSocketConfig $config The configuration for the Web Socket client
106
-	 */
107
-	public function connect(string $socketUrl, WebSocketConfig $config): void
108
-	{
109
-		try {
110
-			$this->config = $config;
111
-			$this->socketUrl = $socketUrl;
112
-			$urlParts = parse_url($this->socketUrl);
113
-
114
-			$this->config->setScheme($urlParts['scheme']);
115
-			$this->config->setHost($urlParts['host']);
116
-			$this->config->setUser($urlParts);
117
-			$this->config->setPassword($urlParts);
118
-			$this->config->setPort($urlParts);
119
-
120
-			$pathWithQuery = $this->getPathWithQuery($urlParts);
121
-			$hostUri = $this->getHostUri($this->config);
122
-
123
-			$context = $this->getStreamContext();
124
-			if ($this->config->hasProxy()) {
125
-				$this->socket = $this->proxy();
126
-			} else {
127
-				$this->socket = @stream_socket_client(
128
-					$hostUri . ':' . $this->config->getPort(),
129
-					$errno,
130
-					$errstr,
131
-					$this->config->getTimeout(),
132
-					STREAM_CLIENT_CONNECT,
133
-					$context
134
-				);
135
-			}
136
-
137
-			if ($this->socket === false) {
138
-				throw new ConnectionException(
139
-					"Could not open socket to \"{$this->config->getHost()}:{$this->config->getPort()}\": $errstr ($errno).",
140
-					CommonsContract::CLIENT_COULD_NOT_OPEN_SOCKET
141
-				);
142
-			}
143
-
144
-			stream_set_timeout($this->socket, $this->config->getTimeout());
145
-
146
-			$key = $this->generateKey();
147
-			$headers = [
148
-				'Host' => $this->config->getHost() . ':' . $this->config->getPort(),
149
-				'User-Agent' => 'Easy-Http/' . self::VERSION . ' (PHP/' . PHP_VERSION . ')',
150
-				'Connection' => 'Upgrade',
151
-				'Upgrade' => 'WebSocket',
152
-				'Sec-WebSocket-Key' => $key,
153
-				'Sec-Websocket-Version' => '13',
154
-			];
155
-
156
-			if ($this->config->getUser() || $this->config->getPassword()) {
157
-				$headers['authorization'] = 'Basic ' . base64_encode($this->config->getUser() . ':' . $this->config->getPassword()) . "\r\n";
158
-			}
159
-
160
-			if (!empty($this->config->getHeaders())) {
161
-				$headers = array_merge($headers, $this->config->getHeaders());
162
-			}
163
-
164
-			$header = $this->getHeaders($pathWithQuery, $headers);
165
-
166
-			$this->write($header);
167
-
168
-			$this->validateResponse($this->config, $pathWithQuery, $key);
169
-			$this->isConnected = true;
170
-
171
-			if ($this->client !== null) {
172
-				$this->client->setConnection($this);
173
-				$this->client->onOpen();
174
-				while ($this->isConnected()) {
175
-					if (is_string(($message = $this->receive()))) {
176
-						$this->client->onMessage($message);
177
-					}
178
-				}
179
-				$this->client->onClose($this->closeStatus);
180
-			}
181
-
182
-		} catch (\Exception $e) {
183
-			$this->client->onError(
184
-				new WebSocketException(
185
-					$e->getMessage(),
186
-					$e->getCode(),
187
-					$e
188
-				)
189
-			);
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * Init a proxy connection
195
-	 *
196
-	 * @return resource|false
197
-	 * @throws \InvalidArgumentException
198
-	 * @throws ConnectionException
199
-	 */
200
-	private function proxy()
201
-	{
202
-		$sock = @stream_socket_client(
203
-			WscCommonsContract::TCP_SCHEME . $this->config->getProxyIp() . ':' . $this->config->getProxyPort(),
204
-			$errno,
205
-			$errstr,
206
-			$this->config->getTimeout(),
207
-			STREAM_CLIENT_CONNECT,
208
-			$this->getStreamContext()
209
-		);
210
-		$write = "CONNECT {$this->config->getProxyIp()}:{$this->config->getProxyPort()} HTTP/1.1\r\n";
211
-		$auth = $this->config->getProxyAuth();
212
-		if ($auth !== NULL) {
213
-			$write .= "Proxy-Authorization: Basic {$auth}\r\n";
214
-		}
215
-		$write .= "\r\n";
216
-		fwrite($sock, $write);
217
-		$resp = fread($sock, 1024);
218
-
219
-		if (preg_match(self::PROXY_MATCH_RESP, $resp) === 1) {
220
-			return $sock;
221
-		}
222
-
223
-		throw new ConnectionException('Failed to connect to the host via proxy');
224
-	}
225
-
226
-	/**
227
-	 * @return mixed
228
-	 * @throws \InvalidArgumentException
229
-	 */
230
-	private function getStreamContext(): mixed
231
-	{
232
-		if ($this->config->getContext() !== null) {
233
-			// Suppress the error since we'll catch it below
234
-			if (@get_resource_type($this->config->getContext()) === 'stream-context') {
235
-				return $this->config->getContext();
236
-			}
237
-
238
-			throw new \InvalidArgumentException(
239
-				'Stream context is invalid',
240
-				CommonsContract::CLIENT_INVALID_STREAM_CONTEXT
241
-			);
242
-		}
243
-
244
-		return stream_context_create($this->config->getContextOptions());
245
-	}
246
-
247
-	/**
248
-	 * @param mixed $urlParts
249
-	 * @return string
250
-	 */
251
-	private function getPathWithQuery(mixed $urlParts): string
252
-	{
253
-		$path = isset($urlParts['path']) ? $urlParts['path'] : '/';
254
-		$query = isset($urlParts['query']) ? $urlParts['query'] : '';
255
-		$fragment = isset($urlParts['fragment']) ? $urlParts['fragment'] : '';
256
-		$pathWithQuery = $path;
257
-		if (!empty($query)) {
258
-			$pathWithQuery .= '?' . $query;
259
-		}
260
-		if (!empty($fragment)) {
261
-			$pathWithQuery .= '#' . $fragment;
262
-		}
263
-
264
-		return $pathWithQuery;
265
-	}
266
-
267
-	/**
268
-	 * @param string $pathWithQuery
269
-	 * @param array $headers
270
-	 * @return string
271
-	 */
272
-	private function getHeaders(string $pathWithQuery, array $headers): string
273
-	{
274
-		return 'GET ' . $pathWithQuery . " HTTP/1.1\r\n"
275
-			. implode(
276
-				"\r\n",
277
-				array_map(
278
-					function ($key, $value) {
279
-						return "$key: $value";
280
-					},
281
-					array_keys($headers),
282
-					$headers
283
-				)
284
-			)
285
-			. "\r\n\r\n";
286
-	}
287
-
288
-	/**
289
-	 * @return string
290
-	 */
291
-	public function getLastOpcode(): string
292
-	{
293
-		return $this->lastOpcode;
294
-	}
295
-
296
-	/**
297
-	 * @return int
298
-	 */
299
-	public function getCloseStatus(): int
300
-	{
301
-		return $this->closeStatus;
302
-	}
303
-
304
-	/**
305
-	 * @return bool
306
-	 */
307
-	public function isConnected(): bool
308
-	{
309
-		return $this->isConnected;
310
-	}
311
-
312
-	/**
313
-	 * @param int $timeout
314
-	 * @param null $microSecs
315
-	 * @return WebSocket
316
-	 */
317
-	public function setTimeout(int $timeout, $microSecs = null): WebSocket
318
-	{
319
-		$this->config->setTimeout($timeout);
320
-		if ($this->socket && get_resource_type($this->socket) === 'stream') {
321
-			stream_set_timeout($this->socket, $timeout, $microSecs);
322
-		}
323
-
324
-		return $this;
325
-	}
326
-
327
-	/**
328
-	 * Sends message to opened socket connection client->server
329
-	 *
330
-	 * @param $payload
331
-	 * @param string $opcode
332
-	 * @throws \Exception
333
-	 */
334
-	public function send($payload, string $opcode = CommonsContract::EVENT_TYPE_TEXT): void
335
-	{
336
-		if (!$this->isConnected) {
337
-			$this->connect($this->socketUrl, new WebSocketConfig());
338
-		}
339
-
340
-		if (array_key_exists($opcode, self::$opcodes) === false) {
341
-			throw new BadOpcodeException(
342
-				"Bad opcode '$opcode'.  Try 'text' or 'binary'.",
343
-				CommonsContract::CLIENT_BAD_OPCODE
344
-			);
345
-		}
346
-
347
-		$payloadLength = strlen($payload);
348
-		$fragmentCursor = 0;
349
-
350
-		while ($payloadLength > $fragmentCursor) {
351
-			$subPayload = substr($payload, $fragmentCursor, $this->config->getFragmentSize());
352
-			$fragmentCursor += $this->config->getFragmentSize();
353
-			$final = $payloadLength <= $fragmentCursor;
354
-			$this->sendFragment($final, $subPayload, $opcode, true);
355
-			$opcode = 'continuation';
356
-		}
357
-	}
358
-
359
-	/**
360
-	 * Receives message client<-server
361
-	 *
362
-	 * @return string|null
363
-	 * @throws \Exception
364
-	 */
365
-	public function receive(): string|null
366
-	{
367
-		if (!$this->isConnected) {
368
-			$this->connect($this->socketUrl, new WebSocketConfig());
369
-		}
370
-
371
-		$this->hugePayload = '';
372
-
373
-		return $this->receiveFragment();
374
-	}
375
-
376
-	/**
377
-	 * Tell the socket to close.
378
-	 *
379
-	 * @param integer $status http://tools.ietf.org/html/rfc6455#section-7.4
380
-	 * @param string $message A closing message, max 125 bytes.
381
-	 * @return bool|null|string
382
-	 * @throws \Exception
383
-	 */
384
-	public function close(int $status = 1000, string $message = 'ttfn'): bool|null|string
385
-	{
386
-		$statusBin = sprintf('%016b', $status);
387
-		$statusStr = '';
388
-
389
-		foreach (str_split($statusBin, 8) as $binstr) {
390
-			$statusStr .= chr(bindec($binstr));
391
-		}
392
-
393
-		$this->send($statusStr . $message, CommonsContract::EVENT_TYPE_CLOSE);
394
-		$this->isClosing = true;
395
-
396
-		return $this->receive(); // Receiving a close frame will close the socket now.
397
-	}
398
-
399
-	/**
400
-	 * @param string $data
401
-	 * @throws ConnectionException
402
-	 */
403
-	protected function write(string $data): void
404
-	{
405
-		Middleware::stream_write($this->socket, $data);
406
-	}
407
-
408
-	/**
409
-	 * @param int $len
410
-	 * @return string|null
411
-	 * @throws ConnectionException
412
-	 */
413
-	protected function read(int $len): string|null
414
-	{
415
-		return Middleware::stream_read($this->socket, $len) ?: false;
416
-	}
417
-
418
-	/**
419
-	 * Helper to convert a binary to a string of '0' and '1'.
420
-	 *
421
-	 * @param string $string
422
-	 * @return string
423
-	 */
424
-	protected static function sprintB(string $string): string
425
-	{
426
-		$return = '';
427
-		$strLen = strlen($string);
428
-		for ($i = 0; $i < $strLen; $i++) {
429
-			$return .= sprintf('%08b', ord($string[$i]));
430
-		}
431
-
432
-		return $return;
433
-	}
22
+    use WSClientTrait;
23
+
24
+    /**
25
+     * App version
26
+     *
27
+     * @var string
28
+     */
29
+    public const VERSION = 'v1.0.0';
30
+
31
+    /**
32
+     * @var resource|bool
33
+     */
34
+    private $socket;
35
+
36
+    /**
37
+     * @var bool
38
+     */
39
+    private bool $isConnected = false;
40
+
41
+    /**
42
+     * @var bool
43
+     */
44
+    private bool $isClosing = false;
45
+
46
+    /**
47
+     * @var string
48
+     */
49
+    private string $lastOpcode;
50
+
51
+    /**
52
+     * @var float|int
53
+     */
54
+    private float|int $closeStatus;
55
+
56
+    /**
57
+     * @var string|null
58
+     */
59
+    private ?string $hugePayload;
60
+
61
+    /**
62
+     * @var array|int[]
63
+     */
64
+    private static array $opcodes = [
65
+        CommonsContract::EVENT_TYPE_CONTINUATION => 0,
66
+        CommonsContract::EVENT_TYPE_TEXT => 1,
67
+        CommonsContract::EVENT_TYPE_BINARY => 2,
68
+        CommonsContract::EVENT_TYPE_CLOSE => 8,
69
+        CommonsContract::EVENT_TYPE_PING => 9,
70
+        CommonsContract::EVENT_TYPE_PONG => 10,
71
+    ];
72
+
73
+    /**
74
+     * @var WebSocketConfig
75
+     */
76
+    protected WebSocketConfig $config;
77
+
78
+    /**
79
+     * @var string
80
+     */
81
+    protected string $socketUrl;
82
+
83
+    /**
84
+     * @var ?SocketClient
85
+     */
86
+    protected ?SocketClient $client = null;
87
+
88
+    /**
89
+     * Sets parameters for Web Socket Client intercommunication
90
+     *
91
+     * @param SocketClient|string $clientOrUri pass the SocketClient object or the URI of the server
92
+     * @param ?WebSocketConfig $config if you're passing the URI, you can pass the config object
93
+     */
94
+    public function __construct(SocketClient|string $clientOrUri, ?WebSocketConfig $config = null)
95
+    {
96
+        if ($clientOrUri instanceof SocketClient) {
97
+            $this->client = $clientOrUri;
98
+        } else {
99
+            $this->connect($clientOrUri, $config === null ? new WebSocketConfig() : $config);
100
+        }
101
+    }
102
+
103
+    /**
104
+     * @param string $socketUrl string that represents the URL of the Web Socket server. e.g. ws://localhost:1337 or wss://localhost:1337
105
+     * @param WebSocketConfig $config The configuration for the Web Socket client
106
+     */
107
+    public function connect(string $socketUrl, WebSocketConfig $config): void
108
+    {
109
+        try {
110
+            $this->config = $config;
111
+            $this->socketUrl = $socketUrl;
112
+            $urlParts = parse_url($this->socketUrl);
113
+
114
+            $this->config->setScheme($urlParts['scheme']);
115
+            $this->config->setHost($urlParts['host']);
116
+            $this->config->setUser($urlParts);
117
+            $this->config->setPassword($urlParts);
118
+            $this->config->setPort($urlParts);
119
+
120
+            $pathWithQuery = $this->getPathWithQuery($urlParts);
121
+            $hostUri = $this->getHostUri($this->config);
122
+
123
+            $context = $this->getStreamContext();
124
+            if ($this->config->hasProxy()) {
125
+                $this->socket = $this->proxy();
126
+            } else {
127
+                $this->socket = @stream_socket_client(
128
+                    $hostUri . ':' . $this->config->getPort(),
129
+                    $errno,
130
+                    $errstr,
131
+                    $this->config->getTimeout(),
132
+                    STREAM_CLIENT_CONNECT,
133
+                    $context
134
+                );
135
+            }
136
+
137
+            if ($this->socket === false) {
138
+                throw new ConnectionException(
139
+                    "Could not open socket to \"{$this->config->getHost()}:{$this->config->getPort()}\": $errstr ($errno).",
140
+                    CommonsContract::CLIENT_COULD_NOT_OPEN_SOCKET
141
+                );
142
+            }
143
+
144
+            stream_set_timeout($this->socket, $this->config->getTimeout());
145
+
146
+            $key = $this->generateKey();
147
+            $headers = [
148
+                'Host' => $this->config->getHost() . ':' . $this->config->getPort(),
149
+                'User-Agent' => 'Easy-Http/' . self::VERSION . ' (PHP/' . PHP_VERSION . ')',
150
+                'Connection' => 'Upgrade',
151
+                'Upgrade' => 'WebSocket',
152
+                'Sec-WebSocket-Key' => $key,
153
+                'Sec-Websocket-Version' => '13',
154
+            ];
155
+
156
+            if ($this->config->getUser() || $this->config->getPassword()) {
157
+                $headers['authorization'] = 'Basic ' . base64_encode($this->config->getUser() . ':' . $this->config->getPassword()) . "\r\n";
158
+            }
159
+
160
+            if (!empty($this->config->getHeaders())) {
161
+                $headers = array_merge($headers, $this->config->getHeaders());
162
+            }
163
+
164
+            $header = $this->getHeaders($pathWithQuery, $headers);
165
+
166
+            $this->write($header);
167
+
168
+            $this->validateResponse($this->config, $pathWithQuery, $key);
169
+            $this->isConnected = true;
170
+
171
+            if ($this->client !== null) {
172
+                $this->client->setConnection($this);
173
+                $this->client->onOpen();
174
+                while ($this->isConnected()) {
175
+                    if (is_string(($message = $this->receive()))) {
176
+                        $this->client->onMessage($message);
177
+                    }
178
+                }
179
+                $this->client->onClose($this->closeStatus);
180
+            }
181
+
182
+        } catch (\Exception $e) {
183
+            $this->client->onError(
184
+                new WebSocketException(
185
+                    $e->getMessage(),
186
+                    $e->getCode(),
187
+                    $e
188
+                )
189
+            );
190
+        }
191
+    }
192
+
193
+    /**
194
+     * Init a proxy connection
195
+     *
196
+     * @return resource|false
197
+     * @throws \InvalidArgumentException
198
+     * @throws ConnectionException
199
+     */
200
+    private function proxy()
201
+    {
202
+        $sock = @stream_socket_client(
203
+            WscCommonsContract::TCP_SCHEME . $this->config->getProxyIp() . ':' . $this->config->getProxyPort(),
204
+            $errno,
205
+            $errstr,
206
+            $this->config->getTimeout(),
207
+            STREAM_CLIENT_CONNECT,
208
+            $this->getStreamContext()
209
+        );
210
+        $write = "CONNECT {$this->config->getProxyIp()}:{$this->config->getProxyPort()} HTTP/1.1\r\n";
211
+        $auth = $this->config->getProxyAuth();
212
+        if ($auth !== NULL) {
213
+            $write .= "Proxy-Authorization: Basic {$auth}\r\n";
214
+        }
215
+        $write .= "\r\n";
216
+        fwrite($sock, $write);
217
+        $resp = fread($sock, 1024);
218
+
219
+        if (preg_match(self::PROXY_MATCH_RESP, $resp) === 1) {
220
+            return $sock;
221
+        }
222
+
223
+        throw new ConnectionException('Failed to connect to the host via proxy');
224
+    }
225
+
226
+    /**
227
+     * @return mixed
228
+     * @throws \InvalidArgumentException
229
+     */
230
+    private function getStreamContext(): mixed
231
+    {
232
+        if ($this->config->getContext() !== null) {
233
+            // Suppress the error since we'll catch it below
234
+            if (@get_resource_type($this->config->getContext()) === 'stream-context') {
235
+                return $this->config->getContext();
236
+            }
237
+
238
+            throw new \InvalidArgumentException(
239
+                'Stream context is invalid',
240
+                CommonsContract::CLIENT_INVALID_STREAM_CONTEXT
241
+            );
242
+        }
243
+
244
+        return stream_context_create($this->config->getContextOptions());
245
+    }
246
+
247
+    /**
248
+     * @param mixed $urlParts
249
+     * @return string
250
+     */
251
+    private function getPathWithQuery(mixed $urlParts): string
252
+    {
253
+        $path = isset($urlParts['path']) ? $urlParts['path'] : '/';
254
+        $query = isset($urlParts['query']) ? $urlParts['query'] : '';
255
+        $fragment = isset($urlParts['fragment']) ? $urlParts['fragment'] : '';
256
+        $pathWithQuery = $path;
257
+        if (!empty($query)) {
258
+            $pathWithQuery .= '?' . $query;
259
+        }
260
+        if (!empty($fragment)) {
261
+            $pathWithQuery .= '#' . $fragment;
262
+        }
263
+
264
+        return $pathWithQuery;
265
+    }
266
+
267
+    /**
268
+     * @param string $pathWithQuery
269
+     * @param array $headers
270
+     * @return string
271
+     */
272
+    private function getHeaders(string $pathWithQuery, array $headers): string
273
+    {
274
+        return 'GET ' . $pathWithQuery . " HTTP/1.1\r\n"
275
+            . implode(
276
+                "\r\n",
277
+                array_map(
278
+                    function ($key, $value) {
279
+                        return "$key: $value";
280
+                    },
281
+                    array_keys($headers),
282
+                    $headers
283
+                )
284
+            )
285
+            . "\r\n\r\n";
286
+    }
287
+
288
+    /**
289
+     * @return string
290
+     */
291
+    public function getLastOpcode(): string
292
+    {
293
+        return $this->lastOpcode;
294
+    }
295
+
296
+    /**
297
+     * @return int
298
+     */
299
+    public function getCloseStatus(): int
300
+    {
301
+        return $this->closeStatus;
302
+    }
303
+
304
+    /**
305
+     * @return bool
306
+     */
307
+    public function isConnected(): bool
308
+    {
309
+        return $this->isConnected;
310
+    }
311
+
312
+    /**
313
+     * @param int $timeout
314
+     * @param null $microSecs
315
+     * @return WebSocket
316
+     */
317
+    public function setTimeout(int $timeout, $microSecs = null): WebSocket
318
+    {
319
+        $this->config->setTimeout($timeout);
320
+        if ($this->socket && get_resource_type($this->socket) === 'stream') {
321
+            stream_set_timeout($this->socket, $timeout, $microSecs);
322
+        }
323
+
324
+        return $this;
325
+    }
326
+
327
+    /**
328
+     * Sends message to opened socket connection client->server
329
+     *
330
+     * @param $payload
331
+     * @param string $opcode
332
+     * @throws \Exception
333
+     */
334
+    public function send($payload, string $opcode = CommonsContract::EVENT_TYPE_TEXT): void
335
+    {
336
+        if (!$this->isConnected) {
337
+            $this->connect($this->socketUrl, new WebSocketConfig());
338
+        }
339
+
340
+        if (array_key_exists($opcode, self::$opcodes) === false) {
341
+            throw new BadOpcodeException(
342
+                "Bad opcode '$opcode'.  Try 'text' or 'binary'.",
343
+                CommonsContract::CLIENT_BAD_OPCODE
344
+            );
345
+        }
346
+
347
+        $payloadLength = strlen($payload);
348
+        $fragmentCursor = 0;
349
+
350
+        while ($payloadLength > $fragmentCursor) {
351
+            $subPayload = substr($payload, $fragmentCursor, $this->config->getFragmentSize());
352
+            $fragmentCursor += $this->config->getFragmentSize();
353
+            $final = $payloadLength <= $fragmentCursor;
354
+            $this->sendFragment($final, $subPayload, $opcode, true);
355
+            $opcode = 'continuation';
356
+        }
357
+    }
358
+
359
+    /**
360
+     * Receives message client<-server
361
+     *
362
+     * @return string|null
363
+     * @throws \Exception
364
+     */
365
+    public function receive(): string|null
366
+    {
367
+        if (!$this->isConnected) {
368
+            $this->connect($this->socketUrl, new WebSocketConfig());
369
+        }
370
+
371
+        $this->hugePayload = '';
372
+
373
+        return $this->receiveFragment();
374
+    }
375
+
376
+    /**
377
+     * Tell the socket to close.
378
+     *
379
+     * @param integer $status http://tools.ietf.org/html/rfc6455#section-7.4
380
+     * @param string $message A closing message, max 125 bytes.
381
+     * @return bool|null|string
382
+     * @throws \Exception
383
+     */
384
+    public function close(int $status = 1000, string $message = 'ttfn'): bool|null|string
385
+    {
386
+        $statusBin = sprintf('%016b', $status);
387
+        $statusStr = '';
388
+
389
+        foreach (str_split($statusBin, 8) as $binstr) {
390
+            $statusStr .= chr(bindec($binstr));
391
+        }
392
+
393
+        $this->send($statusStr . $message, CommonsContract::EVENT_TYPE_CLOSE);
394
+        $this->isClosing = true;
395
+
396
+        return $this->receive(); // Receiving a close frame will close the socket now.
397
+    }
398
+
399
+    /**
400
+     * @param string $data
401
+     * @throws ConnectionException
402
+     */
403
+    protected function write(string $data): void
404
+    {
405
+        Middleware::stream_write($this->socket, $data);
406
+    }
407
+
408
+    /**
409
+     * @param int $len
410
+     * @return string|null
411
+     * @throws ConnectionException
412
+     */
413
+    protected function read(int $len): string|null
414
+    {
415
+        return Middleware::stream_read($this->socket, $len) ?: false;
416
+    }
417
+
418
+    /**
419
+     * Helper to convert a binary to a string of '0' and '1'.
420
+     *
421
+     * @param string $string
422
+     * @return string
423
+     */
424
+    protected static function sprintB(string $string): string
425
+    {
426
+        $return = '';
427
+        $strLen = strlen($string);
428
+        for ($i = 0; $i < $strLen; $i++) {
429
+            $return .= sprintf('%08b', ord($string[$i]));
430
+        }
431
+
432
+        return $return;
433
+    }
434 434
 
435 435
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -225,7 +225,7 @@
 block discarded – undo
225 225
 			. implode(
226 226
 				"\r\n",
227 227
 				array_map(
228
-					function ($key, $value) {
228
+					function($key, $value) {
229 229
 						return "$key: $value";
230 230
 					},
231 231
 					array_keys($headers),
Please login to merge, or discard this patch.
src/Loop.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -14,36 +14,36 @@
 block discarded – undo
14 14
 class Loop
15 15
 {
16 16
 
17
-	/**
18
-	 * Whether the loop is running or not
19
-	 *
20
-	 * @var bool
21
-	 */
22
-	protected static bool $running = false;
17
+    /**
18
+     * Whether the loop is running or not
19
+     *
20
+     * @var bool
21
+     */
22
+    protected static bool $running = false;
23 23
 
24
-	/**
25
-	 * @param callable $callback
26
-	 * @param int $interval in milliseconds
27
-	 * @return void
28
-	 */
29
-	public static function run(callable $callback, int $interval = 500): void
30
-	{
31
-		static::$running = true;
32
-		$last_hit = Toolkit::time();
33
-		while (static::$running) {
34
-			if (Toolkit::time() - $last_hit > $interval) {
35
-				$callback();
36
-				$last_hit = Toolkit::time();
37
-			}
38
-		}
39
-	}
24
+    /**
25
+     * @param callable $callback
26
+     * @param int $interval in milliseconds
27
+     * @return void
28
+     */
29
+    public static function run(callable $callback, int $interval = 500): void
30
+    {
31
+        static::$running = true;
32
+        $last_hit = Toolkit::time();
33
+        while (static::$running) {
34
+            if (Toolkit::time() - $last_hit > $interval) {
35
+                $callback();
36
+                $last_hit = Toolkit::time();
37
+            }
38
+        }
39
+    }
40 40
 
41
-	/**
42
-	 * @return void
43
-	 */
44
-	public static function stop(): void
45
-	{
46
-		static::$running = false;
47
-	}
41
+    /**
42
+     * @return void
43
+     */
44
+    public static function stop(): void
45
+    {
46
+        static::$running = false;
47
+    }
48 48
 
49 49
 }
50 50
\ No newline at end of file
Please login to merge, or discard this patch.
src/Utils/Toolkit.php 2 patches
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -96,25 +96,25 @@
 block discarded – undo
96 96
         return (bool)preg_match_all('/' . $value . '/i', $string);
97 97
     }
98 98
 
99
-	/**
100
-	 * Millisecond sleep
101
-	 *
102
-	 * @param int $milliseconds The milliseconds
103
-	 * @return void
104
-	 */
105
-	public static function sleep(int $milliseconds): void
106
-	{
107
-		usleep($milliseconds * 1000);
108
-	}
99
+    /**
100
+     * Millisecond sleep
101
+     *
102
+     * @param int $milliseconds The milliseconds
103
+     * @return void
104
+     */
105
+    public static function sleep(int $milliseconds): void
106
+    {
107
+        usleep($milliseconds * 1000);
108
+    }
109 109
 
110
-	/**
111
-	 * Get current time in milliseconds
112
-	 *
113
-	 * @return int
114
-	 */
115
-	public static function time(): int
116
-	{
117
-		return (int)(microtime(true) * 1000);
118
-	}
110
+    /**
111
+     * Get current time in milliseconds
112
+     *
113
+     * @return int
114
+     */
115
+    public static function time(): int
116
+    {
117
+        return (int)(microtime(true) * 1000);
118
+    }
119 119
 
120 120
 }
121 121
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
      */
94 94
     public static function insensitiveString(string $string, string $value): bool
95 95
     {
96
-        return (bool)preg_match_all('/' . $value . '/i', $string);
96
+        return (bool) preg_match_all('/' . $value . '/i', $string);
97 97
     }
98 98
 
99 99
 	/**
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 	 */
115 115
 	public static function time(): int
116 116
 	{
117
-		return (int)(microtime(true) * 1000);
117
+		return (int) (microtime(true) * 1000);
118 118
 	}
119 119
 
120 120
 }
121 121
\ No newline at end of file
Please login to merge, or discard this patch.
src/SocketClient.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -20,38 +20,38 @@
 block discarded – undo
20 20
 abstract class SocketClient implements WebSocketContract, MessageContract
21 21
 {
22 22
 
23
-	/**
24
-	 * @var WebSocket
25
-	 */
26
-	protected WebSocket $websocket;
27
-
28
-	/**
29
-	 * @param WebSocket $websocket
30
-	 * @return void
31
-	 */
32
-	protected function setConnection(WebSocket $websocket): void
33
-	{
34
-		$this->websocket = $websocket;
35
-	}
36
-
37
-	/**
38
-	 * @param string $name
39
-	 * @param array $arguments
40
-	 * @return mixed
41
-	 */
42
-	public function __call(string $name, array $arguments): mixed
43
-	{
44
-		if (method_exists($this, $name)) {
45
-			return call_user_func_array([$this, $name], $arguments);
46
-		}
47
-
48
-		if (method_exists($this->websocket, $name)) {
49
-			return call_user_func_array([$this->websocket, $name], $arguments);
50
-		}
51
-
52
-		throw new \BadMethodCallException(sprintf(
53
-			'Method `%s` does not exist at `%s`', $name, get_class($this)
54
-		));
55
-	}
23
+    /**
24
+     * @var WebSocket
25
+     */
26
+    protected WebSocket $websocket;
27
+
28
+    /**
29
+     * @param WebSocket $websocket
30
+     * @return void
31
+     */
32
+    protected function setConnection(WebSocket $websocket): void
33
+    {
34
+        $this->websocket = $websocket;
35
+    }
36
+
37
+    /**
38
+     * @param string $name
39
+     * @param array $arguments
40
+     * @return mixed
41
+     */
42
+    public function __call(string $name, array $arguments): mixed
43
+    {
44
+        if (method_exists($this, $name)) {
45
+            return call_user_func_array([$this, $name], $arguments);
46
+        }
47
+
48
+        if (method_exists($this->websocket, $name)) {
49
+            return call_user_func_array([$this->websocket, $name], $arguments);
50
+        }
51
+
52
+        throw new \BadMethodCallException(sprintf(
53
+            'Method `%s` does not exist at `%s`', $name, get_class($this)
54
+        ));
55
+    }
56 56
 
57 57
 }
Please login to merge, or discard this patch.