Passed
Pull Request — master (#22)
by Rhodri
08:06
created

Client::__construct()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TheCodingMachine\Gotenberg;
6
7
use Exception;
8
use GuzzleHttp\Psr7\MultipartStream;
9
use Http\Client\HttpClient;
10
use Http\Discovery\HttpClientDiscovery;
11
use Http\Discovery\MessageFactoryDiscovery;
12
use Psr\Http\Message\RequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use function fclose;
15
use function fopen;
16
use function fwrite;
17
18
final class Client
19
{
20
    /** @var HttpClient */
21
    private $client;
22
23
    /** @var string */
24
    private $apiURL;
25
26
    public function __construct(string $apiURL, ?HttpClient $client = null)
27
    {
28
        $this->apiURL = $apiURL;
29
        $this->client = $client ?: HttpClientDiscovery::find();
30
    }
31
32
    /**
33
     * Sends the given documents to the API and returns the response.
34
     *
35
     * @throws ClientException
36
     * @throws Exception
37
     */
38
    public function post(GotenbergRequestInterface $request): ResponseInterface
39
    {
40
        return $this->handleResponse($this->client->sendRequest($this->makeMultipartFormDataRequest($request)));
41
    }
42
43
    /**
44
     * Sends the given documents to the API, stores the resulting PDF in the given destination.
45
     *
46
     * @throws ClientException
47
     * @throws RequestException
48
     * @throws Exception
49
     */
50
    public function store(GotenbergRequestInterface $request, string $destination): void
51
    {
52
        if ($request->hasWebhook()) {
53
            throw new RequestException('Cannot use method store with a webhook.');
54
        }
55
        $response = $this->handleResponse($this->client->sendRequest($this->makeMultipartFormDataRequest($request)));
56
        $fileStream = $response->getBody();
57
        $fp = fopen($destination, 'w');
58
        if ($fp === false) {
59
            throw FilesystemException::createFromPhpError();
60
        }
61
62
        if (fwrite($fp, $fileStream->getContents()) === false) {
63
            throw FilesystemException::createFromPhpError();
64
        }
65
66
        if (fclose($fp) === false) {
67
            throw FilesystemException::createFromPhpError();
68
        }
69
    }
70
71
    private function makeMultipartFormDataRequest(GotenbergRequestInterface $request): RequestInterface
72
    {
73
        $multipartData = [];
74
        foreach ($request->getFormValues() as $fieldName => $fieldValue) {
75
            $multipartData[] = [
76
                'name' => $fieldName,
77
                'contents' => $fieldValue,
78
            ];
79
        }
80
        /**
81
         * @var string $filename
82
         * @var Document $document
83
         */
84
        foreach ($request->getFormFiles() as $filename => $document) {
85
            $multipartData[] = [
86
                'name' => 'files',
87
                'filename' => $filename,
88
                'contents' => $document->getFileStream(),
89
            ];
90
        }
91
        $body = new MultipartStream($multipartData);
92
        $messageFactory = MessageFactoryDiscovery::find();
93
        $message = $messageFactory
94
            ->createRequest('POST', $this->apiURL . $request->getPostURL())
95
            ->withHeader('Content-Type', 'multipart/form-data; boundary="' . $body->getBoundary() . '"')
96
            ->withBody($body);
97
        foreach ($request->getCustomHTTPHeaders() as $key => $value) {
98
            $message = $message->withHeader($key, $value);
99
        }
100
101
        return $message;
102
    }
103
104
    /**
105
     * @throws ClientException
106
     */
107
    private function handleResponse(ResponseInterface $response): ResponseInterface
108
    {
109
        switch ($response->getStatusCode()) {
110
            case 200:
111
                return $response;
112
            default:
113
                throw new ClientException($response->getBody()->getContents(), $response->getStatusCode());
114
        }
115
    }
116
}
117