GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ApiClient::createRequest()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Slack API library.
5
 *
6
 * (c) Cas Leentfaar <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CL\Slack\Transport;
13
14
use CL\Slack\Exception\SlackException;
15
use CL\Slack\Payload\PayloadInterface;
16
use CL\Slack\Payload\PayloadResponseInterface;
17
use CL\Slack\Serializer\PayloadResponseSerializer;
18
use CL\Slack\Serializer\PayloadSerializer;
19
use CL\Slack\Transport\Events\RequestEvent;
20
use CL\Slack\Transport\Events\ResponseEvent;
21
use GuzzleHttp\Client;
22
use GuzzleHttp\ClientInterface;
23
use GuzzleHttp\Psr7\Request;
24
use GuzzleHttp\Psr7\Response;
25
use Psr\Http\Message\RequestInterface;
26
use Psr\Http\Message\ResponseInterface;
27
use Symfony\Component\EventDispatcher\EventDispatcher;
28
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
29
30
/**
31
 * @author Cas Leentfaar <[email protected]>
32
 */
33
class ApiClient implements ApiClientInterface
34
{
35
    /**
36
     * The (base) URL used for all communication with the Slack API.
37
     */
38
    const API_BASE_URL = 'https://slack.com/api/';
39
40
    /**
41
     * Event triggered just before it's sent to the Slack API
42
     * Any listeners are passed the request data (array) as the first argument.
43
     */
44
    const EVENT_REQUEST = 'EVENT_REQUEST';
45
46
    /**
47
     * Event triggered just before it's sent to the Slack API
48
     * Any listeners are passed the response data (array) as the first argument.
49
     */
50
    const EVENT_RESPONSE = 'EVENT_RESPONSE';
51
52
    /**
53
     * @var string|null
54
     */
55
    private $token;
56
57
    /**
58
     * @var PayloadSerializer
59
     */
60
    private $payloadSerializer;
61
62
    /**
63
     * @var PayloadResponseSerializer
64
     */
65
    private $payloadResponseSerializer;
66
67
    /**
68
     * @var ClientInterface
69
     */
70
    private $client;
71
72
    /**
73
     * @var EventDispatcherInterface
74
     */
75
    private $eventDispatcher;
76
77
    /**
78
     * @param string|null                   $token
79
     * @param ClientInterface|null          $client
80
     * @param EventDispatcherInterface|null $eventDispatcher
81
     */
82 2
    public function __construct(
83
        $token = null,
84
        ClientInterface $client = null,
85
        EventDispatcherInterface $eventDispatcher = null
86
    ) {
87 2
        $this->token = $token;
88 2
        $this->payloadSerializer = new PayloadSerializer();
89 2
        $this->payloadResponseSerializer = new PayloadResponseSerializer();
90 2
        $this->client = $client ?: new Client();
91 2
        $this->eventDispatcher = $eventDispatcher ?: new EventDispatcher();
92 2
    }
93
94
    /**
95
     * @param PayloadInterface $payload The payload to send
96
     * @param string|null      $token   Optional token to use during the API-call,
97
     *                                  defaults to the one configured during construction
98
     *
99
     * @throws SlackException If the payload could not be sent
100
     *
101
     * @return PayloadResponseInterface Actual class depends on the payload used,
102
     *                                  e.g. chat.postMessage will return an instance of ChatPostMessagePayloadResponse
103
     */
104 2
    public function send(PayloadInterface $payload, $token = null)
105 1
    {
106
        try {
107 2
            if ($token === null && $this->token === null) {
108 1
                throw new \InvalidArgumentException('You must supply a token to send a payload, since you did not provide one during construction');
109
            }
110
111 1
            $serializedPayload = $this->payloadSerializer->serialize($payload);
112 1
            $responseData = $this->doSend($payload->getMethod(), $serializedPayload, $token);
113
114 1
            return $this->payloadResponseSerializer->deserialize($responseData, $payload->getResponseClass());
115 1
        } catch (\Exception $e) {
116 1
            throw new SlackException(sprintf('Failed to send payload: %s', $e->getMessage()), null, $e);
117
        }
118
    }
119
120
    /**
121
     * @param callable $callable
122
     */
123 1
    public function addRequestListener($callable)
124
    {
125 1
        $this->eventDispatcher->addListener(self::EVENT_REQUEST, $callable);
126 1
    }
127
128
    /**
129
     * @param callable $callable
130
     */
131 1
    public function addResponseListener($callable)
132
    {
133 1
        $this->eventDispatcher->addListener(self::EVENT_RESPONSE, $callable);
134 1
    }
135
136
    /**
137
     * @param string      $method
138
     * @param array       $data
139
     * @param string|null $token
140
     *
141
     * @throws SlackException
142
     *
143
     * @return array
144
     */
145 1
    private function doSend($method, array $data, $token = null)
146
    {
147
        try {
148 1
            $data['token'] = $token ?: $this->token;
149
150 1
            $this->eventDispatcher->dispatch(self::EVENT_REQUEST, new RequestEvent($data));
151
152 1
            $request = $this->createRequest($method, $data);
153
154
            /** @var ResponseInterface $response */
155 1
            $response = $this->client->send($request);
156 1
        } catch (\Exception $e) {
157
            throw new SlackException('Failed to send data to the Slack API', null, $e);
158
        }
159
160
        try {
161 1
            $responseData = json_decode($response->getBody()->getContents(), true);
162 1
            if (!is_array($responseData)) {
163
                throw new \Exception(sprintf(
164
                    'Expected JSON-decoded response data to be of type "array", got "%s"',
165
                    gettype($responseData)
166
                ));
167
            }
168
169 1
            $this->eventDispatcher->dispatch(self::EVENT_RESPONSE, new ResponseEvent($responseData));
170
171 1
            return $responseData;
172
        } catch (\Exception $e) {
173
            throw new SlackException('Failed to process response from the Slack API', null, $e);
174
        }
175
    }
176
177
    /**
178
     * @param string $method
179
     * @param array  $payload
180
     *
181
     * @return RequestInterface
182
     */
183 1
    private function createRequest($method, array $payload)
184
    {
185 1
        $request = new Request(
186 1
            'POST',
187 1
            self::API_BASE_URL . $method,
188 1
            ['Content-Type' => 'application/x-www-form-urlencoded'],
189 1
            http_build_query($payload)
190 1
        );
191
192 1
        return $request;
193
    }
194
}
195