Passed
Push — master ( 3896ee...e50616 )
by Raffael
05:45
created

ApiClient::restCall()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 58
ccs 0
cts 34
cp 0
rs 7.983
c 0
b 0
f 0
cc 7
nc 24
nop 3
crap 56

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee.io
7
 *
8
 * @copyright   Copryright (c) 2017-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Tubee\Storage\Balloon;
13
14
use InvalidArgumentException;
15
use Psr\Log\LoggerInterface;
16
17
class ApiClient
18
{
19
    /**
20
     * Logger.
21
     *
22
     * @var LoggerInterface
23
     */
24
    protected $logger;
25
26
    /**
27
     * URI.
28
     *
29
     * @var string
30
     */
31
    protected $uri = 'http://127.0.0.1';
32
33
    /**
34
     * Username.
35
     *
36
     * @var string
37
     */
38
    protected $username;
39
40
    /**
41
     * Password.
42
     *
43
     * @var string
44
     */
45
    protected $password;
46
47
    /**
48
     * CURL options.
49
     *
50
     * @var array
51
     */
52
    protected $curl_options = [
53
        CURLOPT_RETURNTRANSFER => 1,
54
        CURLOPT_CONNECTTIMEOUT => 10,
55
        CURLOPT_SSL_VERIFYPEER => true,
56
    ];
57
58
    /**
59
     * construct.
60
     */
61
    public function __construct(array $config = [], LoggerInterface $logger)
62
    {
63
        $this->setOptions($config);
64
        $this->logger = $logger;
65
    }
66
67
    /**
68
     * Set options.
69
     */
70
    public function setOptions(array $config = []): ApiClient
71
    {
72
        foreach ($config as $option => $value) {
73
            switch ($option) {
74
                case 'url':
75
                    $this->uri = (string) $value;
76
77
                    break;
78
                case 'username':
79
                    $this->username = (string) $value;
80
81
                    break;
82
                case 'password':
83
                    $this->password = (string) $value;
84
85
                    break;
86
                case 'request_options':
87
                    foreach ($value as $key => $opt) {
88
                        $name = constant($key);
89
                        $this->curl_options[$name] = $opt;
90
                    }
91
92
                    break;
93
                default:
94
                    throw new InvalidArgumentException('unknown option '.$option.' given');
95
            }
96
        }
97
98
        return $this;
99
    }
100
101
    /**
102
     * Open stream.
103
     */
104
    public function openSocket(string $url, array $params = [], string $method = 'GET')
105
    {
106
        $opts = [
107
            'http' => [
108
                'method' => $method,
109
                'header' => "Content-Type: application/json\r\n".
110
                          'Authorization: Basic '.base64_encode($this->username.':'.$this->password)."\r\n",
111
            ],
112
        ];
113
114
        $context = stream_context_create($opts);
115
116
        $params = json_encode($params);
117
118
        $url = $this->uri.$url.'?'.urlencode($params);
119
120
        $this->logger->info('open socket for ['.$url.']', [
121
            'category' => get_class($this),
122
        ]);
123
124
        return fopen($url, 'r', false, $context);
125
    }
126
127
    /**
128
     * REST call.
129
     */
130
    public function restCall(string $url, array $params = [], string $method = 'GET'): ?array
131
    {
132
        $url = $this->uri.$url;
133
        $ch = curl_init();
134
135
        $params = json_encode($params);
136
        switch ($method) {
137
            case 'GET':
138
                $url .= '?'.urlencode($params);
139
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
140
141
                break;
142
            case 'PUT':
143
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
144
                curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
145
                // no break
146
            default:
147
                break;
148
        }
149
150
        $this->logger->info('execute curl request ['.$url.']', [
151
            'category' => get_class($this),
152
            'params' => $params,
153
        ]);
154
155
        curl_setopt($ch, CURLOPT_URL, $url);
156
157
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
158
            'Content-Type: application/json',
159
        ]);
160
161
        curl_setopt($ch, CURLOPT_USERPWD, "$this->username:$this->password");
162
        foreach ($this->curl_options as $opt => $value) {
163
            curl_setopt($ch, $opt, $value);
164
        }
165
166
        $result = curl_exec($ch);
167
        $http_code = curl_getinfo($ch)['http_code'];
168
        curl_close($ch);
169
170
        if (substr((string) $http_code, 0, 1) !== '2') {
171
            if ($result !== false) {
172
                $this->logger->error('failed process balloon request ['.$result.']', [
173
                    'category' => get_class($this),
174
                ]);
175
            }
176
177
            throw new Exception\FailedProcessRequest('http request failed with response code '.$http_code);
178
        }
179
180
        $body = json_decode($result, true);
181
182
        if (json_last_error() !== JSON_ERROR_NONE) {
183
            throw new Exception\InvalidApiResponse('failed decode balloon json response with error '.json_last_error());
184
        }
185
186
        return $body;
187
    }
188
}
189