[Form] Options are now passed to buildView() and buildViewBottomUp()
This commit is contained in:
parent
027259eba4
commit
0ef4066983
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
;
|
||||
}
|
||||
|
|
|
@ -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'),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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', '');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -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(
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue