| 1 |
<?php |
| 2 |
|
| 3 |
namespace Stripe; |
| 4 |
|
| 5 |
/** |
| 6 |
* Class ApiResource. |
| 7 |
*/ |
| 8 |
abstract class ApiResource extends StripeObject |
| 9 |
{ |
| 10 |
use ApiOperations\Request; |
| 11 |
|
| 12 |
/** |
| 13 |
* @return \Stripe\Util\Set A list of fields that can be their own type of |
| 14 |
* API resource (say a nested card under an account for example), and if |
| 15 |
* that resource is set, it should be transmitted to the API on a create or |
| 16 |
* update. Doing so is not the default behavior because API resources |
| 17 |
* should normally be persisted on their own RESTful endpoints. |
| 18 |
*/ |
| 19 |
public static function getSavedNestedResources() |
| 20 |
{ |
| 21 |
static $savedNestedResources = null; |
| 22 |
if (null === $savedNestedResources) { |
| 23 |
$savedNestedResources = new Util\Set(); |
| 24 |
} |
| 25 |
|
| 26 |
return $savedNestedResources; |
| 27 |
} |
| 28 |
|
| 29 |
/** |
| 30 |
* @var bool A flag that can be set a behavior that will cause this |
| 31 |
* resource to be encoded and sent up along with an update of its parent |
| 32 |
* resource. This is usually not desirable because resources are updated |
| 33 |
* individually on their own endpoints, but there are certain cases, |
| 34 |
* replacing a customer's source for example, where this is allowed. |
| 35 |
*/ |
| 36 |
public $saveWithParent = false; |
| 37 |
|
| 38 |
public function __set($k, $v) |
| 39 |
{ |
| 40 |
parent::__set($k, $v); |
| 41 |
$v = $this->{$k}; |
| 42 |
if ((static::getSavedNestedResources()->includes($k)) |
| 43 |
&& ($v instanceof ApiResource)) { |
| 44 |
$v->saveWithParent = true; |
| 45 |
} |
| 46 |
} |
| 47 |
|
| 48 |
/** |
| 49 |
* @throws Exception\ApiErrorException |
| 50 |
* |
| 51 |
* @return ApiResource the refreshed resource |
| 52 |
*/ |
| 53 |
public function refresh() |
| 54 |
{ |
| 55 |
$requestor = new ApiRequestor($this->_opts->apiKey, static::baseUrl()); |
| 56 |
$url = $this->instanceUrl(); |
| 57 |
|
| 58 |
list($response, $this->_opts->apiKey) = $requestor->request( |
| 59 |
'get', |
| 60 |
$url, |
| 61 |
$this->_retrieveOptions, |
| 62 |
$this->_opts->headers |
| 63 |
); |
| 64 |
$this->setLastResponse($response); |
| 65 |
$this->refreshFrom($response->json, $this->_opts); |
| 66 |
|
| 67 |
return $this; |
| 68 |
} |
| 69 |
|
| 70 |
/** |
| 71 |
* @return string the base URL for the given class |
| 72 |
*/ |
| 73 |
public static function baseUrl() |
| 74 |
{ |
| 75 |
return Stripe::$apiBase; |
| 76 |
} |
| 77 |
|
| 78 |
/** |
| 79 |
* @return string the endpoint URL for the given class |
| 80 |
*/ |
| 81 |
public static function classUrl() |
| 82 |
{ |
| 83 |
// Replace dots with slashes for namespaced resources, e.g. if the object's name is |
| 84 |
// "foo.bar", then its URL will be "/v1/foo/bars". |
| 85 |
|
| 86 |
/** @phpstan-ignore-next-line */ |
| 87 |
$base = \str_replace('.', '/', static::OBJECT_NAME); |
| 88 |
|
| 89 |
return "/v1/{$base}s"; |
| 90 |
} |
| 91 |
|
| 92 |
/** |
| 93 |
* @param null|string $id the ID of the resource |
| 94 |
* |
| 95 |
* @throws Exception\UnexpectedValueException if $id is null |
| 96 |
* |
| 97 |
* @return string the instance endpoint URL for the given class |
| 98 |
*/ |
| 99 |
public static function resourceUrl($id) |
| 100 |
{ |
| 101 |
if (null === $id) { |
| 102 |
$class = static::class; |
| 103 |
$message = 'Could not determine which URL to request: ' |
| 104 |
. "{$class} instance has invalid ID: {$id}"; |
| 105 |
|
| 106 |
throw new Exception\UnexpectedValueException($message); |
| 107 |
} |
| 108 |
$id = Util\Util::utf8($id); |
| 109 |
$base = static::classUrl(); |
| 110 |
$extn = \urlencode($id); |
| 111 |
|
| 112 |
return "{$base}/{$extn}"; |
| 113 |
} |
| 114 |
|
| 115 |
/** |
| 116 |
* @return string the full API URL for this API resource |
| 117 |
*/ |
| 118 |
public function instanceUrl() |
| 119 |
{ |
| 120 |
return static::resourceUrl($this['id']); |
| 121 |
} |
| 122 |
} |
| 123 |
|