[Form] Options are now passed to buildView() and buildViewBottomUp()

This commit is contained in:
Bernhard Schussek 2012-05-23 18:47:14 +02:00
parent 027259eba4
commit 0ef4066983
35 changed files with 379 additions and 355 deletions

View File

@ -488,6 +488,8 @@
* `getErrorBubbling`
* `getNormTransformers`
* `getClientTransformers`
* `getAttribute`
* `hasAttribute`
You can access these methods on the `FormConfigInterface` object instead.
@ -609,6 +611,24 @@
The second argument `$value` contains the current default value and
does not have to be specified if not needed.
* A third argument $options was added to the methods `buildView()` and
`buildViewBottomUp()` in `FormTypeInterface` and `FormTypeExtensionInterface`.
You should adapt your implementing classes.
Before:
```
public function buildView(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form)
```
After:
```
public function buildView(FormView $view, FormInterface $form, array $options)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
```
### Validator
* The methods `setMessage()`, `getMessageTemplate()` and

View File

@ -35,14 +35,14 @@ abstract class AbstractType implements FormTypeInterface
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
}
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
}

View File

@ -28,14 +28,14 @@ abstract class AbstractTypeExtension implements FormTypeExtensionInterface
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
}
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
}

View File

@ -81,6 +81,8 @@ CHANGELOG
* `getErrorBubbling`
* `getNormTransformers`
* `getClientTransformers`
* `getAttribute`
* `hasAttribute`
* deprecated the option "validation_constraint" in favor of the new
option "constraints"
* removed superfluous methods from DataMapperInterface
@ -92,3 +94,9 @@ CHANGELOG
which accepts an OptionsResolver instance
* deprecated the methods `getDefaultOptions` and `getAllowedOptionValues`
in FormTypeInterface and FormTypeExtensionInterface
* options passed during construction can now be accessed from FormConfigInterface
* [BC BREAK] the options array is now passed as last argument of the
methods
* `buildView`
* `buildViewBottomUp`
in FormTypeInterface and FormTypeExtensionInterface

View File

@ -27,17 +27,16 @@ class CheckboxType extends AbstractType
{
$builder
->appendClientTransformer(new BooleanToStringTransformer($options['value']))
->setAttribute('value', $options['value'])
;
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view
->set('value', $form->getAttribute('value'))
->set('value', $options['value'])
->set('checked', null !== $form->getClientData())
;
}

View File

@ -36,10 +36,6 @@ class ChoiceType extends AbstractType
*/
public function buildForm(FormBuilder $builder, array $options)
{
if ($options['choice_list'] && !$options['choice_list'] instanceof ChoiceListInterface) {
throw new FormException('The "choice_list" must be an instance of "Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface".');
}
if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) {
throw new FormException('Either the option "choices" or "choice_list" must be set.');
}
@ -47,30 +43,7 @@ class ChoiceType extends AbstractType
if ($options['expanded']) {
$this->addSubForms($builder, $options['choice_list']->getPreferredViews(), $options);
$this->addSubForms($builder, $options['choice_list']->getRemainingViews(), $options);
}
// empty value
if ($options['multiple'] || $options['expanded']) {
// never use and empty value for these cases
$emptyValue = null;
} elseif (false === $options['empty_value']) {
// an empty value should be added but the user decided otherwise
$emptyValue = null;
} else {
// empty value has been set explicitly
$emptyValue = $options['empty_value'];
}
$builder
->setAttribute('choice_list', $options['choice_list'])
->setAttribute('preferred_choices', $options['preferred_choices'])
->setAttribute('multiple', $options['multiple'])
->setAttribute('expanded', $options['expanded'])
->setAttribute('required', $options['required'])
->setAttribute('empty_value', $emptyValue)
;
if ($options['expanded']) {
if ($options['multiple']) {
$builder
->appendClientTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list']))
@ -100,20 +73,18 @@ class ChoiceType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$choiceList = $form->getAttribute('choice_list');
$view
->set('multiple', $form->getAttribute('multiple'))
->set('expanded', $form->getAttribute('expanded'))
->set('preferred_choices', $choiceList->getPreferredViews())
->set('choices', $choiceList->getRemainingViews())
->set('multiple', $options['multiple'])
->set('expanded', $options['expanded'])
->set('preferred_choices', $options['choice_list']->getPreferredViews())
->set('choices', $options['choice_list']->getRemainingViews())
->set('separator', '-------------------')
->set('empty_value', $form->getAttribute('empty_value'))
->set('empty_value', $options['empty_value'])
;
if ($view->get('multiple') && !$view->get('expanded')) {
if ($options['multiple'] && !$options['expanded']) {
// Add "[]" to the name in case a select tag with multiple options is
// displayed. Otherwise only one of the selected options is sent in the
// POST request.
@ -124,14 +95,14 @@ class ChoiceType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
if ($view->get('expanded')) {
if ($options['expanded']) {
// Radio buttons should have the same name as the parent
$childName = $view->get('full_name');
// Checkboxes should append "[]" to allow multiple selection
if ($view->get('multiple')) {
if ($options['multiple']) {
$childName .= '[]';
}
@ -166,6 +137,19 @@ class ChoiceType extends AbstractType
return $options['required'] ? null : '';
};
$emptyValueFilter = function (Options $options, $emptyValue) {
if ($options['multiple'] || $options['expanded']) {
// never use an empty value for these cases
return null;
} elseif (false === $emptyValue) {
// an empty value should be added but the user decided otherwise
return null;
}
// empty value has been set explicitly
return $emptyValue;
};
$singleControl = function (Options $options) {
return !$options['expanded'];
};
@ -179,7 +163,15 @@ class ChoiceType extends AbstractType
'empty_data' => $emptyData,
'empty_value' => $emptyValue,
'error_bubbling' => false,
'single_control' => $singleControl,
'single_control' => $singleControl,
));
$resolver->setFilters(array(
'empty_value' => $emptyValueFilter,
));
$resolver->setAllowedTypes(array(
'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'),
));
}

View File

@ -40,34 +40,30 @@ class CollectionType extends AbstractType
$options['allow_delete']
);
$builder
->addEventSubscriber($resizeListener)
->setAttribute('allow_add', $options['allow_add'])
->setAttribute('allow_delete', $options['allow_delete'])
;
$builder->addEventSubscriber($resizeListener);
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view
->set('allow_add', $form->getAttribute('allow_add'))
->set('allow_delete', $form->getAttribute('allow_delete'))
->set('allow_add', $options['allow_add'])
->set('allow_delete', $options['allow_delete'])
;
if ($form->hasAttribute('prototype')) {
$view->set('prototype', $form->getAttribute('prototype')->createView($view));
if ($form->getConfig()->hasAttribute('prototype')) {
$view->set('prototype', $form->getConfig()->getAttribute('prototype')->createView($view));
}
}
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
if ($form->hasAttribute('prototype') && $view->get('prototype')->get('multipart')) {
if ($form->getConfig()->hasAttribute('prototype') && $view->get('prototype')->get('multipart')) {
$view->set('multipart', true);
}
}

View File

@ -111,18 +111,16 @@ class DateTimeType extends AbstractType
new DateTimeToArrayTransformer($options['data_timezone'], $options['data_timezone'], $parts)
));
}
$builder->setAttribute('widget', $options['widget']);
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('widget', $form->getAttribute('widget'));
$view->set('widget', $options['widget']);
if ('single_text' === $form->getAttribute('widget')) {
if ('single_text' === $options['widget']) {
$view->set('type', 'datetime');
}
}

