summaryrefslogtreecommitdiff
path: root/vendor/aws/aws-sdk-php/src/Api/Validator.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/Api/Validator.php')
-rw-r--r--vendor/aws/aws-sdk-php/src/Api/Validator.php346
1 files changed, 346 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/Api/Validator.php b/vendor/aws/aws-sdk-php/src/Api/Validator.php
new file mode 100644
index 0000000..a09aa2c
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Api/Validator.php
@@ -0,0 +1,346 @@
+<?php
+namespace Aws\Api;
+
+use Aws;
+
+/**
+ * Validates a schema against a hash of input.
+ */
+class Validator
+{
+ private $path = [];
+ private $errors = [];
+ private $constraints = [];
+
+ private static $defaultConstraints = [
+ 'required' => true,
+ 'min' => true,
+ 'max' => false,
+ 'pattern' => false
+ ];
+
+ /**
+ * @param array $constraints Associative array of constraints to enforce.
+ * Accepts the following keys: "required", "min",
+ * "max", and "pattern". If a key is not
+ * provided, the constraint will assume false.
+ */
+ public function __construct(array $constraints = null)
+ {
+ static $assumedFalseValues = [
+ 'required' => false,
+ 'min' => false,
+ 'max' => false,
+ 'pattern' => false
+ ];
+ $this->constraints = empty($constraints)
+ ? self::$defaultConstraints
+ : $constraints + $assumedFalseValues;
+ }
+
+ /**
+ * Validates the given input against the schema.
+ *
+ * @param string $name Operation name
+ * @param Shape $shape Shape to validate
+ * @param array $input Input to validate
+ *
+ * @throws \InvalidArgumentException if the input is invalid.
+ */
+ public function validate($name, Shape $shape, array $input)
+ {
+ $this->dispatch($shape, $input);
+
+ if ($this->errors) {
+ $message = sprintf(
+ "Found %d error%s while validating the input provided for the "
+ . "%s operation:\n%s",
+ count($this->errors),
+ count($this->errors) > 1 ? 's' : '',
+ $name,
+ implode("\n", $this->errors)
+ );
+ $this->errors = [];
+
+ throw new \InvalidArgumentException($message);
+ }
+ }
+
+ private function dispatch(Shape $shape, $value)
+ {
+ static $methods = [
+ 'structure' => 'check_structure',
+ 'list' => 'check_list',
+ 'map' => 'check_map',
+ 'blob' => 'check_blob',
+ 'boolean' => 'check_boolean',
+ 'integer' => 'check_numeric',
+ 'float' => 'check_numeric',
+ 'long' => 'check_numeric',
+ 'string' => 'check_string',
+ 'byte' => 'check_string',
+ 'char' => 'check_string'
+ ];
+
+ $type = $shape->getType();
+ if (isset($methods[$type])) {
+ $this->{$methods[$type]}($shape, $value);
+ }
+ }
+
+ private function check_structure(StructureShape $shape, $value)
+ {
+ $isDocument = (isset($shape['document']) && $shape['document']);
+ $isUnion = (isset($shape['union']) && $shape['union']);
+ if ($isDocument) {
+ if (!$this->checkDocumentType($value)) {
+ $this->addError("is not a valid document type");
+ return;
+ }
+ } elseif ($isUnion) {
+ if (!$this->checkUnion($value)) {
+ $this->addError("is a union type and must have exactly one non null value");
+ return;
+ }
+ } elseif (!$this->checkAssociativeArray($value)) {
+ return;
+ }
+
+ if ($this->constraints['required'] && $shape['required']) {
+ foreach ($shape['required'] as $req) {
+ if (!isset($value[$req])) {
+ $this->path[] = $req;
+ $this->addError('is missing and is a required parameter');
+ array_pop($this->path);
+ }
+ }
+ }
+ if (!$isDocument) {
+ foreach ($value as $name => $v) {
+ if ($shape->hasMember($name)) {
+ $this->path[] = $name;
+ $this->dispatch(
+ $shape->getMember($name),
+ isset($value[$name]) ? $value[$name] : null
+ );
+ array_pop($this->path);
+ }
+ }
+ }
+ }
+
+ private function check_list(ListShape $shape, $value)
+ {
+ if (!is_array($value)) {
+ $this->addError('must be an array. Found '
+ . Aws\describe_type($value));
+ return;
+ }
+
+ $this->validateRange($shape, count($value), "list element count");
+
+ $items = $shape->getMember();
+ foreach ($value as $index => $v) {
+ $this->path[] = $index;
+ $this->dispatch($items, $v);
+ array_pop($this->path);
+ }
+ }
+
+ private function check_map(MapShape $shape, $value)
+ {
+ if (!$this->checkAssociativeArray($value)) {
+ return;
+ }
+
+ $values = $shape->getValue();
+ foreach ($value as $key => $v) {
+ $this->path[] = $key;
+ $this->dispatch($values, $v);
+ array_pop($this->path);
+ }
+ }
+
+ private function check_blob(Shape $shape, $value)
+ {
+ static $valid = [
+ 'string' => true,
+ 'integer' => true,
+ 'double' => true,
+ 'resource' => true
+ ];
+
+ $type = gettype($value);
+ if (!isset($valid[$type])) {
+ if ($type != 'object' || !method_exists($value, '__toString')) {
+ $this->addError('must be an fopen resource, a '
+ . 'GuzzleHttp\Stream\StreamInterface object, or something '
+ . 'that can be cast to a string. Found '
+ . Aws\describe_type($value));
+ }
+ }
+ }
+
+ private function check_numeric(Shape $shape, $value)
+ {
+ if (!is_numeric($value)) {
+ $this->addError('must be numeric. Found '
+ . Aws\describe_type($value));
+ return;
+ }
+
+ $this->validateRange($shape, $value, "numeric value");
+ }
+
+ private function check_boolean(Shape $shape, $value)
+ {
+ if (!is_bool($value)) {
+ $this->addError('must be a boolean. Found '
+ . Aws\describe_type($value));
+ }
+ }
+
+ private function check_string(Shape $shape, $value)
+ {
+ if ($shape['jsonvalue']) {
+ if (!self::canJsonEncode($value)) {
+ $this->addError('must be a value encodable with \'json_encode\'.'
+ . ' Found ' . Aws\describe_type($value));
+ }
+ return;
+ }
+
+ if (!$this->checkCanString($value)) {
+ $this->addError('must be a string or an object that implements '
+ . '__toString(). Found ' . Aws\describe_type($value));
+ return;
+ }
+
+ $value = isset($value) ? $value : '';
+ $this->validateRange($shape, strlen($value), "string length");
+
+ if ($this->constraints['pattern']) {
+ $pattern = $shape['pattern'];
+ if ($pattern && !preg_match("/$pattern/", $value)) {
+ $this->addError("Pattern /$pattern/ failed to match '$value'");
+ }
+ }
+ }
+
+ private function validateRange(Shape $shape, $length, $descriptor)
+ {
+ if ($this->constraints['min']) {
+ $min = $shape['min'];
+ if ($min && $length < $min) {
+ $this->addError("expected $descriptor to be >= $min, but "
+ . "found $descriptor of $length");
+ }
+ }
+
+ if ($this->constraints['max']) {
+ $max = $shape['max'];
+ if ($max && $length > $max) {
+ $this->addError("expected $descriptor to be <= $max, but "
+ . "found $descriptor of $length");
+ }
+ }
+ }
+
+ private function checkArray($arr)
+ {
+ return $this->isIndexed($arr) || $this->isAssociative($arr);
+ }
+
+ private function isAssociative($arr)
+ {
+ return count(array_filter(array_keys($arr), "is_string")) == count($arr);
+ }
+
+ private function isIndexed(array $arr)
+ {
+ return $arr == array_values($arr);
+ }
+
+ private function checkCanString($value)
+ {
+ static $valid = [
+ 'string' => true,
+ 'integer' => true,
+ 'double' => true,
+ 'NULL' => true,
+ ];
+
+ $type = gettype($value);
+
+ return isset($valid[$type]) ||
+ ($type == 'object' && method_exists($value, '__toString'));
+ }
+
+ private function checkAssociativeArray($value)
+ {
+ $isAssociative = false;
+
+ if (is_array($value)) {
+ $expectedIndex = 0;
+ $key = key($value);
+
+ do {
+ $isAssociative = $key !== $expectedIndex++;
+ next($value);
+ $key = key($value);
+ } while (!$isAssociative && null !== $key);
+ }
+
+ if (!$isAssociative) {
+ $this->addError('must be an associative array. Found '
+ . Aws\describe_type($value));
+ return false;
+ }
+
+ return true;
+ }
+
+ private function checkDocumentType($value)
+ {
+ if (is_array($value)) {
+ $typeOfFirstKey = gettype(key($value));
+ foreach ($value as $key => $val) {
+ if (!$this->checkDocumentType($val) || gettype($key) != $typeOfFirstKey) {
+ return false;
+ }
+ }
+ return $this->checkArray($value);
+ }
+ return is_null($value)
+ || is_numeric($value)
+ || is_string($value)
+ || is_bool($value);
+ }
+
+ private function checkUnion($value)
+ {
+ if (is_array($value)) {
+ $nonNullCount = 0;
+ foreach ($value as $key => $val) {
+ if (!is_null($val) && !(strpos($key, "@") === 0)) {
+ $nonNullCount++;
+ }
+ }
+ return $nonNullCount == 1;
+ }
+ return !is_null($value);
+ }
+
+ private function addError($message)
+ {
+ $this->errors[] =
+ implode('', array_map(function ($s) { return "[{$s}]"; }, $this->path))
+ . ' '
+ . $message;
+ }
+
+ private function canJsonEncode($data)
+ {
+ return !is_resource($data);
+ }
+}