Skip to content

Commit

Permalink
[Form] Added FormTypeInterface::getAllowedOptionValues() to better va…
Browse files Browse the repository at this point in the history
…lidate passed options
  • Loading branch information
webmozart committed May 13, 2011
1 parent 21013b9 commit da28f8e
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/Symfony/Component/Form/AbstractType.php
Expand Up @@ -46,6 +46,18 @@ public function getDefaultOptions(array $options)
return array();
}

/**
* Returns the allowed option values for each option (if any).
*
* @param array $options
*
* @return array The allowed option values
*/
public function getAllowedOptionValues(array $options)
{
return array();
}

/**
* Returns the name of the parent type.
*
Expand Down
12 changes: 12 additions & 0 deletions src/Symfony/Component/Form/AbstractTypeExtension.php
Expand Up @@ -29,4 +29,16 @@ public function getDefaultOptions(array $options)
{
return array();
}

/**
* Returns the allowed option values for each option (if any).
*
* @param array $options
*
* @return array The allowed option values
*/
public function getAllowedOptionValues(array $options)
{
return array();
}
}
13 changes: 11 additions & 2 deletions src/Symfony/Component/Form/FormFactory.php
Expand Up @@ -114,6 +114,7 @@ public function createNamedBuilder($type, $name, $data = null, array $options =
$types = array();
$knownOptions = array();
$passedOptions = array_keys($options);
$optionValues = array();

if (!array_key_exists('data', $options)) {
$options['data'] = $data;
Expand All @@ -127,12 +128,14 @@ public function createNamedBuilder($type, $name, $data = null, array $options =
}

$defaultOptions = $type->getDefaultOptions($options);
$optionValues = array_merge_recursive($optionValues, $type->getAllowedOptionValues($options));

foreach ($type->getExtensions() as $typeExtension) {
$defaultOptions = array_merge($defaultOptions, $typeExtension->getDefaultOptions($options));
$defaultOptions = array_replace($defaultOptions, $typeExtension->getDefaultOptions($options));
$optionValues = array_merge_recursive($optionValues, $typeExtension->getAllowedOptionValues($options));
}

$options = array_merge($defaultOptions, $options);
$options = array_replace($defaultOptions, $options);
$knownOptions = array_merge($knownOptions, array_keys($defaultOptions));
array_unshift($types, $type);
$type = $type->getParent($options);
Expand All @@ -155,6 +158,12 @@ public function createNamedBuilder($type, $name, $data = null, array $options =
throw new CreationException(sprintf('The option "%s" does not exist', $diff[0]));
}

foreach ($optionValues as $option => $allowedValues) {
if (!in_array($options[$option], $allowedValues, true)) {
throw new CreationException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues)));
}
}

for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) {
$builder = $types[$i]->createBuilder($name, $this, $options);
}
Expand Down
9 changes: 9 additions & 0 deletions src/Symfony/Component/Form/FormTypeExtensionInterface.php
Expand Up @@ -21,5 +21,14 @@ function buildViewBottomUp(FormView $view, FormInterface $form);

function getDefaultOptions(array $options);

/**
* Returns the allowed option values for each option (if any).
*
* @param array $options
*
* @return array The allowed option values
*/
function getAllowedOptionValues(array $options);

function getExtendedType();
}
9 changes: 9 additions & 0 deletions src/Symfony/Component/Form/FormTypeInterface.php
Expand Up @@ -30,6 +30,15 @@ function createBuilder($name, FormFactoryInterface $factory, array $options);
*/
function getDefaultOptions(array $options);

/**
* Returns the allowed option values for each option (if any).
*
* @param array $options
*
* @return array The allowed option values
*/
function getAllowedOptionValues(array $options);

/**
* Returns the name of the parent type.
*
Expand Down
8 changes: 8 additions & 0 deletions tests/Symfony/Tests/Component/Form/Fixtures/FooType.php
Expand Up @@ -31,6 +31,14 @@ public function getDefaultOptions(array $options)
'data' => null,
'required' => false,
'max_length' => null,
'a_or_b' => 'a',
);
}

public function getAllowedOptionValues(array $options)
{
return array(
'a_or_b' => array('a', 'b'),
);
}

Expand Down
Expand Up @@ -12,6 +12,13 @@ public function buildForm(FormBuilder $builder, array $options)
$builder->setAttribute('bar', 'x');
}

public function getAllowedOptionValues(array $options)
{
return array(
'a_or_b' => array('c'),
);
}

public function getExtendedType()
{
return 'foo';
Expand Down
37 changes: 37 additions & 0 deletions tests/Symfony/Tests/Component/Form/FormFactoryTest.php
Expand Up @@ -162,6 +162,9 @@ public function testCreateNamedBuilderExpectsDataOptionToBeSupported()
$type->expects($this->any())
->method('getExtensions')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getAllowedOptionValues')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getDefaultOptions')
->will($this->returnValue(array(
Expand All @@ -186,6 +189,9 @@ public function testCreateNamedBuilderExpectsRequiredOptionToBeSupported()
$type->expects($this->any())
->method('getExtensions')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getAllowedOptionValues')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getDefaultOptions')
->will($this->returnValue(array(
Expand All @@ -210,6 +216,9 @@ public function testCreateNamedBuilderExpectsMaxLengthOptionToBeSupported()
$type->expects($this->any())
->method('getExtensions')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getAllowedOptionValues')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getDefaultOptions')
->will($this->returnValue(array(
Expand All @@ -234,6 +243,9 @@ public function testCreateNamedBuilderExpectsBuilderToBeReturned()
$type->expects($this->any())
->method('getExtensions')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getAllowedOptionValues')
->will($this->returnValue(array()));
$type->expects($this->any())
->method('getDefaultOptions')
->will($this->returnValue(array(
Expand Down Expand Up @@ -263,6 +275,31 @@ public function testCreateNamedBuilderExpectsOptionsToExist()
));
}

/**
* @expectedException Symfony\Component\Form\Exception\CreationException
*/
public function testCreateNamedBuilderExpectsOptionsToBeInValidRange()
{
$type = new FooType();
$this->extension1->addType($type);

$this->factory->createNamedBuilder('foo', 'bar', null, array(
'a_or_b' => 'c',
));
}

public function testCreateNamedBuilderAllowsExtensionsToExtendAllowedOptionValues()
{
$type = new FooType();
$this->extension1->addType($type);
$this->extension1->addTypeExtension(new FooTypeBarExtension());

// no exception this time
$this->factory->createNamedBuilder('foo', 'bar', null, array(
'a_or_b' => 'c',
));
}

public function testCreateNamedBuilderAddsTypeInstances()
{
$type = new FooType();
Expand Down

0 comments on commit da28f8e

Please sign in to comment.