Completed
Push — master ( a39575...82bd32 )
by ARCANEDEV
21:20 queued 06:33
created

StripeResource::checkIsCollectionObject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.864

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
ccs 2
cts 5
cp 0.4
crap 2.864
rs 9.4285
c 0
b 0
f 0
1
<?php namespace Arcanedev\Stripe;
2
3
use Arcanedev\Stripe\Contracts\StripeResource as StripeResourceContract;
4
use Arcanedev\Stripe\Http\RequestOptions;
5
use Arcanedev\Stripe\Http\Requestor;
6
use Arcanedev\Stripe\Utilities\Util;
7
use ReflectionClass;
8
9
/**
10
 * Class     StripeResource
11
 *
12
 * @package  Arcanedev\Stripe
13
 * @author   ARCANEDEV <[email protected]>
14
 */
15
abstract class StripeResource extends StripeObject implements StripeResourceContract
16
{
17
    /* -----------------------------------------------------------------
18
     |  Properties
19
     | -----------------------------------------------------------------
20
     */
21
22
    /** @var array */
23
    private static $persistedHeaders = [
24
        'Stripe-Account' => true,
25
        'Stripe-Version' => true,
26
    ];
27
28
    /* -----------------------------------------------------------------
29
     |  Main Methods
30
     | -----------------------------------------------------------------
31
     */
32
33
    /**
34
     * Get the base url.
35
     *
36
     * @return string
37
     */
38 543
    public static function baseUrl()
39 6
    {
40 543
        return Stripe::getApiBaseUrl();
41
    }
42
43
    /**
44
     * Get the refreshed resource.
45
     *
46
     * @return self
47
     */
48 267
    public function refresh()
49 2
    {
50 267
        list($response, $this->opts->apiKey) = Requestor::make($this->opts->apiKey, self::baseUrl())
51 267
            ->get($this->instanceUrl(), $this->retrieveParameters, $this->opts->headers);
52
53
        /** @var \Arcanedev\Stripe\Http\Response $response */
54 228
        $this->setLastResponse($response);
55 228
        $this->refreshFrom($response->getJson(), $this->opts);
56
57 233
        return $this;
58
    }
59
60
    /**
61
     * Get The name of the class, with namespacing and underscores stripped.
62
     *
63
     * @param  string  $class
64
     *
65
     * @return string
66
     */
67 516
    public static function className($class = '')
68
    {
69 516
        $name = self::getShortNameClass($class);
70 516
        $name = str_split_camelcase($name, '_');
71
72 516
        return strtolower(urlencode($name));
73
    }
74
75
    /**
76
     * Get Class short name.
77
     *
78
     * @param  string  $class
79
     *
80
     * @return string
81
     */
82 516
    protected static function getShortNameClass($class = '')
83
    {
84 516
        if (empty($class))
85 508
            $class = get_called_class();
86
87 516
        return (new ReflectionClass($class))->getShortName();
88
    }
89
90
    /**
91
     * Get the endpoint URL for the given class.
92
     *
93
     * @param  string  $class
94
     *
95
     * @return string
96
     */
97 507
    public static function classUrl($class = '')
98
    {
99 507
        $base = self::className($class);
100
101 507
        return "/v1/${base}s";
102
    }
103
104
    /**
105
     * Get Instance URL.
106
     *
107
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
108
     *
109
     * @return string
110
     */
111
    public function instanceUrl()
112
    {
113 345
        return static::resourceUrl($this['id']);
114
    }
115
116
    /**
117
     * Get the instance endpoint URL for the given class.
118
     *
119
     * @param  string  $id
120
     *
121
     * @return string
122
     *
123
     * @throws Exceptions\InvalidRequestException
124
     */
125
    public static function resourceUrl($id)
126
    {
127 363
        if ($id === null) {
128 9
            $class = get_called_class();
129 9
            throw new Exceptions\InvalidRequestException(
130 9
                "Could not determine which URL to request: $class instance has invalid ID: $id", null
131 3
            );
132
        }
133
134 354
        return static::classUrl().'/'.urlencode(str_utf8($id));
135
    }
136
137
    /* ------------------------------------------------------------------------------------------------
138
     |  Request Functions
139
     | ------------------------------------------------------------------------------------------------
140
     */
141
    /**
142
     * Make a request.
143
     *
144
     * @param  string             $method
145
     * @param  string             $url
146
     * @param  array|null         $params
147
     * @param  array|string|null  $options
148
     *
149
     * @return array
150
     */
151
    protected function request($method, $url, $params = [], $options = null)
152
    {
153 222
        $opts = $this->opts->merge($options);
154
155
        /** @var \Arcanedev\Stripe\Http\Response $response */
156 222
        list($response, $options) = static::staticRequest($method, $url, $params, $opts);
157 222
        $this->setLastResponse($response);
158
159 222
        return [$response->getJson(), $options];
160
    }
161
162
    /**
163
     * Make a request (static).
164
     *
165
     * @param  string             $method
166
     * @param  string             $url
167
     * @param  array|null         $params
168
     * @param  array|string|null  $options
169
     *
170
     * @return array
171
     */
172
    protected static function staticRequest($method, $url, $params, $options)
173
    {
174 513
        $opts      = RequestOptions::parse($options);
175 513
        $requestor = Requestor::make($opts->apiKey, static::baseUrl());
176
177 501
        list($response, $opts->apiKey) =
178 513
            $requestor->request($method, $url, $params, $opts->headers);
179
180 501
        foreach ($opts->headers as $k => $v) {
181 39
            if ( ! array_key_exists($k, self::$persistedHeaders))
182 27
                unset($opts->headers[$k]);
183 167
        }
184
185 501
        return [$response, $opts];
186
    }
187
188
    /* -----------------------------------------------------------------
189
     |  CRUD Scope Methods
190
     | -----------------------------------------------------------------
191
     */
192
193
    /**
194
     * Retrieve scope.
195
     *
196
     * @param  string             $id
197
     * @param  array|string|null  $options
198
     *
199
     * @return self
200
     */
201
    protected static function scopedRetrieve($id, $options = null)
202
    {
203 261
        $class = get_called_class();
204
205
        /** @var self $resource */
206 261
        $resource = new $class($id, RequestOptions::parse($options));
207 261
        $resource->refresh();
208
209 222
        return $resource;
210
    }
211
212
    /**
213
     * List scope.
214
     *
215
     * @param  array|null         $params
216
     * @param  array|string|null  $options
217
     *
218
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
219
     *
220
     * @return \Arcanedev\Stripe\Collection|array
221
     */
222
    protected static function scopedAll($params = [], $options = null)
223
    {
224 91
        self::checkArguments($params, $options);
225
226 84
        $url = static::classUrl();
227
228
        /** @var \Arcanedev\Stripe\Http\Response $response */
229 84
        list($response, $opts) = self::staticRequest('get', $url, $params, $options);
230
231 84
        $object = Util::convertToStripeObject($response->getJson(), $opts);
232
233 84
        self::checkIsCollectionObject($object);
234
235 84
        $object->setLastResponse($response);
236 84
        $object->setRequestParams($params);
237
238 84
        return $object;
239
    }
240
241
    /**
242
     * Create scope.
243
     *
244
     * @param  array|null         $params
245
     * @param  array|string|null  $options
246
     *
247
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
248
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
249
     *
250
     * @return self
251
     */
252
    protected static function scopedCreate($params = [], $options = null)
253
    {
254 432
        self::checkArguments($params, $options);
255
256
        /** @var \Arcanedev\Stripe\Http\Response $response */
257 432
        list($response, $opts) = static::staticRequest('post', static::classUrl(), $params, $options);
258
259 420
        $object = Util::convertToStripeObject($response->getJson(), $opts);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Arcanedev\Stripe\Utilit...nse->getJson(), $opts); of type array|Arcanedev\Stripe\StripeObject adds the type array to the return on line 262 which is incompatible with the return type documented by Arcanedev\Stripe\StripeResource::scopedCreate of type Arcanedev\Stripe\StripeResource.
Loading history...
260 420
        $object->setLastResponse($response);
261
262 420
        return $object;
263
    }
