Passed
Pull Request — master (#22)
by Rhodri
07:26
created

Client::makeMultipartFormDataRequest()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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