GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( f2d00c...a143fe )
by
unknown
02:03
created

LeverPhp::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace ViaWork\LeverPhp;
4
5
use Exception;
6
use GrahamCampbell\GuzzleFactory\GuzzleFactory;
7
use GuzzleHttp\Client as GuzzleClient;
8
use GuzzleHttp\Exception\ClientException;
9
use GuzzleHttp\HandlerStack;
10
use Illuminate\Support\LazyCollection;
11
use Psr\Http\Message\ResponseInterface;
12
use Spatie\GuzzleRateLimiterMiddleware\RateLimiterMiddleware;
13
use Spatie\GuzzleRateLimiterMiddleware\Store;
14
15
class LeverPhp
16
{
17
    const BACKOFF_TIME = 1500;
18
19
    private $leverKey = '';
20
21
    private $endpoint = '';
22
23
    private $client;
24
25
    private $options = [];
26
27
    /**
28
     * LeverPhp constructor.
29
     * @param string|null $leverKey
30
     * @param GuzzleClient|null $client
31
     * @param Store|null $store
32
     */
33
    public function __construct(string $leverKey = null, GuzzleClient $client = null, Store $store = null)
34
    {
35
        $this->leverKey = $leverKey;
36
37
        $stack = HandlerStack::create();
38
39
        $stack->push(DuplicateAggregatorMiddleware::buildQuery());
40
41
        $stack->push(RateLimiterMiddleware::perSecond(10, $store));
42
43
        $this->client = $client ?? GuzzleFactory::make(
44
                [
45
                    'base_uri' => 'https://api.lever.co/v1/',
46
                    'headers' => [
47
                        'Accept' => 'application/json',
48
                    ],
49
                    'auth' => [$leverKey, ''],
50
                    'handler' => $stack,
51
                ],
52
                self::BACKOFF_TIME
53
            );
54
    }
55
56
    private function reset()
57
    {
58
        $this->endpoint = '';
59
        $this->options = [];
60
    }
61
62
    private function post(array $body): ResponseInterface
63
    {
64
        try {
65
            $response = $this->client->post($this->endpoint, $this->options($body));
66
        } catch (ClientException $exception) {
67
            throw $exception;
68
        } finally {
69
            $this->reset();
70
        }
71
72
        return $response;
73
    }
74
75
    private function options($body)
76
    {
77
        if (isset($this->options['hasFiles'])) {
78
            $options = [];
79
80
            foreach ($body as $key => $item) {
81
82
                // TODO add support for files[] and automate filename and headers fields.
83
                if (in_array($key, ['file', 'files', 'resumeFile'])) {
84
                    $options[] = [
85
                        'name' => $key,
86
                        'contents' => $item['file'],
87
                        'filename' =>  $item['name'],
88
                        'headers' => ['Content-Type' => $item['type']],
89
                    ];
90
91
                    continue;
92
                }
93
94
                if (is_array($item)) {
95
                    foreach ($item as $subKey => $subItem) {
96
                        if (is_numeric($subKey)) {
97
                            $options[] = ['name' => $key.'[]', 'contents' => $subItem];
98
                        }
99
100
                        if (is_string($subKey)) {
101
                            $options[] = ['name' => "{$key}[{$subKey}]", 'contents' => $subItem];
102
                        }
103
                    }
104
                }
105
106
                if (is_string($item)) {
107
                    $options[] = ['name' => $key, 'contents' => $item];
108
                }
109
            }
110
111
            unset($this->options['hasFiles']);
112
113
            return array_merge(['multipart' => $options], $this->options);
114
        }
115
116
        return array_merge(['json' => $body], $this->options);
117
    }
118
119
    private function get(): ResponseInterface
120
    {
121
        try {
122
            $response = $this->client->get($this->endpoint, $this->options);
123
        } catch (ClientException $exception) {
124
            throw $exception;
125
        } finally {
126
            $this->reset();
127
        }
128
129
        return $response;
130
    }
131
132
    public function create(array $body, string $method = 'post'): array
133
    {
134
        $response = $this->responseToArray($this->{$method}($body));
135
136
        return $response['data'];
137
    }
138
139
    public function update(array $body): array
140
    {
141
        return $this->create($body);
142
    }
143
144
    public function putUpdate(array $body): array
145
    {
146
        return $this->create($body, 'put');
147
    }
148
149
    /** @return LazyCollection|array */
150
    public function fetch()
151
    {
152
        $response = $this->responseToArray($this->get());
153
154
        if (! array_key_exists('hasNext', $response)) {
155
            return $response['data'];
156
        }
157
158
        return LazyCollection::make(function () use ($response) {
159
            do {
160
                foreach ($response['data'] as $item) {
161
                    yield $item;
162
                }
163
164
                $response['data'] = [];
165
166
                if (! empty($response['next'])) {
167
                    $response = $this->responseToArray(
168
                        $this->addParameter('offset', $response['next'])->get()
169
                    );
170
                }
171
            } while (count($response['data']) > 0);
172
        });
173
    }
174
175
    public function leverKey(): string
176
    {
177
        return $this->leverKey;
178
    }
179
180
    public function client(): GuzzleClient
181
    {
182
        return $this->client;
183
    }
184
185
    private function responseToArray(ResponseInterface $response): array
186
    {
187
        return json_decode($response->getBody()->getContents(), true);
188
    }
189
190
    public function expand($expandable)
191
    {
192
        return $this->addParameter('expand', $expandable);
193
    }
194
195
    public function performAs(string $userId)
196
    {
197
        return $this->addParameter('perform_as', $userId);
198
    }
199
200
    public function include($includable)
201
    {
202
        return $this->addParameter('include', $includable);
203
    }
204
205
    /**
206
     * @param string $field
207
     * @param string|array $value
208
     * @return $this
209
     */
210
    public function addParameter(string $field, $value)
211
    {
212
        if (! empty($field) && ! empty($value)) {
213
            $value = is_string($value) ? [$value] : $value;
214
215
            $this->options['query'][$field] = array_merge($this->options['query'][$field] ?? [], $value);
216
        }
217
218
        return $this;
219
    }
220
221
    public function opportunities(string $opportunityId = '')
222
    {
223
        $this->endpoint = 'opportunities'.(empty($opportunityId) ? '' : '/'.$opportunityId);
224
225
        return $this;
226
    }
227
228
    public function resumes(string $resumeId = '')
229
    {
230
        $this->endpoint .= '/resumes'.(empty($resumeId) ? '' : '/'.$resumeId);
231
232
        return $this;
233
    }
234
235
    public function download()
236
    {
237
        $this->endpoint .= '/download';
238
239
        return $this;
240
    }
241
242
    public function offers()
243
    {
244
        // TODO next release.
245
        // $regex = '/^opportunities\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/';
246
        // if (preg_match($regex, $this->endpoint) === 0){
247
        //     throw new Exception('Did not chain methods in correct order.');
248
        // }
249
250
        $this->endpoint .= '/offers';
251
252
        return $this;
253
    }
254
255
    public function stages()
256
    {
257
        // TODO next release.
258
        // $regex = '/^opportunities\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/';
259
        // if (preg_match($regex, $this->endpoint) === 0){
260
        //     throw new Exception('Did not chain methods in correct order.');
261
        // }
262
263
        $this->endpoint .= '/stage';
264
265
        return $this;
266
    }
267
268
    public function postings(string $postingId = '')
269
    {
270
        $this->endpoint = 'postings'.(empty($postingId) ? '' : '/'.$postingId);
271
272
        return $this;
273
    }
274
275
    public function sendConfirmationEmail()
276
    {
277
        return $this->addParameter('send_confirmation_email', 'true');
278
    }
279
280
    public function apply(array $body): array
281
    {
282
        $this->endpoint .= '/apply';
283
284
        return $this->create($body);
285
    }
286
287
    public function state(string $state)
288
    {
289
        if (! in_array($state, ['published', 'internal', 'closed', 'draft', 'pending', 'rejected'])) {
290
            throw new Exception('Not a valid state');
291
        }
292
293
        return $this->addParameter('state', $state);
294
    }
295
296
    /**
297
     * @param array|string $team
298
     * @return $this
299
     */
300
    public function team($team)
301
    {
302
        return $this->addParameter('team', $team);
303
    }
304
305
    /**
306
     * @param array|string $department
307
     * @return $this
308
     */
309
    public function department($department)
310
    {
311
        return $this->addParameter('department', $department);
312
    }
313
314
    /**
315
     * @return $this
316
     */
317
    public function parse()
318
    {
319
        return $this->addParameter('parse', 'true');
320
    }
321
322
    public function hasFiles()
323
    {
324
        $this->options['hasFiles'] = true;
325
326
        return $this;
327
    }
328
329
    /**
330
     * @param array|string $email
331
     * @return $this
332
     */
333
    public function email($email)
334
    {
335
        return $this->addParameter('email', $email);
336
    }
337
338
    /**
339
     * @param array|string $stageId
340
     * @return $this
341
     */
342
    public function stage($stageId)
343
    {
344
        return $this->addParameter('stage_id', $stageId);
345
    }
346
347
    /**
348
     * @param array|string $postingId
349
     * @return $this
350
     */
351
    public function posting($postingId)
352
    {
353
        return $this->addParameter('posting_id', $postingId);
354
    }
355
}
356