Completed
Push — master ( c454a5...691e75 )
by Christian
06:48
created

HttplugClient::get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
3
/*
4
 * This file is part of the XabbuhPandaClient package.
5
 *
6
 * (c) Christian Flothmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Xabbuh\PandaClient\Api;
13
14
use Http\Discovery\HttpClientDiscovery;
15
use Http\Discovery\MessageFactoryDiscovery;
16
use Http\Discovery\StreamFactoryDiscovery;
17
use Http\Message\RequestFactory;
18
use Http\Message\StreamFactory;
19
use Xabbuh\PandaClient\Exception\ApiException;
20
use Xabbuh\PandaClient\Exception\HttpException;
21
use Xabbuh\PandaClient\Signer\PandaSigner;
22
23
/**
24
 * Panda REST client implementation using the Httplug library.
25
 *
26
 * Sends signed requests (GET, POST, PUT or DELETE) to the Panda encoding
27
 * webservice.
28
 *
29
 * @author Christian Flothmann <[email protected]>
30
 * @author Christophe Coevoet <[email protected]>
31
 */
32
class HttplugClient implements HttpClientInterface
33
{
34
    /**
35
     * @var \Http\Client\HttpClient
36
     */
37
    private $httpClient;
38
39
    /**
40
     * @var RequestFactory
41
     */
42
    private $requestFactory;
43
44
    /**
45
     * @var StreamFactory
46
     */
47
    private $streamFactory;
48
49
    /**
50
     * Panda cloud id
51
     *
52
     * @var string
53
     */
54
    private $cloudId;
55
56
    /**
57
     * Panda Account
58
     *
59
     * @var Account
60
     */
61
    private $account;
62
63
    /**
64
     * HttplugClient constructor.
65
     *
66
     * @param \Http\Client\HttpClient|null $httpClient
67
     * @param RequestFactory|null          $requestFactory
68
     * @param StreamFactory|null           $streamFactory
69
     */
70
    public function __construct(\Http\Client\HttpClient $httpClient = null, RequestFactory $requestFactory = null, StreamFactory $streamFactory = null)
71
    {
72
        $this->httpClient = $httpClient ?: HttpClientDiscovery::find();
73
        $this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find();
74
        $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    public function setCloudId($cloudId)
81
    {
82
        $this->cloudId = $cloudId;
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     */
88
    public function getCloudId()
89
    {
90
        return $this->cloudId;
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96
    public function setAccount(Account $account)
97
    {
98
        $this->account = $account;
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104
    public function getAccount()
105
    {
106
        return $this->account;
107
    }
108
109
    /**
110
     * {@inheritDoc}
111
     */
112
    public function get($path, array $params = array())
113
    {
114
        return $this->request('GET', $path, $params);
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     */
120
    public function post($path, array $params = array())
121
    {
122
        return $this->request('POST', $path, $params);
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function put($path, array $params = array())
129
    {
130
        return $this->request('PUT', $path, $params);
131
    }
132
133
    /**
134
     * {@inheritDoc}
135
     */
136
    public function delete($path, array $params = array())
137
    {
138
        return $this->request('DELETE', $path, $params);
139
    }
140
141
    /**
142
     * Send signed HTTP requests to the API server.
143
     *
144
     * @param string $method HTTP method (GET, POST, PUT or DELETE)
145
     * @param string $path   Request path
146
     * @param array  $params Additional request parameters
147
     *
148
     * @return string The API server's response
149
     *
150
     * @throws ApiException  if an API error occurs
151
     * @throws HttpException if the request fails
152
     */
153
    private function request($method, $path, array $params)
154
    {
155
        // sign the request parameters
156
        $signer = PandaSigner::getInstance($this->cloudId, $this->account);
157
        $params = $signer->signParams($method, $path, $params);
158
159
        // ensure to use relative paths
160
        if (0 === strpos($path, '/')) {
161
            $path = substr($path, 1);
162
        }
163
164
        // append request parameters to the URL
165
        if ('GET' === $method || 'DELETE' === $method) {
166
            $path .= '?'.http_build_query($params, '', '&');
167
        }
168
169
        $body = null;
170
        $headers = array();
171
172
        if ('PUT' === $method || 'POST' === $method) {
173
            $body = $this->streamFactory->createStream(http_build_query($params, '', '&'));
174
            $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
175
        }
176
177
        // prepare the request
178
        $uri = 'https://'.$this->account->getApiHost().'/v2/'.$path;
179
        $request = $this->requestFactory->createRequest($method, $uri, $headers, $body);
180
181
        // and execute it
182
        try {
183
            $response = $this->httpClient->sendRequest($request);
184
        } catch (\Exception $e) {
185
            // throw an exception if the http request failed
186
            throw new HttpException($e->getMessage(), $e->getCode());
187
        }
188
189
        $responseBody = (string) $response->getBody();
190
191
        // throw an API exception if the API response is not valid
192
        if ($response->getStatusCode() < 200 || $response->getStatusCode() > 207) {
193
            $decodedResponse = json_decode($responseBody);
194
            $message = $decodedResponse->error.': '.$decodedResponse->message;
195
196
            throw new ApiException($message, $response->getStatusCode());
197
        }
198
199
        return $responseBody;
200
    }
201
}
202