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.

EventStore::deleteStream()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
crap 2
1
<?php
2
namespace EventStore;
3
4
use EventStore\Exception\ConnectionFailedException;
5
use EventStore\Exception\StreamDeletedException;
6
use EventStore\Exception\StreamNotFoundException;
7
use EventStore\Exception\UnauthorizedException;
8
use EventStore\Exception\WrongExpectedVersionException;
9
use EventStore\Http\Exception\ClientException;
10
use EventStore\Http\Exception\RequestException;
11
use EventStore\Http\HttpClientInterface;
12
use EventStore\Http\ResponseCode;
13
use EventStore\StreamFeed\EntryEmbedMode;
14
use EventStore\StreamFeed\Event;
15
use EventStore\StreamFeed\LinkRelation;
16
use EventStore\StreamFeed\StreamFeed;
17
use EventStore\StreamFeed\StreamFeedIterator;
18
use EventStore\ValueObjects\Identity\UUID;
19
use GuzzleHttp\Psr7\Request;
20
use GuzzleHttp\Psr7\Uri;
21
use Psr\Http\Message\RequestInterface;
22
use Psr\Http\Message\ResponseInterface;
23
24
/**
25
 * Class EventStore
26
 * @package EventStore
27
 */
28
final class EventStore implements EventStoreInterface
29
{
30
    /**
31
     * @var string
32
     */
33
    private $url;
34
35
    /**
36
     * @var HttpClientInterface
37
     */
38
    private $httpClient;
39
40
    /**
41
     * @var ResponseInterface
42
     */
43
    private $lastResponse;
44
45
    /**
46
     * @var array
47
     */
48
    private $badCodeHandlers = [];
49
50
    /**
51
     * @param string $url Endpoint of the EventStore HTTP API
52
     * @param HttpClientInterface $httpClient the http client
53
     */
54 29
    public function __construct($url, HttpClientInterface $httpClient)
55
    {
56 29
        $this->url = $url;
57 29
        $this->httpClient = $httpClient;
58
59 29
        $this->checkConnection();
60 29
        $this->initBadCodeHandlers();
61 29
    }
62
63
    /**
64
     * Delete a stream
65
     *
66
     * @param string         $streamName Name of the stream
67
     * @param StreamDeletion $mode       Deletion mode (soft or hard)
68
     */
69 4
    public function deleteStream($streamName, StreamDeletion $mode)
70
    {
71 4
        $request = new Request('DELETE', $this->getStreamUrl($streamName));
72
73 4
        if ($mode == StreamDeletion::HARD) {
74 3
            $request = $request->withHeader('ES-HardDelete', 'true');
75
        }
76
77 4
        $this->sendRequest($request);
78 4
    }
79
80
    /**
81
     * Get the response from the last HTTP call to the EventStore API
82
     *
83
     * @return ResponseInterface
84
     */
85 26
    public function getLastResponse()
86
    {
87 26
        return $this->lastResponse;
88
    }
89
90
    /**
91
     * Navigate stream feed through link relations
92
     *
93
     * @param  StreamFeed      $streamFeed The stream feed to navigate through
94
     * @param  LinkRelation    $relation   The "direction" expressed as link relation
95
     * @return null|StreamFeed
96
     */
97 9
    public function navigateStreamFeed(StreamFeed $streamFeed, LinkRelation $relation)
98
    {
99 9
        $url = $streamFeed->getLinkUrl($relation);
100
101 9
        if (empty($url)) {
102 3
            return null;
103
        }
104
105 8
        return $this->readStreamFeed($url, $streamFeed->getEntryEmbedMode());
106
    }
107
108
    /**
109
     * Open a stream feed for read and navigation
110
     *
111
     * @param  string         $streamName The stream name
112
     * @param  EntryEmbedMode $embedMode  The event entries embed mode (none, rich or body)
113
     * @return StreamFeed
114
     */
115 20
    public function openStreamFeed($streamName, EntryEmbedMode $embedMode = null)
116
    {
117 20
        $url = $this->getStreamUrl($streamName);
118
119 20
        return $this->readStreamFeed($url, $embedMode);
120
    }
121
122
    /**
123
     * Read a single event
124
     *
125
     * @param  string $eventUrl The url of the event
126
     * @return Event
127
     */
128 4
    public function readEvent($eventUrl)
129
    {
130 4
        $request = $this->getJsonRequest($eventUrl);
131 4
        $this->sendRequest($request);
132
133 4
        $this->ensureStatusCodeIsGood($eventUrl);
134
135 3
        $jsonResponse = $this->lastResponseAsJson();
136
137 3
        return $this->createEventFromResponseContent($jsonResponse['content']);
138
    }
139
140
    /**
141
     * Read a single event
142
     *
143
     * @param  string $eventUrl The url of the event
0 ignored issues
show
Documentation introduced by
There is no parameter named $eventUrl. Did you maybe mean $eventUrls?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
144
     * @return Event
145
     */
146 8
    public function readEventBatch(array $eventUrls)
147
    {
148 8
        $requests = array_map(
149
            function ($eventUrl) {
150 8
                return $this->getJsonRequest($eventUrl);
151 8
            },
152
            $eventUrls
153
        );
154
155 8
        $responses = $this->httpClient->sendRequestBatch($requests);
156
157 8
        return array_map(
158
            function ($response) {
159 8
                $data = json_decode($response->getBody(), true);
160 8
                if (!isset($data['content'])) {
161 1
                    return null;
162
                }
163 8
                return $this->createEventFromResponseContent(
164 8
                    $data['content']
165
                );
166 8
            },
167
            $responses
168
        );
169
    }
170
171
    /**
172
     * @param  array $content
173
     * @return Event
174
     */
175 11
    protected function createEventFromResponseContent(array $content)
176
    {
177 11
        $type = $content['eventType'];
178 11
        $version = (integer) $content['eventNumber'];
179 11
        $data = $content['data'];
180 11
        $metadata = (!empty($content['metadata'])) ? $content['metadata'] : null;
181 11
        $eventId = (!empty($content['eventId']) ? UUID::fromNative($content['eventId']) : null);
182
183 11
        return new Event($type, $version, $data, $metadata, $eventId);
184
    }
185
186
    /**
187
     * Write one or more events to a stream
188
     *
189
     * @param  string                                  $streamName      The stream name
190
     * @param  WritableToStream                        $events          Single event or a collection of events
191
     * @param  int                                     $expectedVersion The expected version of the stream
192
     * @return int|bool                                Either the created version or false otherwise
193
     * @throws Exception\WrongExpectedVersionException
194
     */
195 25
    public function writeToStream($streamName, WritableToStream $events, $expectedVersion = ExpectedVersion::ANY)
196
    {
197 25
        if ($events instanceof WritableEvent) {
198 7
            $events = new WritableEventCollection([$events]);
199
        }
200
201 25
        $streamUrl = $this->getStreamUrl($streamName);
202
203 25
        $request = new Request(
204 25
            'POST',
205
            $streamUrl,
206
            [
207 25
                'ES-ExpectedVersion' => intval($expectedVersion),
208 25
                'Content-Type' => 'application/vnd.eventstore.events+json',
209
            ],
210 25
            json_encode($events->toStreamData())
211
        );
212
213 25
        $this->sendRequest($request);
214
215 25
        $responseStatusCode = $this->getLastResponse()->getStatusCode();
216 25
        if (ResponseCode::HTTP_BAD_REQUEST == $responseStatusCode) {
217 1
            throw new WrongExpectedVersionException();
218
        }
219
220 25
        return $this->extractStreamVersionFromLastResponse($streamUrl);
221
    }
222
223
    /**
224
     * @param  string             $streamName
225
     * @return StreamFeedIterator
226
     */
227 2
    public function forwardStreamFeedIterator($streamName)
228
    {
229 2
        return StreamFeedIterator::forward($this, $streamName);
230
    }
231
232
    /**
233
     * @param  string             $streamName
234
     * @return StreamFeedIterator
235
     */
236 1
    public function backwardStreamFeedIterator($streamName)
237
    {
238 1
        return StreamFeedIterator::backward($this, $streamName);
239
    }
240
241
    /**
242
     * @throws Exception\ConnectionFailedException
243
     */
244 29
    private function checkConnection()
245
    {
246
        try {
247 29
            $request = new Request('GET', $this->url);
248 29
            $this->sendRequest($request);
249 1
        } catch (RequestException $e) {
250 1
            throw new ConnectionFailedException($e->getMessage());
251
        }
252 29
    }
253
254
    /**
255
     * @param  string $streamName
256
     * @return string
257
     */
258 27
    private function getStreamUrl($streamName)
259
    {
260 27
        return sprintf('%s/streams/%s', $this->url, $streamName);
261
    }
262
263
    /**
264
     * @param  string                            $streamUrl
265
     * @param  EntryEmbedMode                    $embedMode
266
     * @return StreamFeed
267
     * @throws Exception\StreamDeletedException
268
     * @throws Exception\StreamNotFoundException
269
     */
270 20
    private function readStreamFeed($streamUrl, EntryEmbedMode $embedMode = null)
271
    {
272 20
        $request = $this->getJsonRequest($streamUrl);
273
274 20
        if ($embedMode != null && $embedMode != EntryEmbedMode::NONE()) {
275 1
            $uri = Uri::withQueryValue(
276 1
                $request->getUri(),
277 1
                'embed',
278 1
                $embedMode->toNative()
279
            );
280
281 1
            $request = $request->withUri($uri);
282
        }
283
284 20
        $this->sendRequest($request);
285
286 20
        $this->ensureStatusCodeIsGood($streamUrl);
287
288 17
        return new StreamFeed($this->lastResponseAsJson(), $embedMode);
289
    }
290
291
    /**
292
     * @param  string                                       $uri
293
     * @return \GuzzleHttp\Message\Request|RequestInterface
294
     */
295 20
    private function getJsonRequest($uri)
296
    {
297 20
        return new Request(
298 20
            'GET',
299
            $uri,
300
            [
301
                'Accept' => 'application/vnd.eventstore.atom+json'
302 20
            ]
303
        );
304
    }
305
306
    /**
307
     * @param RequestInterface $request
308
     */
309 29
    private function sendRequest(RequestInterface $request)
310
    {
311
        try {
312 29
            $this->lastResponse = $this->httpClient->send($request);
313 1
        } catch (ClientException $e) {
314
            $this->lastResponse = $e->getResponse();
315
        }
316 29
    }
317
318
    /**
319
     * @param  string                            $streamUrl
320
     * @throws Exception\StreamDeletedException
321
     * @throws Exception\StreamNotFoundException
322
     * @throws Exception\UnauthorizedException
323
     */
324 20
    private function ensureStatusCodeIsGood($streamUrl)
325
    {
326 20
        $code = $this->lastResponse->getStatusCode();
327
328 20
        if (array_key_exists($code, $this->badCodeHandlers)) {
329 4
            $this->badCodeHandlers[$code]($streamUrl);
330
        }
331 17
    }
332
333 29
    private function initBadCodeHandlers()
334
    {
335 29
        $this->badCodeHandlers = [
336
            ResponseCode::HTTP_NOT_FOUND => function ($streamUrl) {
337 1
                throw new StreamNotFoundException(
338
                        sprintf(
339 1
                            'No stream found at %s',
340
                            $streamUrl
341
                        )
342
                    );
343 29
            },
344
345
            ResponseCode::HTTP_GONE => function ($streamUrl) {
346 2
                throw new StreamDeletedException(
347
                        sprintf(
348 2
                            'Stream at %s has been permanently deleted',
349
                            $streamUrl
350
                        )
351
                    );
352 29
            },
353
354 29
            ResponseCode::HTTP_UNAUTHORIZED => function ($streamUrl) {
355 1
                throw new UnauthorizedException(
356
                        sprintf(
357 1
                            'Tried to open stream %s got 401',
358
                            $streamUrl
359
                        )
360
                    );
361 29
            }
362
        ];
363 29
    }
364
365
    /**
366
     * Extracts created version after writing to a stream.
367
     *
368
     * The Event Store responds with a HTTP message containing a Location
369
     * header pointing to the newly created stream. This method extracts
370
     * the last part of that URI an returns the value.
371
     *
372
     * http://127.0.0.1:2113/streams/newstream/13 -> 13
373
     *
374
     * @param string $streamUrl Initial stream URL
375
     * @return int|bool Either the created version or false otherwise
376
     */
377 25
    private function extractStreamVersionFromLastResponse($streamUrl)
378
    {
379 25
        $locationHeaders = $this->getLastResponse()->getHeader('Location');
380
381
        if (
382 25
            !empty($locationHeaders[0])
383 25
            && strpos($locationHeaders[0], $streamUrl) === 0
384
        ) {
385 25
            $version = substr($locationHeaders[0], strlen($streamUrl));
386 25
            return (int)trim($version, '/');
387
        }
388
389 1
        return false;
390
    }
391
392 17
    private function lastResponseAsJson()
393
    {
394 17
        return json_decode($this->lastResponse->getBody(), true);
395
    }
396
}
397