Passed
Pull Request — master (#1554)
by mingyoung
03:15
created

HasHttpRequests::request()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 3
dl 0
loc 16
ccs 9
cts 9
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\Kernel\Traits;
13
14
use GuzzleHttp\Client;
15
use GuzzleHttp\ClientInterface;
16
use GuzzleHttp\HandlerStack;
17
use Psr\Http\Message\ResponseInterface;
18
19
/**
20
 * Trait HasHttpRequests.
21
 *
22
 * @author overtrue <[email protected]>
23
 */
24
trait HasHttpRequests
25
{
26
    use ResponseCastable;
27
28
    /**
29
     * @var \GuzzleHttp\ClientInterface
30
     */
31
    protected $httpClient;
32
33
    /**
34
     * @var array
35
     */
36
    protected $middlewares = [];
37
38
    /**
39
     * @var \GuzzleHttp\HandlerStack
40
     */
41
    protected $handlerStack;
42
43
    /**
44
     * @var array
45
     */
46
    protected static $defaults = [
47
        'curl' => [
48
            CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
49
        ],
50
    ];
51
52
    /**
53
     * Set guzzle default settings.
54
     *
55
     * @param array $defaults
56
     */
57 1
    public static function setDefaultOptions($defaults = [])
58
    {
59 1
        self::$defaults = $defaults;
60 1
    }
61
62
    /**
63
     * Return current guzzle default settings.
64
     *
65
     * @return array
66
     */
67 1
    public static function getDefaultOptions(): array
68
    {
69 1
        return self::$defaults;
70
    }
71
72
    /**
73
     * Set GuzzleHttp\Client.
74
     *
75
     * @param \GuzzleHttp\ClientInterface $httpClient
76
     *
77
     * @return $this
78
     */
79 47
    public function setHttpClient(ClientInterface $httpClient)
80
    {
81 47
        $this->httpClient = $httpClient;
82
83 47
        return $this;
84
    }
85
86
    /**
87
     * Return GuzzleHttp\ClientInterface instance.
88
     *
89
     * @return ClientInterface
90
     */
91 4
    public function getHttpClient(): ClientInterface
92
    {
93 4
        if (!($this->httpClient instanceof ClientInterface)) {
0 ignored issues
show
introduced by
$this->httpClient is always a sub-type of GuzzleHttp\ClientInterface.
Loading history...
94 2
            if (property_exists($this, 'app') && $this->app['http_client']) {
95 1
                $this->httpClient = $this->app['http_client'];
96
            } else {
97 1
                $this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]);
98
            }
99
        }
100
101 4
        return $this->httpClient;
102
    }
103
104
    /**
105
     * Add a middleware.
106
     *
107
     * @param callable    $middleware
108
     * @param string|null $name
109
     *
110
     * @return $this
111
     */
112 6
    public function pushMiddleware(callable $middleware, string $name = null)
113
    {
114 6
        if (!is_null($name)) {
115 6
            $this->middlewares[$name] = $middleware;
116
        } else {
117 1
            array_push($this->middlewares, $middleware);
118
        }
119
120 6
        return $this;
121
    }
122
123
    /**
124
     * Return all middlewares.
125
     *
126
     * @return array
127
     */
128 1
    public function getMiddlewares(): array
129
    {
130 1
        return $this->middlewares;
131
    }
132
133
    /**
134
     * Make a request.
135
     *
136
     * @param string $url
137
     * @param string $method
138
     * @param array  $options
139
     *
140
     * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string
141
     */
142 2
    public function request($url, $method = 'GET', $options = []): ResponseInterface
143
    {
144 2
        $method = strtoupper($method);
145
146 2
        $options = array_merge(self::$defaults, $options, ['handler' => $this->getHandlerStack()]);
147
148 2
        $options = $this->fixJsonIssue($options);
149
150 2
        if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) {
151 2
            $options['base_uri'] = $this->baseUri;
152
        }
153
154 2
        $response = $this->getHttpClient()->request($method, $url, $options);
155 2
        $response->getBody()->rewind();
156
157 2
        return $response;
158
    }
159
160
    /**
161
     * @param \GuzzleHttp\HandlerStack $handlerStack
162
     *
163
     * @return $this
164
     */
165 1
    public function setHandlerStack(HandlerStack $handlerStack)
166
    {
167 1
        $this->handlerStack = $handlerStack;
168
169 1
        return $this;
170
    }
171
172
    /**
173
     * Build a handler stack.
174
     *
175
     * @return \GuzzleHttp\HandlerStack
176
     */
177 1
    public function getHandlerStack(): HandlerStack
178
    {
179 1
        if ($this->handlerStack) {
180 1
            return $this->handlerStack;
181
        }
182
183 1
        $this->handlerStack = HandlerStack::create($this->getGuzzleHandler());
184
185 1
        foreach ($this->middlewares as $name => $middleware) {
186 1
            $this->handlerStack->push($middleware, $name);
187
        }
188
189 1
        return $this->handlerStack;
190
    }
191
192
    /**
193
     * @param array $options
194
     *
195
     * @return array
196
     */
197 2
    protected function fixJsonIssue(array $options): array
198
    {
199 2
        if (isset($options['json']) && is_array($options['json'])) {
200 1
            $options['headers'] = array_merge($options['headers'] ?? [], ['Content-Type' => 'application/json']);
201
202 1
            if (empty($options['json'])) {
203 1
                $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_FORCE_OBJECT);
204
            } else {
205 1
                $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_UNESCAPED_UNICODE);
206
            }
207
208 1
            unset($options['json']);
209
        }
210
211 2
        return $options;
212
    }
213
214
    /**
215
     * Get guzzle handler.
216
     *
217
     * @return callable
218
     */
219 2
    protected function getGuzzleHandler()
220
    {
221 2
        if ($handler = $this->app->guzzle_handler ?? null) {
222
            return is_string($handler) ? new $handler() : $handler;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_string($handle...w $handler() : $handler also could return the type object which is incompatible with the documented return type callable.
Loading history...
223
        }
224
225 2
        return \GuzzleHttp\choose_handler();
226
    }
227
}
228