diff options
author | Andrew Dolgov <[email protected]> | 2022-11-23 21:14:33 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2022-11-23 21:14:33 +0300 |
commit | 0c8af4992cb0f7589dcafaad65ada12753c64594 (patch) | |
tree | 18e83d068c3e7dd2499331de977782b382279396 /vendor/aws/aws-sdk-php/src/Api/Validator.php |
initial
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/Api/Validator.php')
-rw-r--r-- | vendor/aws/aws-sdk-php/src/Api/Validator.php | 346 |
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); + } +} |