Completed
Pull Request — master (#61)
by Tomas
03:17
created

ConsoleRequest   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 223
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 66.67%

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 3
dl 0
loc 223
ccs 86
cts 129
cp 0.6667
rs 9.1199
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
F makeRequest() 0 107 17
C processValues() 0 48 13
A processParam() 0 21 5
A normalizeValues() 0 17 5

How to fix   Complexity   

Complex Class

Complex classes like ConsoleRequest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ConsoleRequest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Tomaj\NetteApi\Misc;
4
5
use Nette\Http\FileUpload;
6
use Tomaj\NetteApi\Handlers\ApiHandlerInterface;
7
use Tomaj\NetteApi\Params\InputParam;
8
9
class ConsoleRequest
10
{
11
    /** @var ApiHandlerInterface */
12
    private $handler;
13
14 3
    public function __construct(ApiHandlerInterface $handler)
15
    {
16 3
        $this->handler = $handler;
17 3
    }
18
19 3
    public function makeRequest(string $url, string $method, array $values, array $additionalValues = [], ?string $token = null): ConsoleResponse
20
    {
21 3
        list($postFields, $getFields, $cookieFields, $rawPost, $putFields) = $this->processValues($values);
22
23 3
        if (isset($additionalValues['postFields'])) {
24
            $postFields = array_merge($postFields, $additionalValues['postFields']);
25
        }
26
27 3
        if (isset($additionalValues['getFields'])) {
28
            $getFields = array_merge($postFields, $additionalValues['getFields']);
29
        }
30
31 3
        if (isset($additionalValues['cookieFields'])) {
32
            $cookieFields = array_merge($postFields, $additionalValues['cookieFields']);
33
        }
34
35 3
        if (isset($additionalValues['putFields'])) {
36
            $putFields = array_merge($putFields, $additionalValues['putFields']);
37
        }
38
39 3
        $postFields = $this->normalizeValues($postFields);
40 3
        $getFields = $this->normalizeValues($getFields);
41 3
        $putFields = $this->normalizeValues($putFields);
42
43 3
        if (count($getFields)) {
44 3
            $parts = [];
45 3
            foreach ($getFields as $key => $value) {
46 3
                $parts[] = "$key=$value";
47
            }
48 3
            $url = $url . '?' . implode('&', $parts);
49
        }
50
51 3
        $putRawPost = null;
52 3
        if (count($putFields)) {
53
            $parts = [];
54
            foreach ($putFields as $key => $value) {
55
                $parts[] = "$key=$value";
56
            }
57
            $putRawPost = implode('&', $parts);
58
        }
59
60 3
        $startTime = microtime(true);
61
62 3
        $curl = curl_init();
63 3
        curl_setopt($curl, CURLOPT_URL, $url);
64 3
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
65 3
        curl_setopt($curl, CURLOPT_NOBODY, false);
66 3
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
67 3
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
68 3
        curl_setopt($curl, CURLOPT_VERBOSE, false);
69 3
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
70 3
        curl_setopt($curl, CURLOPT_HEADER, true);
71 3
        if (count($postFields)) {
72
            curl_setopt($curl, CURLOPT_POST, true);
73
            curl_setopt($curl, CURLOPT_POSTFIELDS, $postFields);
74
        }
75 3
        if ($rawPost) {
76
            curl_setopt($curl, CURLOPT_POST, true);
77
            curl_setopt($curl, CURLOPT_POSTFIELDS, $rawPost);
78
        }
79 3
        if ($putRawPost) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $putRawPost of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
80
            curl_setopt($curl, CURLOPT_POST, true);
81
            curl_setopt($curl, CURLOPT_POSTFIELDS, $putRawPost);
82
        }
83 3
        if (count($cookieFields)) {
84
            $parts = [];
85
            foreach ($cookieFields as $key => $value) {
86
                $parts[] = "$key=$value";
87
            }
88
            curl_setopt($curl, CURLOPT_HTTPHEADER, ["Cookie: " . implode('&', $parts)]);
89
        }
90
91 3
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);
92 3
        $headers = [];
93 3
        if ($token !== null && $token !== false) {
94
            $headers = ['Authorization: Bearer ' . $token];
95
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
96
        }
97
98 3
        $consoleResponse = new ConsoleResponse(
99 3
            $url,
100 2
            $method,
101 2
            $postFields,
102 2
            $getFields,
103 2
            $cookieFields,
104 2
            $headers,
105 2
            $rawPost
106
        );
107
108 3
        $response = curl_exec($curl);
109 3
        $elapsed = intval((microtime(true) - $startTime) * 1000);
110
111 3
        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
112 3
        $responseHeaders = substr($response, 0, $headerSize);
113 3
        $responseBody = substr($response, $headerSize);
114
115 3
        $curlErrorNumber = curl_errno($curl);
116 3
        $curlError = curl_error($curl);
117 3
        if ($curlErrorNumber > 0) {
118 3
            $consoleResponse->logError($curlErrorNumber, $curlError, $elapsed);
119
        } else {
120
            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
121
            $consoleResponse->logRequest($httpCode, $responseBody, $responseHeaders, $elapsed);
122
        }
123
124 3
        return $consoleResponse;
125
    }
