Completed
Pull Request — master (#46)
by ARCANEDEV
09:49
created

StripeResource::scopedUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 3
dl 0
loc 12
ccs 5
cts 5
cp 1
crap 1
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
    /** @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 344
    public static function baseUrl()
37
    {
38 344
        return Stripe::getApiBaseUrl();
39 4
    }
40
41
    /**
42
     * Get the refreshed resource.
43
     *
44
     * @return self
45
     */
46 166
    public function refresh()
47
    {
48 166
        list($response, $this->opts->apiKey) = Requestor::make($this->opts->apiKey, self::baseUrl())
49 166
            ->get($this->instanceUrl(), $this->retrieveParameters);
50
51
52
        /** @var \Arcanedev\Stripe\Http\Response $response */
53 145
        $this->setLastResponse($response);
54 140
        $this->refreshFrom($response->getJson(), $this->opts);
55
56 140
        return $this;
57
    }
58
59
    /**
60
     * Get The name of the class, with namespacing and underscores stripped.
61
     *
62
     * @param  string  $class
63
     *
64
     * @return string
65
     */
66 326
    public static function className($class = '')
67
    {
68 326
        $name = self::getShortNameClass($class);
69 326
        $name = str_split_camelcase($name, '_');
70
71 326
        return strtolower(urlencode($name));
72
    }
73
74
    /**
75
     * Get Class short name.
76
     *
77
     * @param  string  $class
78
     *
79
     * @return string
80
     */
81 326
    protected static function getShortNameClass($class = '')
82
    {
83 326
        if (empty($class))
84 322
            $class = get_called_class();
85
86 326
        $class = new ReflectionClass($class);
87
88 326
        return $class->getShortName();
89
    }
90
91
    /**
92
     * Get the endpoint URL for the given class.
93
     *
94
     * @param  string  $class
95
     *
96
     * @return string
97
     */
98 320
    public static function classUrl($class = '')
99
    {
100 320
        $base = self::className($class);
101
102 320
        return "/v1/${base}s";
103
    }
104
105
    /**
106
     * Get Instance URL.
107
     *
108
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
109
     *
110
     * @return string
111
     */
112
    public function instanceUrl()
113
    {
114 216
        return static::resourceUrl($this['id']);
115
    }
116
117
    /**
118
     * Get the instance endpoint URL for the given class.
119
     *
120
     * @param  string  $id
121
     *
122
     * @return string
123
     *
124
     * @throws Exceptions\InvalidRequestException
125
     */
126
    public static function resourceUrl($id)
127
    {
128 228
        if ($id === null) {
129 6
            $class = get_called_class();
130 6
            throw new Exceptions\InvalidRequestException(
131 6
                "Could not determine which URL to request: $class instance has invalid ID: $id", null
132 3
            );
133
        }
134
135 222
        return static::classUrl().'/'.urlencode(str_utf8($id));
136
    }
137
138
    /* ------------------------------------------------------------------------------------------------
139
     |  Request Functions
140
     | ------------------------------------------------------------------------------------------------
141
     */
142
    /**
143
     * Make a request.
144
     *
145
     * @param  string             $method
146
     * @param  string             $url
147
     * @param  array|null         $params
148
     * @param  array|string|null  $options
149
     *
150
     * @return array
151
     */
152
    protected function request($method, $url, $params = [], $options = null)
153
    {
154 134
        $opts = $this->opts->merge($options);
155
156
        /** @var \Arcanedev\Stripe\Http\Response $response */
157 134
        list($response, $options) = static::staticRequest($method, $url, $params, $opts);
158 134
        $this->setLastResponse($response);
159
160 134
        return [$response->getJson(), $options];
161
    }
162
163
    /**
164
     * Make a request (static).
165
     *
166
     * @param  string             $method
167
     * @param  string             $url
168
     * @param  array|null         $params
169
     * @param  array|string|null  $options
170
     *
171
     * @return array
172
     */
173
    protected static function staticRequest($method, $url, $params, $options)
174
    {
175 324
        $opts      = RequestOptions::parse($options);
176 324
        $requestor = Requestor::make($opts->apiKey, static::baseUrl());
177
178 316
        list($response, $opts->apiKey) =
179 324
            $requestor->request($method, $url, $params, $opts->headers);
180
181 316
        foreach ($opts->headers as $k => $v) {
182 2
            if ( ! array_key_exists($k, self::$persistedHeaders))
183 2
                unset($opts->headers[$k]);
184 158
        }
185
186 316
        return [$response, $opts];
187
    }
188
189
    /* ------------------------------------------------------------------------------------------------
190
     |  CRUD Scope Functions
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 162
        $class    = get_called_class();
204
205
        /** @var self $resource */
206 162
        $resource = new $class($id, RequestOptions::parse($options));
207 162
        $resource->refresh();
208
209 136
        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 63
        self::checkArguments($params, $options);
225
226 58
        $url = static::classUrl();
227
228
        /** @var \Arcanedev\Stripe\Http\Response $response */
229 58
        list($response, $opts) = self::staticRequest('get', $url, $params, $options);
230
231 58
        $object = Util::convertToStripeObject($response->getJson(), $opts);
232
233 58
        self::checkIsCollectionObject($object);
234
235 58
        $object->setLastResponse($response);
236 58
        $object->setRequestParams($params);
237
238 58
        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 272
        self::checkArguments($params, $options);
255
256
        /** @var \Arcanedev\Stripe\Http\Response $response */
257 272
        list($response, $opts) = static::staticRequest('post', static::classUrl(), $params, $options);
258
259 264
        $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 264
        $object->setLastResponse($response);
261
262 264
        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 34
        self::checkArguments($params, $options);
279
280
        /** @var \Arcanedev\Stripe\Http\Response $response */
281 34
        list($response, $opts) = static::staticRequest('post', static::resourceUrl($id), $params, $options);
282
283 34
        $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 34
        $object->setLastResponse($response);
285
286 34
        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 74
        if (count($params = $this->serializeParameters()) > 0) {
301 66
            self::checkArguments(null, $options);
302 66
            list($response, $opts) = $this->request('post', $this->instanceUrl(), $params, $options);
303 66
            $this->refreshFrom($response, $opts);
304 33
        }
305
306 74
        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 28
        self::checkArguments($params, $options);
322
323 28
        list($response, $opts) = $this->request('delete', $this->instanceUrl(), $params, $options);
324 28
        $this->refreshFrom($response, $opts);
325
326 28
        return $this;
327
    }
