Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Paste
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getRequest
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 lookup
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Icawebdesign\Hibp\Paste;
6
7use Exception;
8use GuzzleHttp\ClientInterface;
9use GuzzleHttp\Exception\ClientException;
10use GuzzleHttp\Exception\GuzzleException;
11use GuzzleHttp\Exception\RequestException;
12use Icawebdesign\Hibp\Exception\InvalidPasteDataException;
13use Icawebdesign\Hibp\Exception\PasteNotFoundException;
14use Icawebdesign\Hibp\HibpHttp;
15use Icawebdesign\Hibp\Traits\HibpConfig;
16use Illuminate\Support\Collection;
17use JsonException;
18use Psr\Http\Message\ResponseInterface;
19use stdClass;
20
21use const JSON_THROW_ON_ERROR;
22
23class Paste implements PasteInterface
24{
25    use HibpConfig;
26
27    protected ClientInterface $client;
28
29    public int $statusCode;
30
31    protected string $apiRoot;
32
33    public function __construct(HibpHttp $hibpHttp)
34    {
35        $this->apiRoot = "{$this->hibpApiRoot}/v{$this->apiVersion}";
36        $this->client = $hibpHttp->client();
37    }
38
39    /**
40     * @param string $uri
41     * @param array<string, mixed> $options
42     *
43     * @return ResponseInterface
44     * @throws GuzzleException
45     */
46    private function getRequest(string $uri, array $options = []): ResponseInterface
47    {
48        return $this->client->request(
49            'GET',
50            $uri,
51            $options,
52        );
53    }
54
55    /**
56     * Check for any pastes containing specified email address
57     *
58     * @param string $emailAddress
59     * @param array<string, mixed> $options
60     *
61     * @return Collection<int, PasteEntity>
62     * @throws GuzzleException|InvalidPasteDataException|Exception
63     */
64    public function lookup(string $emailAddress, array $options = []): Collection
65    {
66        try {
67            $response = $this->getRequest(
68                uri: sprintf('%s/pasteaccount/%s', $this->apiRoot, urlencode($emailAddress)),
69                options: $options,
70            );
71        } catch (ClientException $exception) {
72            $this->statusCode = $exception->getCode();
73
74            throw match ($exception->getCode()) {
75                404 => new PasteNotFoundException($exception->getMessage()),
76                400 => new RequestException($exception->getMessage(), $exception->getRequest()),
77                default => $exception,
78            };
79        }
80
81        $this->statusCode = $response->getStatusCode();
82
83        try {
84            /** @var array<int, stdClass> $data */
85            $data = json_decode((string)$response->getBody(), associative: false, flags: JSON_THROW_ON_ERROR);
86        } catch (JsonException $exception) {
87            throw new InvalidPasteDataException($exception->getMessage());
88        }
89
90        return Collection::make($data)
91            ->map(static fn(stdClass $paste): PasteEntity => new PasteEntity(data: $paste));
92    }
93}