Updated postParse logic to utilize an interface and to avoid unnecessary "supports" checks.

Expanded documentation on new classes and methods.
This commit is contained in:
Josh Hall-Bachner 2013-07-02 21:57:09 -07:00
parent 23f64b84f6
commit 54a6ad566d
4 changed files with 107 additions and 11 deletions

View File

@ -14,6 +14,7 @@ namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Parser\ParserInterface;
use Nelmio\ApiDocBundle\Parser\PostParserInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -268,15 +269,17 @@ class ApiDocExtractor
$normalizedInput = $this->normalizeClassParameter($input);
$supportedParsers = array();
$parameters = array();
foreach ($this->parsers as $parser) {
if ($parser->supports($normalizedInput)) {
$supportedParsers[] = $parser;
$parameters = $this->mergeParameters($parameters, $parser->parse($normalizedInput));
}
}
foreach($this->parsers as $parser) {
if($parser->supports($normalizedInput) && method_exists($parser, 'postParse')) {
foreach($supportedParsers as $parser) {
if($parser instanceof PostParserInterface) {
$mp = $parser->postParse($normalizedInput, $parameters);
$parameters = $this->mergeParameters($parameters, $mp);
}
@ -383,6 +386,18 @@ class ApiDocExtractor
return array_merge($defaults, $input);
}
/**
* Merges two parameter arrays together. This logic allows documentation to be built
* from multiple parser passes, with later passes extending previous passes:
* - Boolean values are true if any parser returns true.
* - Requirement parameters are concatenated.
* - Other string values are overridden by later parsers when present.
* - Array parameters are recursively merged.
*
* @param array $p1 The pre-existing parameters array.
* @param array $p2 The newly-returned parameters array.
* @return array The resulting, merged array.
*/
protected function mergeParameters($p1, $p2)
{
$params = $p1;
@ -403,7 +418,7 @@ class ApiDocExtractor
} elseif(!is_null($value)) {
if(in_array($name, array('required', 'readonly'))) {
$v1[$name] = $v1[$name] || $value;
} elseif($name == 'requirement') {
} elseif(in_array($name, array('requirement'))) {
if(isset($v1[$name])) {
$v1[$name] .= ', ' . $value;
} else {
@ -438,6 +453,12 @@ class ApiDocExtractor
}
}
/**
* Clears the temporary 'class' parameter from the parameters array before it is returned.
*
* @param array $array The source array.
* @return array The cleared array.
*/
protected function clearClasses($array)
{
if(is_array($array)) {

View File

@ -33,6 +33,8 @@ interface ParserInterface
* - readonly boolean
* - children (optional) array of nested property names mapped to arrays
* in the format described here
* - class (optional) the fully-qualified class name of the item, if
* it is represented by an object
*
* @param string $item The string type of input to parse.
* @return array

View File

@ -0,0 +1,38 @@
<?php
/*
* 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.
*/
namespace Nelmio\ApiDocBundle\Parser;
/**
* This is the interface parsers must implement in order to register a second parsing pass after the initial structure
* is populated..
*/
interface PostParserInterface
{
/**
* Reparses an object for additional documentation details after it has already been parsed once, to allow
* parsers to extend information initially documented by other parsers.
*
* Returns an array of class property metadata where each item is a key (the property name) and
* an array of data with the following keys:
* - dataType string
* - required boolean
* - description string
* - readonly boolean
* - children (optional) array of nested property names mapped to arrays
* in the format described here
*
* @param string $item The string type of input to parse.
* @param array $parameters The previously-parsed parameters array.
* @return array
*/
public function postParse(array $item, array $parameters);
}

View File

@ -1,18 +1,34 @@
<?php
/*
* 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.
*/
namespace Nelmio\ApiDocBundle\Parser;
use Nelmio\ApiDocBundle\Parser\ParserInterface;
use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Constraint;
class ValidationParser implements ParserInterface
/**
* Uses the Symfony Validation component to extract information about API objects.
*/
class ValidationParser implements ParserInterface, PostParserInterface
{
/**
* @var \Symfony\Component\Validator\MetadataFactoryInterface
*/
protected $factory;
/**
* Requires a validation MetadataFactory.
*
* @param MetadataFactoryInterface $factory
*/
public function __construct(MetadataFactoryInterface $factory)
{
$this->factory = $factory;
@ -66,7 +82,10 @@ class ValidationParser implements ParserInterface
return $params;
}
public function postParse(array $input, $parameters)
/**
* {@inheritDoc}
*/
public function postParse(array $input, array $parameters)
{
foreach($parameters as $param => $data) {
if(isset($data['class']) && isset($data['children'])) {
@ -83,6 +102,22 @@ class ValidationParser implements ParserInterface
return $parameters;
}
/**
* 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)
*
* @param Constraint $constraint The constraint metadata object.
* @param array $vparams The existing validation parameters.
* @return mixed The parsed list of validation parameters.
*/
protected function parseConstraint(Constraint $constraint, $vparams)
{
$class = substr(get_class($constraint), strlen('Symfony\\Component\\Validator\\Constraints\\'));