264
265
    /**
266
     * Update scope.
267
     *
268
     * @param  string             $id
269
     * @param  array|null         $params
270
     * @param  array|string|null  $options
271
     *
272
     * @return self
273
     *
274
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
275
     */
276
    protected static function scopedUpdate($id, $params = null, $options = null)
277
    {
278 48
        self::checkArguments($params, $options);
279
280
        /** @var \Arcanedev\Stripe\Http\Response $response */
281 48
        list($response, $opts) = static::staticRequest('post', static::resourceUrl($id), $params, $options);
282
283 48
        $object = Util::convertToStripeObject($response->getJson(), $opts);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Arcanedev\Stripe\Utilit...nse->getJson(), $opts); of type array|Arcanedev\Stripe\StripeObject adds the type array to the return on line 286 which is incompatible with the return type documented by Arcanedev\Stripe\StripeResource::scopedUpdate of type Arcanedev\Stripe\StripeResource.
Loading history...
Bug introduced by
It seems like $response->getJson() targeting Arcanedev\Stripe\Http\Response::getJson() can also be of type null; however, Arcanedev\Stripe\Utiliti...convertToStripeObject() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
284 48
        $object->setLastResponse($response);
285
286 48
        return $object;
287
    }
288
289
    /**
290
     * Save scope.
291
     *
292
     * @param  array|string|null  $options
293
     *
294
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
295
     *
296
     * @return self
297
     */
