merged branch bschussek/issue3878 (PR #3923)
Commits -------6e4ed9e
[Form] Fixed regression: bind(null) was not converted to an empty string anymorefcb2227
[Form] Deprecated FieldType, which has been merged into FormTypebfa7ef2
[Form] Removed obsolete exceptions2a49449
[Form] Simplified CSRF mechanism and removed "csrf" type Discussion ---------- [Form] Merged FieldType into FormType Bug fix: no Feature addition: no Backwards compatibility break: yes Symfony2 tests pass: yes Fixes the following tickets: #3878 Todo: update the documentation on theming ![Travis Build Status](https://secure.travis-ci.org/bschussek/symfony.png?branch=issue3878) This PR is a preparatory PR for #3879. See also #3878. --------------------------------------------------------------------------- by juliendidier at 2012-04-13T14:25:19Z What's the benefit ? --------------------------------------------------------------------------- by henrikbjorn at 2012-04-13T14:26:40Z why `input_widget` ? and not just `widget` --------------------------------------------------------------------------- by Burgov at 2012-04-13T14:27:49Z @juliendidier dynamic inheritance is now obsolete which fixes some other issues --------------------------------------------------------------------------- by stloyd at 2012-04-13T14:37:26Z What about __not__ breaking API so *badly* and leaving `FieldType` which will be simple like (with marking as deprecated): ```php <?php class FieldType extends AbstractType { public function getParent(array $options) { return 'form'; } public function getName() { return 'field'; } } --------------------------------------------------------------------------- by bschussek at 2012-04-13T14:43:41Z @stloyd That's a very good idea. --------------------------------------------------------------------------- by mvrhov at 2012-04-13T17:41:21Z IMHO what @stloyd proposed sounds like a good idea, but removing FieldType class, if #3903 will come into life might ensure that more forms will broke and people will check them thoroughly. --------------------------------------------------------------------------- by r1pp3rj4ck at 2012-04-13T18:46:08Z @bschussek looks great, but I'm concerned about how quickly will the third-party bundles adapt to this BC break. I hope really quick, because if they don't the whole stuff will be useless :S of course it's not your problem to solve. --------------------------------------------------------------------------- by stof at 2012-04-13T18:50:32Z @r1pp3rj4ck there is already another BC break requiring to update custom types for Symfony master. So third party bundles already have to do some work. --------------------------------------------------------------------------- by r1pp3rj4ck at 2012-04-13T18:59:37Z @stof which one? I've looked into @bschussek 's RFC about these [foo].bar stuff, but it's not yet implemented. Are you refering to this or another one I've missed? --------------------------------------------------------------------------- by stof at 2012-04-13T19:04:06Z @r1pp3rj4ck the change regarding default options --------------------------------------------------------------------------- by r1pp3rj4ck at 2012-04-13T19:06:10Z @stof oh, I forgot that one. Weird thing is that I've already changed my default options today and still forgetting these stuff :D --------------------------------------------------------------------------- by bschussek at 2012-04-14T08:58:29Z I restored and deprecated FieldType now. I'd appreciate further reviews. --------------------------------------------------------------------------- by stloyd at 2012-04-14T09:02:32Z Maybe we should try to avoid this BC in templates ? What do you think about similar move like with `FieldType` ? (hold old, but inside just render new) --------------------------------------------------------------------------- by bschussek at 2012-04-14T09:07:22Z @stloyd You mean for those cases where people explicitely render the block "field_*"? We can do that. --------------------------------------------------------------------------- by stloyd at 2012-04-14T09:09:45Z @bschussek Yes I mean this case =) Sorry for not being explicit, I need some coffee I think =) --------------------------------------------------------------------------- by bschussek at 2012-04-17T14:45:35Z I added the field_* blocks again for BC. Could someone please review again? Otherwise this can be merged. --------------------------------------------------------------------------- by Burgov at 2012-04-17T15:11:16Z @bschussek I'm not sure what has changed to cause this, but if I try out your branch on our forms, if I leave the value of an input empty, eventually the reverseTransform method receives a null value, rather than a '' (empty string) value, as on the current symfony master. DateTimeToLocalizedStringTransformer, for example, will throw an Exception if the value is not a string ```php if (!is_string($value)) { throw new UnexpectedTypeException($value, 'string'); } ``` Other than that, all forms render just the same as they do on symfony master --------------------------------------------------------------------------- by bschussek at 2012-04-17T15:30:29Z @Burgov Fixed.
This commit is contained in:
commit
85bb439356
@ -267,8 +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.
|
in their name anymore. Their names terminate with "[]" now.
|
||||||
* [BC BREAK] FormType::getDefaultOptions() and FormType::getAllowedOptionValues()
|
* [BC BREAK] FormType::getDefaultOptions() and FormType::getAllowedOptionValues()
|
||||||
don't receive an options array anymore.
|
don't receive an options array anymore.
|
||||||
* Deprecated FormValidatorInterface and substituted its implementations
|
* deprecated FormValidatorInterface and substituted its implementations
|
||||||
by event subscribers
|
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
|
### HttpFoundation
|
||||||
|
|
||||||
|
@ -358,6 +358,13 @@
|
|||||||
(or any other of the BIND events). In case you used the CallbackValidator
|
(or any other of the BIND events). In case you used the CallbackValidator
|
||||||
class, you should now pass the callback directly to `addEventListener`.
|
class, you should now pass the callback directly to `addEventListener`.
|
||||||
|
|
||||||
|
* 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"
|
||||||
|
|
||||||
### Validator
|
### Validator
|
||||||
|
|
||||||
* The methods `setMessage()`, `getMessageTemplate()` and
|
* The methods `setMessage()`, `getMessageTemplate()` and
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
{% block form_widget %}
|
{% block form_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<div {{ block('widget_container_attributes') }}>
|
{% if form.children|length > 0 %}
|
||||||
{{ block('field_rows') }}
|
<div {{ block('widget_container_attributes') }}>
|
||||||
{{ form_rest(form) }}
|
{{ block('form_rows') }}
|
||||||
</div>
|
{{ form_rest(form) }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ block('input') }}
|
||||||
|
{% endif %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock form_widget %}
|
{% endblock form_widget %}
|
||||||
|
|
||||||
@ -83,7 +87,7 @@
|
|||||||
{% block datetime_widget %}
|
{% block datetime_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if widget == 'single_text' %}
|
{% if widget == 'single_text' %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div {{ block('widget_container_attributes') }}>
|
<div {{ block('widget_container_attributes') }}>
|
||||||
{{ form_errors(form.date) }}
|
{{ form_errors(form.date) }}
|
||||||
@ -98,7 +102,7 @@
|
|||||||
{% block date_widget %}
|
{% block date_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if widget == 'single_text' %}
|
{% if widget == 'single_text' %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div {{ block('widget_container_attributes') }}>
|
<div {{ block('widget_container_attributes') }}>
|
||||||
{{ date_pattern|replace({
|
{{ date_pattern|replace({
|
||||||
@ -114,7 +118,7 @@
|
|||||||
{% block time_widget %}
|
{% block time_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if widget == 'single_text' %}
|
{% if widget == 'single_text' %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div {{ block('widget_container_attributes') }}>
|
<div {{ block('widget_container_attributes') }}>
|
||||||
{{ 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 %}
|
{{ 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 %}
|
{% spaceless %}
|
||||||
{# type="number" doesn't work with floats #}
|
{# type="number" doesn't work with floats #}
|
||||||
{% set type = type|default('text') %}
|
{% set type = type|default('text') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock number_widget %}
|
{% endblock number_widget %}
|
||||||
|
|
||||||
{% block integer_widget %}
|
{% block integer_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('number') %}
|
{% set type = type|default('number') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock integer_widget %}
|
{% endblock integer_widget %}
|
||||||
|
|
||||||
{% block money_widget %}
|
{% block money_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{{ money_pattern|replace({ '{{ widget }}': block('field_widget') })|raw }}
|
{{ money_pattern|replace({ '{{ widget }}': block('input') })|raw }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock money_widget %}
|
{% endblock money_widget %}
|
||||||
|
|
||||||
{% block url_widget %}
|
{% block url_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('url') %}
|
{% set type = type|default('url') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock url_widget %}
|
{% endblock url_widget %}
|
||||||
|
|
||||||
{% block search_widget %}
|
{% block search_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('search') %}
|
{% set type = type|default('search') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock search_widget %}
|
{% endblock search_widget %}
|
||||||
|
|
||||||
{% block percent_widget %}
|
{% block percent_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('text') %}
|
{% set type = type|default('text') %}
|
||||||
{{ block('field_widget') }} %
|
{{ block('input') }} %
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock percent_widget %}
|
{% endblock percent_widget %}
|
||||||
|
|
||||||
{% block field_widget %}
|
|
||||||
{% spaceless %}
|
|
||||||
{% set type = type|default('text') %}
|
|
||||||
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endblock field_widget %}
|
|
||||||
|
|
||||||
{% block password_widget %}
|
{% block password_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('password') %}
|
{% set type = type|default('password') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock password_widget %}
|
{% endblock password_widget %}
|
||||||
|
|
||||||
{% block hidden_widget %}
|
{% block hidden_widget %}
|
||||||
{% set type = type|default('hidden') %}
|
{% set type = type|default('hidden') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endblock hidden_widget %}
|
{% endblock hidden_widget %}
|
||||||
|
|
||||||
{% block email_widget %}
|
{% block email_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('email') %}
|
{% set type = type|default('email') %}
|
||||||
{{ block('field_widget') }}
|
{{ block('input') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock email_widget %}
|
{% endblock email_widget %}
|
||||||
|
|
||||||
@ -202,15 +199,11 @@
|
|||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block field_label %}
|
|
||||||
{% spaceless %}
|
|
||||||
{% set attr = attr|merge({'for': id}) %}
|
|
||||||
{{ block('generic_label') }}
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endblock field_label %}
|
|
||||||
|
|
||||||
{% block form_label %}
|
{% block form_label %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
|
{% if form.children|length == 0 %}
|
||||||
|
{% set attr = attr|merge({'for': id}) %}
|
||||||
|
{% endif %}
|
||||||
{{ block('generic_label') }}
|
{{ block('generic_label') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock form_label %}
|
{% endblock form_label %}
|
||||||
@ -219,24 +212,17 @@
|
|||||||
|
|
||||||
{% block repeated_row %}
|
{% block repeated_row %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{{ block('field_rows') }}
|
{{ block('form_rows') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock repeated_row %}
|
{% endblock repeated_row %}
|
||||||
|
|
||||||
{% block field_row %}
|
|
||||||
{% spaceless %}
|
|
||||||
<div>
|
|
||||||
{{ form_label(form, label|default(null)) }}
|
|
||||||
{{ form_errors(form) }}
|
|
||||||
{{ form_widget(form) }}
|
|
||||||
</div>
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endblock field_row %}
|
|
||||||
|
|
||||||
{% block form_row %}
|
{% block form_row %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<div>
|
<div>
|
||||||
{{ form_label(form, label|default(null)) }}
|
{{ form_label(form, label|default(null)) }}
|
||||||
|
{% if form.children|length == 0 %}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
{% endif %}
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
</div>
|
</div>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
@ -248,13 +234,13 @@
|
|||||||
|
|
||||||
{# Misc #}
|
{# Misc #}
|
||||||
|
|
||||||
{% block field_enctype %}
|
{% block form_enctype %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if multipart %}enctype="multipart/form-data"{% endif %}
|
{% if multipart %}enctype="multipart/form-data"{% endif %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_enctype %}
|
{% endblock form_enctype %}
|
||||||
|
|
||||||
{% block field_errors %}
|
{% block form_errors %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if errors|length > 0 %}
|
{% if errors|length > 0 %}
|
||||||
<ul>
|
<ul>
|
||||||
@ -270,9 +256,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_errors %}
|
{% endblock form_errors %}
|
||||||
|
|
||||||
{% block field_rest %}
|
{% block form_rest %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% for child in form %}
|
{% for child in form %}
|
||||||
{% if not child.rendered %}
|
{% if not child.rendered %}
|
||||||
@ -280,18 +266,25 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_rest %}
|
{% endblock form_rest %}
|
||||||
|
|
||||||
{# Support #}
|
{# Support #}
|
||||||
|
|
||||||
{% block field_rows %}
|
{% block form_rows %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{{ form_errors(form) }}
|
{{ form_errors(form) }}
|
||||||
{% for child in form %}
|
{% for child in form %}
|
||||||
{{ form_row(child) }}
|
{{ form_row(child) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_rows %}
|
{% endblock form_rows %}
|
||||||
|
|
||||||
|
{% block input %}
|
||||||
|
{% spaceless %}
|
||||||
|
{% set type = type|default('text') %}
|
||||||
|
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
|
||||||
|
{% endspaceless %}
|
||||||
|
{% endblock input %}
|
||||||
|
|
||||||
{% block widget_attributes %}
|
{% block widget_attributes %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
@ -306,3 +299,47 @@
|
|||||||
{% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %}
|
{% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock widget_container_attributes %}
|
{% 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 %}
|
@ -1,19 +1,5 @@
|
|||||||
{% use "form_div_layout.html.twig" %}
|
{% use "form_div_layout.html.twig" %}
|
||||||
|
|
||||||
{% block field_row %}
|
|
||||||
{% spaceless %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{ form_label(form, label|default(null)) }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ form_errors(form) }}
|
|
||||||
{{ form_widget(form) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endblock field_row %}
|
|
||||||
|
|
||||||
{% block form_row %}
|
{% block form_row %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<tr>
|
<tr>
|
||||||
@ -21,6 +7,9 @@
|
|||||||
{{ form_label(form, label|default(null)) }}
|
{{ form_label(form, label|default(null)) }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
{% if form.children|length == 0 %}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
{% endif %}
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -29,12 +18,16 @@
|
|||||||
|
|
||||||
{% block form_errors %}
|
{% block form_errors %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% if errors|length > 0 %}
|
{% if form.children|length > 0 %}
|
||||||
<tr>
|
{% if errors|length > 0 %}
|
||||||
<td colspan="2">
|
<tr>
|
||||||
{{ block('field_errors') }}
|
<td colspan="2">
|
||||||
</td>
|
{{ parent() }}
|
||||||
</tr>
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{{ parent() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock form_errors %}
|
{% endblock form_errors %}
|
||||||
@ -51,9 +44,13 @@
|
|||||||
|
|
||||||
{% block form_widget %}
|
{% block form_widget %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<table {{ block('widget_container_attributes') }}>
|
{% if form.children|length > 0 %}
|
||||||
{{ block('field_rows') }}
|
<table {{ block('widget_container_attributes') }}>
|
||||||
{{ form_rest(form) }}
|
{{ block('form_rows') }}
|
||||||
</table>
|
{{ form_rest(form) }}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
{{ parent() }}
|
||||||
|
{% endif %}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock form_widget %}
|
{% endblock form_widget %}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{% block field_label %}
|
{% block form_label %}
|
||||||
<label>child</label>
|
<label>child</label>
|
||||||
{% endblock field_label %}
|
{% endblock form_label %}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{% block field_label %}
|
{% block form_label %}
|
||||||
<label>parent</label>
|
<label>parent</label>
|
||||||
{% endblock field_label %}
|
{% endblock form_label %}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% block field_widget %}
|
{% block input %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('text') %}
|
{% set type = type|default('text') %}
|
||||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_widget %}
|
{% endblock input %}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{% extends 'form_div_layout.html.twig' %}
|
{% extends 'form_div_layout.html.twig' %}
|
||||||
|
|
||||||
{% block field_widget %}
|
{% block input %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('text') %}
|
{% set type = type|default('text') %}
|
||||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_widget %}
|
{% endblock input %}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{% use 'form_div_layout.html.twig' %}
|
{% use 'form_div_layout.html.twig' %}
|
||||||
|
|
||||||
{% block field_widget %}
|
{% block input %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% set type = type|default('text') %}
|
{% set type = type|default('text') %}
|
||||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock field_widget %}
|
{% endblock input %}
|
||||||
|
@ -52,7 +52,6 @@
|
|||||||
<!-- CoreExtension -->
|
<!-- CoreExtension -->
|
||||||
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
|
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
|
||||||
<tag name="form.type" alias="field" />
|
<tag name="form.type" alias="field" />
|
||||||
<argument type="service" id="validator" />
|
|
||||||
</service>
|
</service>
|
||||||
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
||||||
<tag name="form.type" alias="form" />
|
<tag name="form.type" alias="form" />
|
||||||
@ -133,8 +132,8 @@
|
|||||||
<tag name="form.type" alias="url" />
|
<tag name="form.type" alias="url" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- FieldTypeValidatorExtension -->
|
<!-- FormTypeValidatorExtension -->
|
||||||
<service id="form.type_extension.field" class="Symfony\Component\Form\Extension\Validator\Type\FieldTypeValidatorExtension">
|
<service id="form.type_extension.field" class="Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension">
|
||||||
<tag name="form.type_extension" alias="field" />
|
<tag name="form.type_extension" alias="field" />
|
||||||
<argument type="service" id="validator" />
|
<argument type="service" id="validator" />
|
||||||
</service>
|
</service>
|
||||||
|
@ -14,12 +14,9 @@
|
|||||||
<argument>%kernel.secret%</argument>
|
<argument>%kernel.secret%</argument>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="form.type.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\CsrfType">
|
|
||||||
<tag name="form.type" alias="csrf" />
|
|
||||||
<argument type="service" id="form.csrf_provider" />
|
|
||||||
</service>
|
|
||||||
<service id="form.type_extension.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension">
|
<service id="form.type_extension.csrf" class="Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension">
|
||||||
<tag name="form.type_extension" alias="form" />
|
<tag name="form.type_extension" alias="form" />
|
||||||
|
<argument type="service" id="form.csrf_provider" />
|
||||||
<argument>%form.type_extension.csrf.enabled%</argument>
|
<argument>%form.type_extension.csrf.enabled%</argument>
|
||||||
<argument>%form.type_extension.csrf.field_name%</argument>
|
<argument>%form.type_extension.csrf.field_name%</argument>
|
||||||
</service>
|
</service>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?php if ($widget == 'single_text'): ?>
|
<?php if ($widget == 'single_text'): ?>
|
||||||
<?php echo $view['form']->renderBlock('field_widget'); ?>
|
<?php echo $view['form']->renderBlock('input'); ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||||
<?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
|
<?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?php if ($widget == 'single_text'): ?>
|
<?php if ($widget == 'single_text'): ?>
|
||||||
<?php echo $view['form']->renderBlock('field_widget'); ?>
|
<?php echo $view['form']->renderBlock('input'); ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||||
<?php echo $view['form']->widget($form['date']).' '.$view['form']->widget($form['time']) ?>
|
<?php echo $view['form']->widget($form['date']).' '.$view['form']->widget($form['time']) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : 'email')) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : 'email')) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php if ($form->get('multipart')): ?>enctype="multipart/form-data"<?php endif ?>
|
<?php echo $view['form']->renderBlock('form_enctype') ?>
|
@ -1,21 +1 @@
|
|||||||
<?php if ($errors): ?>
|
<?php echo $view['form']->renderBlock('form_errors') ?>
|
||||||
<ul>
|
|
||||||
<?php foreach ($errors as $error): ?>
|
|
||||||
<li><?php
|
|
||||||
if (null === $error->getMessagePluralization()) {
|
|
||||||
echo $view['translator']->trans(
|
|
||||||
$error->getMessageTemplate(),
|
|
||||||
$error->getMessageParameters(),
|
|
||||||
'validators'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
echo $view['translator']->transChoice(
|
|
||||||
$error->getMessageTemplate(),
|
|
||||||
$error->getMessagePluralization(),
|
|
||||||
$error->getMessageParameters(),
|
|
||||||
'validators'
|
|
||||||
);
|
|
||||||
}?></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
<?php endif ?>
|
|
@ -1,2 +1 @@
|
|||||||
<?php if ($required) { $attr['class'] = (isset($attr['class']) ? $attr['class'] : '').' required'; } ?>
|
<?php echo $view['form']->renderBlock('form_label') ?>
|
||||||
<label for="<?php echo $view->escape($id) ?>" <?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>
|
|
@ -1,5 +1 @@
|
|||||||
<?php foreach ($form as $child): ?>
|
<?php echo $view['form']->renderBlock('form_rest') ?>
|
||||||
<?php if (!$child->isRendered()): ?>
|
|
||||||
<?php echo $view['form']->row($child) ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endforeach; ?>
|
|
@ -1,5 +1 @@
|
|||||||
<div>
|
<?php echo $view['form']->renderBlock('form_row') ?>
|
||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
|
||||||
<?php echo $view['form']->errors($form) ?>
|
|
||||||
<?php echo $view['form']->widget($form) ?>
|
|
||||||
</div>
|
|
@ -1,4 +1 @@
|
|||||||
<?php echo $view['form']->errors($form) ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
<?php foreach ($form as $child) : ?>
|
|
||||||
<?php echo $view['form']->row($child) ?>
|
|
||||||
<?php endforeach; ?>
|
|
@ -1,5 +1 @@
|
|||||||
<input
|
<?php echo $view['form']->renderBlock('input') ?>
|
||||||
type="<?php echo isset($type) ? $view->escape($type) : "text" ?>"
|
|
||||||
<?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
|
|
||||||
<?php echo $view['form']->renderBlock('attributes') ?>
|
|
||||||
/>
|
|
@ -0,0 +1 @@
|
|||||||
|
<?php if ($form->get('multipart')): ?>enctype="multipart/form-data"<?php endif ?>
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php if ($errors): ?>
|
||||||
|
<ul>
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<li><?php
|
||||||
|
if (null === $error->getMessagePluralization()) {
|
||||||
|
echo $view['translator']->trans(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
echo $view['translator']->transChoice(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessagePluralization(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
}?></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif ?>
|
@ -1,2 +1,3 @@
|
|||||||
<?php if ($required) { $attr['class'] = (isset($attr['class']) ? $attr['class'] : '').' required'; } ?>
|
<?php if ($required) { $attr['class'] = (isset($attr['class']) ? $attr['class'] : '').' required'; } ?>
|
||||||
|
<?php if (!$form->hasChildren()) { $attr['for'] = $id; } ?>
|
||||||
<label <?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>
|
<label <?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<?php foreach ($form as $child): ?>
|
||||||
|
<?php if (!$child->isRendered()): ?>
|
||||||
|
<?php echo $view['form']->row($child) ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
@ -1,4 +1,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||||
|
<?php if (!$form->hasChildren()): ?>
|
||||||
|
<?php echo $view['form']->errors($form) ?>
|
||||||
|
<?php endif ?>
|
||||||
<?php echo $view['form']->widget($form) ?>
|
<?php echo $view['form']->widget($form) ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<?php echo $view['form']->errors($form) ?>
|
||||||
|
<?php foreach ($form as $child) : ?>
|
||||||
|
<?php echo $view['form']->row($child) ?>
|
||||||
|
<?php endforeach; ?>
|
@ -1,5 +1,8 @@
|
|||||||
|
<?php if ($form->hasChildren()): ?>
|
||||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||||
<?php echo $view['form']->renderBlock('field_rows') ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
<?php echo $view['form']->rest($form) ?>
|
<?php echo $view['form']->rest($form) ?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php echo $view['form']->renderBlock('input')?>
|
||||||
|
<?php endif ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "hidden")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "hidden")) ?>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<input
|
||||||
|
type="<?php echo isset($type) ? $view->escape($type) : "text" ?>"
|
||||||
|
<?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
|
||||||
|
<?php echo $view['form']->renderBlock('attributes') ?>
|
||||||
|
/>
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "number")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "number")) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo str_replace('{{ widget }}', $view['form']->renderBlock('field_widget'), $money_pattern) ?>
|
<?php echo str_replace('{{ widget }}', $view['form']->renderBlock('input'), $money_pattern) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "text")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "text")) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "password")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "password")) ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "text")) ?> %
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "text")) ?> %
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_rows') ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "search")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "search")) ?>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?php if ($widget == 'single_text'): ?>
|
<?php if ($widget == 'single_text'): ?>
|
||||||
<?php echo $view['form']->renderBlock('field_widget'); ?>
|
<?php echo $view['form']->renderBlock('input'); ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||||
<?php
|
<?php
|
||||||
|
@ -1 +1 @@
|
|||||||
<?php echo $view['form']->renderBlock('field_widget', array('type' => isset($type) ? $type : "url")) ?>
|
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "url")) ?>
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php echo $view['form']->errors($form) ?>
|
|
||||||
<?php echo $view['form']->widget($form) ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
@ -1,7 +1,51 @@
|
|||||||
<?php if (0 < count($errors)) : ?>
|
<?php if ($form->hasChildren()): ?>
|
||||||
<tr>
|
<?php if (count($errors) > 0): ?>
|
||||||
<td colspan="2">
|
<tr>
|
||||||
<?php echo $view['form']->renderBlock('field_errors'); ?>
|
<td colspan="2">
|
||||||
</td>
|
<?php if ($errors): ?>
|
||||||
</tr>
|
<ul>
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<li><?php
|
||||||
|
if (null === $error->getMessagePluralization()) {
|
||||||
|
echo $view['translator']->trans(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
echo $view['translator']->transChoice(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessagePluralization(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
}?></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php if ($errors): ?>
|
||||||
|
<ul>
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<li><?php
|
||||||
|
if (null === $error->getMessagePluralization()) {
|
||||||
|
echo $view['translator']->trans(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
echo $view['translator']->transChoice(
|
||||||
|
$error->getMessageTemplate(),
|
||||||
|
$error->getMessagePluralization(),
|
||||||
|
$error->getMessageParameters(),
|
||||||
|
'validators'
|
||||||
|
);
|
||||||
|
}?></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
@ -3,6 +3,9 @@
|
|||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<?php if (!$form->hasChildren()): ?>
|
||||||
|
<?php echo $view['form']->errors($form) ?>
|
||||||
|
<?php endif ?>
|
||||||
<?php echo $view['form']->widget($form) ?>
|
<?php echo $view['form']->widget($form) ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
<?php if ($form->hasChildren()): ?>
|
||||||
<table <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
<table <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||||
<?php echo $view['form']->renderBlock('field_rows') ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
<?php echo $view['form']->rest($form) ?>
|
<?php echo $view['form']->rest($form) ?>
|
||||||
</table>
|
</table>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php echo $view['form']->renderBlock('input')?>
|
||||||
|
<?php endif ?>
|
||||||
|
@ -119,7 +119,7 @@ class FormHelper extends Helper
|
|||||||
*/
|
*/
|
||||||
public function widget(FormView $view, array $variables = array())
|
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();
|
$view->setRendered();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $html;
|
return trim($html);
|
||||||
}
|
}
|
||||||
} while (--$typeIndex >= 0);
|
} while (--$typeIndex >= 0);
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ class FormHelper extends Helper
|
|||||||
|
|
||||||
$variables = array_replace_recursive($context['variables'], $variables);
|
$variables = array_replace_recursive($context['variables'], $variables);
|
||||||
|
|
||||||
return $this->engine->render($template, $variables);
|
return trim($this->engine->render($template, $variables));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
|
@ -27,9 +27,9 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||||||
$def = $container->getDefinition('form.type_extension.csrf');
|
$def = $container->getDefinition('form.type_extension.csrf');
|
||||||
|
|
||||||
$this->assertTrue($container->getParameter('form.type_extension.csrf.enabled'));
|
$this->assertTrue($container->getParameter('form.type_extension.csrf.enabled'));
|
||||||
$this->assertEquals('%form.type_extension.csrf.enabled%', $def->getArgument(0));
|
$this->assertEquals('%form.type_extension.csrf.enabled%', $def->getArgument(1));
|
||||||
$this->assertEquals('_csrf', $container->getParameter('form.type_extension.csrf.field_name'));
|
$this->assertEquals('_csrf', $container->getParameter('form.type_extension.csrf.field_name'));
|
||||||
$this->assertEquals('%form.type_extension.csrf.field_name%', $def->getArgument(1));
|
$this->assertEquals('%form.type_extension.csrf.field_name%', $def->getArgument(2));
|
||||||
$this->assertEquals('s3cr3t', $container->getParameterBag()->resolveValue($container->findDefinition('form.csrf_provider')->getArgument(1)));
|
$this->assertEquals('s3cr3t', $container->getParameterBag()->resolveValue($container->findDefinition('form.csrf_provider')->getArgument(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ interface DataTransformerInterface
|
|||||||
* This method is called on two occasions inside a form field:
|
* 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).
|
* 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
|
* 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
|
* 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).
|
* "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
|
* Transforms a value from the transformed representation to its original
|
||||||
* representation.
|
* 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.
|
* into an acceptable format for your data processing/model layer.
|
||||||
*
|
*
|
||||||
* This method must be able to deal with empty values. Usually this will
|
* This method must be able to deal with empty values. Usually this will
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when a field is expected to be added to a form but is not
|
|
||||||
*
|
|
||||||
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
|
|
||||||
*/
|
|
||||||
class DanglingFieldException extends FormException
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Exception;
|
|
||||||
|
|
||||||
class FieldDefinitionException extends FormException
|
|
||||||
{
|
|
||||||
}
|
|
@ -44,8 +44,8 @@ class ChoiceType extends AbstractType
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($options['expanded']) {
|
if ($options['expanded']) {
|
||||||
$this->addSubFields($builder, $options['choice_list']->getPreferredViews(), $options);
|
$this->addSubForms($builder, $options['choice_list']->getPreferredViews(), $options);
|
||||||
$this->addSubFields($builder, $options['choice_list']->getRemainingViews(), $options);
|
$this->addSubForms($builder, $options['choice_list']->getRemainingViews(), $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty value
|
// empty value
|
||||||
@ -182,7 +182,7 @@ class ChoiceType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function getParent(array $options)
|
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 $choiceViews The choice view objects.
|
||||||
* @param array $options The build options.
|
* @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) {
|
foreach ($choiceViews as $i => $choiceView) {
|
||||||
if (is_array($choiceView)) {
|
if (is_array($choiceView)) {
|
||||||
// Flatten groups
|
// Flatten groups
|
||||||
$this->addSubFields($builder, $choiceView, $options);
|
$this->addSubForms($builder, $choiceView, $options);
|
||||||
} else {
|
} else {
|
||||||
$choiceOpts = array(
|
$choiceOpts = array(
|
||||||
'value' => $choiceView->getValue(),
|
'value' => $choiceView->getValue(),
|
||||||
|
@ -153,7 +153,7 @@ class DateTimeType extends AbstractType
|
|||||||
'widget' => null,
|
'widget' => null,
|
||||||
// This will overwrite "empty_value" child options
|
// This will overwrite "empty_value" child options
|
||||||
'empty_value' => null,
|
'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
|
// this option to "\DateTime". Since the internal, normalized
|
||||||
// representation is not \DateTime, but an array, we need to unset
|
// representation is not \DateTime, but an array, we need to unset
|
||||||
// this option.
|
// this option.
|
||||||
@ -200,7 +200,7 @@ class DateTimeType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function getParent(array $options)
|
public function getParent(array $options)
|
||||||
{
|
{
|
||||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
return 'field';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +177,7 @@ class DateType extends AbstractType
|
|||||||
// them like immutable value objects
|
// them like immutable value objects
|
||||||
'by_reference' => false,
|
'by_reference' => false,
|
||||||
'error_bubbling' => 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
|
// this option to "\DateTime". Since the internal, normalized
|
||||||
// representation is not \DateTime, but an array, we need to unset
|
// representation is not \DateTime, but an array, we need to unset
|
||||||
// this option.
|
// this option.
|
||||||
@ -210,7 +210,7 @@ class DateType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function getParent(array $options)
|
public function getParent(array $options)
|
||||||
{
|
{
|
||||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
return 'field';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,179 +23,15 @@ use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener;
|
|||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Exception\FormException;
|
use Symfony\Component\Form\Exception\FormException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated. You should extend FormType instead.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
|
||||||
|
*/
|
||||||
class FieldType extends AbstractType
|
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}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -203,9 +39,4 @@ class FieldType extends AbstractType
|
|||||||
{
|
{
|
||||||
return 'field';
|
return 'field';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function humanize($text)
|
|
||||||
{
|
|
||||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,24 @@ class FileType extends AbstractType
|
|||||||
public function buildView(FormView $view, FormInterface $form)
|
public function buildView(FormView $view, FormInterface $form)
|
||||||
{
|
{
|
||||||
$view
|
$view
|
||||||
->set('multipart', true)
|
|
||||||
->set('type', 'file')
|
->set('type', 'file')
|
||||||
->set('value', '')
|
->set('value', '')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildViewBottomUp(FormView $view, FormInterface $form)
|
||||||
|
{
|
||||||
|
$view
|
||||||
|
->set('multipart', true)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getParent(array $options)
|
public function getParent(array $options)
|
||||||
{
|
{
|
||||||
return 'field';
|
return 'field';
|
||||||
|
@ -13,10 +13,16 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
|||||||
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Options;
|
use Symfony\Component\Form\Options;
|
||||||
|
use Symfony\Component\Form\Util\PropertyPath;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
use Symfony\Component\Form\FormFactoryInterface;
|
||||||
use Symfony\Component\Form\FormView;
|
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\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
|
use Symfony\Component\Form\Exception\FormException;
|
||||||
|
|
||||||
class FormType extends AbstractType
|
class FormType extends AbstractType
|
||||||
{
|
{
|
||||||
@ -25,9 +31,102 @@ class FormType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function buildForm(FormBuilder $builder, array $options)
|
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
|
$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'])
|
->setAttribute('virtual', $options['virtual'])
|
||||||
|
->setData($options['data'])
|
||||||
->setDataMapper(new PropertyPathMapper($options['data_class']))
|
->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()
|
public function getDefaultOptions()
|
||||||
{
|
{
|
||||||
$emptyData = function (Options $options, $currentValue) {
|
// Derive "data_class" option from passed "data" object
|
||||||
if (empty($options['data_class'])) {
|
$dataClass = function (Options $options) {
|
||||||
return array();
|
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(
|
return array(
|
||||||
|
'data' => null,
|
||||||
|
'data_class' => $dataClass,
|
||||||
'empty_data' => $emptyData,
|
'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,
|
'virtual' => false,
|
||||||
// Errors in forms bubble by default, so that form errors will
|
'invalid_message' => 'This value is not valid',
|
||||||
// end up as global errors in the root form
|
'invalid_message_parameters' => array(),
|
||||||
'error_bubbling' => true,
|
'translation_domain' => 'messages',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function createBuilder($name, FormFactoryInterface $factory, array $options)
|
||||||
|
{
|
||||||
|
return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getParent(array $options)
|
public function getParent(array $options)
|
||||||
{
|
{
|
||||||
return 'field';
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,4 +230,9 @@ class FormType extends AbstractType
|
|||||||
{
|
{
|
||||||
return 'form';
|
return 'form';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function humanize($text)
|
||||||
|
{
|
||||||
|
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ class TimeType extends AbstractType
|
|||||||
// them like immutable value objects
|
// them like immutable value objects
|
||||||
'by_reference' => false,
|
'by_reference' => false,
|
||||||
'error_bubbling' => 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
|
// this option to "\DateTime". Since the internal, normalized
|
||||||
// representation is not \DateTime, but an array, we need to unset
|
// representation is not \DateTime, but an array, we need to unset
|
||||||
// this option.
|
// this option.
|
||||||
@ -183,7 +183,7 @@ class TimeType extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function getParent(array $options)
|
public function getParent(array $options)
|
||||||
{
|
{
|
||||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
return 'field';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,27 +32,13 @@ class CsrfExtension extends AbstractExtension
|
|||||||
$this->csrfProvider = $csrfProvider;
|
$this->csrfProvider = $csrfProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
protected function loadTypes()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
new Type\CsrfType($this->csrfProvider),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
protected function loadTypeExtensions()
|
protected function loadTypeExtensions()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
new Type\ChoiceTypeCsrfExtension(),
|
new Type\FormTypeCsrfExtension($this->csrfProvider),
|
||||||
new Type\DateTypeCsrfExtension(),
|
|
||||||
new Type\FormTypeCsrfExtension(),
|
|
||||||
new Type\RepeatedTypeCsrfExtension(),
|
|
||||||
new Type\TimeTypeCsrfExtension(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace Symfony\Component\Form\Extension\Csrf\EventListener;
|
|||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\Form\FormEvents;
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\Form\FormError;
|
use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\Form\Event\DataEvent;
|
use Symfony\Component\Form\Event\FilterDataEvent;
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +22,12 @@ use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
|||||||
*/
|
*/
|
||||||
class CsrfValidationListener implements EventSubscriberInterface
|
class CsrfValidationListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The name of the CSRF field
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $fieldName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provider for generating and validating CSRF tokens
|
* The provider for generating and validating CSRF tokens
|
||||||
* @var CsrfProviderInterface
|
* @var CsrfProviderInterface
|
||||||
@ -45,24 +51,26 @@ class CsrfValidationListener implements EventSubscriberInterface
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(CsrfProviderInterface $csrfProvider, $intention)
|
public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention)
|
||||||
{
|
{
|
||||||
|
$this->fieldName = $fieldName;
|
||||||
$this->csrfProvider = $csrfProvider;
|
$this->csrfProvider = $csrfProvider;
|
||||||
$this->intention = $intention;
|
$this->intention = $intention;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBindClientData(DataEvent $event)
|
public function onBindClientData(FilterDataEvent $event)
|
||||||
{
|
{
|
||||||
$form = $event->getForm();
|
$form = $event->getForm();
|
||||||
$data = $event->getData();
|
$data = $event->getData();
|
||||||
|
|
||||||
if ((!$form->hasParent() || $form->getParent()->isRoot())
|
if ($form->isRoot() && $form->hasChildren() && isset($data[$this->fieldName])) {
|
||||||
&& !$this->csrfProvider->isCsrfTokenValid($this->intention, $data)) {
|
if (!$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) {
|
||||||
$form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form'));
|
$form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form'));
|
||||||
|
}
|
||||||
|
|
||||||
// If the session timed out, the token is invalid now.
|
unset($data[$this->fieldName]);
|
||||||
// Regenerate the token so that a resubmission is possible.
|
|
||||||
$event->setData($this->csrfProvider->generateCsrfToken($this->intention));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$event->setData($data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\EventListener;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\Event\DataEvent;
|
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
|
||||||
use Symfony\Component\Form\FormFactoryInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the CSRF field.
|
|
||||||
*
|
|
||||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
|
||||||
* @author Kris Wallsmith <kris@symfony.com>
|
|
||||||
*/
|
|
||||||
class EnsureCsrfFieldListener
|
|
||||||
{
|
|
||||||
private $factory;
|
|
||||||
private $name;
|
|
||||||
private $intention;
|
|
||||||
private $provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param FormFactoryInterface $factory The form factory
|
|
||||||
* @param string $name A name for the CSRF field
|
|
||||||
* @param string $intention The intention string
|
|
||||||
* @param CsrfProviderInterface $provider The CSRF provider
|
|
||||||
*/
|
|
||||||
public function __construct(FormFactoryInterface $factory, $name, $intention = null, CsrfProviderInterface $provider = null)
|
|
||||||
{
|
|
||||||
$this->factory = $factory;
|
|
||||||
$this->name = $name;
|
|
||||||
$this->intention = $intention;
|
|
||||||
$this->provider = $provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures a root form has a CSRF field.
|
|
||||||
*
|
|
||||||
* This method should be connected to both form.pre_set_data and form.pre_bind.
|
|
||||||
*/
|
|
||||||
public function ensureCsrfField(DataEvent $event)
|
|
||||||
{
|
|
||||||
$form = $event->getForm();
|
|
||||||
|
|
||||||
$options = array();
|
|
||||||
if ($this->intention) {
|
|
||||||
$options['intention'] = $this->intention;
|
|
||||||
}
|
|
||||||
if ($this->provider) {
|
|
||||||
$options['csrf_provider'] = $this->provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
$form->add($this->factory->createNamed('csrf', $this->name, null, $options));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
|
||||||
|
|
||||||
class ChoiceTypeCsrfExtension extends AbstractTypeExtension
|
|
||||||
{
|
|
||||||
public function getDefaultOptions()
|
|
||||||
{
|
|
||||||
return array('csrf_protection' => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExtendedType()
|
|
||||||
{
|
|
||||||
return 'choice';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
|
||||||
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\FormBuilder;
|
|
||||||
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
|
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
|
||||||
|
|
||||||
class CsrfType extends AbstractType
|
|
||||||
{
|
|
||||||
private $csrfProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param CsrfProviderInterface $csrfProvider The provider to use to generate the token
|
|
||||||
*/
|
|
||||||
public function __construct(CsrfProviderInterface $csrfProvider)
|
|
||||||
{
|
|
||||||
$this->csrfProvider = $csrfProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the CSRF field.
|
|
||||||
*
|
|
||||||
* A validator is added to check the token value when the CSRF field is added to
|
|
||||||
* a root form
|
|
||||||
*
|
|
||||||
* @param FormBuilder $builder The form builder
|
|
||||||
* @param array $options The options
|
|
||||||
*/
|
|
||||||
public function buildForm(FormBuilder $builder, array $options)
|
|
||||||
{
|
|
||||||
$csrfProvider = $options['csrf_provider'];
|
|
||||||
$intention = $options['intention'];
|
|
||||||
|
|
||||||
$builder
|
|
||||||
->setData($csrfProvider->generateCsrfToken($intention))
|
|
||||||
->addEventSubscriber(new CsrfValidationListener($csrfProvider, $intention))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function getDefaultOptions()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
'csrf_provider' => $this->csrfProvider,
|
|
||||||
'intention' => null,
|
|
||||||
'property_path' => false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function getParent(array $options)
|
|
||||||
{
|
|
||||||
return 'hidden';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this form.
|
|
||||||
*
|
|
||||||
* @return string 'csrf'
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'csrf';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
|
||||||
|
|
||||||
class DateTypeCsrfExtension extends AbstractTypeExtension
|
|
||||||
{
|
|
||||||
public function getDefaultOptions()
|
|
||||||
{
|
|
||||||
return array('csrf_protection' => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExtendedType()
|
|
||||||
{
|
|
||||||
return 'date';
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,21 +12,27 @@
|
|||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
use Symfony\Component\Form\AbstractTypeExtension;
|
||||||
use Symfony\Component\Form\Extension\Csrf\EventListener\EnsureCsrfFieldListener;
|
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||||
|
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
use Symfony\Component\Form\FormView;
|
use Symfony\Component\Form\FormView;
|
||||||
use Symfony\Component\Form\FormEvents;
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
class FormTypeCsrfExtension extends AbstractTypeExtension
|
class FormTypeCsrfExtension extends AbstractTypeExtension
|
||||||
{
|
{
|
||||||
private $enabled;
|
private $defaultCsrfProvider;
|
||||||
private $fieldName;
|
private $defaultEnabled;
|
||||||
|
private $defaultFieldName;
|
||||||
|
|
||||||
public function __construct($enabled = true, $fieldName = '_token')
|
public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token')
|
||||||
{
|
{
|
||||||
$this->enabled = $enabled;
|
$this->defaultCsrfProvider = $defaultCsrfProvider;
|
||||||
$this->fieldName = $fieldName;
|
$this->defaultEnabled = $defaultEnabled;
|
||||||
|
$this->defaultFieldName = $defaultFieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,35 +47,35 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$listener = new EnsureCsrfFieldListener(
|
|
||||||
$builder->getFormFactory(),
|
|
||||||
$options['csrf_field_name'],
|
|
||||||
$options['intention'],
|
|
||||||
$options['csrf_provider']
|
|
||||||
);
|
|
||||||
|
|
||||||
// use a low priority so higher priority listeners don't remove the field
|
// use a low priority so higher priority listeners don't remove the field
|
||||||
$builder
|
$builder
|
||||||
->setAttribute('csrf_field_name', $options['csrf_field_name'])
|
->setAttribute('csrf_field_name', $options['csrf_field_name'])
|
||||||
->addEventListener(FormEvents::PRE_SET_DATA, array($listener, 'ensureCsrfField'), -10)
|
->setAttribute('csrf_provider', $options['csrf_provider'])
|
||||||
->addEventListener(FormEvents::PRE_BIND, array($listener, 'ensureCsrfField'), -10)
|
->setAttribute('csrf_intention', $options['intention'])
|
||||||
|
->setAttribute('csrf_factory', $builder->getFormFactory())
|
||||||
|
->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention']))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes CSRF fields from all the form views except the root one.
|
* Adds a CSRF field to the root form view.
|
||||||
*
|
*
|
||||||
* @param FormView $view The form view
|
* @param FormView $view The form view
|
||||||
* @param FormInterface $form The form
|
* @param FormInterface $form The form
|
||||||
*/
|
*/
|
||||||
public function buildViewBottomUp(FormView $view, FormInterface $form)
|
public function buildView(FormView $view, FormInterface $form)
|
||||||
{
|
{
|
||||||
if ($view->hasParent() && $form->hasAttribute('csrf_field_name')) {
|
if ($form->isRoot() && $form->hasChildren() && $form->hasAttribute('csrf_field_name')) {
|
||||||
$name = $form->getAttribute('csrf_field_name');
|
$name = $form->getAttribute('csrf_field_name');
|
||||||
|
$csrfProvider = $form->getAttribute('csrf_provider');
|
||||||
|
$intention = $form->getAttribute('csrf_intention');
|
||||||
|
$factory = $form->getAttribute('csrf_factory');
|
||||||
|
$data = $csrfProvider->generateCsrfToken($intention);
|
||||||
|
$csrfForm = $factory->createNamed('hidden', $name, $data, array(
|
||||||
|
'property_path' => false,
|
||||||
|
));
|
||||||
|
|
||||||
if (isset($view[$name])) {
|
$view->addChild($csrfForm->createView($view));
|
||||||
unset($view[$name]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,9 +85,9 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
|
|||||||
public function getDefaultOptions()
|
public function getDefaultOptions()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'csrf_protection' => $this->enabled,
|
'csrf_protection' => $this->defaultEnabled,
|
||||||
'csrf_field_name' => $this->fieldName,
|
'csrf_field_name' => $this->defaultFieldName,
|
||||||
'csrf_provider' => null,
|
'csrf_provider' => $this->defaultCsrfProvider,
|
||||||
'intention' => 'unknown',
|
'intention' => 'unknown',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
|
||||||
|
|
||||||
class RepeatedTypeCsrfExtension extends AbstractTypeExtension
|
|
||||||
{
|
|
||||||
public function getDefaultOptions()
|
|
||||||
{
|
|
||||||
return array('csrf_protection' => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExtendedType()
|
|
||||||
{
|
|
||||||
return 'repeated';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
|
||||||
|
|
||||||
class TimeTypeCsrfExtension extends AbstractTypeExtension
|
|
||||||
{
|
|
||||||
public function getDefaultOptions()
|
|
||||||
{
|
|
||||||
return array('csrf_protection' => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getExtendedType()
|
|
||||||
{
|
|
||||||
return 'time';
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,7 @@ use Symfony\Component\Validator\ValidatorInterface;
|
|||||||
/**
|
/**
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
class FieldTypeValidatorExtension extends AbstractTypeExtension
|
class FormTypeValidatorExtension extends AbstractTypeExtension
|
||||||
{
|
{
|
||||||
private $validator;
|
private $validator;
|
||||||
|
|
||||||
@ -57,6 +57,6 @@ class FieldTypeValidatorExtension extends AbstractTypeExtension
|
|||||||
|
|
||||||
public function getExtendedType()
|
public function getExtendedType()
|
||||||
{
|
{
|
||||||
return 'field';
|
return 'form';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ class ValidatorExtension extends AbstractExtension
|
|||||||
protected function loadTypeExtensions()
|
protected function loadTypeExtensions()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
new Type\FieldTypeValidatorExtension($this->validator),
|
new Type\FormTypeValidatorExtension($this->validator),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
array $types = array(), array $clientTransformers = array(),
|
array $types = array(), array $clientTransformers = array(),
|
||||||
array $normTransformers = array(),
|
array $normTransformers = array(),
|
||||||
DataMapperInterface $dataMapper = null, array $validators = array(),
|
DataMapperInterface $dataMapper = null, array $validators = array(),
|
||||||
$required = false, $disabled = false, $errorBubbling = false,
|
$required = false, $disabled = false, $errorBubbling = null,
|
||||||
$emptyData = null, array $attributes = array())
|
$emptyData = null, array $attributes = array())
|
||||||
{
|
{
|
||||||
$name = (string) $name;
|
$name = (string) $name;
|
||||||
@ -225,7 +225,10 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
$this->validators = $validators;
|
$this->validators = $validators;
|
||||||
$this->required = (Boolean) $required;
|
$this->required = (Boolean) $required;
|
||||||
$this->disabled = (Boolean) $disabled;
|
$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->emptyData = $emptyData;
|
||||||
$this->attributes = $attributes;
|
$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()
|
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
|
* @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
|
* @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->clientData = $clientData;
|
||||||
$this->synchronized = true;
|
$this->synchronized = true;
|
||||||
|
|
||||||
if ($this->dataMapper) {
|
if (count($this->children) > 0 && $this->dataMapper) {
|
||||||
// Update child forms from the data
|
// Update child forms from the data
|
||||||
$this->dataMapper->mapDataToForms($clientData, $this->children);
|
$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
|
* @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.
|
* @return mixed When the form is not bound, the default data is returned.
|
||||||
* When the field is bound, the normalized bound data is
|
* When the form is bound, the normalized bound data is
|
||||||
* returned if the field is valid, null otherwise.
|
* returned if the form is valid, null otherwise.
|
||||||
*/
|
*/
|
||||||
public function getNormData()
|
public function getNormData()
|
||||||
{
|
{
|
||||||
@ -646,7 +649,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
*/
|
*/
|
||||||
public function addError(FormError $error)
|
public function addError(FormError $error)
|
||||||
{
|
{
|
||||||
if ($this->parent && $this->errorBubbling) {
|
if ($this->parent && $this->getErrorBubbling()) {
|
||||||
$this->parent->addError($error);
|
$this->parent->addError($error);
|
||||||
} else {
|
} else {
|
||||||
$this->errors[] = $error;
|
$this->errors[] = $error;
|
||||||
@ -662,11 +665,11 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
*/
|
*/
|
||||||
public function getErrorBubbling()
|
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
|
* @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
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
@ -735,9 +738,8 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
public function hasErrors()
|
public function hasErrors()
|
||||||
{
|
{
|
||||||
// Don't call isValid() here, as its semantics are slightly different
|
// Don't call isValid() here, as its semantics are slightly different
|
||||||
// Field groups are not valid if their children are invalid, but
|
// Forms are not valid if their children are invalid, but
|
||||||
// hasErrors() returns only true if a field/field group itself has
|
// hasErrors() returns only true if a form itself has errors
|
||||||
// errors
|
|
||||||
return count($this->errors) > 0;
|
return count($this->errors) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,7 +896,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
return $this->children[$name];
|
return $this->children[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \InvalidArgumentException(sprintf('Field "%s" does not exist.', $name));
|
throw new \InvalidArgumentException(sprintf('Child "%s" does not exist.', $name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -975,7 +977,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
$parent = $this->parent->createView();
|
$parent = $this->parent->createView();
|
||||||
}
|
}
|
||||||
|
|
||||||
$view = new FormView();
|
$view = new FormView($this->name);
|
||||||
|
|
||||||
$view->setParent($parent);
|
$view->setParent($parent);
|
||||||
|
|
||||||
@ -989,14 +991,10 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$childViews = array();
|
foreach ($this->children as $child) {
|
||||||
|
$view->addChild($child->createView($view));
|
||||||
foreach ($this->children as $key => $child) {
|
|
||||||
$childViews[$key] = $child->createView($view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$view->setChildren($childViews);
|
|
||||||
|
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
$type->buildViewBottomUp($view, $this);
|
$type->buildViewBottomUp($view, $this);
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class FormBuilder
|
|||||||
* Whether added errors should bubble up to the parent
|
* Whether added errors should bubble up to the parent
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $errorBubbling = false;
|
private $errorBubbling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data used for the client data when no value is bound
|
* Data used for the client data when no value is bound
|
||||||
@ -243,7 +243,7 @@ class FormBuilder
|
|||||||
*/
|
*/
|
||||||
public function setErrorBubbling($errorBubbling)
|
public function setErrorBubbling($errorBubbling)
|
||||||
{
|
{
|
||||||
$this->errorBubbling = (Boolean) $errorBubbling;
|
$this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
|||||||
* The content of a disabled form is displayed, but not allowed to be
|
* The content of a disabled form is displayed, but not allowed to be
|
||||||
* modified. The validation of modified disabled forms should fail.
|
* 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.
|
* their own state.
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
|
@ -75,7 +75,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface
|
|||||||
* @param \Closure $closure The closure to execute. Accepts a guesser
|
* @param \Closure $closure The closure to execute. Accepts a guesser
|
||||||
* as argument and should return a Guess instance
|
* 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)
|
private function guess(\Closure $closure)
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,17 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Form;
|
namespace Symfony\Component\Form;
|
||||||
|
|
||||||
class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
|
use ArrayAccess;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use Countable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class FormView implements ArrayAccess, IteratorAggregate, Countable
|
||||||
{
|
{
|
||||||
|
private $name;
|
||||||
|
|
||||||
private $vars = array(
|
private $vars = array(
|
||||||
'value' => null,
|
'value' => null,
|
||||||
'attr' => array(),
|
'attr' => array(),
|
||||||
@ -33,6 +42,16 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
*/
|
*/
|
||||||
private $rendered = false;
|
private $rendered = false;
|
||||||
|
|
||||||
|
public function __construct($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
@ -177,15 +196,29 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the children view.
|
* Adds a child view.
|
||||||
*
|
*
|
||||||
* @param array $children The children as instances of FormView
|
* @param FormView $child The child view to add.
|
||||||
*
|
*
|
||||||
* @return FormView The current view
|
* @return FormView The current view
|
||||||
*/
|
*/
|
||||||
public function setChildren(array $children)
|
public function addChild(FormView $child)
|
||||||
{
|
{
|
||||||
$this->children = $children;
|
$this->children[$child->getName()] = $child;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a child view.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the removed child view.
|
||||||
|
*
|
||||||
|
* @return FormView The current view
|
||||||
|
*/
|
||||||
|
public function removeChild($name)
|
||||||
|
{
|
||||||
|
unset($this->children[$name]);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -222,6 +255,18 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
return count($this->children) > 0;
|
return count($this->children) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this view has a given child.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the child
|
||||||
|
*
|
||||||
|
* @return Boolean Whether the child with the given name exists
|
||||||
|
*/
|
||||||
|
public function hasChild($name)
|
||||||
|
{
|
||||||
|
return isset($this->children[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a child by name (implements \ArrayAccess).
|
* Returns a child by name (implements \ArrayAccess).
|
||||||
*
|
*
|
||||||
|
@ -202,7 +202,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestAndRepeatedWithRowPerField()
|
public function testRestAndRepeatedWithRowPerChild()
|
||||||
{
|
{
|
||||||
$view = $this->factory->createNamedBuilder('form', 'name')
|
$view = $this->factory->createNamedBuilder('form', 'name')
|
||||||
->add('first', 'text')
|
->add('first', 'text')
|
||||||
@ -230,7 +230,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestAndRepeatedWithWidgetPerField()
|
public function testRestAndRepeatedWithWidgetPerChild()
|
||||||
{
|
{
|
||||||
$view = $this->factory->createNamedBuilder('form', 'name')
|
$view = $this->factory->createNamedBuilder('form', 'name')
|
||||||
->add('first', 'text')
|
->add('first', 'text')
|
||||||
@ -348,7 +348,10 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
public function testNestedFormError()
|
public function testNestedFormError()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamedBuilder('form', 'name')
|
$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();
|
->getForm();
|
||||||
|
|
||||||
$form->get('child')->addError(new FormError('Error!'));
|
$form->get('child')->addError(new FormError('Error!'));
|
||||||
@ -363,6 +366,31 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCsrf()
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->any())
|
||||||
|
->method('generateCsrfToken')
|
||||||
|
->will($this->returnValue('foo&bar'));
|
||||||
|
|
||||||
|
$form = $this->factory->createNamedBuilder('form', 'name')
|
||||||
|
->add($this->factory
|
||||||
|
// No CSRF protection on nested forms
|
||||||
|
->createNamedBuilder('form', 'child')
|
||||||
|
->add($this->factory->createNamedBuilder('text', 'grandchild'))
|
||||||
|
)
|
||||||
|
->getForm();
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="hidden"][@id="name__token"][@value="foo&bar"]
|
||||||
|
/following-sibling::div
|
||||||
|
]
|
||||||
|
[count(.//input[@type="hidden"])=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testRepeated()
|
public function testRepeated()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('repeated', 'name', 'foobar', array(
|
$form = $this->factory->createNamed('repeated', 'name', 'foobar', array(
|
||||||
@ -372,7 +400,8 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./div
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::div
|
||||||
[
|
[
|
||||||
./label[@for="name_first"]
|
./label[@for="name_first"]
|
||||||
/following-sibling::input[@type="text"][@id="name_first"]
|
/following-sibling::input[@type="text"][@id="name_first"]
|
||||||
@ -383,7 +412,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
/following-sibling::input[@type="text"][@id="name_second"]
|
/following-sibling::input[@type="text"][@id="name_second"]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[count(.//input)=2]
|
[count(.//input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -399,7 +428,8 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./div
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::div
|
||||||
[
|
[
|
||||||
./label[@for="name_first"][.="[trans]Test[/trans]"]
|
./label[@for="name_first"][.="[trans]Test[/trans]"]
|
||||||
/following-sibling::input[@type="text"][@id="name_first"][@required="required"]
|
/following-sibling::input[@type="text"][@id="name_first"][@required="required"]
|
||||||
@ -410,7 +440,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
/following-sibling::input[@type="text"][@id="name_second"][@required="required"]
|
/following-sibling::input[@type="text"][@id="name_second"][@required="required"]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[count(.//input)=2]
|
[count(.//input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -646,12 +646,13 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
||||||
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
||||||
]
|
]
|
||||||
[count(./input)=2]
|
[count(./input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -668,12 +669,13 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./input[@type="radio"][@name="name"][@id="name_0"][@checked]
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked]
|
||||||
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
||||||
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
|
||||||
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
||||||
]
|
]
|
||||||
[count(./input)=2]
|
[count(./input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -689,12 +691,13 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./input[@type="radio"][@name="name"][@id="name_0"][@checked]
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked]
|
||||||
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
||||||
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)]
|
||||||
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
||||||
]
|
]
|
||||||
[count(./input)=2]
|
[count(./input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -711,14 +714,15 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
|
./input[@type="hidden"][@id="name__token"]
|
||||||
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)]
|
||||||
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
||||||
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)]
|
||||||
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
||||||
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)]
|
||||||
/following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"]
|
/following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"]
|
||||||
]
|
]
|
||||||
[count(./input)=3]
|
[count(./input)=4]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -753,22 +757,6 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCsrf()
|
|
||||||
{
|
|
||||||
$this->csrfProvider->expects($this->any())
|
|
||||||
->method('generateCsrfToken')
|
|
||||||
->will($this->returnValue('foo&bar'));
|
|
||||||
|
|
||||||
$form = $this->factory->createNamed('csrf', 'name');
|
|
||||||
|
|
||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
|
||||||
'/input
|
|
||||||
[@type="hidden"]
|
|
||||||
[@value="foo&bar"]
|
|
||||||
'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDateTime()
|
public function testDateTime()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('datetime', 'name', '2011-02-03 04:05:06', array(
|
$form = $this->factory->createNamed('datetime', 'name', '2011-02-03 04:05:06', array(
|
||||||
|
@ -45,36 +45,10 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$html = $this->renderRow($form->createView());
|
$html = $this->renderRow($form->createView());
|
||||||
|
|
||||||
$this->assertMatchesXpath($html,
|
$this->assertMatchesXpath($html,
|
||||||
'/tr
|
'/tr[@style="display: none"]
|
||||||
[
|
[./td[@colspan="2"]/input
|
||||||
./td
|
[@type="hidden"]
|
||||||
[./label[@for="name_first"]]
|
[@id="name__token"]
|
||||||
/following-sibling::td
|
|
||||||
[./input[@id="name_first"]]
|
|
||||||
]
|
|
||||||
/following-sibling::tr
|
|
||||||
[
|
|
||||||
./td
|
|
||||||
[./label[@for="name_second"]]
|
|
||||||
/following-sibling::td
|
|
||||||
[./input[@id="name_second"]]
|
|
||||||
]
|
|
||||||
[count(../tr)=2]
|
|
||||||
'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRepeatedRowWithErrors()
|
|
||||||
{
|
|
||||||
$form = $this->factory->createNamed('repeated', 'name');
|
|
||||||
$form->addError(new FormError('Error!'));
|
|
||||||
$view = $form->createView();
|
|
||||||
$html = $this->renderRow($view);
|
|
||||||
|
|
||||||
$this->assertMatchesXpath($html,
|
|
||||||
'/tr
|
|
||||||
[./td[@colspan="2"]/ul
|
|
||||||
[./li[.="[trans]Error![/trans]"]]
|
|
||||||
]
|
]
|
||||||
/following-sibling::tr
|
/following-sibling::tr
|
||||||
[
|
[
|
||||||
@ -95,6 +69,42 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRepeatedRowWithErrors()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('repeated', 'name');
|
||||||
|
$form->addError(new FormError('Error!'));
|
||||||
|
$view = $form->createView();
|
||||||
|
$html = $this->renderRow($view);
|
||||||
|
|
||||||
|
$this->assertMatchesXpath($html,
|
||||||
|
'/tr
|
||||||
|
[./td[@colspan="2"]/ul
|
||||||
|
[./li[.="[trans]Error![/trans]"]]
|
||||||
|
]
|
||||||
|
/following-sibling::tr[@style="display: none"]
|
||||||
|
[./td[@colspan="2"]/input
|
||||||
|
[@type="hidden"]
|
||||||
|
[@id="name__token"]
|
||||||
|
]
|
||||||
|
/following-sibling::tr
|
||||||
|
[
|
||||||
|
./td
|
||||||
|
[./label[@for="name_first"]]
|
||||||
|
/following-sibling::td
|
||||||
|
[./input[@id="name_first"]]
|
||||||
|
]
|
||||||
|
/following-sibling::tr
|
||||||
|
[
|
||||||
|
./td
|
||||||
|
[./label[@for="name_second"]]
|
||||||
|
/following-sibling::td
|
||||||
|
[./input[@id="name_second"]]
|
||||||
|
]
|
||||||
|
[count(../tr)=4]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testRest()
|
public function testRest()
|
||||||
{
|
{
|
||||||
$view = $this->factory->createNamedBuilder('form', 'name')
|
$view = $this->factory->createNamedBuilder('form', 'name')
|
||||||
@ -151,9 +161,9 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/table
|
'/table
|
||||||
[
|
[
|
||||||
./tr[./td/input[@type="text"][@value="a"]]
|
./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]
|
||||||
|
/following-sibling::tr[./td/input[@type="text"][@value="a"]]
|
||||||
/following-sibling::tr[./td/input[@type="text"][@value="b"]]
|
/following-sibling::tr[./td/input[@type="text"][@value="b"]]
|
||||||
/following-sibling::tr[./td/input[@type="hidden"][@id="name__token"]]
|
|
||||||
]
|
]
|
||||||
[count(./tr[./td/input])=3]
|
[count(./tr[./td/input])=3]
|
||||||
'
|
'
|
||||||
@ -200,7 +210,10 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
public function testNestedFormError()
|
public function testNestedFormError()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamedBuilder('form', 'name')
|
$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();
|
->getForm();
|
||||||
|
|
||||||
$form->get('child')->addError(new FormError('Error!'));
|
$form->get('child')->addError(new FormError('Error!'));
|
||||||
@ -217,6 +230,34 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCsrf()
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->any())
|
||||||
|
->method('generateCsrfToken')
|
||||||
|
->will($this->returnValue('foo&bar'));
|
||||||
|
|
||||||
|
$form = $this->factory->createNamedBuilder('form', 'name')
|
||||||
|
->add($this->factory
|
||||||
|
// No CSRF protection on nested forms
|
||||||
|
->createNamedBuilder('form', 'child')
|
||||||
|
->add($this->factory->createNamedBuilder('text', 'grandchild'))
|
||||||
|
)
|
||||||
|
->getForm();
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/table
|
||||||
|
[
|
||||||
|
./tr[@style="display: none"]
|
||||||
|
[./td[@colspan="2"]/input
|
||||||
|
[@type="hidden"]
|
||||||
|
[@id="name__token"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[count(.//input[@type="hidden"])=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testRepeated()
|
public function testRepeated()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('repeated', 'name', 'foobar', array(
|
$form = $this->factory->createNamed('repeated', 'name', 'foobar', array(
|
||||||
@ -226,7 +267,12 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/table
|
'/table
|
||||||
[
|
[
|
||||||
./tr
|
./tr[@style="display: none"]
|
||||||
|
[./td[@colspan="2"]/input
|
||||||
|
[@type="hidden"]
|
||||||
|
[@id="name__token"]
|
||||||
|
]
|
||||||
|
/following-sibling::tr
|
||||||
[
|
[
|
||||||
./td
|
./td
|
||||||
[./label[@for="name_first"]]
|
[./label[@for="name_first"]]
|
||||||
@ -241,7 +287,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
[./input[@type="text"][@id="name_second"]]
|
[./input[@type="text"][@id="name_second"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[count(.//input)=2]
|
[count(.//input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -257,7 +303,12 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/table
|
'/table
|
||||||
[
|
[
|
||||||
./tr
|
./tr[@style="display: none"]
|
||||||
|
[./td[@colspan="2"]/input
|
||||||
|
[@type="hidden"]
|
||||||
|
[@id="name__token"]
|
||||||
|
]
|
||||||
|
/following-sibling::tr
|
||||||
[
|
[
|
||||||
./td
|
./td
|
||||||
[./label[@for="name_first"][.="[trans]Test[/trans]"]]
|
[./label[@for="name_first"][.="[trans]Test[/trans]"]]
|
||||||
@ -272,7 +323,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
[./input[@type="password"][@id="name_second"][@required="required"]]
|
[./input[@type="password"][@id="name_second"][@required="required"]]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[count(.//input)=2]
|
[count(.//input)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExpandedChoicesOptionsTurnIntoFields()
|
public function testExpandedChoicesOptionsTurnIntoChildren()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'expanded' => true,
|
'expanded' => true,
|
||||||
@ -141,7 +141,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExpandedRadiosAreRequiredIfChoiceFieldIsRequired()
|
public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
@ -155,7 +155,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExpandedRadiosAreNotRequiredIfChoiceFieldIsNotRequired()
|
public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
@ -288,7 +288,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
$this->assertNull($form[4]->getClientData());
|
$this->assertNull($form[4]->getClientData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBindSingleExpandedWithFalseDoesNotHaveExtraFields()
|
public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
@ -302,7 +302,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
$this->assertNull($form->getData());
|
$this->assertNull($form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBindSingleExpandedWithEmptyField()
|
public function testBindSingleExpandedWithEmptyChild()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
@ -422,7 +422,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||||||
$this->assertNull($form[4]->getClientData());
|
$this->assertNull($form[4]->getClientData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBindMultipleExpandedWithEmptyField()
|
public function testBindMultipleExpandedWithEmptyChild()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('choice', null, array(
|
$form = $this->factory->create('choice', null, array(
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
|
@ -15,10 +15,10 @@ use Symfony\Component\Form\Form;
|
|||||||
|
|
||||||
class CollectionTypeTest extends TypeTestCase
|
class CollectionTypeTest extends TypeTestCase
|
||||||
{
|
{
|
||||||
public function testContainsNoFieldByDefault()
|
public function testContainsNoChildByDefault()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertCount(0, $form);
|
$this->assertCount(0, $form);
|
||||||
@ -27,7 +27,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testSetDataAdjustsSize()
|
public function testSetDataAdjustsSize()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'options' => array(
|
'options' => array(
|
||||||
'max_length' => 20,
|
'max_length' => 20,
|
||||||
),
|
),
|
||||||
@ -53,7 +53,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testThrowsExceptionIfObjectIsNotTraversable()
|
public function testThrowsExceptionIfObjectIsNotTraversable()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
$this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
|
$this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
|
||||||
$form->setData(new \stdClass());
|
$form->setData(new \stdClass());
|
||||||
@ -62,7 +62,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testNotResizedIfBoundWithMissingData()
|
public function testNotResizedIfBoundWithMissingData()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||||
$form->bind(array('foo@bar.com'));
|
$form->bind(array('foo@bar.com'));
|
||||||
@ -76,7 +76,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testResizedDownIfBoundWithMissingDataAndAllowDelete()
|
public function testResizedDownIfBoundWithMissingDataAndAllowDelete()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'allow_delete' => true,
|
'allow_delete' => true,
|
||||||
));
|
));
|
||||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||||
@ -91,7 +91,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testNotResizedIfBoundWithExtraData()
|
public function testNotResizedIfBoundWithExtraData()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
$form->setData(array('foo@bar.com'));
|
$form->setData(array('foo@bar.com'));
|
||||||
$form->bind(array('foo@foo.com', 'bar@bar.com'));
|
$form->bind(array('foo@foo.com', 'bar@bar.com'));
|
||||||
@ -104,7 +104,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testResizedUpIfBoundWithExtraDataAndAllowAdd()
|
public function testResizedUpIfBoundWithExtraDataAndAllowAdd()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'allow_add' => true,
|
'allow_add' => true,
|
||||||
));
|
));
|
||||||
$form->setData(array('foo@bar.com'));
|
$form->setData(array('foo@bar.com'));
|
||||||
@ -120,7 +120,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testAllowAddButNoPrototype()
|
public function testAllowAddButNoPrototype()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'allow_add' => true,
|
'allow_add' => true,
|
||||||
'prototype' => false,
|
'prototype' => false,
|
||||||
));
|
));
|
||||||
@ -169,7 +169,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
public function testPrototypeNameOption()
|
public function testPrototypeNameOption()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'prototype' => true,
|
'prototype' => true,
|
||||||
'allow_add' => true,
|
'allow_add' => true,
|
||||||
));
|
));
|
||||||
@ -177,7 +177,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||||||
$this->assertSame('__name__', $form->getAttribute('prototype')->getName(), '__name__ is the default');
|
$this->assertSame('__name__', $form->getAttribute('prototype')->getName(), '__name__ is the default');
|
||||||
|
|
||||||
$form = $this->factory->create('collection', null, array(
|
$form = $this->factory->create('collection', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'prototype' => true,
|
'prototype' => true,
|
||||||
'allow_add' => true,
|
'allow_add' => true,
|
||||||
'prototype_name' => '__test__',
|
'prototype_name' => '__test__',
|
||||||
|
@ -1,380 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,9 +11,11 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\Util\PropertyPath;
|
||||||
use Symfony\Component\Form\Form;
|
use Symfony\Component\Form\Form;
|
||||||
use Symfony\Component\Form\CallbackTransformer;
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
use Symfony\Component\Form\Tests\Fixtures\Author;
|
use Symfony\Component\Form\Tests\Fixtures\Author;
|
||||||
|
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
|
||||||
|
|
||||||
class FormTest_AuthorWithoutRefSetter
|
class FormTest_AuthorWithoutRefSetter
|
||||||
{
|
{
|
||||||
@ -49,13 +51,388 @@ class FormTest_AuthorWithoutRefSetter
|
|||||||
|
|
||||||
class FormTypeTest extends TypeTestCase
|
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 testBindWithEmptyDataPassesEmptyStringToTransformerIfNoChildren()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createBuilder('form')
|
||||||
|
->appendClientTransformer(new FixedDataTransformer(array(
|
||||||
|
// required for the initial, internal setData(null)
|
||||||
|
null => 'null',
|
||||||
|
// required to test that bind(null) is converted to ''
|
||||||
|
'empty' => '',
|
||||||
|
)))
|
||||||
|
->getForm();
|
||||||
|
|
||||||
|
$form->bind(null);
|
||||||
|
|
||||||
|
$this->assertSame('empty', $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()
|
public function testSubformDoesntCallSetters()
|
||||||
{
|
{
|
||||||
$author = new FormTest_AuthorWithoutRefSetter(new Author());
|
$author = new FormTest_AuthorWithoutRefSetter(new Author());
|
||||||
|
|
||||||
$builder = $this->factory->createBuilder('form');
|
$builder = $this->factory->createBuilder('form');
|
||||||
$builder->add('reference', 'form');
|
$builder->add('reference', 'form');
|
||||||
$builder->get('reference')->add('firstName', 'field');
|
$builder->get('reference')->add('firstName', 'form');
|
||||||
$builder->setData($author);
|
$builder->setData($author);
|
||||||
$form = $builder->getForm();
|
$form = $builder->getForm();
|
||||||
|
|
||||||
@ -77,7 +454,7 @@ class FormTypeTest extends TypeTestCase
|
|||||||
|
|
||||||
$builder = $this->factory->createBuilder('form');
|
$builder = $this->factory->createBuilder('form');
|
||||||
$builder->add('referenceCopy', 'form');
|
$builder->add('referenceCopy', 'form');
|
||||||
$builder->get('referenceCopy')->add('firstName', 'field');
|
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||||
$builder->setData($author);
|
$builder->setData($author);
|
||||||
$form = $builder->getForm();
|
$form = $builder->getForm();
|
||||||
|
|
||||||
@ -99,7 +476,7 @@ class FormTypeTest extends TypeTestCase
|
|||||||
|
|
||||||
$builder = $this->factory->createBuilder('form');
|
$builder = $this->factory->createBuilder('form');
|
||||||
$builder->add('referenceCopy', 'form', array('by_reference' => false));
|
$builder->add('referenceCopy', 'form', array('by_reference' => false));
|
||||||
$builder->get('referenceCopy')->add('firstName', 'field');
|
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||||
$builder->setData($author);
|
$builder->setData($author);
|
||||||
$form = $builder->getForm();
|
$form = $builder->getForm();
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class RepeatedTypeTest extends TypeTestCase
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->form = $this->factory->create('repeated', null, array(
|
$this->form = $this->factory->create('repeated', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
$this->form->setData(null);
|
$this->form->setData(null);
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ class RepeatedTypeTest extends TypeTestCase
|
|||||||
public function testSetOptions()
|
public function testSetOptions()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('repeated', null, array(
|
$form = $this->factory->create('repeated', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'options' => array('label' => 'Global'),
|
'options' => array('label' => 'Global'),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -47,11 +47,11 @@ class RepeatedTypeTest extends TypeTestCase
|
|||||||
$this->assertTrue($form['second']->isRequired());
|
$this->assertTrue($form['second']->isRequired());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetOptionsPerField()
|
public function testSetOptionsPerChild()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('repeated', null, array(
|
$form = $this->factory->create('repeated', null, array(
|
||||||
// the global required value cannot be overriden
|
// the global required value cannot be overriden
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'first_options' => array('label' => 'Test', 'required' => false),
|
'first_options' => array('label' => 'Test', 'required' => false),
|
||||||
'second_options' => array('label' => 'Test2')
|
'second_options' => array('label' => 'Test2')
|
||||||
));
|
));
|
||||||
@ -66,17 +66,17 @@ class RepeatedTypeTest extends TypeTestCase
|
|||||||
{
|
{
|
||||||
$form = $this->factory->create('repeated', null, array(
|
$form = $this->factory->create('repeated', null, array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertFalse($form['first']->isRequired());
|
$this->assertFalse($form['first']->isRequired());
|
||||||
$this->assertFalse($form['second']->isRequired());
|
$this->assertFalse($form['second']->isRequired());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetOptionsPerFieldAndOverwrite()
|
public function testSetOptionsPerChildAndOverwrite()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('repeated', null, array(
|
$form = $this->factory->create('repeated', null, array(
|
||||||
'type' => 'field',
|
'type' => 'form',
|
||||||
'options' => array('label' => 'Label'),
|
'options' => array('label' => 'Label'),
|
||||||
'second_options' => array('label' => 'Second label')
|
'second_options' => array('label' => 'Second label')
|
||||||
));
|
));
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* 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\Csrf\EventListener;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\Event\DataEvent;
|
|
||||||
use Symfony\Component\Form\Extension\Csrf\EventListener\EnsureCsrfFieldListener;
|
|
||||||
|
|
||||||
class EnsureCsrfFieldListenerTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
private $form;
|
|
||||||
private $formFactory;
|
|
||||||
private $field;
|
|
||||||
private $event;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
|
|
||||||
$this->markTestSkipped('The "EventDispatcher" component is not available');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->formFactory = $this->getMock('Symfony\\Component\\Form\\FormFactoryInterface');
|
|
||||||
$this->form = $this->getMock('Symfony\\Component\\Form\\Tests\\FormInterface');
|
|
||||||
$this->field = $this->getMock('Symfony\\Component\\Form\\Tests\\FormInterface');
|
|
||||||
$this->event = new DataEvent($this->form, array());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown()
|
|
||||||
{
|
|
||||||
$this->form = null;
|
|
||||||
$this->formFactory = null;
|
|
||||||
$this->field = null;
|
|
||||||
$this->event = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAddField()
|
|
||||||
{
|
|
||||||
$this->formFactory->expects($this->once())
|
|
||||||
->method('createNamed')
|
|
||||||
->with('csrf', '_token', null, array())
|
|
||||||
->will($this->returnValue($this->field));
|
|
||||||
$this->form->expects($this->once())
|
|
||||||
->method('add')
|
|
||||||
->with($this->isInstanceOf('Symfony\\Component\\Form\\Tests\\FormInterface'));
|
|
||||||
|
|
||||||
$listener = new EnsureCsrfFieldListener($this->formFactory, '_token');
|
|
||||||
$listener->ensureCsrfField($this->event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIntention()
|
|
||||||
{
|
|
||||||
$this->formFactory->expects($this->once())
|
|
||||||
->method('createNamed')
|
|
||||||
->with('csrf', '_token', null, array('intention' => 'something'))
|
|
||||||
->will($this->returnValue($this->field));
|
|
||||||
$this->form->expects($this->once())
|
|
||||||
->method('add')
|
|
||||||
->with($this->isInstanceOf('Symfony\\Component\\Form\\Tests\\FormInterface'));
|
|
||||||
|
|
||||||
$listener = new EnsureCsrfFieldListener($this->formFactory, '_token', 'something');
|
|
||||||
$listener->ensureCsrfField($this->event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testProvider()
|
|
||||||
{
|
|
||||||
$provider = $this->getMock('Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\CsrfProviderInterface');
|
|
||||||
|
|
||||||
$this->formFactory->expects($this->once())
|
|
||||||
->method('createNamed')
|
|
||||||
->with('csrf', '_token', null, array('csrf_provider' => $provider))
|
|
||||||
->will($this->returnValue($this->field));
|
|
||||||
$this->form->expects($this->once())
|
|
||||||
->method('add')
|
|
||||||
->with($this->isInstanceOf('Symfony\\Component\\Form\\Tests\\FormInterface'));
|
|
||||||
|
|
||||||
$listener = new EnsureCsrfFieldListener($this->formFactory, '_token', null, $provider);
|
|
||||||
$listener->ensureCsrfField($this->event);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* 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\Csrf\Type;
|
|
||||||
|
|
||||||
class CsrfTypeTest extends TypeTestCase
|
|
||||||
{
|
|
||||||
protected $provider;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->provider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown()
|
|
||||||
{
|
|
||||||
parent::tearDown();
|
|
||||||
|
|
||||||
$this->provider = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getNonRootForm()
|
|
||||||
{
|
|
||||||
$form = $this->getMock('Symfony\Component\Form\Tests\FormInterface');
|
|
||||||
$form->expects($this->any())
|
|
||||||
->method('isRoot')
|
|
||||||
->will($this->returnValue(false));
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGenerateCsrfToken()
|
|
||||||
{
|
|
||||||
$this->provider->expects($this->once())
|
|
||||||
->method('generateCsrfToken')
|
|
||||||
->with('%INTENTION%')
|
|
||||||
->will($this->returnValue('token'));
|
|
||||||
|
|
||||||
$form = $this->factory->create('csrf', null, array(
|
|
||||||
'csrf_provider' => $this->provider,
|
|
||||||
'intention' => '%INTENTION%'
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertEquals('token', $form->getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testValidateTokenOnBind()
|
|
||||||
{
|
|
||||||
$this->provider->expects($this->once())
|
|
||||||
->method('isCsrfTokenValid')
|
|
||||||
->with('%INTENTION%', 'token')
|
|
||||||
->will($this->returnValue(true));
|
|
||||||
|
|
||||||
$form = $this->factory->create('csrf', null, array(
|
|
||||||
'csrf_provider' => $this->provider,
|
|
||||||
'intention' => '%INTENTION%'
|
|
||||||
));
|
|
||||||
$form->bind('token');
|
|
||||||
|
|
||||||
$this->assertEquals('token', $form->getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDontValidateTokenIfParentIsNotRoot()
|
|
||||||
{
|
|
||||||
$this->provider->expects($this->never())
|
|
||||||
->method('isCsrfTokenValid');
|
|
||||||
|
|
||||||
$form = $this->factory->create('csrf', null, array(
|
|
||||||
'csrf_provider' => $this->provider,
|
|
||||||
'intention' => '%INTENTION%'
|
|
||||||
));
|
|
||||||
$form->setParent($this->getNonRootForm());
|
|
||||||
$form->bind('token');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCsrfTokenIsRegeneratedIfValidationFails()
|
|
||||||
{
|
|
||||||
$this->provider->expects($this->at(0))
|
|
||||||
->method('generateCsrfToken')
|
|
||||||
->with('%INTENTION%')
|
|
||||||
->will($this->returnValue('token1'));
|
|
||||||
$this->provider->expects($this->at(1))
|
|
||||||
->method('isCsrfTokenValid')
|
|
||||||
->with('%INTENTION%', 'invalid')
|
|
||||||
->will($this->returnValue(false));
|
|
||||||
|
|
||||||
// The token is regenerated to avoid stalled tokens, for example when
|
|
||||||
// the session ID changed
|
|
||||||
$this->provider->expects($this->at(2))
|
|
||||||
->method('generateCsrfToken')
|
|
||||||
->with('%INTENTION%')
|
|
||||||
->will($this->returnValue('token2'));
|
|
||||||
|
|
||||||
$form = $this->factory->create('csrf', null, array(
|
|
||||||
'csrf_provider' => $this->provider,
|
|
||||||
'intention' => '%INTENTION%'
|
|
||||||
));
|
|
||||||
$form->bind('invalid');
|
|
||||||
|
|
||||||
$this->assertEquals('token2', $form->getData());
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,43 +11,188 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Form\Tests\Extension\Csrf\Type;
|
namespace Symfony\Component\Form\Tests\Extension\Csrf\Type;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
|
||||||
|
use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase;
|
||||||
|
|
||||||
class FormTypeCsrfExtensionTest extends TypeTestCase
|
class FormTypeCsrfExtensionTest extends TypeTestCase
|
||||||
{
|
{
|
||||||
public function testCsrfProtectionByDefault()
|
protected $csrfProvider;
|
||||||
{
|
|
||||||
$form = $this->factory->create('form', null, array(
|
|
||||||
'csrf_field_name' => 'csrf',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertTrue($form->has('csrf'));
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->csrfProvider = null;
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getExtensions()
|
||||||
|
{
|
||||||
|
return array_merge(parent::getExtensions(), array(
|
||||||
|
new CsrfExtension($this->csrfProvider),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCsrfProtectionByDefaultIfRootAndChildren()
|
||||||
|
{
|
||||||
|
$view = $this->factory
|
||||||
|
->createBuilder('form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
))
|
||||||
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
|
->getForm()
|
||||||
|
->createView();
|
||||||
|
|
||||||
|
$this->assertTrue($view->hasChild('csrf'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoCsrfProtectionByDefaultIfChildrenButNotRoot()
|
||||||
|
{
|
||||||
|
$view = $this->factory
|
||||||
|
->createNamedBuilder('form', 'root')
|
||||||
|
->add($this->factory
|
||||||
|
->createNamedBuilder('form', 'form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
))
|
||||||
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
|
)
|
||||||
|
->getForm()
|
||||||
|
->get('form')
|
||||||
|
->createView();
|
||||||
|
|
||||||
|
$this->assertFalse($view->hasChild('csrf'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoCsrfProtectionByDefaultIfRootButNoChildren()
|
||||||
|
{
|
||||||
|
$view = $this->factory
|
||||||
|
->createBuilder('form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
))
|
||||||
|
->getForm()
|
||||||
|
->createView();
|
||||||
|
|
||||||
|
$this->assertFalse($view->hasChild('csrf'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCsrfProtectionCanBeDisabled()
|
public function testCsrfProtectionCanBeDisabled()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('form', null, array(
|
$view = $this->factory
|
||||||
'csrf_protection' => false,
|
->createBuilder('form', null, array(
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertCount(0, $form);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCsrfTokenIsOnlyIncludedInRootView()
|
|
||||||
{
|
|
||||||
$view =
|
|
||||||
$this->factory->createBuilder('form', null, array(
|
|
||||||
'csrf_field_name' => 'csrf',
|
'csrf_field_name' => 'csrf',
|
||||||
|
'csrf_protection' => false,
|
||||||
))
|
))
|
||||||
->add('notCsrf', 'text')
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
->add(
|
|
||||||
$this->factory->createNamedBuilder('form', 'child', null, array(
|
|
||||||
'csrf_field_name' => 'csrf',
|
|
||||||
))
|
|
||||||
->add('notCsrf', 'text')
|
|
||||||
)
|
|
||||||
->getForm()
|
->getForm()
|
||||||
->createView();
|
->createView();
|
||||||
|
|
||||||
$this->assertEquals(array('csrf', 'notCsrf', 'child'), array_keys(iterator_to_array($view)));
|
$this->assertFalse($view->hasChild('csrf'));
|
||||||
$this->assertEquals(array('notCsrf'), array_keys(iterator_to_array($view['child'])));
|
}
|
||||||
|
|
||||||
|
public function testGenerateCsrfToken()
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->once())
|
||||||
|
->method('generateCsrfToken')
|
||||||
|
->with('%INTENTION%')
|
||||||
|
->will($this->returnValue('token'));
|
||||||
|
|
||||||
|
$view = $this->factory
|
||||||
|
->createBuilder('form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
'csrf_provider' => $this->csrfProvider,
|
||||||
|
'intention' => '%INTENTION%'
|
||||||
|
))
|
||||||
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
|
->getForm()
|
||||||
|
->createView();
|
||||||
|
|
||||||
|
$this->assertEquals('token', $view->getChild('csrf')->get('value'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideBoolean()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(true),
|
||||||
|
array(false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideBoolean
|
||||||
|
*/
|
||||||
|
public function testValidateTokenOnBindIfRootAndChildren($valid)
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->once())
|
||||||
|
->method('isCsrfTokenValid')
|
||||||
|
->with('%INTENTION%', 'token')
|
||||||
|
->will($this->returnValue($valid));
|
||||||
|
|
||||||
|
$form = $this->factory
|
||||||
|
->createBuilder('form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
'csrf_provider' => $this->csrfProvider,
|
||||||
|
'intention' => '%INTENTION%'
|
||||||
|
))
|
||||||
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
|
->getForm();
|
||||||
|
|
||||||
|
$form->bind(array(
|
||||||
|
'child' => 'foobar',
|
||||||
|
'csrf' => 'token',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Remove token from data
|
||||||
|
$this->assertSame(array('child' => 'foobar'), $form->getData());
|
||||||
|
|
||||||
|
// Validate accordingly
|
||||||
|
$this->assertSame($valid, $form->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDontValidateTokenIfChildrenButNoRoot()
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->never())
|
||||||
|
->method('isCsrfTokenValid');
|
||||||
|
|
||||||
|
$form = $this->factory
|
||||||
|
->createNamedBuilder('form', 'root')
|
||||||
|
->add($this->factory
|
||||||
|
->createNamedBuilder('form', 'form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
'csrf_provider' => $this->csrfProvider,
|
||||||
|
'intention' => '%INTENTION%'
|
||||||
|
))
|
||||||
|
->add($this->factory->createNamedBuilder('form', 'child'))
|
||||||
|
)
|
||||||
|
->getForm()
|
||||||
|
->get('form');
|
||||||
|
|
||||||
|
$form->bind(array(
|
||||||
|
'child' => 'foobar',
|
||||||
|
'csrf' => 'token',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDontValidateTokenIfRootButNoChildren()
|
||||||
|
{
|
||||||
|
$this->csrfProvider->expects($this->never())
|
||||||
|
->method('isCsrfTokenValid');
|
||||||
|
|
||||||
|
$form = $this->factory
|
||||||
|
->createBuilder('form', null, array(
|
||||||
|
'csrf_field_name' => 'csrf',
|
||||||
|
'csrf_provider' => $this->csrfProvider,
|
||||||
|
'intention' => '%INTENTION%'
|
||||||
|
))
|
||||||
|
->getForm();
|
||||||
|
|
||||||
|
$form->bind(array(
|
||||||
|
'csrf' => 'token',
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
|
||||||
*
|
|
||||||
* 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\Csrf\Type;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase as BaseTestCase;
|
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
|
|
||||||
|
|
||||||
abstract class TypeTestCase extends BaseTestCase
|
|
||||||
{
|
|
||||||
protected $csrfProvider;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
$this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface');
|
|
||||||
|
|
||||||
parent::setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown()
|
|
||||||
{
|
|
||||||
$this->csrfProvider = null;
|
|
||||||
|
|
||||||
parent::tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getExtensions()
|
|
||||||
{
|
|
||||||
return array_merge(parent::getExtensions(), array(
|
|
||||||
new CsrfExtension($this->csrfProvider),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
@ -93,6 +93,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$builder = new FormBuilder($name, $this->factory, $this->dispatcher);
|
$builder = new FormBuilder($name, $this->factory, $this->dispatcher);
|
||||||
$builder->setAttribute('property_path', new PropertyPath($propertyPath ?: $name));
|
$builder->setAttribute('property_path', new PropertyPath($propertyPath ?: $name));
|
||||||
$builder->setAttribute('error_mapping', array());
|
$builder->setAttribute('error_mapping', array());
|
||||||
|
$builder->setErrorBubbling(false);
|
||||||
|
|
||||||
return $builder;
|
return $builder;
|
||||||
}
|
}
|
||||||
|
@ -13,18 +13,18 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
|
|||||||
|
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
|
||||||
class FieldTypeValidatorExtensionTest extends TypeTestCase
|
class FormTypeValidatorExtensionTest extends TypeTestCase
|
||||||
{
|
{
|
||||||
public function testValidationGroupNullByDefault()
|
public function testValidationGroupNullByDefault()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('field');
|
$form = $this->factory->create('form');
|
||||||
|
|
||||||
$this->assertNull($form->getAttribute('validation_groups'));
|
$this->assertNull($form->getAttribute('validation_groups'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidationGroupsCanBeSetToString()
|
public function testValidationGroupsCanBeSetToString()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('field', null, array(
|
$form = $this->factory->create('form', null, array(
|
||||||
'validation_groups' => 'group',
|
'validation_groups' => 'group',
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||||||
|
|
||||||
public function testValidationGroupsCanBeSetToArray()
|
public function testValidationGroupsCanBeSetToArray()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('field', null, array(
|
$form = $this->factory->create('form', null, array(
|
||||||
'validation_groups' => array('group1', 'group2'),
|
'validation_groups' => array('group1', 'group2'),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||||||
|
|
||||||
public function testValidationGroupsCanBeSetToCallback()
|
public function testValidationGroupsCanBeSetToCallback()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('field', null, array(
|
$form = $this->factory->create('form', null, array(
|
||||||
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
|
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||||||
|
|
||||||
public function testValidationGroupsCanBeSetToClosure()
|
public function testValidationGroupsCanBeSetToClosure()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create('field', null, array(
|
$form = $this->factory->create('form', null, array(
|
||||||
'validation_groups' => function(FormInterface $form){ return null; },
|
'validation_groups' => function(FormInterface $form){ return null; },
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -60,10 +60,10 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||||||
|
|
||||||
public function testBindValidatesData()
|
public function testBindValidatesData()
|
||||||
{
|
{
|
||||||
$builder = $this->factory->createBuilder('field', null, array(
|
$builder = $this->factory->createBuilder('form', null, array(
|
||||||
'validation_groups' => 'group',
|
'validation_groups' => 'group',
|
||||||
));
|
));
|
||||||
$builder->add('firstName', 'field');
|
$builder->add('firstName', 'form');
|
||||||
$form = $builder->getForm();
|
$form = $builder->getForm();
|
||||||
|
|
||||||
$this->validator->expects($this->once())
|
$this->validator->expects($this->once())
|
@ -71,7 +71,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
|||||||
* Changing the name is not allowed, otherwise the name and property path
|
* Changing the name is not allowed, otherwise the name and property path
|
||||||
* are not synchronized anymore
|
* are not synchronized anymore
|
||||||
*
|
*
|
||||||
* @see FieldType::buildForm
|
* @see FormType::buildForm
|
||||||
*/
|
*/
|
||||||
public function testNoSetName()
|
public function testNoSetName()
|
||||||
{
|
{
|
||||||
|
@ -346,7 +346,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('foo', $builder->getName());
|
$this->assertEquals('foo', $builder->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateBuilderForPropertyCreatesFieldWithHighestConfidence()
|
public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence()
|
||||||
{
|
{
|
||||||
$this->guesser1->expects($this->once())
|
$this->guesser1->expects($this->once())
|
||||||
->method('guessType')
|
->method('guessType')
|
||||||
@ -378,7 +378,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('builderInstance', $builder);
|
$this->assertEquals('builderInstance', $builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateBuilderCreatesTextFieldIfNoGuess()
|
public function testCreateBuilderCreatesTextFormIfNoGuess()
|
||||||
{
|
{
|
||||||
$this->guesser1->expects($this->once())
|
$this->guesser1->expects($this->once())
|
||||||
->method('guessType')
|
->method('guessType')
|
||||||
@ -541,7 +541,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$factory->createNamedBuilder($type, "text", "value", array("unknown" => "opt"));
|
$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()));
|
$factory = new FormFactory(array(new \Symfony\Component\Form\Extension\Core\CoreExtension()));
|
||||||
|
|
||||||
|
@ -159,6 +159,35 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(array(), $parent->getErrors());
|
$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()
|
public function testValidIfAllChildrenAreValid()
|
||||||
{
|
{
|
||||||
$this->form->add($this->getValidForm('firstName'));
|
$this->form->add($this->getValidForm('firstName'));
|
||||||
@ -1026,7 +1055,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider requestMethodProvider
|
* @dataProvider requestMethodProvider
|
||||||
*/
|
*/
|
||||||
public function testBindPostOrPutRequestWithSingleFieldForm($method)
|
public function testBindPostOrPutRequestWithSingleChildForm($method)
|
||||||
{
|
{
|
||||||
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
||||||
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
||||||
@ -1063,7 +1092,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider requestMethodProvider
|
* @dataProvider requestMethodProvider
|
||||||
*/
|
*/
|
||||||
public function testBindPostOrPutRequestWithSingleFieldFormUploadedFile($method)
|
public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method)
|
||||||
{
|
{
|
||||||
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
||||||
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
||||||
@ -1247,7 +1276,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testCreateViewAcceptsParent()
|
public function testCreateViewAcceptsParent()
|
||||||
{
|
{
|
||||||
$parent = new FormView();
|
$parent = new FormView('form');
|
||||||
|
|
||||||
$form = $this->getBuilder()->getForm();
|
$form = $this->getBuilder()->getForm();
|
||||||
$view = $form->createView($parent);
|
$view = $form->createView($parent);
|
||||||
|
Reference in New Issue
Block a user