diff options
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php')
-rw-r--r-- | vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php b/vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php new file mode 100644 index 0000000..f86452c --- /dev/null +++ b/vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php @@ -0,0 +1,320 @@ +<?php +namespace Aws\DynamoDb; + +use Psr\Http\Message\StreamInterface; + +/** + * Marshals and unmarshals JSON documents and PHP arrays into DynamoDB items. + */ +class Marshaler +{ + /** @var array Default options to merge into provided options. */ + private static $defaultOptions = [ + 'ignore_invalid' => false, + 'nullify_invalid' => false, + 'wrap_numbers' => false, + ]; + + /** @var array Marshaler options. */ + private $options; + + /** + * Instantiates a DynamoDB Marshaler. + * + * The following options are valid. + * + * - ignore_invalid: (bool) Set to `true` if invalid values should be + * ignored (i.e., not included) during marshaling. + * - nullify_invalid: (bool) Set to `true` if invalid values should be set + * to null. + * - wrap_numbers: (bool) Set to `true` to wrap numbers with `NumberValue` + * objects during unmarshaling to preserve the precision. + * + * @param array $options Marshaler options + */ + public function __construct(array $options = []) + { + $this->options = $options + self::$defaultOptions; + } + + /** + * Creates a special object to represent a DynamoDB binary (B) value. + * + * This helps disambiguate binary values from string (S) values. + * + * @param mixed $value A binary value compatible with Guzzle streams. + * + * @return BinaryValue + * @see GuzzleHttp\Stream\Stream::factory + */ + public function binary($value) + { + return new BinaryValue($value); + } + + /** + * Creates a special object to represent a DynamoDB number (N) value. + * + * This helps maintain the precision of large integer/float in PHP. + * + * @param string|int|float $value A number value. + * + * @return NumberValue + */ + public function number($value) + { + return new NumberValue($value); + } + + /** + * Creates a special object to represent a DynamoDB set (SS/NS/BS) value. + * + * This helps disambiguate set values from list (L) values. + * + * @param array $values The values of the set. + * + * @return SetValue + * + */ + public function set(array $values) + { + return new SetValue($values); + } + + /** + * Marshal a JSON document from a string to a DynamoDB item. + * + * The result is an array formatted in the proper parameter structure + * required by the DynamoDB API for items. + * + * @param string $json A valid JSON document. + * + * @return array Item formatted for DynamoDB. + * @throws \InvalidArgumentException if the JSON is invalid. + */ + public function marshalJson($json) + { + $data = json_decode($json); + if (!($data instanceof \stdClass)) { + throw new \InvalidArgumentException( + 'The JSON document must be valid and be an object at its root.' + ); + } + + return current($this->marshalValue($data)); + } + + /** + * Marshal a native PHP array of data to a DynamoDB item. + * + * The result is an array formatted in the proper parameter structure + * required by the DynamoDB API for items. + * + * @param array|\stdClass $item An associative array of data. + * + * @return array Item formatted for DynamoDB. + */ + public function marshalItem($item) + { + return current($this->marshalValue($item)); + } + + /** + * Marshal a native PHP value into a DynamoDB attribute value. + * + * The result is an associative array that is formatted in the proper + * `[TYPE => VALUE]` parameter structure required by the DynamoDB API. + * + * @param mixed $value A scalar, array, or `stdClass` value. + * + * @return array Attribute formatted for DynamoDB. + * @throws \UnexpectedValueException if the value cannot be marshaled. + */ + public function marshalValue($value) + { + $type = gettype($value); + + // Handle string values. + if ($type === 'string') { + return ['S' => $value]; + } + + // Handle number values. + if ($type === 'integer' + || $type === 'double' + || $value instanceof NumberValue + ) { + return ['N' => (string) $value]; + } + + // Handle boolean values. + if ($type === 'boolean') { + return ['BOOL' => $value]; + } + + // Handle null values. + if ($type === 'NULL') { + return ['NULL' => true]; + } + + // Handle set values. + if ($value instanceof SetValue) { + if (count($value) === 0) { + return $this->handleInvalid('empty sets are invalid'); + } + $previousType = null; + $data = []; + foreach ($value as $v) { + $marshaled = $this->marshalValue($v); + $setType = key($marshaled); + if (!$previousType) { + $previousType = $setType; + } elseif ($setType !== $previousType) { + return $this->handleInvalid('sets must be uniform in type'); + } + $data[] = current($marshaled); + } + + return [$previousType . 'S' => array_values(array_unique($data))]; + } + + // Handle list and map values. + $dbType = 'L'; + if ($value instanceof \stdClass) { + $type = 'array'; + $dbType = 'M'; + } + if ($type === 'array' || $value instanceof \Traversable) { + $data = []; + $index = 0; + foreach ($value as $k => $v) { + if ($v = $this->marshalValue($v)) { + $data[$k] = $v; + if ($dbType === 'L' && (!is_int($k) || $k != $index++)) { + $dbType = 'M'; + } + } + } + return [$dbType => $data]; + } + + // Handle binary values. + if (is_resource($value) || $value instanceof StreamInterface) { + $value = $this->binary($value); + } + if ($value instanceof BinaryValue) { + return ['B' => (string) $value]; + } + + // Handle invalid values. + return $this->handleInvalid('encountered unexpected value'); + } + + /** + * Unmarshal a document (item) from a DynamoDB operation result into a JSON + * document string. + * + * @param array $data Item/document from a DynamoDB result. + * @param int $jsonEncodeFlags Flags to use with `json_encode()`. + * + * @return string + */ + public function unmarshalJson(array $data, $jsonEncodeFlags = 0) + { + return json_encode( + $this->unmarshalValue(['M' => $data], true), + $jsonEncodeFlags + ); + } + + /** + * Unmarshal an item from a DynamoDB operation result into a native PHP + * array. If you set $mapAsObject to true, then a stdClass value will be + * returned instead. + * + * @param array $data Item from a DynamoDB result. + * @param bool $mapAsObject Whether maps should be represented as stdClass. + * + * @return array|\stdClass + */ + public function unmarshalItem(array $data, $mapAsObject = false) + { + return $this->unmarshalValue(['M' => $data], $mapAsObject); + } + + /** + * Unmarshal a value from a DynamoDB operation result into a native PHP + * value. Will return a scalar, array, or (if you set $mapAsObject to true) + * stdClass value. + * + * @param array $value Value from a DynamoDB result. + * @param bool $mapAsObject Whether maps should be represented as stdClass. + * + * @return mixed + * @throws \UnexpectedValueException + */ + public function unmarshalValue(array $value, $mapAsObject = false) + { + $type = key($value); + $value = $value[$type]; + switch ($type) { + case 'S': + case 'BOOL': + return $value; + case 'NULL': + return null; + case 'N': + if ($this->options['wrap_numbers']) { + return new NumberValue($value); + } + + // Use type coercion to unmarshal numbers to int/float. + return $value + 0; + case 'M': + if ($mapAsObject) { + $data = new \stdClass; + foreach ($value as $k => $v) { + $data->$k = $this->unmarshalValue($v, $mapAsObject); + } + return $data; + } + // NOBREAK: Unmarshal M the same way as L, for arrays. + case 'L': + foreach ($value as $k => $v) { + $value[$k] = $this->unmarshalValue($v, $mapAsObject); + } + return $value; + case 'B': + return new BinaryValue($value); + case 'SS': + case 'NS': + case 'BS': + foreach ($value as $k => $v) { + $value[$k] = $this->unmarshalValue([$type[0] => $v]); + } + return new SetValue($value); + } + + throw new \UnexpectedValueException("Unexpected type: {$type}."); + } + + /** + * Handle invalid value based on marshaler configuration. + * + * @param string $message Error message + * + * @return array|null + */ + private function handleInvalid($message) + { + if ($this->options['ignore_invalid']) { + return null; + } + + if ($this->options['nullify_invalid']) { + return ['NULL' => true]; + } + + throw new \UnexpectedValueException("Marshaling error: {$message}."); + } +} |