328
329
    /* ------------------------------------------------------------------------------------------------
330
     |  Custom Scope Functions
331
     | ------------------------------------------------------------------------------------------------
332
     */
333
    /**
334
     * Custom Post Call.
335
     *
336
     * @param  string             $url
337
     * @param  array|null         $params
338
     * @param  array|string|null  $options
339
     *
340
     * @return self
341
     */
342
    protected function scopedPostCall($url, $params = [], $options = null)
343
    {
344
        /** @var \Arcanedev\Stripe\Http\Response $response */
345 18
        list($response, $options) = Requestor::make(RequestOptions::parse($options)->getApiKey(), static::baseUrl())
346 18
            ->post($url, $params);
347
348 18
        $this->refreshFrom($response->getJson(), $options);
349 18
        $this->setLastResponse($response);
350
351 18
        return $this;
352
    }
353
354
    /* ------------------------------------------------------------------------------------------------
355
     |  Check Functions
356
     | ------------------------------------------------------------------------------------------------
357
     */
358
    /**
359
     * Check Arguments.
360
     *
361
     * @param  array|null         $params
362
     * @param  array|string|null  $options
363
     *
364
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
365
     * @throws \Arcanedev\Stripe\Exceptions\BadMethodCallException
366
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
367
     */
368
    protected static function checkArguments($params = [], $options = null)
369
    {
370 324
        self::checkParameters($params);
371 322
        self::checkOptions($options);
372 320
    }
373
374
    /**
375
     * Check parameters.
376
     *
377
     * @param  array|null  $params
378
     *
379
     * @throws \Arcanedev\Stripe\Exceptions\InvalidArgumentException
380
     */
381
    private static function checkParameters($params)
382
    {
383 324
        if ($params && ! is_array($params)) {
384 2
            throw new Exceptions\InvalidArgumentException(
385
                'You must pass an array as the first argument to Stripe API method calls.  '
386
                . '(HINT: an example call to create a charge would be: '
387 1
                . 'StripeCharge::create([\'amount\' => 100, \'currency\' => \'usd\', '
388 1
                . '\'card\' => [\'number\' => 4242424242424242, \'exp_month\' => 5, '
389 2
                . '\'exp_year\' => 2015]]))');
390
        }
391 322
    }
392
393
    /**
394
     * Check Options.
395
     *
396
     * @param  array|string|null  $options
397
     *
398
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
399
     */
400
    private static function checkOptions($options)
401
    {
402 322
        if ($options && (
403 14
                ! $options instanceof RequestOptions &&
404 14
                ! is_string($options) &&
405 163
                ! is_array($options)
406 2
            )
407 161
        ) {
408 2
            throw new Exceptions\ApiException(
409 90
                'The second argument to Stripe API method calls is an '
410
                . 'optional per-request apiKey, which must be a string.  '
411 2
                . '(HINT: you can set a global apiKey by "Stripe::setApiKey(<apiKey>)")',
412 1
                500
413 1
            );
414
        }
415 320
    }
416
417
    /**
418
     * Check the object is a Collection class.
419
     *
420
     * @param  mixed  $object
421
     *
422
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
423
     */
424
    private static function checkIsCollectionObject($object)
425
    {
426 58
        if ( ! is_a($object, Collection::class)) {
427
            throw new Exceptions\ApiException(
428
                'Expected type "Arcanedev\Stripe\Collection", got "'.get_class($object).'" instead'
429
            );
430
        }
431 58
    }
432
}
433