298
    protected function scopedSave($options = null)
299
    {
300 129
        if (count($params = $this->serializeParameters()) > 0) {
301 108
            self::checkArguments(null, $options);
302 108
            list($response, $opts) = $this->request('post', $this->instanceUrl(), $params, $options);
303 108
            $this->refreshFrom($response, $opts);
304 36
        }
305
306 129
        return $this;
307
    }
308
309
    /**
310
     * Delete Scope.
311
     *
312
     * @param  array|null         $params
313
     * @param  array|string|null  $options
314
     *
315
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
316
     *
317
     * @return self
318
     */
319
    protected function scopedDelete($params = [], $options = null)
320
    {
321 48
        self::checkArguments($params, $options);
322
323 48
        list($response, $opts) = $this->request('delete', $this->instanceUrl(), $params, $options);
324 48
        $this->refreshFrom($response, $opts);
325
326 48
        return $this;
327
    }
328
329
    /* -----------------------------------------------------------------
330
     |  Custom Scope Methods
331
     | -----------------------------------------------------------------
332
     */
333
334
    /**
335
     * Custom Post Call.
336
     *
337
     * @param  string             $url
338
     * @param  array|null         $params
339
     * @param  array|string|null  $options
340
     *
341
     * @return self
342
     */
343
    protected function scopedPostCall($url, $params = [], $options = null)
344
    {
345
        /** @var \Arcanedev\Stripe\Http\Response $response */
346 27
        list($response, $options) = Requestor::make(RequestOptions::parse($options)->getApiKey(), static::baseUrl())
347 27
            ->post($url, $params);
348
349 27
        $this->refreshFrom($response->getJson(), $options);
350 27
        $this->setLastResponse($response);
351
352 27
        return $this;
353
    }
354
355
    /* -----------------------------------------------------------------
356
     |  Check Methods
357
     | -----------------------------------------------------------------
358
     */
359
360
    /**
361
     * Check Arguments.
362
     *
363
     * @param  array|null         $params
364
     * @param  array|string|null  $options
365
     */
366
    protected static function checkArguments($params = [], $options = null)
367
    {
368 510
        self::checkParameters($params);
369 507
        self::checkOptions($options);
370 504
    }
371
372
    /**
373
     * Check parameters.
374
     *
375
     * @param  array|null  $params
376
     *
377
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
378
     */
379
    private static function checkParameters($params)
380
    {
381 510
        if ($params && ! is_array($params)) {
382 3
            throw new Exceptions\InvalidArgumentException(
383
                'You must pass an array as the first argument to Stripe API method calls.  '.
384 1
                '(HINT: an example call to create a charge would be: '.
385 2
                "StripeCharge::create(['amount' => 100, 'currency' => 'usd', 'source' => 'tok_1234']))"
386 1
            );
387
        }
388 507
    }
389
390
    /**
391
     * Check Options.
392
     *
393
     * @param  array|string|null  $options
394
     *
395
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
396
     */
397
    private static function checkOptions($options)
398
    {
399 507
        if ($options && (
400 54
                ! $options instanceof RequestOptions &&
401 50
                ! is_string($options) &&
402 197
                ! is_array($options)
403 14
            )
404 169
        ) {
405 3
            throw new Exceptions\ApiException(
406
                'The second argument to Stripe API method calls is an '
407
                . 'optional per-request apiKey, which must be a string.  '
408 3
                . '(HINT: you can set a global apiKey by "Stripe::setApiKey(<apiKey>)")',
409 99
                500
410 1
            );
411
        }
412 504
    }
413
414
    /**
415
     * Check the object is a Collection class.
416
     *
417
     * @param  mixed  $object
418
     *
419
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
420
     */
421
    private static function checkIsCollectionObject($object)
422
    {
423 84
        if ( ! is_a($object, Collection::class)) {
424
            throw new Exceptions\ApiException(
425
                'Expected type "Arcanedev\Stripe\Collection", got "'.get_class($object).'" instead'
426
            );
427
        }
428 84
    }
429
}
430