2013-06-10 17:18:17 -07:00
|
|
|
<?php
|
|
|
|
|
2013-07-02 21:57:09 -07:00
|
|
|
/*
|
|
|
|
* This file is part of the NelmioApiDocBundle.
|
|
|
|
*
|
|
|
|
* (c) Nelmio <hello@nelm.io>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
2013-06-10 17:18:17 -07:00
|
|
|
namespace Nelmio\ApiDocBundle\Parser;
|
|
|
|
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
use Nelmio\ApiDocBundle\DataTypes;
|
2013-11-06 15:25:10 +01:00
|
|
|
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
2013-06-10 17:18:17 -07:00
|
|
|
use Symfony\Component\Validator\MetadataFactoryInterface;
|
|
|
|
use Symfony\Component\Validator\Constraint;
|
2013-11-07 14:11:09 +01:00
|
|
|
use Symfony\Component\Validator\Constraints\Type;
|
2013-06-10 17:18:17 -07:00
|
|
|
|
2013-07-02 21:57:09 -07:00
|
|
|
/**
|
|
|
|
* Uses the Symfony Validation component to extract information about API objects.
|
|
|
|
*/
|
|
|
|
class ValidationParser implements ParserInterface, PostParserInterface
|
2013-06-10 17:18:17 -07:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var \Symfony\Component\Validator\MetadataFactoryInterface
|
|
|
|
*/
|
|
|
|
protected $factory;
|
|
|
|
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
protected $typeMap = array(
|
2014-06-17 17:05:00 -07:00
|
|
|
'integer' => DataTypes::INTEGER,
|
|
|
|
'int' => DataTypes::INTEGER,
|
|
|
|
'scalar' => DataTypes::STRING,
|
|
|
|
'numeric' => DataTypes::INTEGER,
|
|
|
|
'boolean' => DataTypes::BOOLEAN,
|
|
|
|
'string' => DataTypes::STRING,
|
|
|
|
'float' => DataTypes::FLOAT,
|
|
|
|
'double' => DataTypes::FLOAT,
|
|
|
|
'long' => DataTypes::INTEGER,
|
|
|
|
'object' => DataTypes::MODEL,
|
|
|
|
'array' => DataTypes::COLLECTION,
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
'DateTime' => DataTypes::DATETIME,
|
|
|
|
);
|
|
|
|
|
2013-07-02 21:57:09 -07:00
|
|
|
/**
|
|
|
|
* Requires a validation MetadataFactory.
|
|
|
|
*
|
|
|
|
* @param MetadataFactoryInterface $factory
|
|
|
|
*/
|
2013-06-10 17:18:17 -07:00
|
|
|
public function __construct(MetadataFactoryInterface $factory)
|
|
|
|
{
|
|
|
|
$this->factory = $factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
|
|
|
public function supports(array $input)
|
|
|
|
{
|
|
|
|
$className = $input['class'];
|
|
|
|
|
|
|
|
return $this->factory->hasMetadataFor($className);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
|
|
|
public function parse(array $input)
|
|
|
|
{
|
|
|
|
$className = $input['class'];
|
2013-12-11 01:59:59 +01:00
|
|
|
|
2013-11-07 14:11:09 +01:00
|
|
|
return $this->doParse($className, array());
|
|
|
|
}
|
2013-06-10 17:18:17 -07:00
|
|
|
|
2013-11-07 14:11:09 +01:00
|
|
|
/**
|
|
|
|
* Recursively parse constraints.
|
|
|
|
*
|
|
|
|
* @param $className
|
|
|
|
* @param array $visited
|
|
|
|
* @return array
|
|
|
|
*/
|
2013-12-11 01:59:59 +01:00
|
|
|
protected function doParse($className, array $visited)
|
2013-11-07 14:11:09 +01:00
|
|
|
{
|
|
|
|
$params = array();
|
2013-06-10 17:18:17 -07:00
|
|
|
$classdata = $this->factory->getMetadataFor($className);
|
2013-06-30 18:46:00 -07:00
|
|
|
$properties = $classdata->getConstrainedProperties();
|
2013-06-10 17:18:17 -07:00
|
|
|
|
2014-06-26 12:27:47 -07:00
|
|
|
$refl = $classdata->getReflectionClass();
|
|
|
|
$defaults = $refl->getDefaultProperties();
|
|
|
|
|
2013-11-14 10:28:42 +01:00
|
|
|
foreach ($properties as $property) {
|
2013-06-30 18:46:00 -07:00
|
|
|
$vparams = array();
|
2014-06-26 12:27:47 -07:00
|
|
|
|
|
|
|
$vparams['default'] = isset($defaults[$property]) ? $defaults[$property] : null;
|
|
|
|
|
2013-06-30 18:46:00 -07:00
|
|
|
$pds = $classdata->getPropertyMetadata($property);
|
2013-11-14 10:28:42 +01:00
|
|
|
foreach ($pds as $propdata) {
|
2013-06-30 18:46:00 -07:00
|
|
|
$constraints = $propdata->getConstraints();
|
2013-06-10 17:18:17 -07:00
|
|
|
|
2013-11-14 10:28:42 +01:00
|
|
|
foreach ($constraints as $constraint) {
|
2013-11-07 14:11:09 +01:00
|
|
|
$vparams = $this->parseConstraint($constraint, $vparams, $className, $visited);
|
2013-06-30 18:46:00 -07:00
|
|
|
}
|
2013-06-10 17:18:17 -07:00
|
|
|
}
|
|
|
|
|
2013-11-14 10:28:42 +01:00
|
|
|
if (isset($vparams['format'])) {
|
2013-06-10 17:18:17 -07:00
|
|
|
$vparams['format'] = join(', ', $vparams['format']);
|
|
|
|
}
|
2013-06-30 18:46:00 -07:00
|
|
|
|
2014-08-04 09:42:48 -07:00
|
|
|
foreach (array('dataType', 'readonly', 'required', 'subType') as $reqprop) {
|
2013-11-14 10:28:42 +01:00
|
|
|
if (!isset($vparams[$reqprop])) {
|
2013-06-30 18:46:00 -07:00
|
|
|
$vparams[$reqprop] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-07 14:11:09 +01:00
|
|
|
// check for nested classes with All constraint
|
|
|
|
if (isset($vparams['class']) && !in_array($vparams['class'], $visited) && null !== $this->factory->getMetadataFor($vparams['class'])) {
|
|
|
|
$visited[] = $vparams['class'];
|
|
|
|
$vparams['children'] = $this->doParse($vparams['class'], $visited);
|
|
|
|
}
|
|
|
|
|
2014-08-04 09:42:48 -07:00
|
|
|
$vparams['actualType'] = isset($vparams['actualType']) ? $vparams['actualType'] : DataTypes::STRING;
|
|
|
|
|
2013-06-30 18:46:00 -07:00
|
|
|
$params[$property] = $vparams;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $params;
|
|
|
|
}
|
|
|
|
|
2013-07-02 21:57:09 -07:00
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
*/
|
|
|
|
public function postParse(array $input, array $parameters)
|
2013-06-30 18:46:00 -07:00
|
|
|
{
|
2013-11-14 10:28:42 +01:00
|
|
|
foreach ($parameters as $param => $data) {
|
|
|
|
if (isset($data['class']) && isset($data['children'])) {
|
2013-06-30 18:46:00 -07:00
|
|
|
$input = array('class' => $data['class']);
|
2013-06-30 21:28:40 -07:00
|
|
|
$parameters[$param]['children'] = array_merge(
|
|
|
|
$parameters[$param]['children'], $this->postParse($input, $parameters[$param]['children'])
|
|
|
|
);
|
|
|
|
$parameters[$param]['children'] = array_merge(
|
|
|
|
$parameters[$param]['children'], $this->parse($input, $parameters[$param]['children'])
|
|
|
|
);
|
2013-06-30 18:46:00 -07:00
|
|
|
}
|
2013-06-10 17:18:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-30 18:46:00 -07:00
|
|
|
return $parameters;
|
2013-06-10 17:18:17 -07:00
|
|
|
}
|
|
|
|
|
2013-07-02 21:57:09 -07:00
|
|
|
/**
|
|
|
|
* Create a valid documentation parameter based on an individual validation Constraint.
|
|
|
|
* Currently supports:
|
|
|
|
* - NotBlank/NotNull
|
|
|
|
* - Type
|
|
|
|
* - Email
|
|
|
|
* - Url
|
|
|
|
* - Ip
|
|
|
|
* - Length (min and max)
|
|
|
|
* - Choice (single and multiple, min and max)
|
|
|
|
* - Regex (match and non-match)
|
|
|
|
*
|
2013-11-14 10:28:42 +01:00
|
|
|
* @param Constraint $constraint The constraint metadata object.
|
|
|
|
* @param array $vparams The existing validation parameters.
|
|
|
|
* @return mixed The parsed list of validation parameters.
|
2013-07-02 21:57:09 -07:00
|
|
|
*/
|
2013-11-07 14:11:09 +01:00
|
|
|
protected function parseConstraint(Constraint $constraint, $vparams, $className, &$visited = array())
|
2013-06-10 17:18:17 -07:00
|
|
|
{
|
|
|
|
$class = substr(get_class($constraint), strlen('Symfony\\Component\\Validator\\Constraints\\'));
|
|
|
|
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::STRING;
|
2014-06-26 12:27:47 -07:00
|
|
|
$vparams['subType'] = null;
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
|
2013-11-14 10:28:42 +01:00
|
|
|
switch ($class) {
|
2013-06-10 17:18:17 -07:00
|
|
|
case 'NotBlank':
|
2013-11-14 11:12:58 +01:00
|
|
|
$vparams['format'][] = '{not blank}';
|
2013-06-10 17:18:17 -07:00
|
|
|
case 'NotNull':
|
|
|
|
$vparams['required'] = true;
|
|
|
|
break;
|
|
|
|
case 'Type':
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
if (isset($this->typeMap[$constraint->type])) {
|
|
|
|
$vparams['actualType'] = $this->typeMap[$constraint->type];
|
|
|
|
}
|
2013-06-10 17:18:17 -07:00
|
|
|
$vparams['dataType'] = $constraint->type;
|
|
|
|
break;
|
|
|
|
case 'Email':
|
|
|
|
$vparams['format'][] = '{email address}';
|
|
|
|
break;
|
|
|
|
case 'Url':
|
|
|
|
$vparams['format'][] = '{url}';
|
|
|
|
break;
|
|
|
|
case 'Ip':
|
|
|
|
$vparams['format'][] = '{ip address}';
|
|
|
|
break;
|
2013-08-30 11:59:57 +01:00
|
|
|
case 'Date':
|
|
|
|
$vparams['format'][] = '{Date YYYY-MM-DD}';
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::DATE;
|
2013-08-30 11:59:57 +01:00
|
|
|
break;
|
|
|
|
case 'DateTime':
|
|
|
|
$vparams['format'][] = '{DateTime YYYY-MM-DD HH:MM:SS}';
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::DATETIME;
|
2013-08-30 11:59:57 +01:00
|
|
|
break;
|
|
|
|
case 'Time':
|
|
|
|
$vparams['format'][] = '{Time HH:MM:SS}';
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::TIME;
|
2013-08-30 11:59:57 +01:00
|
|
|
break;
|
2013-06-10 17:18:17 -07:00
|
|
|
case 'Length':
|
|
|
|
$messages = array();
|
2013-11-14 10:28:42 +01:00
|
|
|
if (isset($constraint->min)) {
|
2013-06-10 17:18:17 -07:00
|
|
|
$messages[] = "min: {$constraint->min}";
|
|
|
|
}
|
2013-11-14 10:28:42 +01:00
|
|
|
if (isset($constraint->max)) {
|
2013-06-10 17:18:17 -07:00
|
|
|
$messages[] = "max: {$constraint->max}";
|
|
|
|
}
|
|
|
|
$vparams['format'][] = '{length: ' . join(', ', $messages) . '}';
|
|
|
|
break;
|
|
|
|
case 'Choice':
|
2013-11-06 15:25:10 +01:00
|
|
|
$choices = $this->getChoices($constraint, $className);
|
|
|
|
$format = '[' . join('|', $choices) . ']';
|
2013-11-14 10:28:42 +01:00
|
|
|
if ($constraint->multiple) {
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::COLLECTION;
|
|
|
|
$vparams['subType'] = DataTypes::ENUM;
|
2013-06-10 17:18:17 -07:00
|
|
|
$messages = array();
|
2013-11-14 10:28:42 +01:00
|
|
|
if (isset($constraint->min)) {
|
2013-06-10 17:18:17 -07:00
|
|
|
$messages[] = "min: {$constraint->min} ";
|
|
|
|
}
|
2013-11-14 10:28:42 +01:00
|
|
|
if (isset($constraint->max)) {
|
2013-06-10 17:18:17 -07:00
|
|
|
$messages[] = "max: {$constraint->max} ";
|
|
|
|
}
|
|
|
|
$vparams['format'][] = '{' . join ('', $messages) . 'choice of ' . $format . '}';
|
|
|
|
} else {
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::ENUM;
|
2013-06-10 17:18:17 -07:00
|
|
|
$vparams['format'][] = $format;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'Regex':
|
2013-11-14 10:28:42 +01:00
|
|
|
if ($constraint->match) {
|
2013-07-02 21:57:09 -07:00
|
|
|
$vparams['format'][] = '{match: ' . $constraint->pattern . '}';
|
|
|
|
} else {
|
|
|
|
$vparams['format'][] = '{not match: ' . $constraint->pattern . '}';
|
|
|
|
}
|
2013-06-10 17:18:17 -07:00
|
|
|
break;
|
2013-11-07 14:11:09 +01:00
|
|
|
case 'All':
|
|
|
|
foreach ($constraint->constraints as $childConstraint) {
|
|
|
|
if ($childConstraint instanceof Type) {
|
|
|
|
$nestedType = $childConstraint->type;
|
|
|
|
$exp = explode("\\", $nestedType);
|
|
|
|
if (!class_exists($nestedType)) {
|
|
|
|
$nestedType = substr($className, 0, strrpos($className, '\\') + 1).$nestedType;
|
|
|
|
|
|
|
|
if (!class_exists($nestedType)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['dataType'] = sprintf("array of objects (%s)", end($exp));
|
Unified data types [actualType and subType]
This is the result of https://github.com/nelmio/NelmioApiDocBundle/issues/410.
This PR aims to provide a uniform way of declaring data-types of parameters for
parsers and handlers to follow. In turn, this would allow formatters to
determine data-types in a cleaner and less volatile manner. (See use-case that
can be improved with this PR:
https://github.com/nelmio/NelmioApiDocBundle/blob/master/Formatter/AbstractFormatter.php#L103)
This is possible by the addition two properties to each property item in
`response`, and `parameters` fields in each API endpoint produced by the
`ApiDocExtractor`:
* `actualType` Contains a value from one of the `DataTypes` class constants.
* `subType` Can contain either `null`, or any other `DataTypes` class constant.
This is relevant when the `actualType` is a `DataTypes::COLLECTION`, wherein
`subType` would specify the type of the collection items. It is also relevant
when `actualType` is a `DataTypes::MODEL`, wherein `subType` would contain an
identifier of the model (the FQCN or anything the parser would wish to specify)
Examples:
```php
array(
'id' => array(
'dataType' => 'integer',
'actualType' => DataTypes::INTEGER,
'subType' => null,
),
'profile' => array(
'dataType' => 'object (Profile)',
'actualType' => DataTypes::MODEL,
'subType' => 'Foo\Entity\Profile',
'children' => array(
'name' => array(
'dataType' => 'string',
'actualType' => DataTypes::STRING,
'subType' => null,
),
'birthDate' => array(
'dataType' => 'date',
'actualType' => DataTypes::DATE,
'subType' => null,
),
)
),
'languages' => array(
'dataType' => 'array of strings',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::STRING,
),
'roles' => array(
'dataType' => 'array of choices',
'actualType' => DataTypes::COLLECTION,
'subType' => DataTypes::ENUM,
),
'groups' => array(
'dataType' => 'array of objects (Group)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Group',
),
'profileRevisions' => array(
'dataType' => 'array of objects (Profile)',
'actualType' => DataTypes::COLLECTION,
'subType' => 'Foo\Entity\Profile',
),
'address' => array(
'dataType' => 'object (a_type_a_custom_JMS_serializer_handler_handles)',
'actualType' => DataTypes::MODEL,
'subType' => 'a_type_a_custom_JMS_serializer_handler_handles',
),
);
```
When a formatter omits the `dataType` property or leaves it blank, it is
inferred within `ApiDocExtractor` before everything is passed to formatters.
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['actualType'] = DataTypes::COLLECTION;
|
2014-06-17 17:05:00 -07:00
|
|
|
$vparams['subType'] = $nestedType;
|
|
|
|
$vparams['class'] = $nestedType;
|
2013-11-07 14:11:09 +01:00
|
|
|
|
|
|
|
if (!in_array($nestedType, $visited)) {
|
|
|
|
$visited[] = $nestedType;
|
|
|
|
$vparams['children'] = $this->doParse($nestedType, $visited);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-06-10 17:18:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return $vparams;
|
|
|
|
}
|
2013-11-06 15:25:10 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return Choice constraint choices.
|
|
|
|
*
|
2014-06-25 08:46:01 +02:00
|
|
|
* @param Constraint $constraint
|
2013-11-06 15:25:10 +01:00
|
|
|
* @param $className
|
|
|
|
* @return array
|
|
|
|
* @throws \Symfony\Component\Validator\Exception\ConstraintDefinitionException
|
|
|
|
*/
|
2013-11-14 10:28:42 +01:00
|
|
|
protected function getChoices(Constraint $constraint, $className)
|
2013-11-06 15:25:10 +01:00
|
|
|
{
|
|
|
|
if ($constraint->callback) {
|
|
|
|
if (is_callable(array($className, $constraint->callback))) {
|
|
|
|
$choices = call_user_func(array($className, $constraint->callback));
|
|
|
|
} elseif (is_callable($constraint->callback)) {
|
|
|
|
$choices = call_user_func($constraint->callback);
|
|
|
|
} else {
|
|
|
|
throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$choices = $constraint->choices;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $choices;
|
|
|
|
}
|
|
|
|
}
|