diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index ca7edd952a..c9755fdf88 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -267,9 +267,12 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c in their name anymore. Their names terminate with "[]" now. * [BC BREAK] FormType::getDefaultOptions() and FormType::getAllowedOptionValues() don't receive an options array anymore. - * Deprecated FormValidatorInterface and substituted its implementations + * deprecated FormValidatorInterface and substituted its implementations by event subscribers * simplified CSRF protection and removed the csrf type + * deprecated FieldType and merged it into FormType + * [BC BREAK] renamed "field_*" theme blocks to "form_*" and "field_widget" to + "input" ### HttpFoundation diff --git a/UPGRADE-2.1.md b/UPGRADE-2.1.md index d410262a30..a7d577d950 100644 --- a/UPGRADE-2.1.md +++ b/UPGRADE-2.1.md @@ -94,7 +94,7 @@ ``` * The custom factories for the firewall configuration are now registered during the build method of bundles instead of being registered - by the end-user. This means that you will you need to remove the 'factories' + by the end-user. This means that you will you need to remove the 'factories' keys in your security configuration. * The Firewall listener is now registered after the Router listener. This @@ -372,29 +372,29 @@ return isset($options['widget']) && 'single_text' === $options['widget'] ? 'text' : 'choice'; } ``` - + * The methods `getDefaultOptions()` and `getAllowedOptionValues()` of form types no longer receive an option array. - + You can specify options that depend on other options using closures instead. - + Before: - + ``` public function getDefaultOptions(array $options) { $defaultOptions = array(); - + if ($options['multiple']) { $defaultOptions['empty_data'] = array(); } - + return $defaultOptions; } ``` - + After: - + ``` public function getDefaultOptions() { @@ -405,7 +405,7 @@ ); } ``` - + The second argument `$previousValue` does not have to be specified if not needed. @@ -425,6 +425,100 @@ (or any other of the BIND events). In case you used the CallbackValidator class, you should now pass the callback directly to `addEventListener`. + * FieldType was merged into FormType. FieldType itself was deprecated and + will be removed in Symfony 2.3. + + ##### Update your field types + + You are advised to update your custom types that extend FieldType to extend + FormType instead. + + Before: + + ``` + public function getParent(array $options) + { + return 'field'; + } + ``` + + After: + + ``` + public function getParent(array $options) + { + return 'form'; + } + ``` + + You can also remove the getParent() method as this is the default + implementation in AbstractType. + + ##### Update your form themes + + Previously, FieldType was the super type for all other types. Now, since + it is deprecated, FieldType is a subtype of FormType, which is now the base + type for all other types. + + A consequence of this change is that any "form_*" blocks defined in your + themes are now also used for other types that extend "field", unless you + explicitely override the "field_*" or "mytype_*" blocks. + + "field_*" blocks are deprecated and will be unsupported as of Symfony 2.3. + You should merge them into the corresponding "form_*" blocks instead. + + Before: + + ``` + {% block field_label %} + {% spaceless %} + {% set attr = attr|merge({'for': id}) %} + {{ block('generic_label') }} + {% endspaceless %} + {% endblock field_label %} + + {% block form_label %} + {% spaceless %} + {{ block('generic_label') }} + {% endspaceless %} + {% endblock form_label %} + ``` + + After: + + ``` + {% block form_label %} + {% spaceless %} + {% if form.children|length == 0 %} + {% set attr = attr|merge({'for': id}) %} + {% endif %} + {{ block('generic_label') }} + {% endspaceless %} + {% endblock form_label %} + ``` + + The block "field_widget" was renamed to "input" and is still supported. + + Before: + + ``` + {% block field_widget %} + {% spaceless %} + + {% endspaceless %} + {% endblock field_widget %} + ``` + + After: + + ``` + {% block input %} + {% spaceless %} + + {% endspaceless %} + {% endblock input %} + ``` + ### Session * Flash messages now return an array based on their type. The old method is diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index cc3f3fd01d..46420a7122 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -2,10 +2,14 @@ {% block form_widget %} {% spaceless %} -
- {{ block('field_rows') }} - {{ form_rest(form) }} -
+ {% if form.children|length > 0 %} +
+ {{ block('form_rows') }} + {{ form_rest(form) }} +
+ {% else %} + {{ block('input') }} + {% endif %} {% endspaceless %} {% endblock form_widget %} @@ -83,7 +87,7 @@ {% block datetime_widget %} {% spaceless %} {% if widget == 'single_text' %} - {{ block('field_widget') }} + {{ block('input') }} {% else %}
{{ form_errors(form.date) }} @@ -98,7 +102,7 @@ {% block date_widget %} {% spaceless %} {% if widget == 'single_text' %} - {{ block('field_widget') }} + {{ block('input') }} {% else %}
{{ date_pattern|replace({ @@ -114,7 +118,7 @@ {% block time_widget %} {% spaceless %} {% if widget == 'single_text' %} - {{ block('field_widget') }} + {{ block('input') }} {% else %}
{{ form_widget(form.hour, { 'attr': { 'size': '1' } }) }}:{{ form_widget(form.minute, { 'attr': { 'size': '1' } }) }}{% if with_seconds %}:{{ form_widget(form.second, { 'attr': { 'size': '1' } }) }}{% endif %} @@ -127,67 +131,60 @@ {% spaceless %} {# type="number" doesn't work with floats #} {% set type = type|default('text') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock number_widget %} {% block integer_widget %} {% spaceless %} {% set type = type|default('number') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock integer_widget %} {% block money_widget %} {% spaceless %} - {{ money_pattern|replace({ '{{ widget }}': block('field_widget') })|raw }} + {{ money_pattern|replace({ '{{ widget }}': block('input') })|raw }} {% endspaceless %} {% endblock money_widget %} {% block url_widget %} {% spaceless %} {% set type = type|default('url') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock url_widget %} {% block search_widget %} {% spaceless %} {% set type = type|default('search') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock search_widget %} {% block percent_widget %} {% spaceless %} {% set type = type|default('text') %} - {{ block('field_widget') }} % + {{ block('input') }} % {% endspaceless %} {% endblock percent_widget %} -{% block field_widget %} -{% spaceless %} - {% set type = type|default('text') %} - -{% endspaceless %} -{% endblock field_widget %} - {% block password_widget %} {% spaceless %} {% set type = type|default('password') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock password_widget %} {% block hidden_widget %} {% set type = type|default('hidden') %} - {{ block('field_widget') }} + {{ block('input') }} {% endblock hidden_widget %} {% block email_widget %} {% spaceless %} {% set type = type|default('email') %} - {{ block('field_widget') }} + {{ block('input') }} {% endspaceless %} {% endblock email_widget %} @@ -202,15 +199,11 @@ {% endspaceless %} {% endblock %} -{% block field_label %} -{% spaceless %} - {% set attr = attr|merge({'for': id}) %} - {{ block('generic_label') }} -{% endspaceless %} -{% endblock field_label %} - {% block form_label %} {% spaceless %} + {% if form.children|length == 0 %} + {% set attr = attr|merge({'for': id}) %} + {% endif %} {{ block('generic_label') }} {% endspaceless %} {% endblock form_label %} @@ -219,24 +212,17 @@ {% block repeated_row %} {% spaceless %} - {{ block('field_rows') }} + {{ block('form_rows') }} {% endspaceless %} {% endblock repeated_row %} -{% block field_row %} -{% spaceless %} -
- {{ form_label(form, label|default(null)) }} - {{ form_errors(form) }} - {{ form_widget(form) }} -
-{% endspaceless %} -{% endblock field_row %} - {% block form_row %} {% spaceless %}
{{ form_label(form, label|default(null)) }} + {% if form.children|length == 0 %} + {{ form_errors(form) }} + {% endif %} {{ form_widget(form) }}
{% endspaceless %} @@ -248,13 +234,13 @@ {# Misc #} -{% block field_enctype %} +{% block form_enctype %} {% spaceless %} {% if multipart %}enctype="multipart/form-data"{% endif %} {% endspaceless %} -{% endblock field_enctype %} +{% endblock form_enctype %} -{% block field_errors %} +{% block form_errors %} {% spaceless %} {% if errors|length > 0 %}
    @@ -270,9 +256,9 @@
{% endif %} {% endspaceless %} -{% endblock field_errors %} +{% endblock form_errors %} -{% block field_rest %} +{% block form_rest %} {% spaceless %} {% for child in form %} {% if not child.rendered %} @@ -280,18 +266,25 @@ {% endif %} {% endfor %} {% endspaceless %} -{% endblock field_rest %} +{% endblock form_rest %} {# Support #} -{% block field_rows %} +{% block form_rows %} {% spaceless %} {{ form_errors(form) }} {% for child in form %} {{ form_row(child) }} {% endfor %} {% endspaceless %} -{% endblock field_rows %} +{% endblock form_rows %} + +{% block input %} +{% spaceless %} + {% set type = type|default('text') %} + +{% endspaceless %} +{% endblock input %} {% block widget_attributes %} {% spaceless %} @@ -306,3 +299,47 @@ {% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %} {% endspaceless %} {% endblock widget_container_attributes %} + +{# Deprecated in Symfony 2.1, to be removed in 2.3 #} + +{% block field_widget %} +{% spaceless %} + {{ block('input') }} +{% endspaceless %} +{% endblock field_widget %} + +{% block field_label %} +{% spaceless %} + {{ block('form_label') }} +{% endspaceless %} +{% endblock field_label %} + +{% block field_row %} +{% spaceless %} + {{ block('form_row') }} +{% endspaceless %} +{% endblock field_row %} + +{% block field_enctype %} +{% spaceless %} + {{ block('form_enctype') }} +{% endspaceless %} +{% endblock field_enctype %} + +{% block field_errors %} +{% spaceless %} + {{ block('form_errors') }} +{% endspaceless %} +{% endblock field_errors %} + +{% block field_rest %} +{% spaceless %} + {{ block('form_rest') }} +{% endspaceless %} +{% endblock field_rest %} + +{% block field_rows %} +{% spaceless %} + {{ block('form_rows') }} +{% endspaceless %} +{% endblock field_rows %} \ No newline at end of file diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig index 1046c3de36..b053c59e6f 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig @@ -1,19 +1,5 @@ {% use "form_div_layout.html.twig" %} -{% block field_row %} -{% spaceless %} - - - {{ form_label(form, label|default(null)) }} - - - {{ form_errors(form) }} - {{ form_widget(form) }} - - -{% endspaceless %} -{% endblock field_row %} - {% block form_row %} {% spaceless %} @@ -21,6 +7,9 @@ {{ form_label(form, label|default(null)) }} + {% if form.children|length == 0 %} + {{ form_errors(form) }} + {% endif %} {{ form_widget(form) }} @@ -29,12 +18,16 @@ {% block form_errors %} {% spaceless %} - {% if errors|length > 0 %} - - - {{ block('field_errors') }} - - + {% if form.children|length > 0 %} + {% if errors|length > 0 %} + + + {{ parent() }} + + + {% endif %} + {% else %} + {{ parent() }} {% endif %} {% endspaceless %} {% endblock form_errors %} @@ -51,9 +44,13 @@ {% block form_widget %} {% spaceless %} - - {{ block('field_rows') }} - {{ form_rest(form) }} -
+ {% if form.children|length > 0 %} + + {{ block('form_rows') }} + {{ form_rest(form) }} +
+ {% else %} + {{ parent() }} + {% endif %} {% endspaceless %} {% endblock form_widget %} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig index 16c137aaca..061ef428c2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/child_label.html.twig @@ -1,3 +1,3 @@ -{% block field_label %} +{% block form_label %} -{% endblock field_label %} +{% endblock form_label %} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig index fc59d708be..e96278b8f6 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/parent_label.html.twig @@ -1,3 +1,3 @@ -{% block field_label %} +{% block form_label %} -{% endblock field_label %} +{% endblock form_label %} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig index d5016842ea..ee5b19e073 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/theme.html.twig @@ -1,6 +1,6 @@ -{% block field_widget %} +{% block input %} {% spaceless %} {% set type = type|default('text') %} {% endspaceless %} -{% endblock field_widget %} +{% endblock input %} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig index 96bfea20dc..f58e589498 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/theme_extends.html.twig @@ -1,8 +1,8 @@ {% extends 'form_div_layout.html.twig' %} -{% block field_widget %} +{% block input %} {% spaceless %} {% set type = type|default('text') %} {% endspaceless %} -{% endblock field_widget %} +{% endblock input %} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig index 5aee4708a2..9304e9dcfa 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/theme_use.html.twig @@ -1,8 +1,8 @@ {% use 'form_div_layout.html.twig' %} -{% block field_widget %} +{% block input %} {% spaceless %} {% set type = type|default('text') %} {% endspaceless %} -{% endblock field_widget %} +{% endblock input %} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 1422e792b8..bddb2a96e8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -52,7 +52,6 @@ - @@ -133,8 +132,8 @@ - - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php index 4a4fa106e3..bd2c2769af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/date_widget.html.php @@ -1,5 +1,5 @@ - renderBlock('field_widget'); ?> + renderBlock('input'); ?>
renderBlock('container_attributes') ?>> - renderBlock('field_widget'); ?> + renderBlock('input'); ?>
renderBlock('container_attributes') ?>> widget($form['date']).' '.$view['form']->widget($form['time']) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/email_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/email_widget.html.php index c30cfb35c3..a00dda278e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/email_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/email_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : 'email')) ?> +renderBlock('input', array('type' => isset($type) ? $type : 'email')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php index 424d425969..aa4ff39bba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_enctype.html.php @@ -1 +1 @@ -get('multipart')): ?>enctype="multipart/form-data" +renderBlock('form_enctype') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_errors.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_errors.html.php index 339e3d0009..d7b87ea2bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_errors.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_errors.html.php @@ -1,21 +1 @@ - -
    - -
  • getMessagePluralization()) { - echo $view['translator']->trans( - $error->getMessageTemplate(), - $error->getMessageParameters(), - 'validators' - ); - } else { - echo $view['translator']->transChoice( - $error->getMessageTemplate(), - $error->getMessagePluralization(), - $error->getMessageParameters(), - 'validators' - ); - }?>
  • - -
- +renderBlock('form_errors') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_label.html.php index 1434301d4c..7c0c1b7559 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_label.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_label.html.php @@ -1,2 +1 @@ - - +renderBlock('form_label') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php index 89041c6ec6..a570b1045a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rest.html.php @@ -1,5 +1 @@ - - isRendered()): ?> - row($child) ?> - - +renderBlock('form_rest') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_row.html.php index 091807020d..c91dcb5543 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_row.html.php @@ -1,5 +1 @@ -
- label($form, isset($label) ? $label : null) ?> - errors($form) ?> - widget($form) ?> -
+renderBlock('form_row') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rows.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rows.html.php index a5f1dfbf5f..ef0bf384a6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rows.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_rows.html.php @@ -1,4 +1 @@ -errors($form) ?> - - row($child) ?> - +renderBlock('form_rows') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php index 0c86483386..f1ca2edadb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/field_widget.html.php @@ -1,5 +1 @@ -" - value="escape($value) ?>" - renderBlock('attributes') ?> -/> +renderBlock('input') ?> \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_enctype.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_enctype.html.php new file mode 100644 index 0000000000..424d425969 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_enctype.html.php @@ -0,0 +1 @@ +get('multipart')): ?>enctype="multipart/form-data" diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_errors.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_errors.html.php new file mode 100644 index 0000000000..339e3d0009 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_errors.html.php @@ -0,0 +1,21 @@ + +
    + +
  • getMessagePluralization()) { + echo $view['translator']->trans( + $error->getMessageTemplate(), + $error->getMessageParameters(), + 'validators' + ); + } else { + echo $view['translator']->transChoice( + $error->getMessageTemplate(), + $error->getMessagePluralization(), + $error->getMessageParameters(), + 'validators' + ); + }?>
  • + +
+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php index e5c5843c46..3ddc300fd4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php @@ -1,2 +1,3 @@ +hasChildren()) { $attr['for'] = $id; } ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rest.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rest.html.php new file mode 100644 index 0000000000..89041c6ec6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rest.html.php @@ -0,0 +1,5 @@ + + isRendered()): ?> + row($child) ?> + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php index 0a79a0cc53..02fb9ae9b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php @@ -1,4 +1,7 @@
label($form, isset($label) ? $label : null) ?> + hasChildren()): ?> + errors($form) ?> + widget($form) ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rows.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rows.html.php new file mode 100644 index 0000000000..a5f1dfbf5f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_rows.html.php @@ -0,0 +1,4 @@ +errors($form) ?> + + row($child) ?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php index 77fa483c3f..1c9368693b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_widget.html.php @@ -1,5 +1,8 @@ +hasChildren()): ?>
renderBlock('container_attributes') ?>> - renderBlock('field_rows') ?> + renderBlock('form_rows') ?> rest($form) ?>
- + +renderBlock('input')?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php index 11942cfe2b..50a42451ae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/hidden_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "hidden")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "hidden")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/input.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/input.html.php new file mode 100644 index 0000000000..0c86483386 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/input.html.php @@ -0,0 +1,5 @@ +" + value="escape($value) ?>" + renderBlock('attributes') ?> +/> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php index 012211ab5a..1fc6ace34b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/integer_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "number")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "number")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php index 3151ecbd84..a68ad5ddac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/money_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget'), $money_pattern) ?> +renderBlock('input'), $money_pattern) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php index 9a08222c91..7e1a2776a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "text")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "text")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php index 78319fcbae..7aff242ef4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "password")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "password")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php index 4245b52a0c..328321f21f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "text")) ?> % +renderBlock('input', array('type' => isset($type) ? $type : "text")) ?> % diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php index a84bad54df..b9a07bc466 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/repeated_row.html.php @@ -1 +1 @@ -renderBlock('field_rows') ?> +renderBlock('form_rows') ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php index bbfd593dbc..d8a773544e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php @@ -1 +1 @@ -renderBlock('field_widget', array('type' => isset($type) ? $type : "search")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "search")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php index 599750d20a..2178974c74 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/time_widget.html.php @@ -1,5 +1,5 @@ - renderBlock('field_widget'); ?> + renderBlock('input'); ?>
renderBlock('container_attributes') ?>> renderBlock('field_widget', array('type' => isset($type) ? $type : "url")) ?> +renderBlock('input', array('type' => isset($type) ? $type : "url")) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/field_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/field_row.html.php deleted file mode 100644 index b9e5c5639c..0000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/field_row.html.php +++ /dev/null @@ -1,9 +0,0 @@ - - - label($form, isset($label) ? $label : null) ?> - - - errors($form) ?> - widget($form) ?> - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_errors.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_errors.html.php index ac4315f957..05d8c4aea8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_errors.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_errors.html.php @@ -1,7 +1,51 @@ - - - - renderBlock('field_errors'); ?> - - - +hasChildren()): ?> + 0): ?> + + + +
    + +
  • getMessagePluralization()) { + echo $view['translator']->trans( + $error->getMessageTemplate(), + $error->getMessageParameters(), + 'validators' + ); + } else { + echo $view['translator']->transChoice( + $error->getMessageTemplate(), + $error->getMessagePluralization(), + $error->getMessageParameters(), + 'validators' + ); + }?>
  • + +
