Test Failed
Pull Request — master (#46)
by Yuji
04:29
created

Client::setRequestParams()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
namespace Shippinno\YahooShoppingJp;
3
use GuzzleHttp\Client as HttpClient;
4
use GuzzleHttp\Exception\ConnectException as GuzzleConnectException;
5
use GuzzleHttp\Exception\RequestException as GuzzleRequestException;
6
use GuzzleHttp\Exception\ServerException as GuzzleServerException;
7
use GuzzleHttp\Exception\ClientException as GuzzleClientException;
8
use GuzzleHttp\RequestOptions;
9
use Psr\Http\Message\ResponseInterface;
10
use Shippinno\YahooShoppingJp\Api\AbstractApi;
11
use Shippinno\YahooShoppingJp\Exception\ClientException;
12
use Shippinno\YahooShoppingJp\Exception\ConnectException;
13
use Shippinno\YahooShoppingJp\Exception\RequestException;
14
use Shippinno\YahooShoppingJp\Exception\ExpiredAccessTokenException;
15
use Shippinno\YahooShoppingJp\Exception\ServerException;
16
use Shippinno\YahooShoppingJp\Request\AbstractRequest;
17
use SoapBox\Formatter\Formatter;
18
class Client
19
{
20
    /**
21
     * @var string
22
     */
23
    private $baseUrl = 'https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/';
24
    /**
25
     * @var HttpClient
26
     */
27
    private $httpClient;
28
    /**
29
     * @var AbstractApi
30
     */
31
    private $api;
32
    /**
33
     * @var string
34
     */
35
    private $accessToken;
36
    /**
37
     * @var string
38
     */
39
    private $cert;
40
    /**
41
     * @var resource
42
     */
43
    private $certTempFileHandler;
44
    /**
45
     * @var resource
46
     */
47
    private $sslKey;
48
    /**
49
     * @var resource
50
     */
51
    private $sslKeyTempFileHandler;
52
    /**
53
     * @param string $accessToken
54
     * @param string|null $cert
55
     * @param string|null $sslKey
56
     * @param bool $enableTestMode
57
     * @param HttpClient|null $httpClient
58
     */
59
    public function __construct(
60
        string $accessToken,
61
        string $cert = null,
62
        string $sslKey = null,
63
        bool $enableTestMode = false,
64
        HttpClient $httpClient = null
65
    ) {
66
        if ($enableTestMode) {
67
            $this->baseUrl = 'https://test.circus.shopping.yahooapis.jp/ShoppingWebService/V1/';
68
        }
69
        if (null === $httpClient) {
70
            $httpClient = new HttpClient([
71
                'base_uri' => $this->baseUrl,
72
            ]);
73
        }
74
        $this->accessToken = $accessToken;
75
        $this->cert = $cert;
76
        $this->sslKey = $sslKey;
0 ignored issues
show
Documentation Bug introduced by
It seems like $sslKey can also be of type string. However, the property $sslKey is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
77
        $this->httpClient = $httpClient;
78
    }
79
    /**
80
     * @param AbstractRequest $request
81
     * @return array
82
     * @throws ClientException
83
     * @throws ConnectException
84
     * @throws ExpiredAccessTokenException
85
     * @throws RequestException
86
     * @throws ServerException
87
     */
88
    public function execute(AbstractRequest $request): array
89
    {
90
        $this->setApi($request->api());
91
        $options = $this->setAuthorizationHeader($this->setRequestParams($request));
92
        $options = $this->setCertAndSslKey($options);
93
        try {
94
            $rawResponse = $this->request($options);
95
        } catch (GuzzleClientException $e) {
96
            $wwwAuthenticateHeaders = $e->getResponse()->getHeader('WWW-Authenticate');
97
            if ([] !== $wwwAuthenticateHeaders) {
98
                if (false !== strpos($wwwAuthenticateHeaders[0], 'error_description="expired token"')) {
99
                    throw new ExpiredAccessTokenException;
100
                }
101
            }
102
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
103
        } catch (GuzzleServerException $e) {
104
            throw new ServerException($e->getMessage(), $e->getCode(), $e);
105
        } catch (GuzzleConnectException $e) {
106
            throw new ConnectException($e->getMessage(), $e->getCode(), $e);
107
        } catch (GuzzleRequestException $e) {
108
            throw new RequestException($e->getMessage(), $e->getCode(), $e);
109
        }
110
        return $this->api->distillResponse($this->decodeResponse($rawResponse));
111
    }
112
    /**
113
     * @param AbstractApi $api
114
     */
115
    private function setApi(AbstractApi $api)
116
    {
117
        $this->api = $api;
118
    }
119
    /**
120
     * @param array $options
121
     * @return array
122
     */
123
    private function setCertAndSslKey(array $options): array
124
    {
125
        if (null !== $this->cert && null !== $this->sslKey) {
126
            $certTempFileHandler = tmpfile();
127
            fwrite($certTempFileHandler, $this->cert);
128
            $this->certTempFileHandler = $certTempFileHandler;
129
            $sslKeyTempFileHandler = tmpfile();
130
            fwrite($sslKeyTempFileHandler, $this->sslKey);
131
            $this->sslKeyTempFileHandler = $sslKeyTempFileHandler;
132
            $options[RequestOptions::CERT] = stream_get_meta_data($this->certTempFileHandler)['uri'];
133
            $options[RequestOptions::SSL_KEY] = stream_get_meta_data($this->sslKeyTempFileHandler)['uri'];
134
        }
135
        return $options;
136
    }
137
    /**
138
     * @param array $options
139
     * @return array
140
     */
141
    private function setAuthorizationHeader(array $options): array
142
    {
143
        $options['headers'] = [
144
            'Authorization' => 'Bearer ' . $this->accessToken,
145
        ];
146
        return $options;
147
    }
148
    /**
149
     * @param AbstractRequest $request
150
     * @return array
151
     */
152
    private function setRequestParams(AbstractRequest $request): array
153
    {
154
        $options = [];
155
        if ($this->api->httpMethod()->equals(HttpMethod::GET())) {
156
            $options = $this->setRequestParamsForGetRequest($options, $request);
157
        } else {
158
            if ($this->api->httpMethod()->equals(HttpMethod::POST())) {
159
                $options = $this->setRequestParamsForPostRequest($options, $request);
160
            }
161
        }
162
        return $options;
163
    }
164
    /**
165
     * @param array $options
166
     * @param AbstractRequest $request
167
     * @return array
168
     */
169
    private function setRequestParamsForGetRequest(array $options, AbstractRequest $request): array
170
    {
171
        $options['query'] = $request->getParams();
172
        return $options;
173
    }
174
    /**
175
     * @param array $options
176
     * @param AbstractRequest $request
177
     * @return array
178
     */
179
    private function setRequestParamsForPostRequest(array $options, AbstractRequest $request): array
180
    {
181
        if ($this->api->expectsFormFields()) {
182
            $options['form_params'] = $request->getParams();
183
        } else {
184
            $options['body'] = $request->getParams();
185
        }
186
        return $options;
187
    }
188
    /**
189
     * @param $options
190
     * @return mixed|ResponseInterface
191
     */
192
    private function request($options)
193
    {
194
        return $this->httpClient->request(
195
            $this->api->httpMethod()->getValue(),
196
            $this->api->path(),
197
            $options
198
        );
199
    }
200
    /**
201
     * @param ResponseInterface $rawResponse
202
     * @return array
203
     */
204
    private function decodeResponse(ResponseInterface $rawResponse): array
205
    {
206
        $formatter = Formatter::make($rawResponse->getBody()->getContents(), Formatter::XML);
207
        return $formatter->toArray();
208
    }
209
}