Skip to content
Permalink
Browse files

First pass at caster middleware

  • Loading branch information
jacobemerick committed Mar 23, 2017
1 parent 2981d3d commit 62c399c3d13d78d3abd1e42d6e33527ed775fbe0
Showing with 174 additions and 0 deletions.
  1. +174 −0 src/Caster.php
@@ -0,0 +1,174 @@
<?php

namespace AvalancheDevelopment\SwaggerCasterMiddleware;

use AvalancheDevelopment\Peel\HttpError\BadRequest;
use DateTime;
use Exception;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;

class Caster implements LoggerAwareInterface
{

use LoggerAwareTrait;

public function __construct()
{
$this->logger = new NullLogger;
}

/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param callable $next
* @return ResponseInterface $response
*/
public function __invoke(RequestInterface $request, ResponseInterface $response, callable $next)
{
if (!$request->getAttribute('swagger')) {
$this->log('no swagger information found in request, skipping');
return $next($request, $response);
}

$updatedSwagger = $this->updateSwaggerParams($request->getAttribute('swagger'));
$request = $request->withAttribute('swagger', $updatedSwagger);

return $next($request, $response);
}

/**
* @param ParsedSwaggerInterface $swagger
* @return ParsedSwaggerInterface
*/
protected function updateSwaggerParams(ParsedSwaggerInterface $swagger)
{
array_walk($swagger->getParams(), [ $this, 'castType' ]);
return $swagger;
}

/**
* @param array $parameter
* @return mixed
*/
protected function castType(array $parameter)
{
$type = $this->getParameterType($parameter);

switch ($type) {
case 'array':
foreach ($value as $key => $row) {
$value[$key] = $this->castType($row, $parameter['items']);
}
break;
case 'boolean':
$value = (boolean) $value;
break;
case 'file':
break;
case 'integer':
$value = (int) $value;
break;
case 'number':
$value = (float) $value;
break;
case 'object':
$value = $this->formatObject($value, $parameter);
break;
case 'string':
$value = (string) $value;
$value = $this->formatString($value, $parameter);
break;
default:
throw new Exception('Invalid parameter type value defined in swagger');
break;
}

return $value;
}

/**
* @param array $parameter
* @return string
*/
protected function getParameterType(array $parameter)
{
$type = '';

if (isset($parameter['type'])) {
$type = $parameter['type'];
}
if (isset($parameter['in']) && $parameter['in'] === 'body') {
$type = $parameter['schema']['type'];
}

if (empty($type)) {
throw new Exception('Parameter type is not defined in swagger');
}
return $type;
}

/**
* @param string $value
* @param array $parameter
* @return object
*/
protected function formatObject($value, array $parameter)
{
$object = $value;
if (!is_object($object)) {
$object = (string) $object;
$object = json_decode($object);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new BadRequest('Bad json object passed in as parameter');
}
}

$schema = array_key_exists('schema', $parameter) ? $parameter['schema'] : $parameter;
if (empty($schema['properties'])) {
return $object;
}
$properties = $schema['properties'];

foreach ($object as $key => $attribute) {
$object->{$key} = $this->castType($attribute, $properties[$key]);
}

return $object;
}

/**
* @param string $value
* @param array $parameter
* @return mixed
*/
protected function formatString($value, array $parameter)
{
if (!array_key_exists('format', $parameter)) {
return $value;
}

switch ($parameter['format']) {
case 'date':
$value = DateTime::createFromFormat('Y-m-d', $value);
if (!$value) {
throw new BadRequest('Invalid date parameter passed in');
}
break;
case 'date-time':
try {
$value = new DateTime($value);
} catch (Exception $e) {
throw new BadRequest('Invalid date parameter passed in');
}
break;
default:
// this is an open-type property
break;
}

return $value;
}
}

0 comments on commit 62c399c

Please sign in to comment.
You can’t perform that action at this time.