Test Failed
Push — master ( db9bda...7e2f15 )
by James
05:19
created

Request::v2()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 19
rs 9.8333
c 0
b 0
f 0
cc 4
nc 3
nop 4
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: james
5
 * Date: 12/07/2018
6
 * Time: 13:35
7
 */
8
9
namespace CwsOps\LivePerson\Rest;
10
11
use CwsOps\LivePerson\Account\Config;
12
use CwsOps\LivePerson\Traits\HasLoggerTrait;
13
use GuzzleHttp\Client;
14
use GuzzleHttp\Exception\GuzzleException;
15
use GuzzleHttp\HandlerStack;
16
use GuzzleHttp\Subscriber\Oauth\Oauth1;
17
use Psr\Log\LoggerInterface;
18
19
/**
20
 *
21
 * Class Request
22
 *
23
 * @package CwsOps\LivePerson
24
 */
25
class Request
26
{
27
    use HasLoggerTrait;
28
29
    const METHOD_GET = 'GET';
30
    const METHOD_POST = 'POST';
31
32
    /**
33
     * An AccountConfig obj
34
     *
35
     * @var Config $config
36
     */
37
    private $config;
38
39
    /**
40
     * The total retry limit.
41
     *
42
     * @var int $retryLimit
43
     */
44
    private $retryLimit;
45
46
    /**
47
     * @var LoggerInterface $logger
48
     */
49
    private $logger;
50
51
    /**
52
     * The number of times tried.
53
     *
54
     * @var int retry_counter
55
     */
56
    private $retryCounter;
57
    /** @var string $bearer */
58
    private $bearer;
59
    /** @var UrlBuilder */
60
    private $urlBuilder;
61
    /** @var Client */
62
    private $client;
63
64
65
    /**
66
     * Request constructor.
67
     *
68
     * @param Config $accountConfig
69
     * @param int $retryLimit the number of times to retry on failure. Recommended is 3.
70
     * @param LoggerInterface|null $logger
71
     */
72
    public function __construct(Config $accountConfig, int $retryLimit = 3, LoggerInterface $logger = null)
73
    {
74
        $this->config = $accountConfig;
75
        $this->retryLimit = $retryLimit;
76
        $this->logger = $this->hasLogger($logger);
77
78
        // Set the retry counter to zero.
79
        $this->retryCounter = 0;
80
        $this->urlBuilder = new UrlBuilder();
81
82
        $this->requestClient();
83
    }
84
85
    /**
86
     * @codeCoverageIgnore
87
     *
88
     * Gets the domain for a specified service
89
     *
90
     * @param string $service
91
     *
92
     * @return string
93
     */
94
    public function getDomain(string $service)
95
    {
96
        $response = $this->v1("https://api.liveperson.net/api/account/{$this->config->getAccountId()}/service/{$service}/baseURI.json?version=1.0", Request::METHOD_GET);
97
98
        return $response->baseURI;
99
    }
100
101
    /**
102
     * @codeCoverageIgnore
103
     *
104
     * Creates a URLBuilder instance with the domain allready set.
105
     *
106
     * @param $service
107
     *
108
     * @return UrlBuilder|null
109
     */
110
    public function buildUrl($service)
111
    {
112
        try {
113
            return $this->urlBuilder->create(true)
114
                ->setDomain(($this->getDomain($service)));
115
        } catch (BuilderLockedException $e) {
116
            $this->logger->critical($e->getMessage());
117
        }
118
        return $this->urlBuilder;
119
    }
120
121
    /**
122
     * @codeCoverageIgnore
123
     * Performs the actual request on the livePerson api.
124
     *
125
     * @param string $url the URL to make the request to.
126
     * @param string $method The method to request the data
127
     * @param array|null $payload an array of parameters to place into the body of the request.
128
     *
129
     * @return array|\stdClass an array that contains the result or an empty array on error.
130
     */
131
    public function v1($url, $method = Request::METHOD_GET, $payload = null)
132
    {
133
134
135
        $args = [
136
            'auth' => 'oauth',
137
            'headers' => [
138
                'content-type' => 'application/json',
139
            ],
140
            'json' => $payload ?: new \stdClass()
141
        ];
142
143
144
        try {
145
146
147
            $response = $this->requestClient()->request($method, $url, $args);
148
            $responseBody = json_decode($response->getBody());
149
150
            return $responseBody;
151
152
        } catch (GuzzleException $e) {
153
            if ($this->retryCounter < $this->retryLimit || $this->retryLimit === -1) {
154
155
                $this->logger->info(sprintf('attempt $d failed trying in %d seconds', $this->retryCounter + 1, 15000));
156
157
                usleep(15000);
158
                $this->retryCounter++;
159
                $responseBody = $this->v1($url, $method, $payload);
160
161
                return $responseBody;
162
            } else {
163
                $this->logger->critical(sprintf('client error: %s', $e->getMessage()));
164
                return [];
165
            }
166
        }
167
168
    }
169
170
    private function requestClient()
171
    {
172
        $consumer_key = $this->config->getConsumerKey();
173
        $consumer_secret = $this->config->getConsumerSecret();
174
        $token = $this->config->getToken();
175
        $secret = $this->config->getTokenSecret();
176
        $stack = HandlerStack::create();
177
        $auth = new Oauth1([
178
            'consumer_key' => $consumer_key,
179
            'consumer_secret' => $consumer_secret,
180
            'token' => $token,
181
            'token_secret' => $secret,
182
            'signature_method' => Oauth1::SIGNATURE_METHOD_HMAC,
183
        ]);
184
        $stack->push($auth);
185
        $client = new Client([
186
            'handler' => $stack,
187
        ]);
188
189
190
        return $client;
191
    }
192
193
    /**
194
     * @codeCoverageIgnore
195
     *
196
     * Performs the actual request on the livePerson api.
197
     *
198
     * @param string $url the URL to make the request to.
199
     * @param string $method The method to request the data
200
     * @param array|null $payload an array of parameters to place into the body of the request.
201
     * @param array $headers
202
     *
203
     * @return \stdClass an array that contains the result or an empty array on error.
204
     */
205
    public function v2(string $url, $method, $payload = [], $headers = [])
206
    {
207
        $this->login();
208
        $args = [
209
            'headers' => array_merge([
210
                'content-type' => 'application/json',
211
                'Authorization' => 'Bearer ' . $this->bearer
212
            ], $headers ?: []),
213
            'form_params' => $payload ?: '{}'
214
        ];
215
216
217
        try {
218
            $response = $this->client->request($method, $url, $args);
219
220
            return json_decode($response->getBody());
221
        } catch (GuzzleException $e) {
222
            $this->logger->critical(sprintf('client error: %s', $e->getMessage()));
223
            return new \stdClass();
224
        }
225
    }
226
227
    /**
228
     * Gets the the Guzzle Client.
229
     *
230
     * @return Client
231
     */
232
    public function getClient()
233
    {
234
235
        return $this->client;
236
    }
237
238
    /**
239
     * Sets the Guzzle Client.
240
     *
241
     * @param Client $client
242
     */
243
    public function setClient(Client $client)
244
    {
245
        $this->client = $client;
246
    }
247
248
249
    /**
250
     * @codeCoverageIgnore
251
     * Logs into the API.
252
     */
253
    private function login()
254
    {
255
        $auth = [
256
            'username' => $this->config->getUsername(),
257
            'appKey' => $this->config->getConsumerKey(),
258
            'secret' => $this->config->getConsumerSecret(),
259
            'accessToken' => $this->config->getToken(),
260
            'accsessTokenSecret' => $this->config->getTokenSecret()
261
        ];
262
263
        $url = "https://api/account/{$this->config->getAccountId()}/login?v-1.3";
264
265
        $response = $this->v1($url, Request::METHOD_POST, $auth);
266
267
        $this->bearer = $response->bearer;
268
    }
269
}
270