123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- <?php
- namespace Aws;
- use Aws\Api\ListShape;
- use Aws\Api\MapShape;
- use Aws\Api\Service;
- use Aws\Api\Shape;
- use Aws\Api\StructureShape;
- use Closure;
- /**
- * Inspects command input values and casts them to their modeled type.
- * This covers query compatible services which have migrated from query
- * to JSON wire protocols.
- *
- * @internal
- */
- class QueryCompatibleInputMiddleware
- {
- /** @var callable */
- private $nextHandler;
- /** @var Service */
- private $service;
- /** @var CommandInterface */
- private $command;
- /**
- * Create a middleware wrapper function.
- *
- * @param Service $service
- * @return Closure
- */
- public static function wrap(Service $service) : Closure
- {
- return static function (callable $handler) use ($service) {
- return new self($handler, $service);
- };
- }
- public function __construct(callable $nextHandler, Service $service)
- {
- $this->service = $service;
- $this->nextHandler = $nextHandler;
- }
- public function __invoke(CommandInterface $cmd)
- {
- $this->command = $cmd;
- $nextHandler = $this->nextHandler;
- $op = $this->service->getOperation($cmd->getName());
- $inputMembers = $op->getInput()->getMembers();
- $input = $cmd->toArray();
- foreach ($input as $param => $value) {
- if (isset($inputMembers[$param])) {
- $shape = $inputMembers[$param];
- $this->processInput($value, $shape, [$param]);
- }
- }
- return $nextHandler($this->command);
- }
- /**
- * Recurses a given input shape. if a given scalar input does not match its
- * modeled type, it is cast to its modeled type.
- *
- * @param $input
- * @param $shape
- * @param array $path
- *
- * @return void
- */
- private function processInput($input, $shape, array $path) : void
- {
- switch ($shape->getType()) {
- case 'structure':
- $this->processStructure($input, $shape, $path);
- break;
- case 'list':
- $this->processList($input, $shape, $path);
- break;
- case 'map':
- $this->processMap($input, $shape, $path);
- break;
- default:
- $this->processScalar($input, $shape, $path);
- }
- }
- /**
- * @param array $input
- * @param StructureShape $shape
- * @param array $path
- *
- * @return void
- */
- private function processStructure(
- array $input,
- StructureShape $shape,
- array $path
- ) : void
- {
- foreach ($input as $param => $value) {
- if ($shape->hasMember($param)) {
- $memberPath = array_merge($path, [$param]);
- $this->processInput($value, $shape->getMember($param), $memberPath);
- }
- }
- }
- /**
- * @param array $input
- * @param ListShape $shape
- * @param array $path
- *
- * @return void
- */
- private function processList(
- array $input,
- ListShape $shape,
- array $path
- ) : void
- {
- foreach ($input as $param => $value) {
- $memberPath = array_merge($path, [$param]);
- $this->processInput($value, $shape->getMember(), $memberPath);
- }
- }
- /**
- * @param array $input
- * @param MapShape $shape
- * @param array $path
- *
- * @return void
- */
- private function processMap(array $input, MapShape $shape, array $path) : void
- {
- foreach ($input as $param => $value) {
- $memberPath = array_merge($path, [$param]);
- $this->processInput($value, $shape->getValue(), $memberPath);
- }
- }
- /**
- * @param $input
- * @param Shape $shape
- * @param array $path
- *
- * @return void
- */
- private function processScalar($input, Shape $shape, array $path) : void
- {
- $expectedType = $shape->getType();
- if (!$this->isModeledType($input, $expectedType)) {
- trigger_error(
- "The provided type for `". implode(' -> ', $path) ."` value was `"
- . (gettype($input) === 'double' ? 'float' : gettype($input)) . "`."
- . " The modeled type is `{$expectedType}`.",
- E_USER_WARNING
- );
- $value = $this->castValue($input, $expectedType);
- $this->changeValueAtPath($path, $value);
- }
- }
- /**
- * Modifies command in place
- *
- * @param array $path
- * @param $newValue
- *
- * @return void
- */
- private function changeValueAtPath(array $path, $newValue) : void
- {
- $commandRef = &$this->command;
- foreach ($path as $segment) {
- if (!isset($commandRef[$segment])) {
- return;
- }
- $commandRef = &$commandRef[$segment];
- }
- $commandRef = $newValue;
- }
- /**
- * @param $value
- * @param $type
- *
- * @return bool
- */
- private function isModeledType($value, $type) : bool
- {
- switch ($type) {
- case 'string':
- return is_string($value);
- case 'integer':
- case 'long':
- return is_int($value);
- case 'float':
- return is_float($value);
- default:
- return true;
- }
- }
- /**
- * @param $value
- * @param $type
- *
- * @return float|int|mixed|string
- */
- private function castValue($value, $type)
- {
- switch ($type) {
- case 'integer':
- return (int) $value;
- case 'long' :
- return $value + 0;
- case 'float':
- return (float) $value;
- case 'string':
- return (string) $value;
- default:
- return $value;
- }
- }
- }
|