Completed
Push — master ( c7860e...7f0412 )
by Tomas
16s queued 11s
created

ConsoleRequest::processParam()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6.8088

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 7
cts 12
cp 0.5833
rs 9.2728
c 0
b 0
f 0
cc 5
nc 5
nop 3
crap 6.8088
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Tomaj\NetteApi\Misc;
6
7
use Nette\Http\FileUpload;
8
use Tomaj\NetteApi\EndpointInterface;
9
use Tomaj\NetteApi\Handlers\ApiHandlerInterface;
10
use Tomaj\NetteApi\Link\ApiLink;
11
use Tomaj\NetteApi\Params\InputParam;
12
use Tomaj\NetteApi\Params\ParamInterface;
13
14
class ConsoleRequest
15
{
16
    /** @var ApiHandlerInterface */
17
    private $handler;
18
19
    /** @var EndpointInterface|null */
20
    private $endpoint;
21
22
    /** @var ApiLink|null */
23
    private $apiLink;
24
25 3
    public function __construct(ApiHandlerInterface $handler, ?EndpointInterface $endpoint = null, ?ApiLink $apiLink = null)
26
    {
27 3
        $this->handler = $handler;
28 3
        $this->endpoint = $endpoint;
29 3
        $this->apiLink = $apiLink;
30 3
    }
31
32 3
    public function makeRequest(string $url, string $method, array $values, array $additionalValues = [], ?string $token = null): ConsoleResponse
33
    {
34 3
        list($postFields, $getFields, $cookieFields, $rawPost, $putFields) = $this->processValues($values);
35
36 3
        $postFields = array_merge($postFields, $additionalValues['postFields'] ?? []);
37 3
        $getFields = array_merge($getFields, $additionalValues['getFields'] ?? []);
38 3
        $cookieFields = array_merge($cookieFields, $additionalValues['cookieFields'] ?? []);
39 3
        $putFields = array_merge($putFields, $additionalValues['putFields'] ?? []);
40
41 3
        $postFields = $this->normalizeValues($postFields);
42 3
        $getFields = $this->normalizeValues($getFields);
43 3
        $putFields = $this->normalizeValues($putFields);
44
45 3
        if ($this->endpoint && $this->apiLink) {
46
            $url = $this->apiLink->link($this->endpoint, $getFields);
47 3
        } elseif (count($getFields)) {
48 3
            $parts = [];
49 3
            foreach ($getFields as $key => $value) {
50 3
                $parts[] = "$key=$value";
51
            }
52 3
            $url = $url . '?' . implode('&', $parts);
53
        }
54
55 3
        $putRawPost = null;
56 3
        if (count($putFields)) {
57
            $parts = [];
58
            foreach ($putFields as $key => $value) {
59
                $parts[] = "$key=$value";
60
            }
61
            $putRawPost = implode('&', $parts);
62
        }
63
64 3
        $startTime = microtime(true);
65
66 3
        $curl = curl_init();
67 3
        curl_setopt($curl, CURLOPT_URL, $url);
68 3
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
69 3
        curl_setopt($curl, CURLOPT_NOBODY, false);
70 3
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
71 3
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
72 3
        curl_setopt($curl, CURLOPT_VERBOSE, false);
73 3
        curl_setopt($curl, CURLOPT_TIMEOUT, $additionalValues['timeout'] ?? 30);
74 3
        curl_setopt($curl, CURLOPT_HEADER, true);
75
76 3
        if (count($postFields) || $rawPost || $putRawPost !== null) {
77
            curl_setopt($curl, CURLOPT_POST, true);
78
            curl_setopt($curl, CURLOPT_POSTFIELDS, count($postFields) ? $postFields : ($rawPost ?: $putRawPost));
79
        }
80
81 3
        $headers = $additionalValues['headers'] ?? [];
82 3
        if (count($cookieFields)) {
83
            $parts = [];
84
            foreach ($cookieFields as $key => $value) {
85
                $parts[] = "$key=$value";
86
            }
87
            $headers[] = "Cookie: " . implode('&', $parts);
88
        }
89 3
        if ($token !== null && $token !== false) {
90
            $headers[] = 'Authorization: Bearer ' . $token;
91
        }
92 3
        if (count($headers)) {
93
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
94
        }
95
96 3
        $basicAuthUsername = $values['basic_authentication_username'] ?? null;
97 3
        $basicAuthPassword = $values['basic_authentication_password'] ?? null;
98 3
        if ($basicAuthUsername && $basicAuthPassword) {
99
            curl_setopt($curl, CURLOPT_USERPWD, "$basicAuthUsername:$basicAuthPassword");
100
        }
101
102 3
        $consoleResponse = new ConsoleResponse(
103 3
            $url,
104 2
            $method,
105 2
            $postFields,
106 2
            $getFields,
107 2
            $cookieFields,
108 2
            $headers,
109 2
            $rawPost
110
        );
111
112 3
        $response = curl_exec($curl);
113 3
        $elapsed = intval((microtime(true) - $startTime) * 1000);
114
115 3
        if ($response === false) {
116 3
            $response = '';
117
        }
118
119 3
        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
120 3
        $responseHeaders = substr($response, 0, $headerSize);
121 3
        $responseBody = substr($response, $headerSize);
122
123 3
        $curlErrorNumber = curl_errno($curl);
124 3
        $curlError = curl_error($curl);
125 3
        if ($curlErrorNumber > 0) {
126 3
            $consoleResponse->logError($curlErrorNumber, $curlError, $elapsed);
127
        } else {
128
            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
129
            $consoleResponse->logRequest($httpCode, $responseBody, $responseHeaders, $elapsed);
130
        }
131
132 3
        return $consoleResponse;
133
    }
134
135
    /**
136
     * Process given values to POST and GET fields
137
     *
138
     * @param array $values
139
     *
140
     * @return array
141
     */
142 3
    private function processValues(array $values): array
143
    {
144 3
        $params = $this->handler->params();
145
146 3
        $postFields = [];
147 3
        $rawPost = isset($values['post_raw']) ? $values['post_raw'] : null;
148 3
        $getFields = [];
149 3
        $putFields = [];
150 3
        $cookieFields = [];
151
152 3
        foreach ($values as $key => $value) {
153 3
            if (strstr($key, '___') !== false) {
154
                $parts = explode('___', $key);
155
                $key = $parts[0];
156
            }
157
158 3
            foreach ($params as $param) {
159 3
                $valueData = $this->processParam($param, $key, $value);
160 3
                if ($valueData === null) {
161 3
                    continue;
162
                }
163
164 3
                if ($param->isMulti()) {
165
                    if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) {
166
                        $postFields[$key][] = $valueData;
167
                    } elseif ($param->getType() === InputParam::TYPE_PUT) {
168
                        $putFields[$key][] = $valueData;
169
                    } elseif ($param->getType() === InputParam::TYPE_COOKIE) {
170
                        $cookieFields[$key][] = $valueData;
171
                    } else {
172
                        $getFields[$key][] = urlencode($valueData);
173
                    }
174
                } else {
175 3
                    if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) {
176
                        $postFields[$key] = $valueData;
177 3
                    } elseif ($param->getType() === InputParam::TYPE_PUT) {
178
                        $putFields[$key] = $valueData;
179 3
                    } elseif ($param->getType() === InputParam::TYPE_COOKIE) {
180
                        $cookieFields[$key] = $valueData;
181
                    } else {
182 3
                        $getFields[$key] = urlencode($valueData);
183
                    }
184
                }
185
            }
186
        }