+ + + + + + +
    + +
  • getMessagePluralization()) { + echo $view['translator']->trans( + $error->getMessageTemplate(), + $error->getMessageParameters(), + 'validators' + ); + } else { + echo $view['translator']->transChoice( + $error->getMessageTemplate(), + $error->getMessagePluralization(), + $error->getMessageParameters(), + 'validators' + ); + }?>
  • + +
+ + \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php index d1bbbb1b2a..9262a1bae1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php @@ -3,6 +3,9 @@ label($form, isset($label) ? $label : null) ?> + hasChildren()): ?> + errors($form) ?> + widget($form) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget.html.php index d802ccf050..171f1eb40c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget.html.php @@ -1,5 +1,8 @@ +hasChildren()): ?> renderBlock('container_attributes') ?>> - renderBlock('field_rows') ?> + renderBlock('form_rows') ?> rest($form) ?>
- + +renderBlock('input')?> + diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php index 2004b4e67e..8fd4adef89 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @@ -119,7 +119,7 @@ class FormHelper extends Helper */ public function widget(FormView $view, array $variables = array()) { - return trim($this->renderSection($view, 'widget', $variables)); + return $this->renderSection($view, 'widget', $variables); } /** @@ -276,7 +276,7 @@ class FormHelper extends Helper $view->setRendered(); } - return $html; + return trim($html); } } while (--$typeIndex >= 0); @@ -311,7 +311,7 @@ class FormHelper extends Helper $variables = array_replace_recursive($context['variables'], $variables); - return $this->engine->render($template, $variables); + return trim($this->engine->render($template, $variables)); } public function getName() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/field_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php similarity index 100% rename from src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/field_label.html.php rename to src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/field_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_label.html.php similarity index 100% rename from src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/field_label.html.php rename to src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_label.html.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/field_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/input.html.php similarity index 100% rename from src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/field_widget.html.php rename to src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/input.html.php diff --git a/src/Symfony/Component/Form/DataTransformerInterface.php b/src/Symfony/Component/Form/DataTransformerInterface.php index add2ce3d9b..2f1543e91b 100644 --- a/src/Symfony/Component/Form/DataTransformerInterface.php +++ b/src/Symfony/Component/Form/DataTransformerInterface.php @@ -24,7 +24,7 @@ interface DataTransformerInterface * This method is called on two occasions inside a form field: * * 1. When the form field is initialized with the data attached from the datasource (object or array). - * 2. When data from a request is bound using {@link Field::bind()} to transform the new input data + * 2. When data from a request is bound using {@link Form::bind()} to transform the new input data * back into the renderable format. For example if you have a date field and bind '2009-10-10' onto * it you might accept this value because its easily parsed, but the transformer still writes back * "2009/10/10" onto the form field (for further displaying or other purposes). @@ -52,7 +52,7 @@ interface DataTransformerInterface * Transforms a value from the transformed representation to its original * representation. * - * This method is called when {@link Field::bind()} is called to transform the requests tainted data + * This method is called when {@link Form::bind()} is called to transform the requests tainted data * into an acceptable format for your data processing/model layer. * * This method must be able to deal with empty values. Usually this will diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 1ed495248b..1a8ba2d1be 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -44,8 +44,8 @@ class ChoiceType extends AbstractType } if ($options['expanded']) { - $this->addSubFields($builder, $options['choice_list']->getPreferredViews(), $options); - $this->addSubFields($builder, $options['choice_list']->getRemainingViews(), $options); + $this->addSubForms($builder, $options['choice_list']->getPreferredViews(), $options); + $this->addSubForms($builder, $options['choice_list']->getRemainingViews(), $options); } // empty value @@ -182,7 +182,7 @@ class ChoiceType extends AbstractType */ public function getParent(array $options) { - return isset($options['expanded']) && $options['expanded'] ? 'form' : 'field'; + return 'field'; } /** @@ -200,12 +200,12 @@ class ChoiceType extends AbstractType * @param array $choiceViews The choice view objects. * @param array $options The build options. */ - private function addSubFields(FormBuilder $builder, array $choiceViews, array $options) + private function addSubForms(FormBuilder $builder, array $choiceViews, array $options) { foreach ($choiceViews as $i => $choiceView) { if (is_array($choiceView)) { // Flatten groups - $this->addSubFields($builder, $choiceView, $options); + $this->addSubForms($builder, $choiceView, $options); } else { $choiceOpts = array( 'value' => $choiceView->getValue(), diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 6eba72d4f6..f428054ede 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -153,7 +153,7 @@ class DateTimeType extends AbstractType 'widget' => null, // This will overwrite "empty_value" child options 'empty_value' => null, - // If initialized with a \DateTime object, FieldType initializes + // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. @@ -200,7 +200,7 @@ class DateTimeType extends AbstractType */ public function getParent(array $options) { - return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form'; + return 'field'; } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index e58d0d9340..c506714c7f 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -177,7 +177,7 @@ class DateType extends AbstractType // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, - // If initialized with a \DateTime object, FieldType initializes + // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. @@ -210,7 +210,7 @@ class DateType extends AbstractType */ public function getParent(array $options) { - return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form'; + return 'field'; } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php index b676d81984..c509abe6a5 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php @@ -23,179 +23,15 @@ use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Exception\FormException; +/** + * Deprecated. You should extend FormType instead. + * + * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.1, to be removed in 2.3. + */ class FieldType extends AbstractType { - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilder $builder, array $options) - { - if (null === $options['property_path']) { - $options['property_path'] = $builder->getName(); - } - - if (false === $options['property_path'] || '' === $options['property_path']) { - $options['property_path'] = null; - } else { - $options['property_path'] = new PropertyPath($options['property_path']); - } - if (!is_array($options['attr'])) { - throw new FormException('The "attr" option must be "array".'); - } - - $builder - ->setRequired($options['required']) - ->setDisabled($options['disabled']) - ->setErrorBubbling($options['error_bubbling']) - ->setEmptyData($options['empty_data']) - ->setAttribute('read_only', $options['read_only']) - ->setAttribute('by_reference', $options['by_reference']) - ->setAttribute('property_path', $options['property_path']) - ->setAttribute('error_mapping', $options['error_mapping']) - ->setAttribute('max_length', $options['max_length']) - ->setAttribute('pattern', $options['pattern']) - ->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName())) - ->setAttribute('attr', $options['attr'] ?: array()) - ->setAttribute('invalid_message', $options['invalid_message']) - ->setAttribute('invalid_message_parameters', $options['invalid_message_parameters']) - ->setAttribute('translation_domain', $options['translation_domain']) - ->setData($options['data']) - ->addEventSubscriber(new ValidationListener()) - ; - - if ($options['trim']) { - $builder->addEventSubscriber(new TrimListener()); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form) - { - $name = $form->getName(); - $readOnly = $form->getAttribute('read_only'); - - if ($view->hasParent()) { - if ('' === $name) { - throw new FormException('Form node with empty name can be used only as root form node.'); - } - - if ('' !== ($parentFullName = $view->getParent()->get('full_name'))) { - $id = sprintf('%s_%s', $view->getParent()->get('id'), $name); - $fullName = sprintf('%s[%s]', $parentFullName, $name); - } else { - $id = $name; - $fullName = $name; - } - - // Complex fields are read-only if themselves or their parent is. - $readOnly = $readOnly || $view->getParent()->get('read_only'); - } else { - $id = $name; - $fullName = $name; - - // Strip leading underscores and digits. These are allowed in - // form names, but not in HTML4 ID attributes. - // http://www.w3.org/TR/html401/struct/global.html#adef-id - $id = ltrim($id, '_0123456789'); - } - - $types = array(); - foreach ($form->getTypes() as $type) { - $types[] = $type->getName(); - } - - $view - ->set('form', $view) - ->set('id', $id) - ->set('name', $name) - ->set('full_name', $fullName) - ->set('read_only', $readOnly) - ->set('errors', $form->getErrors()) - ->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('size', null) - ->set('label', $form->getAttribute('label')) - ->set('multipart', false) - ->set('attr', $form->getAttribute('attr')) - ->set('types', $types) - ->set('translation_domain', $form->getAttribute('translation_domain')) - ; - } - - /** - * {@inheritdoc} - */ - public function getDefaultOptions() - { - // Derive "data_class" option from passed "data" object - $dataClass = function (Options $options) { - if (is_object($options['data'])) { - return get_class($options['data']); - } - - return null; - }; - - // Derive "empty_data" closure from "data_class" option - $emptyData = function (Options $options) { - $class = $options['data_class']; - - if (null !== $class) { - return function (FormInterface $form) use ($class) { - if ($form->isEmpty() && !$form->isRequired()) { - return null; - } - - return new $class(); - }; - } - - return ''; - }; - - return array( - 'data' => null, - 'data_class' => $dataClass, - 'empty_data' => $emptyData, - 'trim' => true, - 'required' => true, - 'read_only' => false, - 'disabled' => false, - 'max_length' => null, - 'pattern' => null, - 'property_path' => null, - 'by_reference' => true, - 'error_bubbling' => false, - 'error_mapping' => array(), - 'label' => null, - 'attr' => array(), - 'invalid_message' => 'This value is not valid', - 'invalid_message_parameters' => array(), - 'translation_domain' => 'messages', - ); - } - - /** - * {@inheritdoc} - */ - public function createBuilder($name, FormFactoryInterface $factory, array $options) - { - return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']); - } - - /** - * {@inheritdoc} - */ - public function getParent(array $options) - { - return null; - } - /** * {@inheritdoc} */ @@ -203,9 +39,4 @@ class FieldType extends AbstractType { return 'field'; } - - private function humanize($text) - { - return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text)))); - } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index 30f37203b2..468c65a0f3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -23,12 +23,24 @@ class FileType extends AbstractType public function buildView(FormView $view, FormInterface $form) { $view - ->set('multipart', true) ->set('type', 'file') ->set('value', '') ; } + /** + * {@inheritdoc} + */ + public function buildViewBottomUp(FormView $view, FormInterface $form) + { + $view + ->set('multipart', true) + ; + } + + /** + * {@inheritdoc} + */ public function getParent(array $options) { return 'field'; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php index 36e0c0c63b..7288cd177c 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php @@ -13,10 +13,16 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Options; +use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormView; +use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; +use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Exception\FormException; class FormType extends AbstractType { @@ -25,9 +31,102 @@ class FormType extends AbstractType */ public function buildForm(FormBuilder $builder, array $options) { + if (null === $options['property_path']) { + $options['property_path'] = $builder->getName(); + } + + if (false === $options['property_path'] || '' === $options['property_path']) { + $options['property_path'] = null; + } else { + $options['property_path'] = new PropertyPath($options['property_path']); + } + if (!is_array($options['attr'])) { + throw new FormException('The "attr" option must be "array".'); + } + $builder + ->setRequired($options['required']) + ->setDisabled($options['disabled']) + ->setErrorBubbling($options['error_bubbling']) + ->setEmptyData($options['empty_data']) + ->setAttribute('read_only', $options['read_only']) + ->setAttribute('by_reference', $options['by_reference']) + ->setAttribute('property_path', $options['property_path']) + ->setAttribute('error_mapping', $options['error_mapping']) + ->setAttribute('max_length', $options['max_length']) + ->setAttribute('pattern', $options['pattern']) + ->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName())) + ->setAttribute('attr', $options['attr'] ?: array()) + ->setAttribute('invalid_message', $options['invalid_message']) + ->setAttribute('invalid_message_parameters', $options['invalid_message_parameters']) + ->setAttribute('translation_domain', $options['translation_domain']) ->setAttribute('virtual', $options['virtual']) + ->setData($options['data']) ->setDataMapper(new PropertyPathMapper($options['data_class'])) + ->addEventSubscriber(new ValidationListener()) + ; + + if ($options['trim']) { + $builder->addEventSubscriber(new TrimListener()); + } + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form) + { + $name = $form->getName(); + $readOnly = $form->getAttribute('read_only'); + + if ($view->hasParent()) { + if ('' === $name) { + throw new FormException('Form node with empty name can be used only as root form node.'); + } + + if ('' !== ($parentFullName = $view->getParent()->get('full_name'))) { + $id = sprintf('%s_%s', $view->getParent()->get('id'), $name); + $fullName = sprintf('%s[%s]', $parentFullName, $name); + } else { + $id = $name; + $fullName = $name; + } + + // Complex fields are read-only if themselves or their parent is. + $readOnly = $readOnly || $view->getParent()->get('read_only'); + } else { + $id = $name; + $fullName = $name; + + // Strip leading underscores and digits. These are allowed in + // form names, but not in HTML4 ID attributes. + // http://www.w3.org/TR/html401/struct/global.html#adef-id + $id = ltrim($id, '_0123456789'); + } + + $types = array(); + foreach ($form->getTypes() as $type) { + $types[] = $type->getName(); + } + + $view + ->set('form', $view) + ->set('id', $id) + ->set('name', $name) + ->set('full_name', $fullName) + ->set('read_only', $readOnly) + ->set('errors', $form->getErrors()) + ->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('size', null) + ->set('label', $form->getAttribute('label')) + ->set('multipart', false) + ->set('attr', $form->getAttribute('attr')) + ->set('types', $types) + ->set('translation_domain', $form->getAttribute('translation_domain')) ; } @@ -53,29 +152,75 @@ class FormType extends AbstractType */ public function getDefaultOptions() { - $emptyData = function (Options $options, $currentValue) { - if (empty($options['data_class'])) { - return array(); + // Derive "data_class" option from passed "data" object + $dataClass = function (Options $options) { + if (is_object($options['data'])) { + return get_class($options['data']); } - return $currentValue; + return null; }; + // Derive "empty_data" closure from "data_class" option + $emptyData = function (Options $options) { + $class = $options['data_class']; + + if (null !== $class) { + return function (FormInterface $form) use ($class) { + if ($form->isEmpty() && !$form->isRequired()) { + return null; + } + + return new $class(); + }; + } + + return function (FormInterface $form) { + if ($form->hasChildren()) { + return array(); + } + }; + + return ''; + }; + return array( + 'data' => null, + 'data_class' => $dataClass, 'empty_data' => $emptyData, + 'trim' => true, + 'required' => true, + 'read_only' => false, + 'disabled' => false, + 'max_length' => null, + 'pattern' => null, + 'property_path' => null, + 'by_reference' => true, + 'error_bubbling' => false, + 'error_mapping' => array(), + 'label' => null, + 'attr' => array(), 'virtual' => false, - // Errors in forms bubble by default, so that form errors will - // end up as global errors in the root form - 'error_bubbling' => true, + 'invalid_message' => 'This value is not valid', + 'invalid_message_parameters' => array(), + 'translation_domain' => 'messages', ); } + /** + * {@inheritdoc} + */ + public function createBuilder($name, FormFactoryInterface $factory, array $options) + { + return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']); + } + /** * {@inheritdoc} */ public function getParent(array $options) { - return 'field'; + return null; } /** @@ -85,4 +230,9 @@ class FormType extends AbstractType { return 'form'; } + + private function humanize($text) + { + return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text)))); + } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index 3f7258bb82..546220d0ab 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -150,7 +150,7 @@ class TimeType extends AbstractType // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, - // If initialized with a \DateTime object, FieldType initializes + // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. @@ -183,7 +183,7 @@ class TimeType extends AbstractType */ public function getParent(array $options) { - return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form'; + return 'field'; } /** diff --git a/src/Symfony/Component/Form/Extension/Validator/Type/FieldTypeValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php similarity index 95% rename from src/Symfony/Component/Form/Extension/Validator/Type/FieldTypeValidatorExtension.php rename to src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php index 8d0db3f4f6..77754669f3 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Type/FieldTypeValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -19,7 +19,7 @@ use Symfony\Component\Validator\ValidatorInterface; /** * @author Bernhard Schussek */ -class FieldTypeValidatorExtension extends AbstractTypeExtension +class FormTypeValidatorExtension extends AbstractTypeExtension { private $validator; @@ -57,6 +57,6 @@ class FieldTypeValidatorExtension extends AbstractTypeExtension public function getExtendedType() { - return 'field'; + return 'form'; } } diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php index 94b6ea699d..b4efa1679a 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php @@ -38,7 +38,7 @@ class ValidatorExtension extends AbstractExtension protected function loadTypeExtensions() { return array( - new Type\FieldTypeValidatorExtension($this->validator), + new Type\FormTypeValidatorExtension($this->validator), ); } } diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 4798c7e5cd..5669e0ead4 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -191,7 +191,7 @@ class Form implements \IteratorAggregate, FormInterface array $types = array(), array $clientTransformers = array(), array $normTransformers = array(), DataMapperInterface $dataMapper = null, array $validators = array(), - $required = false, $disabled = false, $errorBubbling = false, + $required = false, $disabled = false, $errorBubbling = null, $emptyData = null, array $attributes = array()) { $name = (string) $name; @@ -225,7 +225,10 @@ class Form implements \IteratorAggregate, FormInterface $this->validators = $validators; $this->required = (Boolean) $required; $this->disabled = (Boolean) $disabled; - $this->errorBubbling = (Boolean) $errorBubbling; + // NULL is the default meaning: + // bubble up if the form has children (complex forms) + // don't bubble up if the form has no children (primitive fields) + $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; $this->emptyData = $emptyData; $this->attributes = $attributes; @@ -312,9 +315,9 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns the parent field. + * Returns the parent form. * - * @return FormInterface The parent field + * @return FormInterface The parent form */ public function getParent() { @@ -342,7 +345,7 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns whether the field is the root of the form tree. + * Returns whether the form is the root of the form tree. * * @return Boolean */ @@ -374,7 +377,7 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Updates the field with default data. + * Updates the form with default data. * * @param array $appData The data formatted as expected for the underlying object * @@ -408,7 +411,7 @@ class Form implements \IteratorAggregate, FormInterface $this->clientData = $clientData; $this->synchronized = true; - if ($this->dataMapper) { + if (count($this->children) > 0 && $this->dataMapper) { // Update child forms from the data $this->dataMapper->mapDataToForms($clientData, $this->children); } @@ -450,7 +453,7 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Binds data to the field, transforms and validates it. + * Binds data to the form, transforms and validates it. * * @param string|array $clientData The data * @@ -626,11 +629,11 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns the normalized data of the field. + * Returns the normalized data of the form. * - * @return mixed When the field is not bound, the default data is returned. - * When the field is bound, the normalized bound data is - * returned if the field is valid, null otherwise. + * @return mixed When the form is not bound, the default data is returned. + * When the form is bound, the normalized bound data is + * returned if the form is valid, null otherwise. */ public function getNormData() { @@ -646,7 +649,7 @@ class Form implements \IteratorAggregate, FormInterface */ public function addError(FormError $error) { - if ($this->parent && $this->errorBubbling) { + if ($this->parent && $this->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; @@ -662,11 +665,11 @@ class Form implements \IteratorAggregate, FormInterface */ public function getErrorBubbling() { - return $this->errorBubbling; + return null === $this->errorBubbling ? $this->hasChildren() : $this->errorBubbling; } /** - * Returns whether the field is bound. + * Returns whether the form is bound. * * @return Boolean true if the form is bound to input values, false otherwise */ @@ -702,7 +705,7 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns whether the field is valid. + * Returns whether the form is valid. * * @return Boolean */ @@ -735,9 +738,8 @@ class Form implements \IteratorAggregate, FormInterface public function hasErrors() { // Don't call isValid() here, as its semantics are slightly different - // Field groups are not valid if their children are invalid, but - // hasErrors() returns only true if a field/field group itself has - // errors + // Forms are not valid if their children are invalid, but + // hasErrors() returns only true if a form itself has errors return count($this->errors) > 0; } @@ -894,7 +896,7 @@ class Form implements \IteratorAggregate, FormInterface return $this->children[$name]; } - throw new \InvalidArgumentException(sprintf('Field "%s" does not exist.', $name)); + throw new \InvalidArgumentException(sprintf('Child "%s" does not exist.', $name)); } /** diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index 208a518518..b8f7da16c6 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -106,7 +106,7 @@ class FormBuilder * Whether added errors should bubble up to the parent * @var Boolean */ - private $errorBubbling = false; + private $errorBubbling; /** * Data used for the client data when no value is bound @@ -243,7 +243,7 @@ class FormBuilder */ public function setErrorBubbling($errorBubbling) { - $this->errorBubbling = (Boolean) $errorBubbling; + $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; return $this; } diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index d0d8a80a8d..f3ca837356 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -183,7 +183,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable * The content of a disabled form is displayed, but not allowed to be * modified. The validation of modified disabled forms should fail. * - * Fields whose parents are disabled are considered disabled regardless of + * Forms whose parents are disabled are considered disabled regardless of * their own state. * * @return Boolean diff --git a/src/Symfony/Component/Form/FormTypeGuesserChain.php b/src/Symfony/Component/Form/FormTypeGuesserChain.php index b3ca91a460..9d915698ca 100644 --- a/src/Symfony/Component/Form/FormTypeGuesserChain.php +++ b/src/Symfony/Component/Form/FormTypeGuesserChain.php @@ -75,7 +75,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance * - * @return FieldFactoryGuess The guess with the highest confidence + * @return Guess The guess with the highest confidence */ private function guess(\Closure $closure) { diff --git a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php index 986f99b7b4..7d1512f003 100644 --- a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php @@ -202,7 +202,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest ); } - public function testRestAndRepeatedWithRowPerField() + public function testRestAndRepeatedWithRowPerChild() { $view = $this->factory->createNamedBuilder('form', 'name') ->add('first', 'text') @@ -230,7 +230,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest ); } - public function testRestAndRepeatedWithWidgetPerField() + public function testRestAndRepeatedWithWidgetPerChild() { $view = $this->factory->createNamedBuilder('form', 'name') ->add('first', 'text') @@ -348,7 +348,10 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest public function testNestedFormError() { $form = $this->factory->createNamedBuilder('form', 'name') - ->add('child', 'form', array('error_bubbling' => false)) + ->add($this->factory + ->createNamedBuilder('form', 'child', null, array('error_bubbling' => false)) + ->add('grandChild', 'form') + ) ->getForm(); $form->get('child')->addError(new FormError('Error!')); diff --git a/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php index 5ea8780d89..0943b06c41 100644 --- a/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php @@ -210,7 +210,10 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest public function testNestedFormError() { $form = $this->factory->createNamedBuilder('form', 'name') - ->add('child', 'form', array('error_bubbling' => false)) + ->add($this->factory + ->createNamedBuilder('form', 'child', null, array('error_bubbling' => false)) + ->add('grandChild', 'form') + ) ->getForm(); $form->get('child')->addError(new FormError('Error!')); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 9cf54e25ed..fbda65a3b6 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -98,7 +98,7 @@ class ChoiceTypeTest extends TypeTestCase )); } - public function testExpandedChoicesOptionsTurnIntoFields() + public function testExpandedChoicesOptionsTurnIntoChildren() { $form = $this->factory->create('choice', null, array( 'expanded' => true, @@ -141,7 +141,7 @@ class ChoiceTypeTest extends TypeTestCase } } - public function testExpandedRadiosAreRequiredIfChoiceFieldIsRequired() + public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -155,7 +155,7 @@ class ChoiceTypeTest extends TypeTestCase } } - public function testExpandedRadiosAreNotRequiredIfChoiceFieldIsNotRequired() + public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -288,7 +288,7 @@ class ChoiceTypeTest extends TypeTestCase $this->assertNull($form[4]->getClientData()); } - public function testBindSingleExpandedWithFalseDoesNotHaveExtraFields() + public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -302,7 +302,7 @@ class ChoiceTypeTest extends TypeTestCase $this->assertNull($form->getData()); } - public function testBindSingleExpandedWithEmptyField() + public function testBindSingleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -422,7 +422,7 @@ class ChoiceTypeTest extends TypeTestCase $this->assertNull($form[4]->getClientData()); } - public function testBindMultipleExpandedWithEmptyField() + public function testBindMultipleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => true, diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php index b0bb62508f..5461258e95 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -15,10 +15,10 @@ use Symfony\Component\Form\Form; class CollectionTypeTest extends TypeTestCase { - public function testContainsNoFieldByDefault() + public function testContainsNoChildByDefault() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', )); $this->assertCount(0, $form); @@ -27,7 +27,7 @@ class CollectionTypeTest extends TypeTestCase public function testSetDataAdjustsSize() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'options' => array( 'max_length' => 20, ), @@ -53,7 +53,7 @@ class CollectionTypeTest extends TypeTestCase public function testThrowsExceptionIfObjectIsNotTraversable() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', )); $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $form->setData(new \stdClass()); @@ -62,7 +62,7 @@ class CollectionTypeTest extends TypeTestCase public function testNotResizedIfBoundWithMissingData() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', )); $form->setData(array('foo@foo.com', 'bar@bar.com')); $form->bind(array('foo@bar.com')); @@ -76,7 +76,7 @@ class CollectionTypeTest extends TypeTestCase public function testResizedDownIfBoundWithMissingDataAndAllowDelete() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'allow_delete' => true, )); $form->setData(array('foo@foo.com', 'bar@bar.com')); @@ -91,7 +91,7 @@ class CollectionTypeTest extends TypeTestCase public function testNotResizedIfBoundWithExtraData() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', )); $form->setData(array('foo@bar.com')); $form->bind(array('foo@foo.com', 'bar@bar.com')); @@ -104,7 +104,7 @@ class CollectionTypeTest extends TypeTestCase public function testResizedUpIfBoundWithExtraDataAndAllowAdd() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'allow_add' => true, )); $form->setData(array('foo@bar.com')); @@ -120,7 +120,7 @@ class CollectionTypeTest extends TypeTestCase public function testAllowAddButNoPrototype() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'allow_add' => true, 'prototype' => false, )); @@ -169,7 +169,7 @@ class CollectionTypeTest extends TypeTestCase public function testPrototypeNameOption() { $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'prototype' => true, 'allow_add' => true, )); @@ -177,7 +177,7 @@ class CollectionTypeTest extends TypeTestCase $this->assertSame('__name__', $form->getAttribute('prototype')->getName(), '__name__ is the default'); $form = $this->factory->create('collection', null, array( - 'type' => 'field', + 'type' => 'form', 'prototype' => true, 'allow_add' => true, 'prototype_name' => '__test__', diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FieldTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FieldTypeTest.php deleted file mode 100644 index b588d4433f..0000000000 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FieldTypeTest.php +++ /dev/null @@ -1,380 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Extension\Core\Type; - -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Form; -use Symfony\Component\Form\Tests\Fixtures\Author; -use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; - -class FieldTypeTest extends TypeTestCase -{ - public function testGetPropertyPathDefaultPath() - { - $form = $this->factory->createNamed('field', 'title'); - - $this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path')); - } - - public function testGetPropertyPathPathIsZero() - { - $form = $this->factory->create('field', null, array('property_path' => '0')); - - $this->assertEquals(new PropertyPath('0'), $form->getAttribute('property_path')); - } - - public function testGetPropertyPathPathIsEmpty() - { - $form = $this->factory->create('field', null, array('property_path' => '')); - - $this->assertNull($form->getAttribute('property_path')); - } - - public function testGetPropertyPathPathIsFalse() - { - $form = $this->factory->create('field', null, array('property_path' => false)); - - $this->assertNull($form->getAttribute('property_path')); - } - - public function testGetPropertyPathPathIsNull() - { - $form = $this->factory->createNamed('field', 'title', null, array('property_path' => null)); - - $this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path')); - } - - public function testPassRequiredAsOption() - { - $form = $this->factory->create('field', null, array('required' => false)); - - $this->assertFalse($form->isRequired()); - - $form = $this->factory->create('field', null, array('required' => true)); - - $this->assertTrue($form->isRequired()); - } - - public function testPassDisabledAsOption() - { - $form = $this->factory->create('field', null, array('disabled' => true)); - - $this->assertTrue($form->isDisabled()); - } - - public function testBoundDataIsTrimmedBeforeTransforming() - { - $form = $this->factory->createBuilder('field') - ->appendClientTransformer(new FixedDataTransformer(array( - null => '', - 'reverse[a]' => 'a', - ))) - ->getForm(); - - $form->bind(' a '); - - $this->assertEquals('a', $form->getClientData()); - $this->assertEquals('reverse[a]', $form->getData()); - } - - public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming() - { - $form = $this->factory->createBuilder('field', null, array('trim' => false)) - ->appendClientTransformer(new FixedDataTransformer(array( - null => '', - 'reverse[ a ]' => ' a ', - ))) - ->getForm(); - - $form->bind(' a '); - - $this->assertEquals(' a ', $form->getClientData()); - $this->assertEquals('reverse[ a ]', $form->getData()); - } - - public function testPassIdAndNameToView() - { - $form = $this->factory->createNamed('field', 'name'); - $view = $form->createView(); - - $this->assertEquals('name', $view->get('id')); - $this->assertEquals('name', $view->get('name')); - $this->assertEquals('name', $view->get('full_name')); - } - - public function testStripLeadingUnderscoresAndDigitsFromId() - { - $form = $this->factory->createNamed('field', '_09name'); - $view = $form->createView(); - - $this->assertEquals('name', $view->get('id')); - $this->assertEquals('_09name', $view->get('name')); - $this->assertEquals('_09name', $view->get('full_name')); - } - - public function testPassIdAndNameToViewWithParent() - { - $parent = $this->factory->createNamed('field', 'parent'); - $parent->add($this->factory->createNamed('field', 'child')); - $view = $parent->createView(); - - $this->assertEquals('parent_child', $view['child']->get('id')); - $this->assertEquals('child', $view['child']->get('name')); - $this->assertEquals('parent[child]', $view['child']->get('full_name')); - } - - public function testPassIdAndNameToViewWithGrandParent() - { - $parent = $this->factory->createNamed('field', 'parent'); - $parent->add($this->factory->createNamed('field', 'child')); - $parent['child']->add($this->factory->createNamed('field', 'grand_child')); - $view = $parent->createView(); - - $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->get('id')); - $this->assertEquals('grand_child', $view['child']['grand_child']->get('name')); - $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->get('full_name')); - } - - public function testNonReadOnlyFieldWithReadOnlyParentBeingReadOnly() - { - $parent = $this->factory->createNamed('field', 'parent', null, array('read_only' => true)); - $child = $this->factory->createNamed('field', 'child'); - $view = $parent->add($child)->createView(); - - $this->assertTrue($view['child']->get('read_only')); - } - - public function testReadOnlyFieldWithNonReadOnlyParentBeingReadOnly() - { - $parent = $this->factory->createNamed('field', 'parent'); - $child = $this->factory->createNamed('field', 'child', null, array('read_only' => true)); - $view = $parent->add($child)->createView(); - - $this->assertTrue($view['child']->get('read_only')); - } - - public function testNonReadOnlyFieldWithNonReadOnlyParentBeingNonReadOnly() - { - $parent = $this->factory->createNamed('field', 'parent'); - $child = $this->factory->createNamed('field', 'child'); - $view = $parent->add($child)->createView(); - - $this->assertFalse($view['child']->get('read_only')); - } - - public function testPassMaxLengthToView() - { - $form = $this->factory->create('field', null, array('max_length' => 10)); - $view = $form->createView(); - - $this->assertSame(10, $view->get('max_length')); - } - - public function testPassTranslationDomainToView() - { - $form = $this->factory->create('field', null, array('translation_domain' => 'test')); - $view = $form->createView(); - - $this->assertSame('test', $view->get('translation_domain')); - } - - public function testPassDefaultLabelToView() - { - $form = $this->factory->createNamed('field', '__test___field'); - $view = $form->createView(); - - $this->assertSame('Test field', $view->get('label')); - } - - public function testPassLabelToView() - { - $form = $this->factory->createNamed('field', '__test___field', null, array('label' => 'My label')); - $view = $form->createView(); - - $this->assertSame('My label', $view->get('label')); - } - - public function testDefaultTranslationDomain() - { - $form = $this->factory->create('field'); - $view = $form->createView(); - - $this->assertSame('messages', $view->get('translation_domain')); - } - - public function testBindWithEmptyDataCreatesObjectIfClassAvailable() - { - $form = $this->factory->create('form', null, array( - 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', - 'required' => false, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - $form->add($this->factory->createNamed('field', 'lastName')); - - $form->setData(null); - // partially empty, still an object is created - $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); - - $author = new Author(); - $author->firstName = 'Bernhard'; - $author->setLastName(''); - - $this->assertEquals($author, $form->getData()); - } - - public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject() - { - $form = $this->factory->create('form', null, array( - // data class is inferred from the passed object - 'data' => new Author(), - 'required' => false, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - $form->add($this->factory->createNamed('field', 'lastName')); - - $form->setData(null); - // partially empty, still an object is created - $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); - - $author = new Author(); - $author->firstName = 'Bernhard'; - $author->setLastName(''); - - $this->assertEquals($author, $form->getData()); - } - - public function testBindWithEmptyDataDoesNotCreateObjectIfDataClassIsNull() - { - $form = $this->factory->create('form', null, array( - 'data' => new Author(), - 'data_class' => null, - 'required' => false, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - - $form->setData(null); - $form->bind(array('firstName' => 'Bernhard')); - - $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); - } - - public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired() - { - $form = $this->factory->create('form', null, array( - 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', - 'required' => false, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - $form->add($this->factory->createNamed('field', 'lastName')); - - $form->setData(null); - $form->bind(array('firstName' => '', 'lastName' => '')); - - $this->assertNull($form->getData()); - } - - public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() - { - $form = $this->factory->create('form', null, array( - 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', - 'required' => true, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - $form->add($this->factory->createNamed('field', 'lastName')); - - $form->setData(null); - $form->bind(array('firstName' => '', 'lastName' => '')); - - $this->assertEquals(new Author(), $form->getData()); - } - - /* - * We need something to write the field values into - */ - public function testBindWithEmptyDataStoresArrayIfNoClassAvailable() - { - $form = $this->factory->create('form'); - $form->add($this->factory->createNamed('field', 'firstName')); - - $form->setData(null); - $form->bind(array('firstName' => 'Bernhard')); - - $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); - } - - public function testBindWithEmptyDataUsesEmptyDataOption() - { - $author = new Author(); - - $form = $this->factory->create('form', null, array( - 'empty_data' => $author, - )); - $form->add($this->factory->createNamed('field', 'firstName')); - - $form->bind(array('firstName' => 'Bernhard')); - - $this->assertSame($author, $form->getData()); - $this->assertEquals('Bernhard', $author->firstName); - } - - public function testGetAttributesIsEmpty() - { - $form = $this->factory->create('field', null, array('attr' => array())); - - $this->assertCount(0, $form->getAttribute('attr')); - } - - /** - * @see https://github.com/symfony/symfony/issues/1986 - */ - public function testSetDataThroughParamsWithZero() - { - $form = $this->factory->create('field', null, array('data' => 0)); - $view = $form->createView(); - - $this->assertFalse($form->isEmpty()); - - $this->assertSame('0', $view->get('value')); - $this->assertSame('0', $form->getData()); - - $form = $this->factory->create('field', null, array('data' => '0')); - $view = $form->createView(); - - $this->assertFalse($form->isEmpty()); - - $this->assertSame('0', $view->get('value')); - $this->assertSame('0', $form->getData()); - - $form = $this->factory->create('field', null, array('data' => '00000')); - $view = $form->createView(); - - $this->assertFalse($form->isEmpty()); - - $this->assertSame('00000', $view->get('value')); - $this->assertSame('00000', $form->getData()); - } - - /** - * @expectedException Symfony\Component\Form\Exception\FormException - */ - public function testAttributesException() - { - $form = $this->factory->create('field', null, array('attr' => '')); - } - - public function testNameCanBeEmptyString() - { - $form = $this->factory->createNamed('field', ''); - - $this->assertEquals('', $form->getName()); - } -} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php index eff0719692..72ba0fc98e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\Form; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Tests\Fixtures\Author; +use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; class FormTest_AuthorWithoutRefSetter { @@ -49,13 +51,372 @@ class FormTest_AuthorWithoutRefSetter class FormTypeTest extends TypeTestCase { + public function testGetPropertyPathDefaultPath() + { + $form = $this->factory->createNamed('form', 'title'); + + $this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path')); + } + + public function testGetPropertyPathPathIsZero() + { + $form = $this->factory->create('form', null, array('property_path' => '0')); + + $this->assertEquals(new PropertyPath('0'), $form->getAttribute('property_path')); + } + + public function testGetPropertyPathPathIsEmpty() + { + $form = $this->factory->create('form', null, array('property_path' => '')); + + $this->assertNull($form->getAttribute('property_path')); + } + + public function testGetPropertyPathPathIsFalse() + { + $form = $this->factory->create('form', null, array('property_path' => false)); + + $this->assertNull($form->getAttribute('property_path')); + } + + public function testGetPropertyPathPathIsNull() + { + $form = $this->factory->createNamed('form', 'title', null, array('property_path' => null)); + + $this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path')); + } + + public function testPassRequiredAsOption() + { + $form = $this->factory->create('form', null, array('required' => false)); + + $this->assertFalse($form->isRequired()); + + $form = $this->factory->create('form', null, array('required' => true)); + + $this->assertTrue($form->isRequired()); + } + + public function testPassDisabledAsOption() + { + $form = $this->factory->create('form', null, array('disabled' => true)); + + $this->assertTrue($form->isDisabled()); + } + + public function testBoundDataIsTrimmedBeforeTransforming() + { + $form = $this->factory->createBuilder('form') + ->appendClientTransformer(new FixedDataTransformer(array( + null => '', + 'reverse[a]' => 'a', + ))) + ->getForm(); + + $form->bind(' a '); + + $this->assertEquals('a', $form->getClientData()); + $this->assertEquals('reverse[a]', $form->getData()); + } + + public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming() + { + $form = $this->factory->createBuilder('form', null, array('trim' => false)) + ->appendClientTransformer(new FixedDataTransformer(array( + null => '', + 'reverse[ a ]' => ' a ', + ))) + ->getForm(); + + $form->bind(' a '); + + $this->assertEquals(' a ', $form->getClientData()); + $this->assertEquals('reverse[ a ]', $form->getData()); + } + + public function testPassIdAndNameToView() + { + $form = $this->factory->createNamed('form', 'name'); + $view = $form->createView(); + + $this->assertEquals('name', $view->get('id')); + $this->assertEquals('name', $view->get('name')); + $this->assertEquals('name', $view->get('full_name')); + } + + public function testStripLeadingUnderscoresAndDigitsFromId() + { + $form = $this->factory->createNamed('form', '_09name'); + $view = $form->createView(); + + $this->assertEquals('name', $view->get('id')); + $this->assertEquals('_09name', $view->get('name')); + $this->assertEquals('_09name', $view->get('full_name')); + } + + public function testPassIdAndNameToViewWithParent() + { + $parent = $this->factory->createNamed('form', 'parent'); + $parent->add($this->factory->createNamed('form', 'child')); + $view = $parent->createView(); + + $this->assertEquals('parent_child', $view['child']->get('id')); + $this->assertEquals('child', $view['child']->get('name')); + $this->assertEquals('parent[child]', $view['child']->get('full_name')); + } + + public function testPassIdAndNameToViewWithGrandParent() + { + $parent = $this->factory->createNamed('form', 'parent'); + $parent->add($this->factory->createNamed('form', 'child')); + $parent['child']->add($this->factory->createNamed('form', 'grand_child')); + $view = $parent->createView(); + + $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->get('id')); + $this->assertEquals('grand_child', $view['child']['grand_child']->get('name')); + $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->get('full_name')); + } + + public function testNonReadOnlyFormWithReadOnlyParentBeingReadOnly() + { + $parent = $this->factory->createNamed('form', 'parent', null, array('read_only' => true)); + $child = $this->factory->createNamed('form', 'child'); + $view = $parent->add($child)->createView(); + + $this->assertTrue($view['child']->get('read_only')); + } + + public function testReadOnlyFormWithNonReadOnlyParentBeingReadOnly() + { + $parent = $this->factory->createNamed('form', 'parent'); + $child = $this->factory->createNamed('form', 'child', null, array('read_only' => true)); + $view = $parent->add($child)->createView(); + + $this->assertTrue($view['child']->get('read_only')); + } + + public function testNonReadOnlyFormWithNonReadOnlyParentBeingNonReadOnly() + { + $parent = $this->factory->createNamed('form', 'parent'); + $child = $this->factory->createNamed('form', 'child'); + $view = $parent->add($child)->createView(); + + $this->assertFalse($view['child']->get('read_only')); + } + + public function testPassMaxLengthToView() + { + $form = $this->factory->create('form', null, array('max_length' => 10)); + $view = $form->createView(); + + $this->assertSame(10, $view->get('max_length')); + } + + public function testPassTranslationDomainToView() + { + $form = $this->factory->create('form', null, array('translation_domain' => 'test')); + $view = $form->createView(); + + $this->assertSame('test', $view->get('translation_domain')); + } + + public function testPassDefaultLabelToView() + { + $form = $this->factory->createNamed('form', '__test___field'); + $view = $form->createView(); + + $this->assertSame('Test field', $view->get('label')); + } + + public function testPassLabelToView() + { + $form = $this->factory->createNamed('form', '__test___field', null, array('label' => 'My label')); + $view = $form->createView(); + + $this->assertSame('My label', $view->get('label')); + } + + public function testDefaultTranslationDomain() + { + $form = $this->factory->create('form'); + $view = $form->createView(); + + $this->assertSame('messages', $view->get('translation_domain')); + } + + public function testBindWithEmptyDataCreatesObjectIfClassAvailable() + { + $form = $this->factory->create('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => false, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + $form->add($this->factory->createNamed('form', 'lastName')); + + $form->setData(null); + // partially empty, still an object is created + $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); + + $author = new Author(); + $author->firstName = 'Bernhard'; + $author->setLastName(''); + + $this->assertEquals($author, $form->getData()); + } + + public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject() + { + $form = $this->factory->create('form', null, array( + // data class is inferred from the passed object + 'data' => new Author(), + 'required' => false, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + $form->add($this->factory->createNamed('form', 'lastName')); + + $form->setData(null); + // partially empty, still an object is created + $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); + + $author = new Author(); + $author->firstName = 'Bernhard'; + $author->setLastName(''); + + $this->assertEquals($author, $form->getData()); + } + + public function testBindWithEmptyDataDoesNotCreateObjectIfDataClassIsNull() + { + $form = $this->factory->create('form', null, array( + 'data' => new Author(), + 'data_class' => null, + 'required' => false, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + + $form->setData(null); + $form->bind(array('firstName' => 'Bernhard')); + + $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); + } + + public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired() + { + $form = $this->factory->create('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => false, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + $form->add($this->factory->createNamed('form', 'lastName')); + + $form->setData(null); + $form->bind(array('firstName' => '', 'lastName' => '')); + + $this->assertNull($form->getData()); + } + + public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() + { + $form = $this->factory->create('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => true, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + $form->add($this->factory->createNamed('form', 'lastName')); + + $form->setData(null); + $form->bind(array('firstName' => '', 'lastName' => '')); + + $this->assertEquals(new Author(), $form->getData()); + } + + /* + * We need something to write the field values into + */ + public function testBindWithEmptyDataStoresArrayIfNoClassAvailable() + { + $form = $this->factory->create('form'); + $form->add($this->factory->createNamed('form', 'firstName')); + + $form->setData(null); + $form->bind(array('firstName' => 'Bernhard')); + + $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); + } + + public function testBindWithEmptyDataUsesEmptyDataOption() + { + $author = new Author(); + + $form = $this->factory->create('form', null, array( + 'empty_data' => $author, + )); + $form->add($this->factory->createNamed('form', 'firstName')); + + $form->bind(array('firstName' => 'Bernhard')); + + $this->assertSame($author, $form->getData()); + $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 + */ + public function testSetDataThroughParamsWithZero() + { + $form = $this->factory->create('form', null, array('data' => 0)); + $view = $form->createView(); + + $this->assertFalse($form->isEmpty()); + + $this->assertSame('0', $view->get('value')); + $this->assertSame('0', $form->getData()); + + $form = $this->factory->create('form', null, array('data' => '0')); + $view = $form->createView(); + + $this->assertFalse($form->isEmpty()); + + $this->assertSame('0', $view->get('value')); + $this->assertSame('0', $form->getData()); + + $form = $this->factory->create('form', null, array('data' => '00000')); + $view = $form->createView(); + + $this->assertFalse($form->isEmpty()); + + $this->assertSame('00000', $view->get('value')); + $this->assertSame('00000', $form->getData()); + } + + /** + * @expectedException Symfony\Component\Form\Exception\FormException + */ + public function testAttributesException() + { + $form = $this->factory->create('form', null, array('attr' => '')); + } + + public function testNameCanBeEmptyString() + { + $form = $this->factory->createNamed('form', ''); + + $this->assertEquals('', $form->getName()); + } public function testSubformDoesntCallSetters() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); $builder = $this->factory->createBuilder('form'); $builder->add('reference', 'form'); - $builder->get('reference')->add('firstName', 'field'); + $builder->get('reference')->add('firstName', 'form'); $builder->setData($author); $form = $builder->getForm(); @@ -77,7 +438,7 @@ class FormTypeTest extends TypeTestCase $builder = $this->factory->createBuilder('form'); $builder->add('referenceCopy', 'form'); - $builder->get('referenceCopy')->add('firstName', 'field'); + $builder->get('referenceCopy')->add('firstName', 'form'); $builder->setData($author); $form = $builder->getForm(); @@ -99,7 +460,7 @@ class FormTypeTest extends TypeTestCase $builder = $this->factory->createBuilder('form'); $builder->add('referenceCopy', 'form', array('by_reference' => false)); - $builder->get('referenceCopy')->add('firstName', 'field'); + $builder->get('referenceCopy')->add('firstName', 'form'); $builder->setData($author); $form = $builder->getForm(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php index df571ba9d8..6d9139633e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -21,7 +21,7 @@ class RepeatedTypeTest extends TypeTestCase parent::setUp(); $this->form = $this->factory->create('repeated', null, array( - 'type' => 'field', + 'type' => 'form', )); $this->form->setData(null); } @@ -37,7 +37,7 @@ class RepeatedTypeTest extends TypeTestCase public function testSetOptions() { $form = $this->factory->create('repeated', null, array( - 'type' => 'field', + 'type' => 'form', 'options' => array('label' => 'Global'), )); @@ -47,11 +47,11 @@ class RepeatedTypeTest extends TypeTestCase $this->assertTrue($form['second']->isRequired()); } - public function testSetOptionsPerField() + public function testSetOptionsPerChild() { $form = $this->factory->create('repeated', null, array( // the global required value cannot be overriden - 'type' => 'field', + 'type' => 'form', 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); @@ -66,17 +66,17 @@ class RepeatedTypeTest extends TypeTestCase { $form = $this->factory->create('repeated', null, array( 'required' => false, - 'type' => 'field', + 'type' => 'form', )); $this->assertFalse($form['first']->isRequired()); $this->assertFalse($form['second']->isRequired()); } - public function testSetOptionsPerFieldAndOverwrite() + public function testSetOptionsPerChildAndOverwrite() { $form = $this->factory->create('repeated', null, array( - 'type' => 'field', + 'type' => 'form', 'options' => array('label' => 'Label'), 'second_options' => array('label' => 'Second label') )); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/DelegatingValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/DelegatingValidationListenerTest.php index 0071b36fd7..187ce1a2b7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/DelegatingValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/DelegatingValidationListenerTest.php @@ -93,6 +93,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase $builder = new FormBuilder($name, $this->factory, $this->dispatcher); $builder->setAttribute('property_path', new PropertyPath($propertyPath ?: $name)); $builder->setAttribute('error_mapping', array()); + $builder->setErrorBubbling(false); return $builder; } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FieldTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php similarity index 79% rename from src/Symfony/Component/Form/Tests/Extension/Validator/Type/FieldTypeValidatorExtensionTest.php rename to src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index fdf011d66a..5cd0ea753b 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FieldTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -13,18 +13,18 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\FormInterface; -class FieldTypeValidatorExtensionTest extends TypeTestCase +class FormTypeValidatorExtensionTest extends TypeTestCase { public function testValidationGroupNullByDefault() { - $form = $this->factory->create('field'); + $form = $this->factory->create('form'); $this->assertNull($form->getAttribute('validation_groups')); } public function testValidationGroupsCanBeSetToString() { - $form = $this->factory->create('field', null, array( + $form = $this->factory->create('form', null, array( 'validation_groups' => 'group', )); @@ -33,7 +33,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase public function testValidationGroupsCanBeSetToArray() { - $form = $this->factory->create('field', null, array( + $form = $this->factory->create('form', null, array( 'validation_groups' => array('group1', 'group2'), )); @@ -42,7 +42,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase public function testValidationGroupsCanBeSetToCallback() { - $form = $this->factory->create('field', null, array( + $form = $this->factory->create('form', null, array( 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), )); @@ -51,7 +51,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase public function testValidationGroupsCanBeSetToClosure() { - $form = $this->factory->create('field', null, array( + $form = $this->factory->create('form', null, array( 'validation_groups' => function(FormInterface $form){ return null; }, )); @@ -60,10 +60,10 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase public function testBindValidatesData() { - $builder = $this->factory->createBuilder('field', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'validation_groups' => 'group', )); - $builder->add('firstName', 'field'); + $builder->add('firstName', 'form'); $form = $builder->getForm(); $this->validator->expects($this->once()) diff --git a/src/Symfony/Component/Form/Tests/FormBuilderTest.php b/src/Symfony/Component/Form/Tests/FormBuilderTest.php index f5276f322e..bbae7ee2dd 100644 --- a/src/Symfony/Component/Form/Tests/FormBuilderTest.php +++ b/src/Symfony/Component/Form/Tests/FormBuilderTest.php @@ -71,7 +71,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase * Changing the name is not allowed, otherwise the name and property path * are not synchronized anymore * - * @see FieldType::buildForm + * @see FormType::buildForm */ public function testNoSetName() { diff --git a/src/Symfony/Component/Form/Tests/FormFactoryTest.php b/src/Symfony/Component/Form/Tests/FormFactoryTest.php index 96ceea5532..49e53e8337 100644 --- a/src/Symfony/Component/Form/Tests/FormFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/FormFactoryTest.php @@ -346,7 +346,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase $this->assertEquals('foo', $builder->getName()); } - public function testCreateBuilderForPropertyCreatesFieldWithHighestConfidence() + public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() { $this->guesser1->expects($this->once()) ->method('guessType') @@ -378,7 +378,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase $this->assertEquals('builderInstance', $builder); } - public function testCreateBuilderCreatesTextFieldIfNoGuess() + public function testCreateBuilderCreatesTextFormIfNoGuess() { $this->guesser1->expects($this->once()) ->method('guessType') @@ -541,7 +541,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase $factory->createNamedBuilder($type, "text", "value", array("unknown" => "opt")); } - public function testFieldTypeCreatesDefaultValueForEmptyDataOption() + public function testFormTypeCreatesDefaultValueForEmptyDataOption() { $factory = new FormFactory(array(new \Symfony\Component\Form\Extension\Core\CoreExtension())); diff --git a/src/Symfony/Component/Form/Tests/FormTest.php b/src/Symfony/Component/Form/Tests/FormTest.php index bc25e16a1f..08ef363e4b 100644 --- a/src/Symfony/Component/Form/Tests/FormTest.php +++ b/src/Symfony/Component/Form/Tests/FormTest.php @@ -159,6 +159,35 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array(), $parent->getErrors()); } + public function testErrorsBubbleUpIfNullAndChildren() + { + $error = new FormError('Error!'); + $parent = $this->form; + $form = $this->getBuilder() + ->setErrorBubbling(null) + ->add($this->getBuilder('child')) + ->getForm(); + + $form->setParent($parent); + $form->addError($error); + + $this->assertEquals(array(), $form->getErrors()); + $this->assertEquals(array($error), $parent->getErrors()); + } + + public function testErrorsDontBubbleUpIfNullAndNoChildren() + { + $error = new FormError('Error!'); + $parent = $this->form; + $form = $this->getBuilder()->setErrorBubbling(null)->getForm(); + + $form->setParent($parent); + $form->addError($error); + + $this->assertEquals(array($error), $form->getErrors()); + $this->assertEquals(array(), $parent->getErrors()); + } + public function testValidIfAllChildrenAreValid() { $this->form->add($this->getValidForm('firstName')); @@ -1026,7 +1055,7 @@ class FormTest extends \PHPUnit_Framework_TestCase /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequestWithSingleFieldForm($method) + public function testBindPostOrPutRequestWithSingleChildForm($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -1063,7 +1092,7 @@ class FormTest extends \PHPUnit_Framework_TestCase /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequestWithSingleFieldFormUploadedFile($method) + public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available');