Completed
Push — master ( 6efa89...d59b5b )
by ARCANEDEV
9s
created

src/StripeResource.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 775
    public static function baseUrl()
37
    {
38 775
        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();
0 ignored issues
show
Consider using a different name than the parameter $class. This often makes code more readable.
Loading history...
87 592
        }
88
89 760
        $class = new ReflectionClass($class);
0 ignored issues
show
Consider using a different name than the parameter $class. This often makes code more readable.
Loading history...
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 749
        $opts      = RequestOptions::parse($options);
182 749
        $requestor = Requestor::make($opts->apiKey, static::baseUrl());
183
184 734
        list($response, $opts->apiKey) =
185 749
            $requestor->request($method, $url, $params, $opts->headers);
186
187 734
        foreach ($opts->headers as $k => $v) {
188 5
            if ( ! array_key_exists($k, self::$persistedHeaders)) {
189 5
                unset($opts->headers[$k]);
190 4
            }
191 587
        }
192
193 734
        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 649
        self::checkArguments($params, $options);
262
263 649
        $url = static::classUrl();
264
265
        /** @var \Arcanedev\Stripe\Http\Response $response */
266 649
        list($response, $opts) = self::staticRequest('post', $url, $params, $options);
267
268 634
        $object = Util::convertToStripeObject($response->getJson(), $opts);
269 634
        $object->setLastResponse($response);
270
271 634
        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);
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 754
        self::checkParameters($params);
388 749
        self::checkOptions($options);
389 744
    }
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 754
        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 749
    }
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 749
        if ($options && (
421 35
                ! $options instanceof RequestOptions &&
422 35
                ! is_string($options) &&
423 158
                ! is_array($options)
424 8
            )
425 599
        ) {
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 744
    }
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