View File

@ -130,24 +130,22 @@ class DateType extends AbstractType
));
}
$builder
->setAttribute('formatter', $formatter)
->setAttribute('widget', $options['widget']);
$builder->setAttribute('formatter', $formatter);
}
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
$view->set('widget', $form->getAttribute('widget'));
$view->set('widget', $options['widget']);
if ('single_text' === $form->getAttribute('widget')) {
if ('single_text' === $options['widget']) {
$view->set('type', 'date');
}
if ($view->hasChildren()) {
$pattern = $form->getAttribute('formatter')->getPattern();
$pattern = $form->getConfig()->getAttribute('formatter')->getPattern();
// set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy)
// lookup various formats at http://userguide.icu-project.org/formatparse/datetime

View File

@ -21,7 +21,7 @@ class FileType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view
->set('type', 'file')
@ -32,7 +32,7 @@ class FileType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
$view
->set('multipart', true)

View File

@ -31,14 +31,6 @@ class FormType extends AbstractType
*/
public function buildForm(FormBuilder $builder, array $options)
{
if (!is_array($options['attr'])) {
throw new FormException('The "attr" option must be an "array".');
}
if (!is_array($options['label_attr'])) {
throw new FormException('The "label_attr" option must be an "array".');
}
$builder
->setRequired($options['required'])
->setDisabled($options['disabled'])
@ -49,14 +41,6 @@ class FormType extends AbstractType
->setMapped($options['mapped'])
->setByReference($options['by_reference'])
->setVirtual($options['virtual'])
->setAttribute('read_only', $options['read_only'])
->setAttribute('max_length', $options['max_length'])
->setAttribute('pattern', $options['pattern'])
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))
->setAttribute('attr', $options['attr'])
->setAttribute('label_attr', $options['label_attr'])
->setAttribute('translation_domain', $options['translation_domain'])
->setAttribute('single_control', $options['single_control'])
->setData($options['data'])
->setDataMapper(new PropertyPathMapper())
;
@ -69,10 +53,10 @@ class FormType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$name = $form->getName();
$readOnly = $form->getAttribute('read_only');
$readOnly = $options['read_only'];
if ($view->hasParent()) {
if ('' === $name) {
@ -115,23 +99,23 @@ class FormType extends AbstractType
->set('value', $form->getClientData())
->set('disabled', $form->isDisabled())
->set('required', $form->isRequired())
->set('max_length', $form->getAttribute('max_length'))
->set('pattern', $form->getAttribute('pattern'))
->set('max_length', $options['max_length'])
->set('pattern', $options['pattern'])
->set('size', null)
->set('label', $form->getAttribute('label'))
->set('label', $options['label'] ?: $this->humanize($form->getName()))
->set('multipart', false)
->set('attr', $form->getAttribute('attr'))
->set('label_attr', $form->getAttribute('label_attr'))
->set('single_control', $form->getAttribute('single_control'))
->set('attr', $options['attr'])
->set('label_attr', $options['label_attr'])
->set('single_control', $options['single_control'])
->set('types', $types)
->set('translation_domain', $form->getAttribute('translation_domain'))
->set('translation_domain', $options['translation_domain'])
;
}
/**
* {@inheritdoc}
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
$multipart = false;
@ -214,6 +198,11 @@ class FormType extends AbstractType
'single_control' => false,
'translation_domain' => 'messages',
));
$resolver->setAllowedTypes(array(
'attr' => 'array',
'label_attr' => 'array',
));
}
/**
@ -221,7 +210,7 @@ class FormType extends AbstractType
*/
public function createBuilder($name, FormFactoryInterface $factory, array $options)
{
return new FormBuilder($name, $options['data_class'], new EventDispatcher(), $factory);
return new FormBuilder($name, $options['data_class'], new EventDispatcher(), $factory, $options);
}
/**

View File

@ -34,16 +34,15 @@ class MoneyType extends AbstractType
null,
$options['divisor']
))
->setAttribute('currency', $options['currency'])
;
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('money_pattern', self::getPattern($form->getAttribute('currency')));
$view->set('money_pattern', self::getPattern($options['currency']));
}
/**

View File

@ -22,17 +22,9 @@ class PasswordType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilder $builder, array $options)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$builder->setAttribute('always_empty', $options['always_empty']);
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
{
if ($form->getAttribute('always_empty') || !$form->isBound()) {
if ($options['always_empty'] || !$form->isBound()) {
$view->set('value', '');
}
}

View File

@ -20,7 +20,7 @@ class TextareaType extends AbstractType
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('pattern', null);
}

View File

@ -42,12 +42,6 @@ class TimeType extends AbstractType
$hourOptions = $minuteOptions = $secondOptions = array();
if ('choice' === $options['widget']) {
if (is_array($options['empty_value'])) {
$options['empty_value'] = array_merge(array('hour' => null, 'minute' => null, 'second' => null), $options['empty_value']);
} else {
$options['empty_value'] = array('hour' => $options['empty_value'], 'minute' => $options['empty_value'], 'second' => $options['empty_value']);
}
$hours = $minutes = array();
foreach ($options['hours'] as $hour) {
@ -114,24 +108,19 @@ class TimeType extends AbstractType
new DateTimeToArrayTransformer($options['data_timezone'], $options['data_timezone'], $parts)
));
}
$builder
->setAttribute('widget', $options['widget'])
->setAttribute('with_seconds', $options['with_seconds'])
;
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form)
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view
->set('widget', $form->getAttribute('widget'))
->set('with_seconds', $form->getAttribute('with_seconds'))
->set('widget', $options['widget'])
->set('with_seconds', $options['with_seconds'])
;
if ('single_text' === $form->getAttribute('widget')) {
if ('single_text' === $options['widget']) {
$view->set('type', 'time');
}
}
@ -145,6 +134,21 @@ class TimeType extends AbstractType
return $options['widget'] === 'single_text';
};
$emptyValueFilter = function (Options $options, $emptyValue) {
if (is_array($emptyValue)) {
return array_merge(
array('hour' => null, 'minute' => null, 'second' => null),
$emptyValue
);
}
return array(
'hour' => $emptyValue,
'minute' => $emptyValue,
'second' => $emptyValue
);
};
$resolver->setDefaults(array(
'hours' => range(0, 23),
'minutes' => range(0, 59),
@ -164,7 +168,11 @@ class TimeType extends AbstractType
// representation is not \DateTime, but an array, we need to unset
// this option.
'data_class' => null,
'single_control' => $singleControl,
'single_control' => $singleControl,
));
$resolver->setFilters(array(
'empty_value' => $emptyValueFilter,
));
$resolver->setAllowedValues(array(

View File

@ -63,7 +63,7 @@ class CsrfValidationListener implements EventSubscriberInterface
$form = $event->getForm();
$data = $event->getData();
if ($form->isRoot() && !$form->getAttribute('single_control')) {
if ($form->isRoot() && !$form->getConfig()->getOption('single_control')) {
if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) {
$form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form'));
}

View File

@ -47,11 +47,7 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
return;
}
// use a low priority so higher priority listeners don't remove the field
$builder
->setAttribute('csrf_field_name', $options['csrf_field_name'])
->setAttribute('csrf_provider', $options['csrf_provider'])
->setAttribute('csrf_intention', $options['intention'])
->setAttribute('csrf_factory', $builder->getFormFactory())
->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention']))
;
@ -63,15 +59,13 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
* @param FormView $view The form view
* @param FormInterface $form The form
*/
public function buildViewBottomUp(FormView $view, FormInterface $form)
public function buildViewBottomUp(FormView $view, FormInterface $form, array $options)
{
if (!$view->hasParent() && !$form->getAttribute('single_control') && $form->hasAttribute('csrf_field_name')) {
$name = $form->getAttribute('csrf_field_name');
$csrfProvider = $form->getAttribute('csrf_provider');
$intention = $form->getAttribute('csrf_intention');
$factory = $form->getAttribute('csrf_factory');
$data = $csrfProvider->generateCsrfToken($intention);
$csrfForm = $factory->createNamed('hidden', $name, $data, array(
if ($options['csrf_protection'] && !$view->hasParent() && !$options['single_control']) {
$factory = $form->getConfig()->getAttribute('csrf_factory');
$data = $options['csrf_provider']->generateCsrfToken($options['intention']);
$csrfForm = $factory->createNamed('hidden', $options['csrf_field_name'], $data, array(
'property_path' => false,
));

View File

@ -55,6 +55,7 @@ class FormValidator extends ConstraintValidator
$path = $this->context->getPropertyPath();
$graphWalker = $this->context->getGraphWalker();
$groups = $this->getValidationGroups($form);
$config = $form->getConfig();
if (!empty($path)) {
$path .= '.';
@ -72,7 +73,7 @@ class FormValidator extends ConstraintValidator
// Validate the data against the constraints defined
// in the form
$constraints = $form->getAttribute('constraints');
$constraints = $config->getOption('constraints');
foreach ($constraints as $constraint) {
foreach ($groups as $group) {
$graphWalker->walkConstraint($constraint, $form->getData(), $group, $path . 'data');
@ -85,7 +86,7 @@ class FormValidator extends ConstraintValidator
// Mark the form with an error if it is not synchronized
$this->context->addViolation(
$form->getAttribute('invalid_message'),
$config->getOption('invalid_message'),
array('{{ value }}' => $clientDataAsString),
$form->getClientData(),
null,
@ -96,7 +97,7 @@ class FormValidator extends ConstraintValidator
// Mark the form with an error if it contains extra fields
if (count($form->getExtraData()) > 0) {
$this->context->addViolation(
$form->getAttribute('extra_fields_message'),
$config->getOption('extra_fields_message'),
array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))),
$form->getExtraData()
);
@ -126,7 +127,7 @@ class FormValidator extends ConstraintValidator
if ($length > $maxLength) {
$this->context->addViolation(
$form->getAttribute('post_max_size_message'),
$config->getOption('post_max_size_message'),
array('{{ max }}' => $max),
$length
);
@ -161,7 +162,7 @@ class FormValidator extends ConstraintValidator
$parent = $form->getParent();
while (null !== $parent) {
if (!$parent->getAttribute('cascade_validation')) {
if (!$parent->getConfig()->getOption('cascade_validation')) {
return false;
}
@ -182,29 +183,18 @@ class FormValidator extends ConstraintValidator
{
$groups = null;
if ($form->hasAttribute('validation_groups')) {
$groups = $form->getAttribute('validation_groups');
while (null !== $form && null === $groups) {
$groups = $form->getConfig()->getOption('validation_groups');
if (is_callable($groups)) {
$groups = (array) call_user_func($groups, $form);
}
}
$currentForm = $form;
while (!$groups && $currentForm->hasParent()) {
$currentForm = $currentForm->getParent();
if ($currentForm->hasAttribute('validation_groups')) {
$groups = $currentForm->getAttribute('validation_groups');
if (is_callable($groups)) {
$groups = (array) call_user_func($groups, $currentForm);
}
}
$form = $form->getParent();
}
if (null === $groups) {
$groups = array('Default');
$groups = array(Constraint::DEFAULT_GROUP);
}
return (array) $groups;

View File

@ -45,29 +45,7 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
*/
public function buildForm(FormBuilder $builder, array $options)
{
if (empty($options['validation_groups'])) {
$options['validation_groups'] = null;
} else {
$options['validation_groups'] = is_callable($options['validation_groups'])
? $options['validation_groups']
: (array) $options['validation_groups'];
}
// Objects, when casted to an array, are split into their properties
$constraints = is_object($options['constraints'])
? array($options['constraints'])
: (array) $options['constraints'];
$builder
->setAttribute('error_mapping', $options['error_mapping'])
->setAttribute('validation_groups', $options['validation_groups'])
->setAttribute('constraints', $constraints)
->setAttribute('cascade_validation', $options['cascade_validation'])
->setAttribute('invalid_message', $options['invalid_message'])
->setAttribute('extra_fields_message', $options['extra_fields_message'])
->setAttribute('post_max_size_message', $options['post_max_size_message'])
->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper))
;
$builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper));
}
/**
@ -80,6 +58,22 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
return $options['validation_constraint'];
};
// Make sure that validation groups end up as null, closure or array
$validationGroupsFilter = function (Options $options, $groups) {
if (empty($groups)) {
return null;
} elseif (is_callable($groups)) {
return $groups;
}
return (array) $groups;
};
// Constraint should always be converted to an array
$constraintsFilter = function (Options $options, $constraints) {
return is_object($constraints) ? array($constraints) : (array) $constraints;
};
$resolver->setDefaults(array(
'error_mapping' => array(),
'validation_groups' => null,
@ -91,6 +85,11 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
'extra_fields_message' => 'This form should not contain extra fields.',
'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.',
));
$resolver->setFilters(array(
'validation_groups' => $validationGroupsFilter,
'constraints' => $constraintsFilter,
));
}
/**

View File

@ -109,12 +109,12 @@ class ViolationMapper implements ViolationMapperInterface
}
// Follow dot rules until we have the final target
$mapping = $this->scope->getAttribute('error_mapping');
$mapping = $this->scope->getConfig()->getAttribute('error_mapping');
while ($this->isValidScope() && isset($mapping['.'])) {
$dotRule = new MappingRule($this->scope, '.', $mapping['.']);
$this->scope = $dotRule->getTarget();
$mapping = $this->scope->getAttribute('error_mapping');
$mapping = $this->scope->getConfig()->getAttribute('error_mapping');
}
// Only add the error if the form is synchronized
@ -281,7 +281,7 @@ class ViolationMapper implements ViolationMapperInterface
$this->children = new \RecursiveIteratorIterator(
new VirtualFormAwareIterator($form->getChildren())
);
foreach ($form->getAttribute('error_mapping') as $propertyPath => $targetPath) {
foreach ($form->getConfig()->getAttribute('error_mapping') as $propertyPath => $targetPath) {
// Dot rules are considered at the very end
if ('.' !== $propertyPath) {
$this->rules[] = new MappingRule($form, $propertyPath, $targetPath);

View File

@ -288,6 +288,9 @@ class Form implements \IteratorAggregate, FormInterface
* @param string $name The name of the attribute.
*
* @return Boolean Whether the attribute exists.
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
* {@link getConfig()} and {@link FormConfigInterface::hasAttribute()} instead.
*/
public function hasAttribute($name)
{
@ -300,6 +303,9 @@ class Form implements \IteratorAggregate, FormInterface
* @param string $name The name of the attribute
*
* @return mixed The attribute value.
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
* {@link getConfig()} and {@link FormConfigInterface::getAttribute()} instead.
*/
public function getAttribute($name)
{
@ -936,12 +942,13 @@ class Form implements \IteratorAggregate, FormInterface
$view->setParent($parent);
$types = (array) $this->config->getTypes();
$options = $this->config->getOptions();
foreach ($types as $type) {
$type->buildView($view, $this);
$type->buildView($view, $this, $options);
foreach ($type->getExtensions() as $typeExtension) {
$typeExtension->buildView($view, $this);
$typeExtension->buildView($view, $this, $options);
}
}
@ -950,10 +957,10 @@ class Form implements \IteratorAggregate, FormInterface
}
foreach ($types as $type) {
$type->buildViewBottomUp($view, $this);
$type->buildViewBottomUp($view, $this, $options);
foreach ($type->getExtensions() as $typeExtension) {
$typeExtension->buildViewBottomUp($view, $this);
$typeExtension->buildViewBottomUp($view, $this, $options);
}
}

View File

@ -61,9 +61,9 @@ class FormBuilder extends FormConfig
* @param EventDispatcherInterface $dispatcher
* @param FormFactoryInterface $factory
*/
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory)
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = array())
{
parent::__construct($name, $dataClass, $dispatcher);
parent::__construct($name, $dataClass, $dispatcher, $options);
$this->factory = $factory;
}

View File

@ -113,6 +113,11 @@ class FormConfig implements FormConfigInterface
*/
private $dataClass;
/**
* @var array
*/
private $options;
/**
* Creates an empty form configuration.
*
@ -124,7 +129,7 @@ class FormConfig implements FormConfigInterface
* @throws \InvalidArgumentException If the data class is not a valid class or if
* the name contains invalid characters.
*/
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher)
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array())
{
$name = (string) $name;
@ -137,6 +142,7 @@ class FormConfig implements FormConfigInterface
$this->name = $name;
$this->dataClass = $dataClass;
$this->dispatcher = $dispatcher;
$this->options = $options;
}
/**
@ -408,9 +414,9 @@ class FormConfig implements FormConfigInterface
/**
* {@inheritdoc}
*/
public function getAttribute($name)
public function getAttribute($name, $default = null)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
}
/**
@ -429,6 +435,30 @@ class FormConfig implements FormConfigInterface
return $this->dataClass;
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return $this->options;
}
/**
* {@inheritdoc}
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* {@inheritdoc}
*/
public function getOption($name, $default = null)
{
return isset($this->options[$name]) ? $this->options[$name] : $default;
}
/**
* Sets the value for an attribute.
*

View File

@ -149,11 +149,12 @@ interface FormConfigInterface
/**
* Returns the value of the given attribute.
*
* @param string $name The attribute name.
* @param string $name The attribute name.
* @param mixed $default The value returned if the attribute does not exist.
*
* @return mixed The attribute value.
*/
function getAttribute($name);
function getAttribute($name, $default = null);
/**
* Returns the initial data of the form.
@ -168,4 +169,30 @@ interface FormConfigInterface
* @return string The data class or null.
*/
function getDataClass();
/**
* Returns all options passed during the construction of the form.
*
* @return array The passed options.
*/
function getOptions();
/**
* Returns whether a specific option exists.
*
* @param string $name The option name,
*
* @return Boolean Whether the option exists.
*/
function hasOption($name);
/**
* Returns the value of a specific option.
*
* @param string $name The option name.
* @param mixed $default The value returned if the option does not exist.
*
* @return mixed The option value.
*/
function getOption($name, $default = null);
}

View File

@ -228,20 +228,6 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
*/
function bind($data);
/**
* Returns whether the form has an attribute with the given name.
*
* @param string $name The name of the attribute
*/
function hasAttribute($name);
/**
* Returns the value of the attributes with the given name.
*
* @param string $name The name of the attribute
*/
function getAttribute($name);
/**
* Returns the root of the form tree.
*

View File

@ -39,10 +39,11 @@ interface FormTypeExtensionInterface
*
* @see FormTypeInterface::buildView()
*
* @param FormView $view The view
* @param FormInterface $form The form
* @param FormView $view The view
* @param FormInterface $form The form
* @param array $options The options
*/
function buildView(FormView $view, FormInterface $form);
function buildView(FormView $view, FormInterface $form, array $options);
/**
* Builds the view.
@ -52,10 +53,11 @@ interface FormTypeExtensionInterface
*
* @see FormTypeInterface::buildViewBottomUp()
*
* @param FormView $view The view
* @param FormInterface $form The form
* @param FormView $view The view
* @param FormInterface $form The form
* @param array $options The options
*/
function buildViewBottomUp(FormView $view, FormInterface $form);
function buildViewBottomUp(FormView $view, FormInterface $form, array $options);
/**
* Overrides the default options from the extended type.

View File

@ -41,10 +41,11 @@ interface FormTypeInterface
*
* @see FormTypeExtensionInterface::buildView()
*
* @param FormView $view The view
* @param FormInterface $form The form
* @param FormView $view The view
* @param FormInterface $form The form
* @param array $options The options
*/
function buildView(FormView $view, FormInterface $form);
function buildView(FormView $view, FormInterface $form, array $options);
/**
* Builds the form view.
@ -58,10 +59,11 @@ interface FormTypeInterface
*
* @see FormTypeExtensionInterface::buildViewBottomUp()
*
* @param FormView $view The view
* @param FormInterface $form The form
* @param FormView $view The view
* @param FormInterface $form The form
* @param array $options The options
*/
function buildViewBottomUp(FormView $view, FormInterface $form);
function buildViewBottomUp(FormView $view, FormInterface $form, array $options);
/**
* Returns a builder for the current type.

View File

@ -18,33 +18,6 @@ use Symfony\Component\Form\FormConfigInterface;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
abstract class PropertyPathMapperTest_Form implements FormInterface
{
private $attributes = array();
private $data;
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
}
public function getAttribute($name)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
}
public function setData($data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
{
/**

View File

@ -74,17 +74,17 @@ class ChoiceTypeTest extends TypeTestCase
*/
public function testChoicesOptionExpectsArray()
{
$form = $this->factory->create('choice', null, array(
$this->factory->create('choice', null, array(
'choices' => new \ArrayObject(),
));
}
/**
* @expectedException Symfony\Component\Form\Exception\FormException
* @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testChoiceListOptionExpectsChoiceListInterface()
{
$form = $this->factory->create('choice', null, array(
$this->factory->create('choice', null, array(
'choice_list' => array('foo' => 'foo'),
));
}
@ -94,7 +94,7 @@ class ChoiceTypeTest extends TypeTestCase
*/
public function testEitherChoiceListOrChoicesMustBeSet()
{
$form = $this->factory->create('choice', null, array(
$this->factory->create('choice', null, array(
));
}

View File

@ -39,15 +39,15 @@ class CollectionTypeTest extends TypeTestCase
$this->assertCount(2, $form);
$this->assertEquals('foo@foo.com', $form[0]->getData());
$this->assertEquals('foo@bar.com', $form[1]->getData());
$this->assertEquals(20, $form[0]->getAttribute('max_length'));
$this->assertEquals(20, $form[1]->getAttribute('max_length'));
$this->assertEquals(20, $form[0]->getConfig()->getOption('max_length'));
$this->assertEquals(20, $form[1]->getConfig()->getOption('max_length'));
$form->setData(array('foo@baz.com'));
$this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]);
$this->assertFalse(isset($form[1]));
$this->assertCount(1, $form);
$this->assertEquals('foo@baz.com', $form[0]->getData());
$this->assertEquals(20, $form[0]->getAttribute('max_length'));
$this->assertEquals(20, $form[0]->getConfig()->getOption('max_length'));
}
public function testThrowsExceptionIfObjectIsNotTraversable()
@ -174,7 +174,7 @@ class CollectionTypeTest extends TypeTestCase
'allow_add' => true,
));
$this->assertSame('__name__', $form->getAttribute('prototype')->getName(), '__name__ is the default');
$this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default');
$form = $this->factory->create('collection', null, array(
'type' => 'form',
@ -183,7 +183,7 @@ class CollectionTypeTest extends TypeTestCase
'prototype_name' => '__test__',
));
$this->assertSame('__test__', $form->getAttribute('prototype')->getName());
$this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName());
}
public function testPrototypeDefaultLabel()

View File

@ -341,13 +341,6 @@ class FormTypeTest extends TypeTestCase
$this->assertEquals('Bernhard', $author->firstName);
}
public function testGetAttributesIsEmpty()
{
$form = $this->factory->create('form', null, array('attr' => array()));
$this->assertCount(0, $form->getAttribute('attr'));
}
/**
* @see https://github.com/symfony/symfony/issues/1986
*/
@ -379,11 +372,11 @@ class FormTypeTest extends TypeTestCase
}
/**
* @expectedException Symfony\Component\Form\Exception\FormException
* @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testAttributesException()
{
$form = $this->factory->create('form', null, array('attr' => ''));
$this->factory->create('form', null, array('attr' => ''));
}
public function testNameCanBeEmptyString()

View File

@ -41,8 +41,8 @@ class RepeatedTypeTest extends TypeTestCase
'options' => array('label' => 'Global'),
));
$this->assertEquals('Global', $form['first']->getAttribute('label'));
$this->assertEquals('Global', $form['second']->getAttribute('label'));
$this->assertEquals('Global', $form['first']->getConfig()->getOption('label'));
$this->assertEquals('Global', $form['second']->getConfig()->getOption('label'));
$this->assertTrue($form['first']->isRequired());
$this->assertTrue($form['second']->isRequired());
}
@ -56,8 +56,8 @@ class RepeatedTypeTest extends TypeTestCase
'second_options' => array('label' => 'Test2')
));
$this->assertEquals('Test', $form['first']->getAttribute('label'));
$this->assertEquals('Test2', $form['second']->getAttribute('label'));
$this->assertEquals('Test', $form['first']->getConfig()->getOption('label'));
$this->assertEquals('Test2', $form['second']->getConfig()->getOption('label'));
$this->assertTrue($form['first']->isRequired());
$this->assertTrue($form['second']->isRequired());
}
@ -81,8 +81,8 @@ class RepeatedTypeTest extends TypeTestCase
'second_options' => array('label' => 'Second label')
));
$this->assertEquals('Label', $form['first']->getAttribute('label'));
$this->assertEquals('Second label', $form['second']->getAttribute('label'));
$this->assertEquals('Label', $form['first']->getConfig()->getOption('label'));
$this->assertEquals('Second label', $form['second']->getConfig()->getOption('label'));
$this->assertTrue($form['first']->isRequired());
$this->assertTrue($form['second']->isRequired());
}

View File

@ -64,8 +64,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', array('group1', 'group2'))
$options = array('validation_groups' => array('group1', 'group2'));
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
@ -88,9 +88,11 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$constraint1 = $this->getMock('Symfony\Component\Validator\Constraint');
$constraint2 = $this->getMock('Symfony\Component\Validator\Constraint');
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', array('group1', 'group2'))
->setAttribute('constraints', array($constraint1, $constraint2))
$options = array(
'validation_groups' => array('group1', 'group2'),
'constraints' => array($constraint1, $constraint2),
);
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
@ -126,12 +128,9 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
->setAttribute('cascade_validation', false)
->getForm();
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', array('group1', 'group2'))
->getForm();
$parent = $this->getBuilder('parent', null, array('cascade_validation' => false))->getForm();
$options = array('validation_groups' => array('group1', 'group2'));
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
$parent->add($form);
$form->setData($object);
@ -151,12 +150,12 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$constraint1 = $this->getMock('Symfony\Component\Validator\Constraint');
$constraint2 = $this->getMock('Symfony\Component\Validator\Constraint');
$parent = $this->getBuilder()
->setAttribute('cascade_validation', false)
->getForm();
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', array('group1', 'group2'))
->setAttribute('constraints', array($constraint1, $constraint2))
$parent = $this->getBuilder('parent', null, array('cascade_validation' => false))->getForm();
$options = array(
'validation_groups' => array('group1', 'group2'),
'constraints' => array($constraint1, $constraint2),
);
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
$parent->add($form);
@ -184,9 +183,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder('name', '\stdClass')
$form = $this->getBuilder('name', '\stdClass', array('invalid_message' => 'Invalid!'))
->setData($object)
->setAttribute('invalid_message', 'Invalid!')
->appendClientTransformer(new CallbackTransformer(
function ($data) { return $data; },
function () { throw new TransformationFailedException(); }
@ -214,10 +212,12 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$constraint1 = $this->getMock('Symfony\Component\Validator\Constraint');
$constraint2 = $this->getMock('Symfony\Component\Validator\Constraint');
$form = $this->getBuilder('name', '\stdClass')
$options = array(
'validation_groups' => array('group1', 'group2'),
'constraints' => array($constraint1, $constraint2),
);
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->setAttribute('validation_groups', array('group1', 'group2'))
->setAttribute('constraints', array($constraint1, $constraint2))
->appendClientTransformer(new CallbackTransformer(
function ($data) { return $data; },
function () { throw new TransformationFailedException(); }
@ -239,8 +239,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
$options = array('validation_groups' => array($this, 'getValidationGroups'));
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
@ -260,10 +260,10 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$context = $this->getExecutionContext();
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', function(FormInterface $form){
return array('group1', 'group2');
})
$options = array('validation_groups' => function(FormInterface $form){
return array('group1', 'group2');
});
$form = $this->getBuilder('name', '\stdClass', $options)
->setData($object)
->getForm();
@ -284,13 +284,12 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
->setAttribute('validation_groups', 'group')
->setAttribute('cascade_validation', true)
->getForm();
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', null)
->getForm();
$parentOptions = array(
'validation_groups' => 'group',
'cascade_validation' => true,
);
$parent = $this->getBuilder('parent', null, $parentOptions)->getForm();
$form = $this->getBuilder('name', '\stdClass')->getForm();
$parent->add($form);
$form->setData($object);
@ -309,13 +308,12 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
->setAttribute('cascade_validation', true)
->getForm();
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', null)
->getForm();
$parentOptions = array(
'validation_groups' => array($this, 'getValidationGroups'),
'cascade_validation' => true,
);
$parent = $this->getBuilder('parent', null, $parentOptions)->getForm();
$form = $this->getBuilder('name', '\stdClass')->getForm();
$parent->add($form);
$form->setData($object);
@ -337,15 +335,14 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
$graphWalker = $context->getGraphWalker();
$object = $this->getMock('\stdClass');
$parent = $this->getBuilder()
->setAttribute('validation_groups', function(FormInterface $form){
$parentOptions = array(
'validation_groups' => function(FormInterface $form){
return array('group1', 'group2');
})
->setAttribute('cascade_validation', true)
->getForm();
$form = $this->getBuilder('name', '\stdClass')
->setAttribute('validation_groups', null)
->getForm();
},
'cascade_validation' => true,
);
$parent = $this->getBuilder('parent', null, $parentOptions)->getForm();
$form = $this->getBuilder('name', '\stdClass')->getForm();
$parent->add($form);
$form->setData($object);
@ -398,9 +395,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
{
$context = $this->getExecutionContext();
$form = $this->getBuilder()
$form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!'))
->add($this->getBuilder('child'))
->setAttribute('extra_fields_message', 'Extra!')
->getForm();
$form->bind(array('foo' => 'bar'));
@ -422,9 +418,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue('1G'));
$context = $this->getExecutionContext();
$form = $this->getBuilder()
->setAttribute('post_max_size_message', 'Max {{ max }}!')
->getForm();
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->getBuilder('name', null, $options)->getForm();
$this->validator->initialize($context);
$this->validator->validate($form, new Form());
@ -443,9 +438,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue('1g'));
$context = $this->getExecutionContext();
$form = $this->getBuilder()
->setAttribute('post_max_size_message', 'Max {{ max }}!')
->getForm();
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->getBuilder('name', null, $options)->getForm();
$this->validator->initialize($context);
$this->validator->validate($form, new Form());
@ -482,9 +476,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue('1M'));
$context = $this->getExecutionContext();
$form = $this->getBuilder()
->setAttribute('post_max_size_message', 'Max {{ max }}!')
->getForm();
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->getBuilder('name', null, $options)->getForm();
$this->validator->initialize($context);
$this->validator->validate($form, new Form());
@ -521,9 +514,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue('1K'));
$context = $this->getExecutionContext();
$form = $this->getBuilder()
->setAttribute('post_max_size_message', 'Max {{ max }}!')
->getForm();
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->getBuilder('name', null, $options)->getForm();
$this->validator->initialize($context);
$this->validator->validate($form, new Form());
@ -598,9 +590,8 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(' 1K '));
$context = $this->getExecutionContext();
$form = $this->getBuilder()
->setAttribute('post_max_size_message', 'Max {{ max }}!')
->getForm();
$options = array('post_max_size_message' => 'Max {{ max }}!');
$form = $this->getBuilder('name', null, $options)->getForm();
$this->validator->initialize($context);
$this->validator->validate($form, new Form());
@ -679,12 +670,13 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase
/**
* @return FormBuilder
*/
private function getBuilder($name = 'name', $dataClass = null)
private function getBuilder($name = 'name', $dataClass = null, array $options = array())
{
$builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory);
$builder->setAttribute('constraints', array());
$options = array_replace(array(
'constraints' => array(),
), $options);
return $builder;
return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options);
}
private function getForm($name = 'name', $dataClass = null)

