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.

WebhookRequestHandler::dispatchCallbackEvents()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.1502

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 9
cts 11
cp 0.8182
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 7
nc 5
nop 0
crap 5.1502
1
<?php
2
3
namespace Tgallice\FBMessenger;
4
5
use GuzzleHttp\Psr7\ServerRequest;
6
use Psr\Http\Message\ServerRequestInterface;
7
use Symfony\Component\EventDispatcher\EventDispatcher;
8
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
9
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
use Tgallice\FBMessenger\Callback\CallbackEvent;
11
use Tgallice\FBMessenger\Callback\MessageEvent;
12
use Tgallice\FBMessenger\Callback\PostbackEvent;
13
use Tgallice\FBMessenger\Model\Callback\Entry;
14
15
class WebhookRequestHandler
16
{
17
    /**
18
     * @var ServerRequestInterface
19
     */
20
    private $request;
21
22
    /**
23
     * App secret used to verify the request sha1
24
     *
25
     * @var string
26
     */
27
    private $secret;
28
29
    /**
30
     * @var array
31
     */
32
    private $decodedBody;
33
34
    /**
35
     * @var Entry[]
36
     */
37
    private $hydratedEntries;
38
39
    /**
40
     * @var string
41
     */
42
    private $body;
43
44
    /**
45
     * @var string
46
     */
47
    private $verifyToken;
48
49
    /**
50
     * @var EventDispatcherInterface
51
     */
52
    private $dispatcher;
53
54
    /**
55
     * @param $secret
56
     * @param $verifyToken
57
     * @param EventDispatcherInterface|null $dispatcher
58
     */
59 12
    public function __construct($secret, $verifyToken, EventDispatcherInterface $dispatcher = null)
60
    {
61 12
        $this->secret = $secret;
62 12
        $this->verifyToken = $verifyToken;
63 12
        $this->dispatcher = $dispatcher ?: new EventDispatcher();
64 12
    }
65
66
    /**
67
     * @param ServerRequestInterface $request
68
     */
69 12
    public function handleRequest(ServerRequestInterface $request)
70
    {
71 12
        $this->request = $request;
72 12
    }
73
74
    /**
75
     * Check if the token match with the given verify token.
76
     * This is useful in the webhook setup process.
77
     *
78
     * @return bool
79
     */
80 1
    public function isValidVerifyTokenRequest()
81
    {
82 1
        if ($this->getRequest()->getMethod() !== 'GET') {
83
            return false;
84
        }
85
86 1
        $params = $this->getRequest()->getQueryParams();
87
88 1
        if (!isset($params['hub_verify_token'])) {
89
            return false;
90
        }
91
92 1
        return  $params['hub_verify_token'] === $this->verifyToken;
93
    }
94
95
    /**
96
     * @return null|string
97
     */
98 1
    public function getChallenge()
99
    {
100 1
        $params = $this->getRequest()->getQueryParams();
101
102 1
        return isset($params['hub_challenge']) ? $params['hub_challenge'] : null;
103
    }
104
105
    /**
106
     * Check if the request is a valid webhook request
107
     *
108
     * @return bool
109
     */
110 3
    public function isValidCallbackRequest()
111
    {
112 3
        if (!$this->isValidHubSignature()) {
113 2
            return false;
114
        }
115
116 1
        $decoded = $this->getDecodedBody();
117
118 1
        $object = isset($decoded['object']) ? $decoded['object'] : null;
119 1
        $entry = isset($decoded['entry']) ? $decoded['entry'] : null;
120
121 1
        return $object === 'page' && null !== $entry;
122
    }
123
124
    /**
125
     * Check if the request is a valid webhook request
126
     *
127
     * @deprecated use WebhookRequestHandler::isValidCallbackRequest() instead
128
     *
129
     * @return bool
130
     */
131
    public function isValid()
132
    {
133
        return $this->isValidCallbackRequest();
134
    }
135
136
    /**
137
     * @return CallbackEvent[]
138
     */
139 2
    public function getAllCallbackEvents()
140
    {
141 2
        $events = [];
142
143 2
        foreach ($this->getHydratedEntries() as $hydratedEntry) {
144 2
            $events = array_merge($events, $hydratedEntry->getCallbackEvents());
145 2
        }
146
147 2
        return $events;
148
    }
149
150
    /**
151
     * @return Entry[]
152
     */
153 1
    public function getEntries()
154
    {
155 1
        return $this->getHydratedEntries();
156
    }
157
158
    /**
159
     * @return ServerRequestInterface
160
     */
161 10
    public function getRequest()
162
    {
163 10
        if ($this->request) {
164 10
            return $this->request;
165
        }
166
167
        return $this->request = ServerRequest::fromGlobals();
168
    }
169
170
    /**
171
     * @return array
172
     */
173 5
    public function getDecodedBody()
174
    {
175 5
        if (isset($this->decodedBody)) {
176
            return $this->decodedBody;
177
        }
178
179 5
        $decoded = @json_decode($this->getBody(), true);
180
181 5
        return $this->decodedBody = null === $decoded ? [] : $decoded;
182
    }
183
184
    /**
185
     * Dispatch events to listeners
186
     */
187 1
    public function dispatchCallbackEvents()
188
    {
189 1
        foreach ($this->getAllCallbackEvents() as $event) {
190 1
            $this->dispatcher->dispatch($event->getName(), $event);
191
192 1
            if ($event instanceof PostbackEvent) {
193
                // Dispatch postback payload
194
                $this->dispatcher->dispatch($event->getPostback()->getPayload(), $event);
195
            }
196
197 1
            if ($event instanceof MessageEvent && $event->isQuickReply()) {
198
                // Dispatch quick reply payload
199 1
                $this->dispatcher->dispatch($event->getQuickReplyPayload(), $event);
200 1
            }
201 1
        }
202 1
    }
203
204
    /**
205
     * @param EventSubscriberInterface $subscriber
206
     */
207 1
    public function addEventSubscriber(EventSubscriberInterface $subscriber)
208
    {
209 1
        $this->dispatcher->addSubscriber($subscriber);
210 1
    }
211
212
    /**
213
     * @return Entry[]
214
     */
215 3
    private function getHydratedEntries()
216
    {
217 3
        if (isset($this->hydratedEntries)) {
218
            return $this->hydratedEntries;
219
        }
220
221 3
        $decodedBody = $this->getDecodedBody();
222 3
        $entries = $decodedBody['entry'];
223
224 3
        $hydrated = [];
225
226 3
        foreach ($entries as $entry) {
227 3
            $hydrated[] = Entry::create($entry);
228 3
        }
229
230 3
        return $this->hydratedEntries = $hydrated;
231
    }
232
233
    /**
234
     * @return string
235
     */
236 7
    private function getBody()
237
    {
238 7
        if (isset($this->body)) {
239 1
            return $this->body;
240
        }
241
242 7
        $this->body = (string) $this->getRequest()->getBody();
243
244 7
        return $this->body;
245
    }
246
247
    /**
248
     * @return bool
249
     */
250 3
    private function isValidHubSignature()
251
    {
252 3
        $headers = $this->getRequest()->getHeader('X-Hub-Signature');
253
254 3
        if (empty($headers)) {
255
            return false;
256
        }
257
258 3
        $signature = XHubSignature::parseHeader($headers[0]);
259
260 3
        return XHubSignature::validate($this->getBody(), $this->secret, $signature);
261
    }
262
}
263