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.
Test Setup Failed
Branch event_dispatcher (856f7d)
by Gallice
02:26
created

WebhookRequestHandler::isValidCallbackRequest()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

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