Merge pull request #329 from maxromanovsky/form-type-parser-improvements

Form Parser improvements for date, datetime & choice form types (format & types)
This commit is contained in:
William Durand 2014-05-12 11:56:00 -04:00
commit 36c223ab3a
4 changed files with 218 additions and 0 deletions

View File

@ -13,6 +13,8 @@ namespace Nelmio\ApiDocBundle\Parser;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\Exception\FormException;
@ -42,6 +44,7 @@ class FormTypeParser implements ParserInterface
'integer' => 'int',
'textarea' => 'string',
'country' => 'string',
'choice' => 'choice',
);
public function __construct(FormFactoryInterface $formFactory)
@ -153,6 +156,37 @@ class FormTypeParser implements ParserInterface
'description' => $config->getAttribute('description'),
'readonly' => $config->getDisabled(),
);
switch ($bestType) {
case 'datetime':
if (($format = $config->getOption('date_format')) && is_string($format)) {
$parameters[$name]['format'] = $format;
} elseif ('single_text' == $config->getOption('widget') && $format = $config->getOption('format')) {
$parameters[$name]['format'] = $format;
}
break;
case 'date':
if (($format = $config->getOption('format')) && is_string($format)) {
$parameters[$name]['format'] = $format;
}
break;
case 'choice':
if ($config->getOption('multiple')) {
$parameters[$name]['dataType'] = sprintf('array of %ss', $parameters[$name]['dataType']);
}
if (($choices = $config->getOption('choices')) && is_array($choices) && count($choices)) {
$parameters[$name]['format'] = json_encode($choices);
} elseif (($choiceList = $config->getOption('choice_list')) && $choiceList instanceof ChoiceListInterface) {
$choices = $this->handleChoiceListValues($choiceList);
if (is_array($choices) && count($choices)) {
$parameters[$name]['format'] = json_encode($choices);
}
}
break;
}
}
return $parameters;
@ -188,4 +222,24 @@ class FormTypeParser implements ParserInterface
// nothing
}
}
private function handleChoiceListValues(ChoiceListInterface $choiceList) {
$choices = array();
foreach (array($choiceList->getPreferredViews(), $choiceList->getRemainingViews()) as $viewList) {
$choices = array_merge($choices, $this->handleChoiceViewsHierarchy($viewList));
}
return $choices;
}
private function handleChoiceViewsHierarchy(array $choiceViews) {
$choices = array();
foreach ($choiceViews as $item) {
if ($item instanceof ChoiceView) {
$choices[$item->value] = $item->label;
} elseif (is_array($item)) {
$choices = array_merge($choices, $this->handleChoiceViewsHierarchy($item));
}
}
return $choices;
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* Created by PhpStorm.
* User: Maxim_Romanovsky
* Date: 4/4/14
* Time: 11:00 AM
*/
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ImprovedTestType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('dt1', 'datetime', array('widget' => 'single_text', 'description' => 'A nice description'))
->add('dt2', 'datetime', array('date_format' => 'M/d/y'))
->add('dt3', 'datetime', array('widget' => 'single_text', 'format' => 'M/d/y H:i:s'))
->add('dt4', 'datetime', array('date_format' => \IntlDateFormatter::MEDIUM))
->add('dt5', 'datetime', array('format' => 'M/d/y H:i:s'))
->add('d1', 'date', array('format' => \IntlDateFormatter::MEDIUM))
->add('d2', 'date', array('format' => 'd-M-y'))
->add('c1', 'choice', array('choices' => array('m' => 'Male', 'f' => 'Female')))
->add('c2', 'choice', array('choices' => array('m' => 'Male', 'f' => 'Female'), 'multiple' => true))
->add('c3', 'choice', array('choices' => array()))
->add('c4', 'choice', array('choice_list' => new SimpleChoiceList(array('foo' => 'bar', 'bazgroup' => array('baz' => 'Buzz')))))
;
}
/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Model\ImprovedTest',
));
return;
}
public function getName()
{
return '';
}
}

View File

@ -0,0 +1,29 @@
<?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\Tests\Fixtures\Model;
use Symfony\Component\Validator\Constraints as Assert;
class ImprovedTest
{
public $dt1;
public $dt2;
public $dt3;
public $dt4;
public $dt5;
public $d1;
public $d2;
public $c1;
public $c2;
public $c3;
public $c4;
}

View File

@ -5,6 +5,7 @@ use Nelmio\ApiDocBundle\Form\Extension\DescriptionFormTypeExtension;
use Nelmio\ApiDocBundle\Parser\FormTypeParser;
use Nelmio\ApiDocBundle\Tests\Fixtures;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormFactoryBuilder;
use Symfony\Component\Form\ResolvedFormTypeFactory;
@ -147,6 +148,84 @@ class FormTypeParserTest extends \PHPUnit_Framework_TestCase
)
)
),
array(
array('class' => 'Nelmio\ApiDocBundle\Tests\Fixtures\Form\ImprovedTestType'),
array(
'dt1' => array(
'dataType' => 'datetime',
'required' => true,
'description' => 'A nice description',
'readonly' => false,
'format' => DateTimeType::HTML5_FORMAT,
),
'dt2' => array(
'dataType' => 'datetime',
'required' => true,
'description' => '',
'readonly' => false,
'format' => 'M/d/y',
),
'dt3' => array(
'dataType' => 'datetime',
'required' => true,
'description' => '',
'readonly' => false,
'format' => 'M/d/y H:i:s',
),
'dt4' => array(
'dataType' => 'datetime',
'required' => true,
'description' => '',
'readonly' => false,
),
'dt5' => array(
'dataType' => 'datetime',
'required' => true,
'description' => '',
'readonly' => false,
),
'd1' => array(
'dataType' => 'date',
'required' => true,
'description' => '',
'readonly' => false,
),
'd2' => array(
'dataType' => 'date',
'required' => true,
'description' => '',
'readonly' => false,
'format' => 'd-M-y',
),
'c1' => array(
'dataType' => 'choice',
'required' => true,
'description' => '',
'readonly' => false,
'format' => json_encode(array('m' => 'Male', 'f' => 'Female')),
),
'c2' => array(
'dataType' => 'array of choices',
'required' => true,
'description' => '',
'readonly' => false,
'format' => json_encode(array('m' => 'Male', 'f' => 'Female')),
),
'c3' => array(
'dataType' => 'choice',
'required' => true,
'description' => '',
'readonly' => false,
),
'c4' => array(
'dataType' => 'choice',
'required' => true,
'description' => '',
'readonly' => false,
'format' => json_encode(array('foo' => 'bar', 'baz' => 'Buzz')),
),
)
),
);
}
}