Completed
Push — master ( cdcbf9...7e5724 )
by Julien
05:30
created

Client::post()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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