126
127
    /**
128
     * Process given values to POST and GET fields
129
     *
130
     * @param array $values
131
     *
132
     * @return array
133
     */
134 3
    private function processValues(array $values): array
135
    {
136 3
        $params = $this->handler->params();
137
138 3
        $postFields = [];
139 3
        $rawPost = isset($values['post_raw']) ? $values['post_raw'] : false;
140 3
        $getFields = [];
141 3
        $putFields = [];
142 3
        $cookieFields = [];
143
144 3
        foreach ($values as $key => $value) {
145 3
            if (strstr($key, '___') !== false) {
146
                $parts = explode('___', $key);
147
                $key = $parts[0];
148
            }
149
150 3
            foreach ($params as $param) {
151 3
                $valueData = $this->processParam($param, $key, $value);
152 3
                if ($valueData === null) {
153 3
                    continue;
154
                }
155
156 3
                if ($param->isMulti()) {
157
                    if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) {
158
                        $postFields[$key][] = $valueData;
159
                    } elseif ($param->getType() == InputParam::TYPE_PUT) {
160
                        $putFields[$key][] = $valueData;
161
                    } elseif ($param->getType() == InputParam::TYPE_COOKIE) {
162
                        $cookieFields[$key][] = $valueData;
163
                    } else {
164
                        $getFields[$key][] = $valueData;
165
                    }
166
                } else {
167 3
                    if (in_array($param->getType(), [InputParam::TYPE_POST, InputParam::TYPE_FILE])) {
168
                        $postFields[$key] = $valueData;
169 3
                    } elseif ($param->getType() == InputParam::TYPE_PUT) {
170
                        $putFields[$key] = $valueData;
171 3
                    } elseif ($param->getType() == InputParam::TYPE_COOKIE) {
172
                        $cookieFields[$key] = $valueData;
173
                    } else {
174 3
                        $getFields[$key] = $valueData;
175
                    }
176
                }
177
            }
178
        }
179
180 3
        return [$postFields, $getFields, $cookieFields, $rawPost, $putFields];
181
    }
182
183
    /**
184
     * Process one param and returns value
185
     *
186
     * @param InputParam  $param   input param
187
     * @param string      $key     param key
188
     * @param mixed      $value   actual value from request
189
     *
190
     * @return string|null
191
     */
192 3
    private function processParam(InputParam $param, string $key, $value): ?string
193
    {
194 3
        if ($param->getKey() == $key) {
195 3
            $valueData = $value;
196
197 3
            if ($param->getType() === InputParam::TYPE_FILE) {
198
                /** @var FileUpload $file */
199
                $file = $value;
200
                if ($file->isOk()) {
201
                    $valueData = curl_file_create($file->getTemporaryFile(), $file->getContentType(), $file->getName());
202
                } else {
203
                    $valueData = false;
204
                }
205 3
            } elseif ($param->getType() === InputParam::TYPE_POST_RAW) {
206
                $valueData = file_get_contents('php://input');
207
            }
208
209 3
            return $valueData;
210
        }
211 3
        return null;
212
    }
213
214 3
    private function normalizeValues(array $values): array
215
    {
216 3
        $result = [];
217 3
        foreach ($values as $key => $value) {
218 3
            if (is_array($value)) {
219
                $counter = 0;
220
                foreach ($value as $innerValue) {
221
                    if ($innerValue != null) {
222
                        $result[$key . "[".$counter++."]"] = $innerValue;
223
                    }
224
                }
225
            } else {
226 3
                $result[$key] = $value;
227
            }
228
        }
229 3
        return $result;
230
    }
231
}
232