Completed
Push — master ( 66a1c0...6efa89 )
by ARCANEDEV
08:32
created

StripeResource::scopedUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
cc 1
eloc 7
nc 1
nop 3
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
1
<?php namespace Arcanedev\Stripe;
2
3
use Arcanedev\Stripe\Contracts\StripeResourceInterface;
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 StripeResourceInterface
16
{
17
    /* ------------------------------------------------------------------------------------------------
18
     |  Properties
19
     | ------------------------------------------------------------------------------------------------
20
     */
21
    /** @var array */
22
    private static $persistedHeaders = [
23
        'Stripe-Account' => true,
24
        'Stripe-Version' => true
25
    ];
26
27
    /* ------------------------------------------------------------------------------------------------
28
     |  Main Functions
29
     | ------------------------------------------------------------------------------------------------
30
     */
31
    /**
32
     * Get the base url.
33
     *
34
     * @return string
35
     */
36 770
    public static function baseUrl()
37
    {
38 770
        return Stripe::getApiBaseUrl();
39
    }
40
41
    /**
42
     * Get the refreshed resource.
43
     *
44
     * @return self
45
     */
46 360
    public function refresh()
47
    {
48 360
        $url    = $this->instanceUrl();
49
50 360
        list($response, $this->opts->apiKey) = Requestor::make($this->opts->apiKey, self::baseUrl())
51 360
            ->get($url, $this->retrieveParameters);
52
53
54
        /** @var \Arcanedev\Stripe\Http\Response $response */
55 305
        $this->setLastResponse($response);
56 305
        $this->refreshFrom($response->getJson(), $this->opts);
57
58 305
        return $this;
59
    }
60
61
    /**
62
     * Get The name of the class, with namespacing and underscores stripped.
63
     *
64
     * @param  string  $class
65
     *
66
     * @return string
67
     */
68 760
    public static function className($class = '')
69
    {
70 760
        $name = self::getShortNameClass($class);
71 760
        $name = str_split_camelcase($name, '_');
72
73 760
        return strtolower(urlencode($name));
74
    }
75
76
    /**
77
     * Get Class short name.
78
     *
79
     * @param  string  $class
80
     *
81
     * @return string
82
     */
83 760
    protected static function getShortNameClass($class = '')
84
    {
85 760
        if (empty($class)) {
86 740
            $class = get_called_class();
87 592
        }
88
89 760
        $class = new ReflectionClass($class);
90
91 760
        return $class->getShortName();
92
    }
93
94
    /**
95
     * Get the endpoint URL for the given class.
96
     *
97
     * @param  string  $class
98
     *
99
     * @return string
100
     */
101 745
    public static function classUrl($class = '')
102
    {
103 745
        $base = self::className($class);
104
105 745
        return "/v1/${base}s";
106
    }
107
108
    /**
109
     * Get Instance URL.
110
     *
111
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
112
     *
113
     * @return string
114
     */
115
    public function instanceUrl()
116
    {
117 480
        return static::resourceUrl($this['id']);
118
    }
119
120
    /**
121
     * Get the instance endpoint URL for the given class.
122
     *
123
     * @param  string  $id
124
     *
125
     * @return string
126
     *
127
     * @throws Exceptions\InvalidRequestException
128
     */
129
    public static function resourceUrl($id)
130
    {
131 510
        if ($id === null) {
132 15
            $class = get_called_class();
133 15
            throw new Exceptions\InvalidRequestException(
134 15
                "Could not determine which URL to request: $class instance has invalid ID: $id", null
135 12
            );
136
        }
137
138 495
        $base     = static::classUrl();
139 495
        $endpoint = urlencode(str_utf8($id));
140
141 495
        return "$base/$endpoint";
142
    }
143
144
    /* ------------------------------------------------------------------------------------------------
145
     |  Request Functions
146
     | ------------------------------------------------------------------------------------------------
147
     */
148
    /**
149
     * Make a request.
150
     *
151
     * @param  string             $method
152
     * @param  string             $url
153
     * @param  array|null         $params
154
     * @param  array|string|null  $options
155
     *
156
     * @return array
157
     */
158
    protected function request($method, $url, $params = [], $options = null)
159
    {
160 300
        $opts = $this->opts->merge($options);
161
162
        /** @var \Arcanedev\Stripe\Http\Response $response */
163 300
        list($response, $options) = static::staticRequest($method, $url, $params, $opts);
164 300
        $this->setLastResponse($response);
165
166 300
        return [$response->getJson(), $options];
167
    }
168
169
    /**
170
     * Make a request (static).
171
     *
172
     * @param  string             $method
173
     * @param  string             $url
174
     * @param  array|null         $params
175
     * @param  array|string|null  $options
176
     *
177
     * @return array
178
     */
179
    protected static function staticRequest($method, $url, $params, $options)
180
    {
181 744
        $opts      = RequestOptions::parse($options);
182 744
        $requestor = Requestor::make($opts->apiKey, static::baseUrl());
183
184 729
        list($response, $opts->apiKey) =
185 744
            $requestor->request($method, $url, $params, $opts->headers);
186
187 729
        foreach ($opts->headers as $k => $v) {
188 5
            if ( ! array_key_exists($k, self::$persistedHeaders)) {
189 5
                unset($opts->headers[$k]);
190 4
            }
191 583
        }
192
193 729
        return [$response, $opts];
194
    }
195
196
    /* ------------------------------------------------------------------------------------------------
197
     |  CRUD Scope Functions
198
     | ------------------------------------------------------------------------------------------------
199
     */
200
    /**
201
     * Retrieve scope.
202
     *
203
     * @param  string             $id
204
     * @param  array|string|null  $options
205
     *
206
     * @return self
207
     */
208
    protected static function scopedRetrieve($id, $options = null)
209
    {
210 350
        $class    = get_called_class();
211
212
        /** @var self $resource */
213 350
        $resource = new $class($id, RequestOptions::parse($options));
214 350
        $resource->refresh();
215
216 295
        return $resource;
217
    }
218
219
    /**
220
     * List scope.
221
     *
222
     * @param  array|null        $params
223
     * @param  array|string|null $options
224
     *
225
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
226
     *
227
     * @return \Arcanedev\Stripe\Collection|array
228
     */
229
    protected static function scopedAll($params = [], $options = null)
230
    {
231 145
        self::checkArguments($params, $options);
232
233 135
        $url = static::classUrl();
234
235
        /** @var \Arcanedev\Stripe\Http\Response $response */
236 135
        list($response, $opts) = self::staticRequest('get', $url, $params, $options);
237
238 135
        $object = Util::convertToStripeObject($response->getJson(), $opts);
239
240 135
        self::checkIsCollectionObject($object);
241
242 135
        $object->setLastResponse($response);
243 135
        $object->setRequestParams($params);
244
245 135
        return $object;
246
    }
247
248
    /**
249
     * Create scope.
250
     *
251
     * @param  array|null         $params
252
     * @param  array|string|null  $options
253
     *
254
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
255
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
256
     *
257
     * @return self
258
     */
259
    protected static function scopedCreate($params = [], $options = null)
260
    {
261 644
        self::checkArguments($params, $options);
262
263 644
        $url = static::classUrl();
264
265
        /** @var \Arcanedev\Stripe\Http\Response $response */
266 644
        list($response, $opts) = self::staticRequest('post', $url, $params, $options);
267
268 629
        $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 271 which is incompatible with the return type documented by Arcanedev\Stripe\StripeResource::scopedCreate of type Arcanedev\Stripe\StripeResource.
Loading history...
269 629
        $object->setLastResponse($response);
270
271 629
        return $object;
272
    }
273
274
    /**
275
     * Update scope.
276
     *
277
     * @param  string             $id
278
     * @param  array|null         $params
279
     * @param  array|string|null  $options
280
     *
281
     * @return self
282
     *
283
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
284
     */
285
    protected static function scopedUpdate($id, $params = null, $options = null)
286
    {
287 75
        self::checkArguments($params, $options);
288
289 75
        $url = static::resourceUrl($id);
290
291
        /** @var \Arcanedev\Stripe\Http\Response $response */
292 75
        list($response, $opts) = static::staticRequest('post', $url, $params, $options);
293
294 75
        $object = Util::convertToStripeObject($response->getJson(), $opts);
0 ignored issues
show
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...
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 297 which is incompatible with the return type documented by Arcanedev\Stripe\StripeResource::scopedUpdate of type Arcanedev\Stripe\StripeResource.
Loading history...
295 75
        $object->setLastResponse($response);
296
297 75
        return $object;
298
    }
299
300
    /**
301
     * Save scope.
302
     *
303
     * @param  array|string|null  $options
304
     *
305
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
306
     *
307
     * @return self
308
     */
309
    protected function scopedSave($options = null)
310
    {
311 170
        $params = $this->serializeParameters();
312
313 170
        if (count($params) > 0) {
314 150
            self::checkArguments(null, $options);
315 150
            list($response, $opts) = $this->request('post', $this->instanceUrl(), $params, $options);
316 150
            $this->refreshFrom($response, $opts);
317 120
        }
318
319 170
        return $this;
320
    }
321
322
    /**
323
     * Delete Scope.
324
     *
325
     * @param  array|null         $params
326
     * @param  array|string|null  $options
327
     *
328
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
329
     *
330
     * @return self
331
     */
332
    protected function scopedDelete($params = [], $options = null)
333
    {
334 60
        self::checkArguments($params, $options);
335
336 60
        $url = $this->instanceUrl();
337
338 60
        list($response, $opts) = $this->request('delete', $url, $params, $options);
339 60
        $this->refreshFrom($response, $opts);
340
341 60
        return $this;
342
    }
343
344
    /* ------------------------------------------------------------------------------------------------
345
     |  Custom Scope Functions
346
     | ------------------------------------------------------------------------------------------------
347
     */
348
    /**
349
     * Custom Post Call.
350
     *
351
     * @param  string             $url
352
     * @param  array|null         $params
353
     * @param  array|string|null  $options
354
     *
355
     * @return self
356
     */
357
    protected function scopedPostCall($url, $params = [], $options = null)
358
    {
359 45
        $opts      = RequestOptions::parse($options);
360 45
        $requestor = Requestor::make($opts->getApiKey(), static::baseUrl());
361
362
        /** @var \Arcanedev\Stripe\Http\Response $response */
363 45
        list($response, $options) = $requestor->post($url, $params);
364
365 45
        $this->refreshFrom($response->getJson(), $options);
366 45
        $this->setLastResponse($response);
367
368 45
        return $this;
369
    }
370
371
    /* ------------------------------------------------------------------------------------------------
372
     |  Check Functions
373
     | ------------------------------------------------------------------------------------------------
374
     */
375
    /**
376
     * Check Arguments.
377
     *
378
     * @param  array|null         $params
379
     * @param  array|string|null  $options
380
     *
381
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
382
     * @throws \Arcanedev\Stripe\Exceptions\BadMethodCallException
383
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
384
     */
385
    private static function checkArguments($params = [], $options = null)
386
    {
387 749
        self::checkParameters($params);
388 744
        self::checkOptions($options);
389 739
    }
390
391
    /**
392
     * Check parameters.
393
     *
394
     * @param  array|null  $params
395
     *
396
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
397
     */
398
    private static function checkParameters($params)
399
    {
400 749
        if ($params && ! is_array($params)) {
401
            $message = 'You must pass an array as the first argument to Stripe API method calls.  '
402
                . '(HINT: an example call to create a charge would be: '
403 4
                . 'StripeCharge::create([\'amount\' => 100, \'currency\' => \'usd\', '
404 4
                . '\'card\' => [\'number\' => 4242424242424242, \'exp_month\' => 5, '
405 5
                . '\'exp_year\' => 2015]]))';
406
407 5
            throw new Exceptions\InvalidArgumentException($message);
408
        }
409 744
    }
410
411
    /**
412
     * Check Options.
413
     *
414
     * @param  array|string|null  $options
415
     *
416
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
417
     */
418
    private static function checkOptions($options)
419
    {
420 744
        if ($options && (
421 35
                ! $options instanceof RequestOptions &&
422 35
                ! is_string($options) &&
423 157
                ! is_array($options)
424 8
            )
425 595
        ) {
426
            $message = 'The second argument to Stripe API method calls is an '
427
                . 'optional per-request apiKey, which must be a string.  '
428 5
                . '(HINT: you can set a global apiKey by "Stripe::setApiKey(<apiKey>)")';
429
430 5
            throw new Exceptions\ApiException($message, 500);
431
        }
432 739
    }
433
434
    /**
435
     * Check the object is a Collection class.
436
     *
437
     * @param  mixed  $object
438
     *
439
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
440
     */
441
    private static function checkIsCollectionObject($object)
442
    {
443 135
        if ( ! is_a($object, 'Arcanedev\\Stripe\\Collection')) {
444
            $class   = get_class($object);
445
            $message = 'Expected type "Arcanedev\Stripe\Collection", got "' . $class . '" instead';
446
447
            throw new Exceptions\ApiException($message);
448
        }
449 135
    }
450
}
451