Completed
Push — master ( 7a3efc...f79493 )
by Al3x
02:58
created

RequestService::checkResponseCode()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.2
ccs 10
cts 10
cp 1
cc 4
eloc 10
nc 4
nop 1
crap 4
1
<?php
2
declare(strict_types=1);
3
4
namespace InvoiceNinjaModule\Service;
5
6
use InvoiceNinjaModule\Exception\ApiAuthException;
7
use InvoiceNinjaModule\Exception\EmptyResponseException;
8
use InvoiceNinjaModule\Exception\HttpClientAuthException;
9
use InvoiceNinjaModule\Exception\HttpClientException;
10
use InvoiceNinjaModule\Options\Interfaces\RequestOptionsInterface;
11
use InvoiceNinjaModule\Options\Interfaces\ModuleOptionsInterface;
12
use InvoiceNinjaModule\Service\Interfaces\RequestServiceInterface;
13
use Zend\Http\Client;
14
use Zend\Http\Client\Adapter\Curl;
15
use Zend\Http\Exception\InvalidArgumentException;
16
use Zend\Http\Exception\RuntimeException;
17
use Zend\Http\Request;
18
use Zend\Http\Response;
19
use Zend\Stdlib\Parameters;
20
21
/**
22
 * Class RequestService
23
 */
24
final class RequestService implements RequestServiceInterface
25
{
26
    const RETURN_KEY = 'data';
27
    /** @var ModuleOptionsInterface */
28
    private $moduleOptions;
29
    /** @var Client  */
30
    private $httpClient;
31
32
    /**
33
     * RequestService constructor.
34
     *
35
     * @param ModuleOptionsInterface $moduleOptions
36
     * @param Client                 $client
37
     *
38
     * @throws \Zend\Http\Exception\InvalidArgumentException
39
     */
40 16
    public function __construct(ModuleOptionsInterface $moduleOptions, Client $client)
41
    {
42 16
        $this->moduleOptions = $moduleOptions;
43 16
        $this->httpClient    = $client;
44 16
        $this->initHttpClient();
45 16
    }
46
47
    /**
48
     * Sends the request to the server
49
     *
50
     * @param string                  $reqMethod
51
     * @param string                  $reqRoute
52
     * @param RequestOptionsInterface $requestOptions
53
     *
54
     * @return array
55
     * @throws \InvoiceNinjaModule\Exception\ApiAuthException
56
     * @throws \InvoiceNinjaModule\Exception\EmptyResponseException
57
     * @throws \InvoiceNinjaModule\Exception\HttpClientException
58
     * @throws \InvoiceNinjaModule\Exception\HttpClientAuthException
59
     */
60 14
    public function dispatchRequest($reqMethod, $reqRoute, RequestOptionsInterface $requestOptions) :array
61
    {
62 14
        $request = new Request();
63 14
        $request->setAllowCustomMethods(false);
64
        try {
65 14
            $request->setMethod($reqMethod);
66 1
        } catch (InvalidArgumentException $e) {
67 1
            throw new HttpClientException($e->getMessage());
68
        }
69
70 13
        $request->setQuery(new Parameters($requestOptions->getQueryArray()));
71
72 13
        $postArray = $requestOptions->getPostArray();
73 13
        if (!empty($postArray)) {
74 1
            $request->setContent(\json_encode($postArray));
75
        }
76
77
        try {
78 13
            $request->getHeaders()->addHeaders($this->getRequestHeaderArray());
79 13
            $request->setUri($this->moduleOptions->getHostUrl().$reqRoute);
80
        } catch (InvalidArgumentException $e) {
81
            throw new HttpClientException($e->getMessage());
82
        }
83
84
        try {
85 13
            $response = $this->httpClient->send($request);
86 1
        } catch (RuntimeException $e) {
87 1
            throw new HttpClientException($e->getMessage());
88
        }
89
90 12
        $this->checkResponseCode($response);
91
92 9
        return $this->convertResponse($response);
93
    }
94
95
    /**
96
     * @param Response $response
97
     *
98
     * @throws \InvoiceNinjaModule\Exception\ApiAuthException
99
     * @throws \InvoiceNinjaModule\Exception\HttpClientException
100
     * @throws \InvoiceNinjaModule\Exception\HttpClientAuthException
101
     */
102 12
    private function checkResponseCode(Response $response) :void
103
    {
104 12
        switch ($response->getStatusCode()) {
105 12
            case Response::STATUS_CODE_200:
106 9
                break;
107 3
            case Response::STATUS_CODE_403:
108 1
                throw new ApiAuthException($response->getStatusCode() .' '.$response->getReasonPhrase());
109 2
            case Response::STATUS_CODE_401:
110 1
                throw new HttpClientAuthException($response->getStatusCode() .' '.$response->getReasonPhrase());
111
            default:
112 1
                throw new HttpClientException($response->getStatusCode() .' '.$response->getReasonPhrase());
113
        }
114 9
    }
115
116
    /**
117
     * @param Response $response
118
     *
119
     * @return array
120
     * @throws \InvoiceNinjaModule\Exception\EmptyResponseException
121
     */
122 9
    private function convertResponse(Response $response) :array
123
    {
124 9
        $headers = $response->getHeaders();
125
        //check if it is a file
126 9
        $contentDisposition = $headers->get('Content-disposition');
127 9
        if ($contentDisposition !== false) {
128 2
            $needle = 'attachment; filename="';
129 2
            $subString = \strstr($contentDisposition->getFieldValue(), $needle);
130
131 2
            if ($subString === false) {
132 1
                return [];
133
            }
134
135 1
            $fileName = \substr($subString, \strlen($needle), -1);
136 1
            return [$fileName => $response->getBody()];
137
        }
138
139 7
        $result = \json_decode($response->getBody(), true);
140 7
        if (\is_array($result)) {
141 6
            return $this->checkResponseKey($result);
142
        }
143 1
        throw new EmptyResponseException();
144
    }
145
146
    /**
147
     * @param array $result
148
     *
149
     * @return array
150
     * @throws \InvoiceNinjaModule\Exception\EmptyResponseException
151
     */
152 6
    private function checkResponseKey(array $result) :array
153
    {
154 6
        if (!\array_key_exists(self::RETURN_KEY, $result) || empty($result[self::RETURN_KEY])) {
155 2
            throw new EmptyResponseException();
156
        }
157 4
        return $result[self::RETURN_KEY];
158
    }
159
160
    /**
161
     * @return array
162
     */
163 13
    private function getRequestHeaderArray() :array
164
    {
165
        return [
166 13
            'Accept'                             => 'application/json',
167 13
            'Content-type'                       => 'application/json; charset=UTF-8',
168 13
            $this->moduleOptions->getTokenType() => $this->moduleOptions->getToken()
169
        ];
170
    }
171
172
    /**
173
     * @return void
174
     * @throws \Zend\Http\Exception\InvalidArgumentException
175
     */
176 16
    private function initHttpClient() :void
177
    {
178
        $options = [
179 16
            'timeout' => $this->moduleOptions->getTimeout()
180
        ];
181 16
        $this->httpClient->setOptions($options);
182 16
        $this->httpClient->setAdapter(Curl::class);
183
184 16
        $authOptions = $this->moduleOptions->getAuthOptions();
185
186 16
        if ($authOptions->isAuthorization()) {
187 1
            $this->httpClient->setAuth(
188 1
                $authOptions->getUsername(),
189 1
                $authOptions->getPassword(),
190 1
                $authOptions->getAuthType()
191
            );
192
        }
193 16
    }
194
}
195