View File

@ -19,7 +19,7 @@ class FormTypeValidatorExtensionTest extends TypeTestCase
{
$form = $this->factory->create('form');
$this->assertNull($form->getAttribute('validation_groups'));
$this->assertNull($form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToString()
@ -28,7 +28,7 @@ class FormTypeValidatorExtensionTest extends TypeTestCase
'validation_groups' => 'group',
));
$this->assertEquals(array('group'), $form->getAttribute('validation_groups'));
$this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToArray()
@ -37,7 +37,7 @@ class FormTypeValidatorExtensionTest extends TypeTestCase
'validation_groups' => array('group1', 'group2'),
));
$this->assertEquals(array('group1', 'group2'), $form->getAttribute('validation_groups'));
$this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups'));
}
public function testValidationGroupsCanBeSetToCallback()
@ -46,7 +46,7 @@ class FormTypeValidatorExtensionTest extends TypeTestCase
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
));
$this->assertTrue(is_callable($form->getAttribute('validation_groups')));
$this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
}
public function testValidationGroupsCanBeSetToClosure()
@ -55,7 +55,7 @@ class FormTypeValidatorExtensionTest extends TypeTestCase
'validation_groups' => function(FormInterface $form){ return null; },
));
$this->assertTrue(is_callable($form->getAttribute('validation_groups')));
$this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups')));
}
public function testBindValidatesData()

View File

@ -112,6 +112,11 @@ class UnmodifiableFormConfig implements FormConfigInterface
*/
private $dataClass;
/**
* @var array
*/
private $options;
/**
* Creates an unmodifiable copy of a given configuration.
*
@ -142,6 +147,7 @@ class UnmodifiableFormConfig implements FormConfigInterface
$this->attributes = $config->getAttributes();
$this->data = $config->getData();
$this->dataClass = $config->getDataClass();
$this->options = $config->getOptions();
}
/**
@ -285,9 +291,9 @@ class UnmodifiableFormConfig implements FormConfigInterface
/**
* {@inheritdoc}
*/
public function getAttribute($name)
public function getAttribute($name, $default = null)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
}
/**
@ -305,4 +311,28 @@ class UnmodifiableFormConfig implements FormConfigInterface
{
return $this->dataClass;
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return $this->options;
}
/**
* {@inheritdoc}
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* {@inheritdoc}
*/
public function getOption($name, $default = null)
{
return isset($this->options[$name]) ? $this->options[$name] : $default;
}
}