187
188 3
        return [$postFields, $getFields, $cookieFields, $rawPost, $putFields];
189
    }
190
191
    /**
192
     * Process one param and returns value
193
     *
194
     * @param ParamInterface  $param   input param
195
     * @param string          $key     param key
196
     * @param mixed           $value   actual value from request
197
     *
198
     * @return mixed
199
     */
200 3
    private function processParam(ParamInterface $param, string $key, $value)
201
    {
202 3
        if ($param->getKey() === $key) {
203 3
            $valueData = $value;
204
205 3
            if ($param->getType() === InputParam::TYPE_FILE) {
206
                /** @var FileUpload $file */
207
                $file = $value;
208
                if ($file->isOk()) {
209
                    $valueData = curl_file_create($file->getTemporaryFile(), $file->getContentType(), $file->getName());
210
                } else {
211
                    $valueData = false;
212
                }
213 3
            } elseif ($param->getType() === InputParam::TYPE_POST_RAW) {
214
                $valueData = file_get_contents('php://input');
215
            }
216
217 3
            return $valueData;
218
        }
219 3
        return null;
220
    }
221
222 3
    private function normalizeValues(array $values): array
223
    {
224 3
        $result = [];
225 3
        foreach ($values as $key => $value) {
226 3
            if (!is_array($value)) {
227 3
                $result[$key] = $value;
228 3
                continue;
229
            }
230
231
            foreach ($value as $innerKey => $innerValue) {
232
                if ($innerValue !== '' && $innerValue !== null) {
233
                    $result[$key . "[" . $innerKey . "]"] = $innerValue;
234
                }
235
            }
236
        }
237 3
        return $result;
238
    }
239
}
240