Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Branch master (dfc5d1)
by Denis
01:12
created

Centrifuge   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 324
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 4
dl 0
loc 324
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A initConfiguration() 0 18 3
A publish() 0 7 1
A broadcast() 0 6 1
A presence() 0 4 1
A presence_stats() 0 4 1
A history() 0 4 1
A history_remove() 0 6 1
A unsubscribe() 0 7 1
A disconnect() 0 4 1
A channels() 0 4 1
A info() 0 4 1
A generateConnectionToken() 0 19 3
A generatePrivateChannelToken() 0 19 3
A getSecret() 0 4 1
A send() 0 39 4
A prepareUrl() 0 11 2
A urlsafeB64Encode() 0 4 1
A sign() 0 4 1
1
<?php
2
3
namespace denis660\Centrifuge;
4
5
use denis660\Centrifuge\Contracts\Centrifuge as CentrifugeContract;
6
use GuzzleHttp\Client as HttpClient;
7
use GuzzleHttp\Exception\ClientException;
8
9
class Centrifuge implements CentrifugeContract
10
{
11
    const API_PATH = '/api';
12
13
    /**
14
     * @var \GuzzleHttp\Client
15
     */
16
    protected $httpClient;
17
18
    /**
19
     * @var array
20
     */
21
    protected $config;
22
23
    /**
24
     * Create a new Centrifugo instance.
25
     *
26
     * @param array $config
27
     * @param \GuzzleHttp\Client $httpClient
28
     */
29
    public function __construct(array $config, HttpClient $httpClient)
30
    {
31
        $this->httpClient = $httpClient;
32
        $this->config = $this->initConfiguration($config);
33
    }
34
35
    /**
36
     * Init centrifugo configuration.
37
     *
38
     * @param  array $config
39
     * @return array
40
     */
41
    protected function initConfiguration(array $config)
42
    {
43
        $defaults = [
44
            'url'              => 'http://localhost:8000',
45
            'secret'           => null,
46
            'apikey'           => null,
47
            'ssl_key'          => null,
48
            'verify'           => true,
49
        ];
50
51
        foreach ($config as $key => $value) {
52
            if (array_key_exists($key, $defaults)) {
53
                $defaults[$key] = $value;
54
            }
55
        }
56
57
        return $defaults;
58
    }
59
60
    /**
61
     * Send message into channel.
62
     *
63
     * @param string $channel
64
     * @param array $data
65
     * @return mixed
66
     */
67
    public function publish(string $channel, array $data)
68
    {
69
        return $this->send('publish', [
70
            'channel' => $channel,
71
            'data' => $data,
72
        ]);
73
    }
74
75
    /**
76
     * Send message into multiple channel.
77
     *
78
     * @param array $channels
79
     * @param array $data
80
     * @return mixed
81
     */
82
    public function broadcast(array $channels, array $data)
83
    {
84
        $params = ['channels' => $channels, 'data' => $data];
85
86
        return $this->send('broadcast', $params);
87
    }
88
89
    /**
90
     * Get channel presence information (all clients currently subscribed on this channel).
91
     *
92
     * @param string $channel
93
     * @return mixed
94
     */
95
    public function presence(string $channel)
96
    {
97
        return $this->send('presence', ['channel' => $channel]);
98
    }
99
100
    /**
101
     * Get channel presence information in short form.
102
     *
103
     * @param string $channel
104
     * @return mixed
105
     */
106
    public function presence_stats(string $channel)
107
    {
108
        return $this->send('presence_stats', ['channel' => $channel]);
109
    }
110
111
    /**
112
     * Get channel history information (list of last messages sent into channel).
113
     *
114
     * @param string $channel
115
     * @return mixed
116
     */
117
    public function history(string $channel)
118
    {
119
        return $this->send('history', ['channel' => $channel]);
120
    }
121
122
    /**
123
     * Remove channel history information.
124
     *
125
     * @param string $channel
126
     * @return mixed
127
     */
128
    public function history_remove(string $channel)
129
    {
130
        return $this->send('history_remove', [
131
            'channel' => $channel,
132
        ]);
133
    }
134
135
    /**
136
     * Unsubscribe user from channel.
137
     *
138
     * @param string $channel
139
     * @param string $user
140
     * @return mixed
141
     */
142
    public function unsubscribe(string $channel, string $user)
143
    {
144
        return $this->send('unsubscribe', [
145
            'channel' => $channel,
146
            'user' => $user,
147
        ]);
148
    }
149
150
    /**
151
     * Disconnect user by its ID.
152
     *
153
     * @param string $user_id
154
     * @return mixed
155
     */
156
    public function disconnect(string $user_id)
157
    {
158
        return $this->send('disconnect', ['user' => (string) $user_id]);
159
    }
160
161
    /**
162
     * Get channels information (list of currently active channels).
163
     *
164
     * @return mixed
165
     */
166
    public function channels()
167
    {
168
        return $this->send('channels');
169
    }
170
171
    /**
172
     * Get stats information about running server nodes.
173
     *
174
     * @return mixed
175
     */
176
    public function info()
177
    {
178
        return $this->send('info');
179
    }
180
181
    /**
182
     * Generate connection token.
183
     *
184
     * @param string $userId
185
     * @param int $exp
186
     * @param array $info
187
     * @return string
188
     */
189
    public function generateConnectionToken(string $userId = '', int $exp = 0, array $info = [])
190
    {
191
        $header = ['typ' => 'JWT', 'alg' => 'HS256'];
192
        $payload = ['sub' => $userId];
193
        if (! empty($info)) {
194
            $payload['info'] = $info;
195
        }
196
        if ($exp) {
197
            $payload['exp'] = $exp;
198
        }
199
        $segments = [];
200
        $segments[] = $this->urlsafeB64Encode(json_encode($header));
201
        $segments[] = $this->urlsafeB64Encode(json_encode($payload));
202
        $signing_input = implode('.', $segments);
203
        $signature = $this->sign($signing_input, $this->getSecret());
204
        $segments[] = $this->urlsafeB64Encode($signature);
205
206
        return implode('.', $segments);
207
    }
208
209
    /**
210
     * Generate private channel token.
211
     *
212
     * @param string $client
213
     * @param string $channel
214
     * @param int $exp
215
     * @param array $info
216
     * @return string
217
     */
218
    public function generatePrivateChannelToken(string $client, string $channel, int $exp = 0, array $info = [])
219
    {
220
        $header = ['typ' => 'JWT', 'alg' => 'HS256'];
221
        $payload = ['channel' => $channel, 'client' => $client];
222
        if (! empty($info)) {
223
            $payload['info'] = $info;
224
        }
225
        if ($exp) {
226
            $payload['exp'] = $exp;
227
        }
228
        $segments = [];
229
        $segments[] = $this->urlsafeB64Encode(json_encode($header));
230
        $segments[] = $this->urlsafeB64Encode(json_encode($payload));
231
        $signing_input = implode('.', $segments);
232
        $signature = $this->sign($signing_input, $this->getSecret());
233
        $segments[] = $this->urlsafeB64Encode($signature);
234
235
        return implode('.', $segments);
236
    }
237
238
    /**
239
     * Get secret key.
240
     *
241
     * @return string
242
     */
243
    protected function getSecret()
244
    {
245
        return $this->config['secret'];
246
    }
247
248
    /**
249
     * Send message to centrifugo server.
250
     *
251
     * @param  string $method
252
     * @param  array $params
253
     * @return mixed
254
     */
255
    protected function send($method, array $params = [])
256
    {
257
        $json = json_encode(['method' => $method, 'params' => $params]);
258
259
        $headers = [
260
            'Content-type'  => 'application/json',
261
            'Authorization' => 'apikey '.$this->config['apikey'],
262
        ];
263
264
        try {
265
            $url = parse_url($this->prepareUrl());
266
267
            $config = collect([
268
                'headers'     => $headers,
269
                'body'        => $json,
270
                'http_errors' => false,
271
            ]);
272
273
            if ($url['scheme'] == 'https') {
274
                $config->put('verify', collect($this->config)->get('verify', false));
275
276
                if (collect($this->config)->get('ssl_key')) {
277
                    $config->put('ssl_key', collect($this->config)->get('ssl_key'));
278
                }
279
            }
280
281
            $response = $this->httpClient->post($this->prepareUrl(), $config->toArray());
282
283
            $result = json_decode((string) $response->getBody(), true);
284
        } catch (ClientException $e) {
285
            $result = [
286
                'method' => $method,
287
                'error'  => $e->getMessage(),
288
                'body'   => $params,
289
            ];
290
        }
291
292
        return $result;
293
    }
294
295
    /**
296
     * Prepare URL to send the http request.
297
     *
298
     * @return string
299
     */
300
    protected function prepareUrl()
301
    {
302
        $address = rtrim($this->config['url'], '/');
303
304
        if (substr_compare($address, static::API_PATH, -strlen(static::API_PATH)) !== 0) {
305
            $address .= static::API_PATH;
306
        }
307
        //$address .= '/';
308
309
        return $address;
310
    }
311
312
    /**
313
     * Safely encode string in base64.
314
     * @param string $input
315
     * @return string
316
     */
317
    private function urlsafeB64Encode($input)
318
    {
319
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
320
    }
321
322
    /**
323
     * Sign message with secret key.
324
     * @param string $msg
325
     * @param string $key
326
     * @return string
327
     */
328
    private function sign($msg, $key)
329
    {
330
        return hash_hmac('sha256', $msg, $key, true);
331
    }
332
}
333