// // For example, if the value is unsaved (meaning the user has set it), and // it looks like the API resource is persisted with an ID, then we include // the object so that parameters are serialized with a reference to its // ID. // // Another example is that on save API calls it's sometimes desirable to // update a customer's default source by setting a new card (or other) // object with `->source=` and then saving the customer. The // `saveWithParent` flag to override the default behavior allows us to // handle these exceptions. // // We throw an error if a property was set explicitly but we can't do // anything with it because the integration is probably not working as the // user intended it to. if (null === $value) { return ''; } if (($value instanceof ApiResource) && (!$value->saveWithParent)) { if (!$unsaved) { return null; } if (isset($value->id)) { return $value; } throw new Exception\InvalidArgumentException( "Cannot save property `{$key}` containing an API resource of type " . \get_class($value) . ". It doesn't appear to be persisted and is " . 'not marked as `saveWithParent`.' ); } if (\is_array($value)) { if (Util\Util::isList($value)) { // Sequential array, i.e. a list $update = []; foreach ($value as $v) { $update[] = $this->serializeParamsValue($v, null, true, $force); } // This prevents an array that's unchanged from being resent. if ($update !== $this->serializeParamsValue($original, null, true, $force, $key)) { return $update; } } else { // Associative array, i.e. a map return Util\Util::convertToStripeObject($value, $this->_opts)->serializeParameters(); } } elseif ($value instanceof StripeObject) { $update = $value->serializeParameters($force); if ($original && $unsaved && $key && static::getAdditiveParams()->includes($key)) { $update = \array_merge(self::emptyValues($original), $update); } return $update; } else { return $value; } } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->toArray(); } /** * Returns an associative array with the key and values composing the * Stripe object. * * @return array the associative array */ public function toArray() { $maybeToArray = function ($value) { if (null === $value) { return null; } return \is_object($value) && \method_exists($value, 'toArray') ? $value->toArray() : $value; }; return \array_reduce(\array_keys($this->_values), function ($acc, $k) use ($maybeToArray) { if ('_' === \substr((string) $k, 0, 1)) { return $acc; } $v = $this->_values[$k]; if (Util\Util::isList($v)) { $acc[$k] = \array_map($maybeToArray, $v); } else { $acc[$k] = $maybeToArray($v); } return $acc; }, []); } /** * Returns a pretty JSON representation of the Stripe object. * * @return string the JSON representation of the Stripe object */ public function toJSON() { return \json_encode($this->toArray(), \JSON_PRETTY_PRINT); } public function __toString() { $class = static::class; return $class . ' JSON: ' . $this->toJSON(); } /** * Sets all keys within the StripeObject as unsaved so that they will be * included with an update when `serializeParameters` is called. This * method is also recursive, so any StripeObjects contained as values or * which are values in a tenant array are also marked as dirty. */ public function dirty() { $this->_unsavedValues = new Util\Set(\array_keys($this->_values)); foreach ($this->_values as $k => $v) { $this->dirtyValue($v); } } protected function dirtyValue($value) { if (\is_array($value)) { foreach ($value as $v) { $this->dirtyValue($v); } } elseif ($value instanceof StripeObject) { $value->dirty(); } } /** * Produces a deep copy of the given object including support for arrays * and StripeObjects. * * @param mixed $obj */ protected static function deepCopy($obj) { if (\is_array($obj)) { $copy = []; foreach ($obj as $k => $v) { $copy[$k] = self::deepCopy($v); } return $copy; } if ($obj instanceof StripeObject) { return $obj::constructFrom( self::deepCopy($obj->_values), clone $obj->_opts ); } return $obj; } /** * Returns a hash of empty values for all the values that are in the given * StripeObject. * * @param mixed $obj */ public static function emptyValues($obj) { if (\is_array($obj)) { $values = $obj; } elseif ($obj instanceof StripeObject) { $values = $obj->_values; } else { throw new Exception\InvalidArgumentException( 'empty_values got unexpected object type: ' . \get_class($obj) ); } return \array_fill_keys(\array_keys($values), ''); } /** * @return null|ApiResponse The last response from the Stripe API */ public function getLastResponse() { return $this->_lastResponse; } /** * Sets the last response from the Stripe API. * * @param ApiResponse $resp */ public function setLastResponse($resp) { $this->_lastResponse = $resp; } /** * Indicates whether or not the resource has been deleted on the server. * Note that some, but not all, resources can indicate whether they have * been deleted. * * @return bool whether the resource is deleted */ public function isDeleted() { return isset($this->_values['deleted']) ? $this->_values['deleted'] : false; } }