[PHP][Symfony] Enhancements (#6615)

* Removed commented code

* Input validation is now supported as strict JSON validation

* [PHP][Symfony] Improve the implementation
Closes #6614

* Generated code is tested to assure it compiles and updated README to dynamically load dependencies via composer

* Updated shell script because shippable tests were failing
This commit is contained in:
naelrashdeen
2017-10-23 16:50:56 +02:00
committed by wing328
parent a63e3f14f5
commit b034e4446a
84 changed files with 8575 additions and 956 deletions

View File

@@ -0,0 +1,91 @@
<?php
namespace Swagger\Server\Service;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use Swagger\Server\Service\StrictJsonDeserializationVisitor;
use JMS\Serializer\XmlDeserializationVisitor;
class JmsSerializer implements SerializerInterface
{
protected $serializer;
public function __construct()
{
$naming_strategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
$this->serializer = SerializerBuilder::create()
->setDeserializationVisitor('json', new StrictJsonDeserializationVisitor($naming_strategy))
->setDeserializationVisitor('xml', new XmlDeserializationVisitor($naming_strategy))
->build();
}
public function serialize($data, $format)
{
return SerializerBuilder::create()->build()->serialize($data, $this->convertFormat($format));
}
public function deserialize($data, $type, $format)
{
if ($format == 'string') {
return $this->deserializeString($data, $type);
}
// If we end up here, let JMS serializer handle the deserialization
return $this->serializer->deserialize($data, $type, $this->convertFormat($format));
}
private function convertFormat($format)
{
switch ($format) {
case 'application/json':
return 'json';
case 'application/xml':
return 'xml';
}
return null;
}
private function deserializeString($data, $type)
{
switch ($type) {
case 'int':
case 'integer':
if (is_int($data)) {
return $data;
}
if (is_numeric($data)) {
return $data + 0;
}
break;
case 'string':
break;
case 'boolean':
case 'bool':
if (strtolower($data) === 'true') {
return true;
}
if (strtolower($data) === 'false') {
return false;
}
break;
case 'array<csv>':
return explode(',', $data);
case 'array<ssv>':
return explode(' ', $data);
case 'array<tsv>':
return explode("\t", $data);
case 'array<pipes>':
return explode('|', $data);
}
// If we end up here, just return data
return $data;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Swagger\Server\Service;
interface SerializerInterface
{
/**
* Serializes the given data to the specified output format.
*
* @param object|array|scalar $data
* @param string $format
*
* @return string
*/
public function serialize($data, $format);
/**
* Deserializes the given data to the specified type.
*
* @param string $data
* @param string $type
* @param string $format
*
* @return object|array|scalar
*/
public function deserialize($data, $type, $format);
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* Copyright 2017 Dmitriy Simushev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Swagger\Server\Service;
use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor;
class StrictJsonDeserializationVisitor extends JsonDeserializationVisitor
{
/**
* {@inheritdoc}
*/
public function visitString($data, array $type, Context $context)
{
if (!is_string($data)) {
throw TypeMismatchException::fromValue('string', $data, $context);
}
return parent::visitString($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitBoolean($data, array $type, Context $context)
{
if (!is_bool($data)) {
throw TypeMismatchException::fromValue('boolean', $data, $context);
}
return parent::visitBoolean($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitInteger($data, array $type, Context $context)
{
if (!is_int($data)) {
throw TypeMismatchException::fromValue('integer', $data, $context);
}
return parent::visitInteger($data, $type, $context);
}
/**
* {@inheritdoc}
*/
public function visitDouble($data, array $type, Context $context)
{
if (!is_float($data) && !is_integer($data)) {
throw TypeMismatchException::fromValue('double', $data, $context);
}
return parent::visitDouble($data, $type, $context);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Swagger\Server\Service;
use Symfony\Component\Validator\Validation;
class SymfonyValidator implements ValidatorInterface
{
protected $validator;
public function __construct()
{
$this->validator = Validation::createValidator();
}
public function validate($value, $constraints = null, $groups = null)
{
return $this->validator->validate($value, $constraints, $groups);
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* Copyright 2017 Dmitriy Simushev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Swagger\Server\Service;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\Exception\RuntimeException;
class TypeMismatchException extends RuntimeException
{
/**
* A handy method for building exception instance.
*
* @param string $expected_type
* @param mixed $actual_value
* @param DeserializationContext|null $context
* @return TypeMismatchException
*/
public static function fromValue(
$expected_type,
$actual_value,
DeserializationContext $context = null
) {
if (null !== $context && count($context->getCurrentPath()) > 0) {
$property = sprintf('property "%s" to be ', implode('.', $context->getCurrentPath()));
} else {
$property = '';
}
return new static(sprintf(
'Expected %s%s, but got %s: %s',
$property,
$expected_type,
gettype($actual_value),
json_encode($actual_value)
));
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Swagger\Server\Service;
interface ValidatorInterface
{
/**
* Validates a value against a constraint or a list of constraints.
*
* If no constraint is passed, the constraint
* {@link \Symfony\Component\Validator\Constraints\Valid} is assumed.
*
* @param mixed $value The value to validate
* @param Constraint|Constraint[] $constraints The constraint(s) to validate
* against
* @param array|null $groups The validation groups to
* validate. If none is given,
* "Default" is assumed
*
* @return ConstraintViolationListInterface A list of constraint violations
* If the list is empty, validation
* succeeded
*/
public function validate($value, $constraints = null, $groups = null);
}