You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
5.8 KiB
236 lines
5.8 KiB
4 months ago
|
<?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;
|
||
|
}
|
||
|
}
|
||
|
}
|