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
Push — master ( 8156a4...df5fb6 )
by Denis
01:02
created

Centrifuge::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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