Completed
Push — master ( 116dd8...98663d )
by Al3x
02:26
created

RequestService::dispatchRequest()   B

Complexity

Conditions 5
Paths 28

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
c 0
b 0
f 0
rs 8.439
cc 5
eloc 19
nc 28
nop 3
1
<?php
2
3
namespace InvoiceNinjaModule\Service;
4
5
use InvoiceNinjaModule\Exception\ApiException;
6
use InvoiceNinjaModule\Exception\EmptyResponseException;
7
use InvoiceNinjaModule\Model\Interfaces\RequestOptionsInterface;
8
use InvoiceNinjaModule\Model\Interfaces\SettingsInterface;
9
use InvoiceNinjaModule\Service\Interfaces\RequestServiceInterface;
10
use Zend\Http\Client;
11
use Zend\Http\Client\Adapter\Curl;
12
use Zend\Http\Exception\InvalidArgumentException;
13
use Zend\Http\Exception\RuntimeException;
14
use Zend\Http\Request;
15
use Zend\Http\Response;
16
use Zend\Stdlib\Parameters;
17
18
/**
19
 * Class RequestService
20
 *
21
 * @package InvoiceNinjaModule\Service
22
 */
23
final class RequestService implements RequestServiceInterface
24
{
25
    const RETURN_KEY = 'data';
26
    /** @var SettingsInterface */
27
    private $settings;
28
    /** @var Client  */
29
    private $httpClient;
30
31
    /**
32
     * RequestService constructor.
33
     *
34
     * @param SettingsInterface $settings
35
     * @param Client            $client
36
     * @throws InvalidArgumentException
37
     */
38
    public function __construct(SettingsInterface $settings, Client $client)
39
    {
40
        $this->settings = $settings;
41
        $this->httpClient = $client;
42
        $this->initHttpClient();
43
    }
44
45
    /**
46
     * Sends the request to the server
47
     * @param string                  $reqMethod
48
     * @param string                  $reqRoute
49
     * @param RequestOptionsInterface $requestOptions
50
     *
51
     * @return array
52
     * @throws ApiException
53
     * @throws EmptyResponseException
54
     */
55
    public function dispatchRequest($reqMethod, $reqRoute, RequestOptionsInterface $requestOptions) :array
56
    {
57
        try {
58
            $request = new Request();
59
            $request->setAllowCustomMethods(false);
60
            $request->setMethod($reqMethod);
61
            $request->setQuery(new Parameters($requestOptions->getQueryArray()));
62
63
            $postArray = $requestOptions->getPostArray();
64
            if (!empty($postArray)) {
65
                $request->setContent(json_encode($postArray));
66
            }
67
68
            $request->getHeaders()->addHeaders($this->getRequestHeaderArray());
69
            $request->setUri($this->settings->getHostUrl().$reqRoute);
70
71
            $response = $this->httpClient->send($request);
72
        } catch (InvalidArgumentException $e) {
73
            throw new ApiException($e->getMessage());
74
        } catch (RuntimeException $e) {
75
            throw new ApiException($e->getMessage());
76
        }
77
78
        if ($response->getStatusCode() !== Response::STATUS_CODE_200) {
79
            throw new ApiException($response->getStatusCode() .' '.$response->getReasonPhrase());
80
        }
81
82
        return $this->convertResponse($response);
83
    }
84
85
    /**
86
     * @param Response $response
87
     *
88
     * @return array
89
     * @throws EmptyResponseException
90
     */
91
    private function convertResponse(Response $response) :array
92
    {
93
        $headers = $response->getHeaders();
94
        //check if it is a file
95
        $contentDisposition = $headers->get('Content-disposition');
96
        if ($contentDisposition !== false) {
97
            $needle = 'attachment; filename="';
98
            $fileName = substr(strstr($contentDisposition->getFieldValue(), $needle), strlen($needle), -1);
99
            if (\is_string($fileName)) {
100
                return [$fileName => $response->getBody()];
101
            }
102
            return [];
103
        }
104
105
        $result = json_decode($response->getBody(), true);
106
        if (is_array($result)) {
107
            return $this->checkResponseKey($result);
108
        }
109
        return [];
110
    }
111
112
    /**
113
     * @param array $result
114
     *
115
     * @return array
116
     * @throws EmptyResponseException
117
     */
118
    private function checkResponseKey(array $result) :array
119
    {
120
        if (!array_key_exists(self::RETURN_KEY, $result) || empty($result[self::RETURN_KEY])) {
121
            throw new EmptyResponseException();
122
        }
123
        return $result[self::RETURN_KEY];
124
    }
125
126
    /**
127
     * @return array
128
     */
129
    private function getRequestHeaderArray() :array
130
    {
131
        return [
132
            'Accept' => 'application/json',
133
            'Content-type' => 'application/json; charset=UTF-8',
134
            $this->settings->getTokenType() => $this->settings->getToken()
135
        ];
136
    }
137
138
    /**
139
     * @return void
140
     * @throws InvalidArgumentException
141
     */
142
    private function initHttpClient() :void
143
    {
144
        $options = [
145
            'timeout' => $this->settings->getTimeout()
146
        ];
147
        $this->httpClient->setOptions($options);
148
        $this->httpClient->setAdapter(Curl::class);
149
    }
150
}
151