[Form] Deprecated FieldType, which has been merged into FormType
This commit is contained in:
parent
bfa7ef2d9b
commit
fcb2227ac9
|
@ -267,9 +267,12 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
|||
in their name anymore. Their names terminate with "[]" now.
|
||||
* [BC BREAK] FormType::getDefaultOptions() and FormType::getAllowedOptionValues()
|
||||
don't receive an options array anymore.
|
||||
* Deprecated FormValidatorInterface and substituted its implementations
|
||||
* deprecated FormValidatorInterface and substituted its implementations
|
||||
by event subscribers
|
||||
* simplified CSRF protection and removed the csrf type
|
||||
* deprecated FieldType and merged it into FormType
|
||||
* [BC BREAK] renamed "field_*" theme blocks to "form_*" and "field_widget" to
|
||||
"input"
|
||||
|
||||
### HttpFoundation
|
||||
|
||||
|
|
114
UPGRADE-2.1.md
114
UPGRADE-2.1.md
|
@ -94,7 +94,7 @@
|
|||
```
|
||||
* The custom factories for the firewall configuration are now
|
||||
registered during the build method of bundles instead of being registered
|
||||
by the end-user. This means that you will you need to remove the 'factories'
|
||||
by the end-user. This means that you will you need to remove the 'factories'
|
||||
keys in your security configuration.
|
||||
|
||||
* The Firewall listener is now registered after the Router listener. This
|
||||
|
@ -372,29 +372,29 @@
|
|||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'text' : 'choice';
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
* The methods `getDefaultOptions()` and `getAllowedOptionValues()` of form
|
||||
types no longer receive an option array.
|
||||
|
||||
|
||||
You can specify options that depend on other options using closures instead.
|
||||
|
||||
|
||||
Before:
|
||||
|
||||
|
||||
```
|
||||
public function getDefaultOptions(array $options)
|
||||
{
|
||||
$defaultOptions = array();
|
||||
|
||||
|
||||
if ($options['multiple']) {
|
||||
$defaultOptions['empty_data'] = array();
|
||||
}
|
||||
|
||||
|
||||
return $defaultOptions;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
After:
|
||||
|
||||
|
||||
```
|
||||
public function getDefaultOptions()
|
||||
{
|
||||
|
@ -405,7 +405,7 @@
|
|||
);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The second argument `$previousValue` does not have to be specified if not
|
||||
needed.
|
||||
|
||||
|
@ -425,6 +425,100 @@
|
|||
(or any other of the BIND events). In case you used the CallbackValidator
|
||||
class, you should now pass the callback directly to `addEventListener`.
|
||||
|
||||
* FieldType was merged into FormType. FieldType itself was deprecated and
|
||||
will be removed in Symfony 2.3.
|
||||
|
||||
##### Update your field types
|
||||
|
||||
You are advised to update your custom types that extend FieldType to extend
|
||||
FormType instead.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return 'field';
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
```
|
||||
|
||||
You can also remove the getParent() method as this is the default
|
||||
implementation in AbstractType.
|
||||
|
||||
##### Update your form themes
|
||||
|
||||
Previously, FieldType was the super type for all other types. Now, since
|
||||
it is deprecated, FieldType is a subtype of FormType, which is now the base
|
||||
type for all other types.
|
||||
|
||||
A consequence of this change is that any "form_*" blocks defined in your
|
||||
themes are now also used for other types that extend "field", unless you
|
||||
explicitely override the "field_*" or "mytype_*" blocks.
|
||||
|
||||
"field_*" blocks are deprecated and will be unsupported as of Symfony 2.3.
|
||||
You should merge them into the corresponding "form_*" blocks instead.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
{% block field_label %}
|
||||
{% spaceless %}
|
||||
{% set attr = attr|merge({'for': id}) %}
|
||||
{{ block('generic_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_label %}
|
||||
|
||||
{% block form_label %}
|
||||
{% spaceless %}
|
||||
{{ block('generic_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock form_label %}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
{% block form_label %}
|
||||
{% spaceless %}
|
||||
{% if form.children|length == 0 %}
|
||||
{% set attr = attr|merge({'for': id}) %}
|
||||
{% endif %}
|
||||
{{ block('generic_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock form_label %}
|
||||
```
|
||||
|
||||
The block "field_widget" was renamed to "input" and is still supported.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
{% block field_widget %}
|
||||
{% spaceless %}
|
||||
<!-- custom input tag -->
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
{% block input %}
|
||||
{% spaceless %}
|
||||
<!-- custom input tag -->
|
||||
{% endspaceless %}
|
||||
{% endblock input %}
|
||||
```
|
||||
|
||||
### Session
|
||||
|
||||
* Flash messages now return an array based on their type. The old method is
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
|
||||
{% block form_widget %}
|
||||
{% spaceless %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ block('field_rows') }}
|
||||
{{ form_rest(form) }}
|
||||
</div>
|
||||
{% if form.children|length > 0 %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ block('form_rows') }}
|
||||
{{ form_rest(form) }}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ block('input') }}
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
{% endblock form_widget %}
|
||||
|
||||
|
@ -83,7 +87,7 @@
|
|||
{% block datetime_widget %}
|
||||
{% spaceless %}
|
||||
{% if widget == 'single_text' %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% else %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ form_errors(form.date) }}
|
||||
|
@ -98,7 +102,7 @@
|
|||
{% block date_widget %}
|
||||
{% spaceless %}
|
||||
{% if widget == 'single_text' %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% else %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ date_pattern|replace({
|
||||
|
@ -114,7 +118,7 @@
|
|||
{% block time_widget %}
|
||||
{% spaceless %}
|
||||
{% if widget == 'single_text' %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% else %}
|
||||
<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 %}
|
||||
|
@ -127,67 +131,60 @@
|
|||
{% spaceless %}
|
||||
{# type="number" doesn't work with floats #}
|
||||
{% set type = type|default('text') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock number_widget %}
|
||||
|
||||
{% block integer_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('number') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock integer_widget %}
|
||||
|
||||
{% block money_widget %}
|
||||
{% spaceless %}
|
||||
{{ money_pattern|replace({ '{{ widget }}': block('field_widget') })|raw }}
|
||||
{{ money_pattern|replace({ '{{ widget }}': block('input') })|raw }}
|
||||
{% endspaceless %}
|
||||
{% endblock money_widget %}
|
||||
|
||||
{% block url_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('url') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock url_widget %}
|
||||
|
||||
{% block search_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('search') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock search_widget %}
|
||||
|
||||
{% block percent_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
{{ block('field_widget') }} %
|
||||
{{ block('input') }} %
|
||||
{% endspaceless %}
|
||||
{% endblock percent_widget %}
|
||||
|
||||
{% block field_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
|
||||
{% block password_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('password') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock password_widget %}
|
||||
|
||||
{% block hidden_widget %}
|
||||
{% set type = type|default('hidden') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endblock hidden_widget %}
|
||||
|
||||
{% block email_widget %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('email') %}
|
||||
{{ block('field_widget') }}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock email_widget %}
|
||||
|
||||
|
@ -202,15 +199,11 @@
|
|||
{% endspaceless %}
|
||||
{% endblock %}
|
||||
|
||||
{% block field_label %}
|
||||
{% spaceless %}
|
||||
{% set attr = attr|merge({'for': id}) %}
|
||||
{{ block('generic_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_label %}
|
||||
|
||||
{% block form_label %}
|
||||
{% spaceless %}
|
||||
{% if form.children|length == 0 %}
|
||||
{% set attr = attr|merge({'for': id}) %}
|
||||
{% endif %}
|
||||
{{ block('generic_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock form_label %}
|
||||
|
@ -219,24 +212,17 @@
|
|||
|
||||
{% block repeated_row %}
|
||||
{% spaceless %}
|
||||
{{ block('field_rows') }}
|
||||
{{ block('form_rows') }}
|
||||
{% endspaceless %}
|
||||
{% endblock repeated_row %}
|
||||
|
||||
{% block field_row %}
|
||||
{% spaceless %}
|
||||
<div>
|
||||
{{ form_label(form, label|default(null)) }}
|
||||
{{ form_errors(form) }}
|
||||
{{ form_widget(form) }}
|
||||
</div>
|
||||
{% endspaceless %}
|
||||
{% endblock field_row %}
|
||||
|
||||
{% block form_row %}
|
||||
{% spaceless %}
|
||||
<div>
|
||||
{{ form_label(form, label|default(null)) }}
|
||||
{% if form.children|length == 0 %}
|
||||
{{ form_errors(form) }}
|
||||
{% endif %}
|
||||
{{ form_widget(form) }}
|
||||
</div>
|
||||
{% endspaceless %}
|
||||
|
@ -248,13 +234,13 @@
|
|||
|
||||
{# Misc #}
|
||||
|
||||
{% block field_enctype %}
|
||||
{% block form_enctype %}
|
||||
{% spaceless %}
|
||||
{% if multipart %}enctype="multipart/form-data"{% endif %}
|
||||
{% endspaceless %}
|
||||
{% endblock field_enctype %}
|
||||
{% endblock form_enctype %}
|
||||
|
||||
{% block field_errors %}
|
||||
{% block form_errors %}
|
||||
{% spaceless %}
|
||||
{% if errors|length > 0 %}
|
||||
<ul>
|
||||
|
@ -270,9 +256,9 @@
|
|||
</ul>
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
{% endblock field_errors %}
|
||||
{% endblock form_errors %}
|
||||
|
||||
{% block field_rest %}
|
||||
{% block form_rest %}
|
||||
{% spaceless %}
|
||||
{% for child in form %}
|
||||
{% if not child.rendered %}
|
||||
|
@ -280,18 +266,25 @@
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endspaceless %}
|
||||
{% endblock field_rest %}
|
||||
{% endblock form_rest %}
|
||||
|
||||
{# Support #}
|
||||
|
||||
{% block field_rows %}
|
||||
{% block form_rows %}
|
||||
{% spaceless %}
|
||||
{{ form_errors(form) }}
|
||||
{% for child in form %}
|
||||
{{ form_row(child) }}
|
||||
{% endfor %}
|
||||
{% endspaceless %}
|
||||
{% endblock field_rows %}
|
||||
{% endblock form_rows %}
|
||||
|
||||
{% block input %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
|
||||
{% endspaceless %}
|
||||
{% endblock input %}
|
||||
|
||||
{% block widget_attributes %}
|
||||
{% spaceless %}
|
||||
|
@ -306,3 +299,47 @@
|
|||
{% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %}
|
||||
{% endspaceless %}
|
||||
{% endblock widget_container_attributes %}
|
||||
|
||||
{# Deprecated in Symfony 2.1, to be removed in 2.3 #}
|
||||
|
||||
{% block field_widget %}
|
||||
{% spaceless %}
|
||||
{{ block('input') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
|
||||
{% block field_label %}
|
||||
{% spaceless %}
|
||||
{{ block('form_label') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_label %}
|
||||
|
||||
{% block field_row %}
|
||||
{% spaceless %}
|
||||
{{ block('form_row') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_row %}
|
||||
|
||||
{% block field_enctype %}
|
||||
{% spaceless %}
|
||||
{{ block('form_enctype') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_enctype %}
|
||||
|
||||
{% block field_errors %}
|
||||
{% spaceless %}
|
||||
{{ block('form_errors') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_errors %}
|
||||
|
||||
{% block field_rest %}
|
||||
{% spaceless %}
|
||||
{{ block('form_rest') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_rest %}
|
||||
|
||||
{% block field_rows %}
|
||||
{% spaceless %}
|
||||
{{ block('form_rows') }}
|
||||
{% endspaceless %}
|
||||
{% endblock field_rows %}
|
|
@ -1,19 +1,5 @@
|
|||
{% 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 %}
|
||||
{% spaceless %}
|
||||
<tr>
|
||||
|
@ -21,6 +7,9 @@
|
|||
{{ form_label(form, label|default(null)) }}
|
||||
</td>
|
||||
<td>
|
||||
{% if form.children|length == 0 %}
|
||||
{{ form_errors(form) }}
|
||||
{% endif %}
|
||||
{{ form_widget(form) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -29,12 +18,16 @@
|
|||
|
||||
{% block form_errors %}
|
||||
{% spaceless %}
|
||||
{% if errors|length > 0 %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{ block('field_errors') }}
|
||||
</td>
|
||||
</tr>
|
||||
{% if form.children|length > 0 %}
|
||||
{% if errors|length > 0 %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{ parent() }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
{% endblock form_errors %}
|
||||
|
@ -51,9 +44,13 @@
|
|||
|
||||
{% block form_widget %}
|
||||
{% spaceless %}
|
||||
<table {{ block('widget_container_attributes') }}>
|
||||
{{ block('field_rows') }}
|
||||
{{ form_rest(form) }}
|
||||
</table>
|
||||
{% if form.children|length > 0 %}
|
||||
<table {{ block('widget_container_attributes') }}>
|
||||
{{ block('form_rows') }}
|
||||
{{ form_rest(form) }}
|
||||
</table>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
{% endblock form_widget %}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{% block field_label %}
|
||||
{% block form_label %}
|
||||
<label>child</label>
|
||||
{% endblock field_label %}
|
||||
{% endblock form_label %}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{% block field_label %}
|
||||
{% block form_label %}
|
||||
<label>parent</label>
|
||||
{% endblock field_label %}
|
||||
{% endblock form_label %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% block field_widget %}
|
||||
{% block input %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
{% endblock input %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{% extends 'form_div_layout.html.twig' %}
|
||||
|
||||
{% block field_widget %}
|
||||
{% block input %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
{% endblock input %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{% use 'form_div_layout.html.twig' %}
|
||||
|
||||
{% block field_widget %}
|
||||
{% block input %}
|
||||
{% spaceless %}
|
||||
{% set type = type|default('text') %}
|
||||
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
|
||||
{% endspaceless %}
|
||||
{% endblock field_widget %}
|
||||
{% endblock input %}
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
<!-- CoreExtension -->
|
||||
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
|
||||
<tag name="form.type" alias="field" />
|
||||
<argument type="service" id="validator" />
|
||||
</service>
|
||||
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
||||
<tag name="form.type" alias="form" />
|
||||
|
@ -133,8 +132,8 @@
|
|||
<tag name="form.type" alias="url" />
|
||||
</service>
|
||||
|
||||
<!-- FieldTypeValidatorExtension -->
|
||||
<service id="form.type_extension.field" class="Symfony\Component\Form\Extension\Validator\Type\FieldTypeValidatorExtension">
|
||||
<!-- FormTypeValidatorExtension -->
|
||||
<service id="form.type_extension.field" class="Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension">
|
||||
<tag name="form.type_extension" alias="field" />
|
||||
<argument type="service" id="validator" />
|
||||
</service>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php if ($widget == 'single_text'): ?>
|
||||
<?php echo $view['form']->renderBlock('field_widget'); ?>
|
||||
<?php echo $view['form']->renderBlock('input'); ?>
|
||||
<?php else: ?>
|
||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||
<?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php if ($widget == 'single_text'): ?>
|
||||
<?php echo $view['form']->renderBlock('field_widget'); ?>
|
||||
<?php echo $view['form']->renderBlock('input'); ?>
|
||||
<?php else: ?>
|
||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||
<?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): ?>
|
||||
<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 echo $view['form']->renderBlock('form_errors') ?>
|
|
@ -1,2 +1 @@
|
|||
<?php if ($required) { $attr['class'] = (isset($attr['class']) ? $attr['class'] : '').' required'; } ?>
|
||||
<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>
|
||||
<?php echo $view['form']->renderBlock('form_label') ?>
|
|
@ -1,5 +1 @@
|
|||
<?php foreach ($form as $child): ?>
|
||||
<?php if (!$child->isRendered()): ?>
|
||||
<?php echo $view['form']->row($child) ?>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php echo $view['form']->renderBlock('form_rest') ?>
|
|
@ -1,5 +1 @@
|
|||
<div>
|
||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||
<?php echo $view['form']->errors($form) ?>
|
||||
<?php echo $view['form']->widget($form) ?>
|
||||
</div>
|
||||
<?php echo $view['form']->renderBlock('form_row') ?>
|
|
@ -1,4 +1 @@
|
|||
<?php echo $view['form']->errors($form) ?>
|
||||
<?php foreach ($form as $child) : ?>
|
||||
<?php echo $view['form']->row($child) ?>
|
||||
<?php endforeach; ?>
|
||||
<?php echo $view['form']->renderBlock('form_rows') ?>
|
|
@ -1,5 +1 @@
|
|||
<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') ?>
|
||||
/>
|
||||
<?php echo $view['form']->renderBlock('input') ?>
|
|
@ -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 (!$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>
|
||||
|
|
|
@ -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>
|
||||
<?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) ?>
|
||||
</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') ?>>
|
||||
<?php echo $view['form']->renderBlock('field_rows') ?>
|
||||
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||
<?php echo $view['form']->rest($form) ?>
|
||||
</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 echo $view['form']->renderBlock('field_widget'); ?>
|
||||
<?php echo $view['form']->renderBlock('input'); ?>
|
||||
<?php else: ?>
|
||||
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
|
||||
<?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)) : ?>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<?php echo $view['form']->renderBlock('field_errors'); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php if ($form->hasChildren()): ?>
|
||||
<?php if (count($errors) > 0): ?>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<?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 ?>
|
||||
</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; ?>
|
|
@ -3,6 +3,9 @@
|
|||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if (!$form->hasChildren()): ?>
|
||||
<?php echo $view['form']->errors($form) ?>
|
||||
<?php endif ?>
|
||||
<?php echo $view['form']->widget($form) ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<?php if ($form->hasChildren()): ?>
|
||||
<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) ?>
|
||||
</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())
|
||||
{
|
||||
return trim($this->renderSection($view, 'widget', $variables));
|
||||
return $this->renderSection($view, 'widget', $variables);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,7 +276,7 @@ class FormHelper extends Helper
|
|||
$view->setRendered();
|
||||
}
|
||||
|
||||
return $html;
|
||||
return trim($html);
|
||||
}
|
||||
} while (--$typeIndex >= 0);
|
||||
|
||||
|
@ -311,7 +311,7 @@ class FormHelper extends Helper
|
|||
|
||||
$variables = array_replace_recursive($context['variables'], $variables);
|
||||
|
||||
return $this->engine->render($template, $variables);
|
||||
return trim($this->engine->render($template, $variables));
|
||||
}
|
||||
|
||||
public function getName()
|
||||
|
|
|
@ -24,7 +24,7 @@ interface DataTransformerInterface
|
|||
* This method is called on two occasions inside a form field:
|
||||
*
|
||||
* 1. When the form field is initialized with the data attached from the datasource (object or array).
|
||||
* 2. When data from a request is bound using {@link Field::bind()} to transform the new input data
|
||||
* 2. When data from a request is bound using {@link Form::bind()} to transform the new input data
|
||||
* back into the renderable format. For example if you have a date field and bind '2009-10-10' onto
|
||||
* it you might accept this value because its easily parsed, but the transformer still writes back
|
||||
* "2009/10/10" onto the form field (for further displaying or other purposes).
|
||||
|
@ -52,7 +52,7 @@ interface DataTransformerInterface
|
|||
* Transforms a value from the transformed representation to its original
|
||||
* representation.
|
||||
*
|
||||
* This method is called when {@link Field::bind()} is called to transform the requests tainted data
|
||||
* This method is called when {@link Form::bind()} is called to transform the requests tainted data
|
||||
* into an acceptable format for your data processing/model layer.
|
||||
*
|
||||
* This method must be able to deal with empty values. Usually this will
|
||||
|
|
|
@ -44,8 +44,8 @@ class ChoiceType extends AbstractType
|
|||
}
|
||||
|
||||
if ($options['expanded']) {
|
||||
$this->addSubFields($builder, $options['choice_list']->getPreferredViews(), $options);
|
||||
$this->addSubFields($builder, $options['choice_list']->getRemainingViews(), $options);
|
||||
$this->addSubForms($builder, $options['choice_list']->getPreferredViews(), $options);
|
||||
$this->addSubForms($builder, $options['choice_list']->getRemainingViews(), $options);
|
||||
}
|
||||
|
||||
// empty value
|
||||
|
@ -182,7 +182,7 @@ class ChoiceType extends AbstractType
|
|||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return isset($options['expanded']) && $options['expanded'] ? 'form' : 'field';
|
||||
return 'field';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,12 +200,12 @@ class ChoiceType extends AbstractType
|
|||
* @param array $choiceViews The choice view objects.
|
||||
* @param array $options The build options.
|
||||
*/
|
||||
private function addSubFields(FormBuilder $builder, array $choiceViews, array $options)
|
||||
private function addSubForms(FormBuilder $builder, array $choiceViews, array $options)
|
||||
{
|
||||
foreach ($choiceViews as $i => $choiceView) {
|
||||
if (is_array($choiceView)) {
|
||||
// Flatten groups
|
||||
$this->addSubFields($builder, $choiceView, $options);
|
||||
$this->addSubForms($builder, $choiceView, $options);
|
||||
} else {
|
||||
$choiceOpts = array(
|
||||
'value' => $choiceView->getValue(),
|
||||
|
|
|
@ -153,7 +153,7 @@ class DateTimeType extends AbstractType
|
|||
'widget' => null,
|
||||
// This will overwrite "empty_value" child options
|
||||
'empty_value' => null,
|
||||
// If initialized with a \DateTime object, FieldType initializes
|
||||
// If initialized with a \DateTime object, FormType initializes
|
||||
// this option to "\DateTime". Since the internal, normalized
|
||||
// representation is not \DateTime, but an array, we need to unset
|
||||
// this option.
|
||||
|
@ -200,7 +200,7 @@ class DateTimeType extends AbstractType
|
|||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
||||
return 'field';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -177,7 +177,7 @@ class DateType extends AbstractType
|
|||
// them like immutable value objects
|
||||
'by_reference' => false,
|
||||
'error_bubbling' => false,
|
||||
// If initialized with a \DateTime object, FieldType initializes
|
||||
// If initialized with a \DateTime object, FormType initializes
|
||||
// this option to "\DateTime". Since the internal, normalized
|
||||
// representation is not \DateTime, but an array, we need to unset
|
||||
// this option.
|
||||
|
@ -210,7 +210,7 @@ class DateType extends AbstractType
|
|||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
||||
return 'field';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,179 +23,15 @@ use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener;
|
|||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
|
||||
/**
|
||||
* Deprecated. You should extend FormType instead.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
|
||||
*/
|
||||
class FieldType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
if (null === $options['property_path']) {
|
||||
$options['property_path'] = $builder->getName();
|
||||
}
|
||||
|
||||
if (false === $options['property_path'] || '' === $options['property_path']) {
|
||||
$options['property_path'] = null;
|
||||
} else {
|
||||
$options['property_path'] = new PropertyPath($options['property_path']);
|
||||
}
|
||||
if (!is_array($options['attr'])) {
|
||||
throw new FormException('The "attr" option must be "array".');
|
||||
}
|
||||
|
||||
$builder
|
||||
->setRequired($options['required'])
|
||||
->setDisabled($options['disabled'])
|
||||
->setErrorBubbling($options['error_bubbling'])
|
||||
->setEmptyData($options['empty_data'])
|
||||
->setAttribute('read_only', $options['read_only'])
|
||||
->setAttribute('by_reference', $options['by_reference'])
|
||||
->setAttribute('property_path', $options['property_path'])
|
||||
->setAttribute('error_mapping', $options['error_mapping'])
|
||||
->setAttribute('max_length', $options['max_length'])
|
||||
->setAttribute('pattern', $options['pattern'])
|
||||
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))
|
||||
->setAttribute('attr', $options['attr'] ?: array())
|
||||
->setAttribute('invalid_message', $options['invalid_message'])
|
||||
->setAttribute('invalid_message_parameters', $options['invalid_message_parameters'])
|
||||
->setAttribute('translation_domain', $options['translation_domain'])
|
||||
->setData($options['data'])
|
||||
->addEventSubscriber(new ValidationListener())
|
||||
;
|
||||
|
||||
if ($options['trim']) {
|
||||
$builder->addEventSubscriber(new TrimListener());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildView(FormView $view, FormInterface $form)
|
||||
{
|
||||
$name = $form->getName();
|
||||
$readOnly = $form->getAttribute('read_only');
|
||||
|
||||
if ($view->hasParent()) {
|
||||
if ('' === $name) {
|
||||
throw new FormException('Form node with empty name can be used only as root form node.');
|
||||
}
|
||||
|
||||
if ('' !== ($parentFullName = $view->getParent()->get('full_name'))) {
|
||||
$id = sprintf('%s_%s', $view->getParent()->get('id'), $name);
|
||||
$fullName = sprintf('%s[%s]', $parentFullName, $name);
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
}
|
||||
|
||||
// Complex fields are read-only if themselves or their parent is.
|
||||
$readOnly = $readOnly || $view->getParent()->get('read_only');
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
|
||||
// Strip leading underscores and digits. These are allowed in
|
||||
// form names, but not in HTML4 ID attributes.
|
||||
// http://www.w3.org/TR/html401/struct/global.html#adef-id
|
||||
$id = ltrim($id, '_0123456789');
|
||||
}
|
||||
|
||||
$types = array();
|
||||
foreach ($form->getTypes() as $type) {
|
||||
$types[] = $type->getName();
|
||||
}
|
||||
|
||||
$view
|
||||
->set('form', $view)
|
||||
->set('id', $id)
|
||||
->set('name', $name)
|
||||
->set('full_name', $fullName)
|
||||
->set('read_only', $readOnly)
|
||||
->set('errors', $form->getErrors())
|
||||
->set('value', $form->getClientData())
|
||||
->set('disabled', $form->isDisabled())
|
||||
->set('required', $form->isRequired())
|
||||
->set('max_length', $form->getAttribute('max_length'))
|
||||
->set('pattern', $form->getAttribute('pattern'))
|
||||
->set('size', null)
|
||||
->set('label', $form->getAttribute('label'))
|
||||
->set('multipart', false)
|
||||
->set('attr', $form->getAttribute('attr'))
|
||||
->set('types', $types)
|
||||
->set('translation_domain', $form->getAttribute('translation_domain'))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOptions()
|
||||
{
|
||||
// Derive "data_class" option from passed "data" object
|
||||
$dataClass = function (Options $options) {
|
||||
if (is_object($options['data'])) {
|
||||
return get_class($options['data']);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Derive "empty_data" closure from "data_class" option
|
||||
$emptyData = function (Options $options) {
|
||||
$class = $options['data_class'];
|
||||
|
||||
if (null !== $class) {
|
||||
return function (FormInterface $form) use ($class) {
|
||||
if ($form->isEmpty() && !$form->isRequired()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $class();
|
||||
};
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
return array(
|
||||
'data' => null,
|
||||
'data_class' => $dataClass,
|
||||
'empty_data' => $emptyData,
|
||||
'trim' => true,
|
||||
'required' => true,
|
||||
'read_only' => false,
|
||||
'disabled' => false,
|
||||
'max_length' => null,
|
||||
'pattern' => null,
|
||||
'property_path' => null,
|
||||
'by_reference' => true,
|
||||
'error_bubbling' => false,
|
||||
'error_mapping' => array(),
|
||||
'label' => null,
|
||||
'attr' => array(),
|
||||
'invalid_message' => 'This value is not valid',
|
||||
'invalid_message_parameters' => array(),
|
||||
'translation_domain' => 'messages',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createBuilder($name, FormFactoryInterface $factory, array $options)
|
||||
{
|
||||
return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -203,9 +39,4 @@ class FieldType extends AbstractType
|
|||
{
|
||||
return 'field';
|
||||
}
|
||||
|
||||
private function humanize($text)
|
||||
{
|
||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,24 @@ class FileType extends AbstractType
|
|||
public function buildView(FormView $view, FormInterface $form)
|
||||
{
|
||||
$view
|
||||
->set('multipart', true)
|
||||
->set('type', 'file')
|
||||
->set('value', '')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildViewBottomUp(FormView $view, FormInterface $form)
|
||||
{
|
||||
$view
|
||||
->set('multipart', true)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return 'field';
|
||||
|
|
|
@ -13,10 +13,16 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
|||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Options;
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\ValidationListener;
|
||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
|
||||
class FormType extends AbstractType
|
||||
{
|
||||
|
@ -25,9 +31,102 @@ class FormType extends AbstractType
|
|||
*/
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
if (null === $options['property_path']) {
|
||||
$options['property_path'] = $builder->getName();
|
||||
}
|
||||
|
||||
if (false === $options['property_path'] || '' === $options['property_path']) {
|
||||
$options['property_path'] = null;
|
||||
} else {
|
||||
$options['property_path'] = new PropertyPath($options['property_path']);
|
||||
}
|
||||
if (!is_array($options['attr'])) {
|
||||
throw new FormException('The "attr" option must be "array".');
|
||||
}
|
||||
|
||||
$builder
|
||||
->setRequired($options['required'])
|
||||
->setDisabled($options['disabled'])
|
||||
->setErrorBubbling($options['error_bubbling'])
|
||||
->setEmptyData($options['empty_data'])
|
||||
->setAttribute('read_only', $options['read_only'])
|
||||
->setAttribute('by_reference', $options['by_reference'])
|
||||
->setAttribute('property_path', $options['property_path'])
|
||||
->setAttribute('error_mapping', $options['error_mapping'])
|
||||
->setAttribute('max_length', $options['max_length'])
|
||||
->setAttribute('pattern', $options['pattern'])
|
||||
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))
|
||||
->setAttribute('attr', $options['attr'] ?: array())
|
||||
->setAttribute('invalid_message', $options['invalid_message'])
|
||||
->setAttribute('invalid_message_parameters', $options['invalid_message_parameters'])
|
||||
->setAttribute('translation_domain', $options['translation_domain'])
|
||||
->setAttribute('virtual', $options['virtual'])
|
||||
->setData($options['data'])
|
||||
->setDataMapper(new PropertyPathMapper($options['data_class']))
|
||||
->addEventSubscriber(new ValidationListener())
|
||||
;
|
||||
|
||||
if ($options['trim']) {
|
||||
$builder->addEventSubscriber(new TrimListener());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildView(FormView $view, FormInterface $form)
|
||||
{
|
||||
$name = $form->getName();
|
||||
$readOnly = $form->getAttribute('read_only');
|
||||
|
||||
if ($view->hasParent()) {
|
||||
if ('' === $name) {
|
||||
throw new FormException('Form node with empty name can be used only as root form node.');
|
||||
}
|
||||
|
||||
if ('' !== ($parentFullName = $view->getParent()->get('full_name'))) {
|
||||
$id = sprintf('%s_%s', $view->getParent()->get('id'), $name);
|
||||
$fullName = sprintf('%s[%s]', $parentFullName, $name);
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
}
|
||||
|
||||
// Complex fields are read-only if themselves or their parent is.
|
||||
$readOnly = $readOnly || $view->getParent()->get('read_only');
|
||||
} else {
|
||||
$id = $name;
|
||||
$fullName = $name;
|
||||
|
||||
// Strip leading underscores and digits. These are allowed in
|
||||
// form names, but not in HTML4 ID attributes.
|
||||
// http://www.w3.org/TR/html401/struct/global.html#adef-id
|
||||
$id = ltrim($id, '_0123456789');
|
||||
}
|
||||
|
||||
$types = array();
|
||||
foreach ($form->getTypes() as $type) {
|
||||
$types[] = $type->getName();
|
||||
}
|
||||
|
||||
$view
|
||||
->set('form', $view)
|
||||
->set('id', $id)
|
||||
->set('name', $name)
|
||||
->set('full_name', $fullName)
|
||||
->set('read_only', $readOnly)
|
||||
->set('errors', $form->getErrors())
|
||||
->set('value', $form->getClientData())
|
||||
->set('disabled', $form->isDisabled())
|
||||
->set('required', $form->isRequired())
|
||||
->set('max_length', $form->getAttribute('max_length'))
|
||||
->set('pattern', $form->getAttribute('pattern'))
|
||||
->set('size', null)
|
||||
->set('label', $form->getAttribute('label'))
|
||||
->set('multipart', false)
|
||||
->set('attr', $form->getAttribute('attr'))
|
||||
->set('types', $types)
|
||||
->set('translation_domain', $form->getAttribute('translation_domain'))
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -53,29 +152,75 @@ class FormType extends AbstractType
|
|||
*/
|
||||
public function getDefaultOptions()
|
||||
{
|
||||
$emptyData = function (Options $options, $currentValue) {
|
||||
if (empty($options['data_class'])) {
|
||||
return array();
|
||||
// Derive "data_class" option from passed "data" object
|
||||
$dataClass = function (Options $options) {
|
||||
if (is_object($options['data'])) {
|
||||
return get_class($options['data']);
|
||||
}
|
||||
|
||||
return $currentValue;
|
||||
return null;
|
||||
};
|
||||
|
||||
// Derive "empty_data" closure from "data_class" option
|
||||
$emptyData = function (Options $options) {
|
||||
$class = $options['data_class'];
|
||||
|
||||
if (null !== $class) {
|
||||
return function (FormInterface $form) use ($class) {
|
||||
if ($form->isEmpty() && !$form->isRequired()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $class();
|
||||
};
|
||||
}
|
||||
|
||||
return function (FormInterface $form) {
|
||||
if ($form->hasChildren()) {
|
||||
return array();
|
||||
}
|
||||
};
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
return array(
|
||||
'data' => null,
|
||||
'data_class' => $dataClass,
|
||||
'empty_data' => $emptyData,
|
||||
'trim' => true,
|
||||
'required' => true,
|
||||
'read_only' => false,
|
||||
'disabled' => false,
|
||||
'max_length' => null,
|
||||
'pattern' => null,
|
||||
'property_path' => null,
|
||||
'by_reference' => true,
|
||||
'error_bubbling' => false,
|
||||
'error_mapping' => array(),
|
||||
'label' => null,
|
||||
'attr' => array(),
|
||||
'virtual' => false,
|
||||
// Errors in forms bubble by default, so that form errors will
|
||||
// end up as global errors in the root form
|
||||
'error_bubbling' => true,
|
||||
'invalid_message' => 'This value is not valid',
|
||||
'invalid_message_parameters' => array(),
|
||||
'translation_domain' => 'messages',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createBuilder($name, FormFactoryInterface $factory, array $options)
|
||||
{
|
||||
return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return 'field';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,4 +230,9 @@ class FormType extends AbstractType
|
|||
{
|
||||
return 'form';
|
||||
}
|
||||
|
||||
private function humanize($text)
|
||||
{
|
||||
return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ class TimeType extends AbstractType
|
|||
// them like immutable value objects
|
||||
'by_reference' => false,
|
||||
'error_bubbling' => false,
|
||||
// If initialized with a \DateTime object, FieldType initializes
|
||||
// If initialized with a \DateTime object, FormType initializes
|
||||
// this option to "\DateTime". Since the internal, normalized
|
||||
// representation is not \DateTime, but an array, we need to unset
|
||||
// this option.
|
||||
|
@ -183,7 +183,7 @@ class TimeType extends AbstractType
|
|||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return isset($options['widget']) && 'single_text' === $options['widget'] ? 'field' : 'form';
|
||||
return 'field';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,7 @@ use Symfony\Component\Validator\ValidatorInterface;
|
|||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class FieldTypeValidatorExtension extends AbstractTypeExtension
|
||||
class FormTypeValidatorExtension extends AbstractTypeExtension
|
||||
{
|
||||
private $validator;
|
||||
|
||||
|
@ -57,6 +57,6 @@ class FieldTypeValidatorExtension extends AbstractTypeExtension
|
|||
|
||||
public function getExtendedType()
|
||||
{
|
||||
return 'field';
|
||||
return 'form';
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ class ValidatorExtension extends AbstractExtension
|
|||
protected function loadTypeExtensions()
|
||||
{
|
||||
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 $normTransformers = array(),
|
||||
DataMapperInterface $dataMapper = null, array $validators = array(),
|
||||
$required = false, $disabled = false, $errorBubbling = false,
|
||||
$required = false, $disabled = false, $errorBubbling = null,
|
||||
$emptyData = null, array $attributes = array())
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
@ -225,7 +225,10 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
$this->validators = $validators;
|
||||
$this->required = (Boolean) $required;
|
||||
$this->disabled = (Boolean) $disabled;
|
||||
$this->errorBubbling = (Boolean) $errorBubbling;
|
||||
// NULL is the default meaning:
|
||||
// bubble up if the form has children (complex forms)
|
||||
// don't bubble up if the form has no children (primitive fields)
|
||||
$this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling;
|
||||
$this->emptyData = $emptyData;
|
||||
$this->attributes = $attributes;
|
||||
|
||||
|
@ -312,9 +315,9 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the parent field.
|
||||
* Returns the parent form.
|
||||
*
|
||||
* @return FormInterface The parent field
|
||||
* @return FormInterface The parent form
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
|
@ -342,7 +345,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns whether the field is the root of the form tree.
|
||||
* Returns whether the form is the root of the form tree.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
|
@ -374,7 +377,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates the field with default data.
|
||||
* Updates the form with default data.
|
||||
*
|
||||
* @param array $appData The data formatted as expected for the underlying object
|
||||
*
|
||||
|
@ -408,7 +411,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
$this->clientData = $clientData;
|
||||
$this->synchronized = true;
|
||||
|
||||
if ($this->dataMapper) {
|
||||
if (count($this->children) > 0 && $this->dataMapper) {
|
||||
// Update child forms from the data
|
||||
$this->dataMapper->mapDataToForms($clientData, $this->children);
|
||||
}
|
||||
|
@ -450,7 +453,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Binds data to the field, transforms and validates it.
|
||||
* Binds data to the form, transforms and validates it.
|
||||
*
|
||||
* @param string|array $clientData The data
|
||||
*
|
||||
|
@ -626,11 +629,11 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized data of the field.
|
||||
* Returns the normalized data of the form.
|
||||
*
|
||||
* @return mixed When the field is not bound, the default data is returned.
|
||||
* When the field is bound, the normalized bound data is
|
||||
* returned if the field is valid, null otherwise.
|
||||
* @return mixed When the form is not bound, the default data is returned.
|
||||
* When the form is bound, the normalized bound data is
|
||||
* returned if the form is valid, null otherwise.
|
||||
*/
|
||||
public function getNormData()
|
||||
{
|
||||
|
@ -646,7 +649,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
*/
|
||||
public function addError(FormError $error)
|
||||
{
|
||||
if ($this->parent && $this->errorBubbling) {
|
||||
if ($this->parent && $this->getErrorBubbling()) {
|
||||
$this->parent->addError($error);
|
||||
} else {
|
||||
$this->errors[] = $error;
|
||||
|
@ -662,11 +665,11 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
*/
|
||||
public function getErrorBubbling()
|
||||
{
|
||||
return $this->errorBubbling;
|
||||
return null === $this->errorBubbling ? $this->hasChildren() : $this->errorBubbling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the field is bound.
|
||||
* Returns whether the form is bound.
|
||||
*
|
||||
* @return Boolean true if the form is bound to input values, false otherwise
|
||||
*/
|
||||
|
@ -702,7 +705,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns whether the field is valid.
|
||||
* Returns whether the form is valid.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
|
@ -735,9 +738,8 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
public function hasErrors()
|
||||
{
|
||||
// Don't call isValid() here, as its semantics are slightly different
|
||||
// Field groups are not valid if their children are invalid, but
|
||||
// hasErrors() returns only true if a field/field group itself has
|
||||
// errors
|
||||
// Forms are not valid if their children are invalid, but
|
||||
// hasErrors() returns only true if a form itself has errors
|
||||
return count($this->errors) > 0;
|
||||
}
|
||||
|
||||
|
@ -894,7 +896,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||
return $this->children[$name];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Field "%s" does not exist.', $name));
|
||||
throw new \InvalidArgumentException(sprintf('Child "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -106,7 +106,7 @@ class FormBuilder
|
|||
* Whether added errors should bubble up to the parent
|
||||
* @var Boolean
|
||||
*/
|
||||
private $errorBubbling = false;
|
||||
private $errorBubbling;
|
||||
|
||||
/**
|
||||
* Data used for the client data when no value is bound
|
||||
|
@ -243,7 +243,7 @@ class FormBuilder
|
|||
*/
|
||||
public function setErrorBubbling($errorBubbling)
|
||||
{
|
||||
$this->errorBubbling = (Boolean) $errorBubbling;
|
||||
$this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
|||
* The content of a disabled form is displayed, but not allowed to be
|
||||
* modified. The validation of modified disabled forms should fail.
|
||||
*
|
||||
* Fields whose parents are disabled are considered disabled regardless of
|
||||
* Forms whose parents are disabled are considered disabled regardless of
|
||||
* their own state.
|
||||
*
|
||||
* @return Boolean
|
||||
|
|
|
@ -75,7 +75,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface
|
|||
* @param \Closure $closure The closure to execute. Accepts a guesser
|
||||
* as argument and should return a Guess instance
|
||||
*
|
||||
* @return FieldFactoryGuess The guess with the highest confidence
|
||||
* @return Guess The guess with the highest confidence
|
||||
*/
|
||||
private function guess(\Closure $closure)
|
||||
{
|
||||
|
|
|
@ -202,7 +202,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||
);
|
||||
}
|
||||
|
||||
public function testRestAndRepeatedWithRowPerField()
|
||||
public function testRestAndRepeatedWithRowPerChild()
|
||||
{
|
||||
$view = $this->factory->createNamedBuilder('form', 'name')
|
||||
->add('first', 'text')
|
||||
|
@ -230,7 +230,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||
);
|
||||
}
|
||||
|
||||
public function testRestAndRepeatedWithWidgetPerField()
|
||||
public function testRestAndRepeatedWithWidgetPerChild()
|
||||
{
|
||||
$view = $this->factory->createNamedBuilder('form', 'name')
|
||||
->add('first', 'text')
|
||||
|
@ -348,7 +348,10 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||
public function testNestedFormError()
|
||||
{
|
||||
$form = $this->factory->createNamedBuilder('form', 'name')
|
||||
->add('child', 'form', array('error_bubbling' => false))
|
||||
->add($this->factory
|
||||
->createNamedBuilder('form', 'child', null, array('error_bubbling' => false))
|
||||
->add('grandChild', 'form')
|
||||
)
|
||||
->getForm();
|
||||
|
||||
$form->get('child')->addError(new FormError('Error!'));
|
||||
|
|
|
@ -210,7 +210,10 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||
public function testNestedFormError()
|
||||
{
|
||||
$form = $this->factory->createNamedBuilder('form', 'name')
|
||||
->add('child', 'form', array('error_bubbling' => false))
|
||||
->add($this->factory
|
||||
->createNamedBuilder('form', 'child', null, array('error_bubbling' => false))
|
||||
->add('grandChild', 'form')
|
||||
)
|
||||
->getForm();
|
||||
|
||||
$form->get('child')->addError(new FormError('Error!'));
|
||||
|
|
|
@ -98,7 +98,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
));
|
||||
}
|
||||
|
||||
public function testExpandedChoicesOptionsTurnIntoFields()
|
||||
public function testExpandedChoicesOptionsTurnIntoChildren()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'expanded' => true,
|
||||
|
@ -141,7 +141,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
}
|
||||
}
|
||||
|
||||
public function testExpandedRadiosAreRequiredIfChoiceFieldIsRequired()
|
||||
public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
|
@ -155,7 +155,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
}
|
||||
}
|
||||
|
||||
public function testExpandedRadiosAreNotRequiredIfChoiceFieldIsNotRequired()
|
||||
public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
|
@ -288,7 +288,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedWithFalseDoesNotHaveExtraFields()
|
||||
public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
|
@ -302,7 +302,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
$this->assertNull($form->getData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedWithEmptyField()
|
||||
public function testBindSingleExpandedWithEmptyChild()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
|
@ -422,7 +422,7 @@ class ChoiceTypeTest extends TypeTestCase
|
|||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleExpandedWithEmptyField()
|
||||
public function testBindMultipleExpandedWithEmptyChild()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => true,
|
||||
|
|
|
@ -15,10 +15,10 @@ use Symfony\Component\Form\Form;
|
|||
|
||||
class CollectionTypeTest extends TypeTestCase
|
||||
{
|
||||
public function testContainsNoFieldByDefault()
|
||||
public function testContainsNoChildByDefault()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
|
||||
$this->assertCount(0, $form);
|
||||
|
@ -27,7 +27,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testSetDataAdjustsSize()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'options' => array(
|
||||
'max_length' => 20,
|
||||
),
|
||||
|
@ -53,7 +53,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testThrowsExceptionIfObjectIsNotTraversable()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
$this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException');
|
||||
$form->setData(new \stdClass());
|
||||
|
@ -62,7 +62,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testNotResizedIfBoundWithMissingData()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||
$form->bind(array('foo@bar.com'));
|
||||
|
@ -76,7 +76,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testResizedDownIfBoundWithMissingDataAndAllowDelete()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'allow_delete' => true,
|
||||
));
|
||||
$form->setData(array('foo@foo.com', 'bar@bar.com'));
|
||||
|
@ -91,7 +91,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testNotResizedIfBoundWithExtraData()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
$form->bind(array('foo@foo.com', 'bar@bar.com'));
|
||||
|
@ -104,7 +104,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testResizedUpIfBoundWithExtraDataAndAllowAdd()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'allow_add' => true,
|
||||
));
|
||||
$form->setData(array('foo@bar.com'));
|
||||
|
@ -120,7 +120,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testAllowAddButNoPrototype()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'allow_add' => true,
|
||||
'prototype' => false,
|
||||
));
|
||||
|
@ -169,7 +169,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
public function testPrototypeNameOption()
|
||||
{
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'prototype' => true,
|
||||
'allow_add' => true,
|
||||
));
|
||||
|
@ -177,7 +177,7 @@ class CollectionTypeTest extends TypeTestCase
|
|||
$this->assertSame('__name__', $form->getAttribute('prototype')->getName(), '__name__ is the default');
|
||||
|
||||
$form = $this->factory->create('collection', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'prototype' => true,
|
||||
'allow_add' => true,
|
||||
'prototype_name' => '__test__',
|
||||
|
|
|
@ -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;
|
||||
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\Form\Tests\Fixtures\Author;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
|
||||
|
||||
class FormTest_AuthorWithoutRefSetter
|
||||
{
|
||||
|
@ -49,13 +51,372 @@ class FormTest_AuthorWithoutRefSetter
|
|||
|
||||
class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
public function testGetPropertyPathDefaultPath()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', 'title');
|
||||
|
||||
$this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsZero()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => '0'));
|
||||
|
||||
$this->assertEquals(new PropertyPath('0'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsEmpty()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => ''));
|
||||
|
||||
$this->assertNull($form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsFalse()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => false));
|
||||
|
||||
$this->assertNull($form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsNull()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', 'title', null, array('property_path' => null));
|
||||
|
||||
$this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testPassRequiredAsOption()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('required' => false));
|
||||
|
||||
$this->assertFalse($form->isRequired());
|
||||
|
||||
$form = $this->factory->create('form', null, array('required' => true));
|
||||
|
||||
$this->assertTrue($form->isRequired());
|
||||
}
|
||||
|
||||
public function testPassDisabledAsOption()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('disabled' => true));
|
||||
|
||||
$this->assertTrue($form->isDisabled());
|
||||
}
|
||||
|
||||
public function testBoundDataIsTrimmedBeforeTransforming()
|
||||
{
|
||||
$form = $this->factory->createBuilder('form')
|
||||
->appendClientTransformer(new FixedDataTransformer(array(
|
||||
null => '',
|
||||
'reverse[a]' => 'a',
|
||||
)))
|
||||
->getForm();
|
||||
|
||||
$form->bind(' a ');
|
||||
|
||||
$this->assertEquals('a', $form->getClientData());
|
||||
$this->assertEquals('reverse[a]', $form->getData());
|
||||
}
|
||||
|
||||
public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming()
|
||||
{
|
||||
$form = $this->factory->createBuilder('form', null, array('trim' => false))
|
||||
->appendClientTransformer(new FixedDataTransformer(array(
|
||||
null => '',
|
||||
'reverse[ a ]' => ' a ',
|
||||
)))
|
||||
->getForm();
|
||||
|
||||
$form->bind(' a ');
|
||||
|
||||
$this->assertEquals(' a ', $form->getClientData());
|
||||
$this->assertEquals('reverse[ a ]', $form->getData());
|
||||
}
|
||||
|
||||
public function testPassIdAndNameToView()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', 'name');
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals('name', $view->get('id'));
|
||||
$this->assertEquals('name', $view->get('name'));
|
||||
$this->assertEquals('name', $view->get('full_name'));
|
||||
}
|
||||
|
||||
public function testStripLeadingUnderscoresAndDigitsFromId()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', '_09name');
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals('name', $view->get('id'));
|
||||
$this->assertEquals('_09name', $view->get('name'));
|
||||
$this->assertEquals('_09name', $view->get('full_name'));
|
||||
}
|
||||
|
||||
public function testPassIdAndNameToViewWithParent()
|
||||
{
|
||||
$parent = $this->factory->createNamed('form', 'parent');
|
||||
$parent->add($this->factory->createNamed('form', 'child'));
|
||||
$view = $parent->createView();
|
||||
|
||||
$this->assertEquals('parent_child', $view['child']->get('id'));
|
||||
$this->assertEquals('child', $view['child']->get('name'));
|
||||
$this->assertEquals('parent[child]', $view['child']->get('full_name'));
|
||||
}
|
||||
|
||||
public function testPassIdAndNameToViewWithGrandParent()
|
||||
{
|
||||
$parent = $this->factory->createNamed('form', 'parent');
|
||||
$parent->add($this->factory->createNamed('form', 'child'));
|
||||
$parent['child']->add($this->factory->createNamed('form', 'grand_child'));
|
||||
$view = $parent->createView();
|
||||
|
||||
$this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->get('id'));
|
||||
$this->assertEquals('grand_child', $view['child']['grand_child']->get('name'));
|
||||
$this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->get('full_name'));
|
||||
}
|
||||
|
||||
public function testNonReadOnlyFormWithReadOnlyParentBeingReadOnly()
|
||||
{
|
||||
$parent = $this->factory->createNamed('form', 'parent', null, array('read_only' => true));
|
||||
$child = $this->factory->createNamed('form', 'child');
|
||||
$view = $parent->add($child)->createView();
|
||||
|
||||
$this->assertTrue($view['child']->get('read_only'));
|
||||
}
|
||||
|
||||
public function testReadOnlyFormWithNonReadOnlyParentBeingReadOnly()
|
||||
{
|
||||
$parent = $this->factory->createNamed('form', 'parent');
|
||||
$child = $this->factory->createNamed('form', 'child', null, array('read_only' => true));
|
||||
$view = $parent->add($child)->createView();
|
||||
|
||||
$this->assertTrue($view['child']->get('read_only'));
|
||||
}
|
||||
|
||||
public function testNonReadOnlyFormWithNonReadOnlyParentBeingNonReadOnly()
|
||||
{
|
||||
$parent = $this->factory->createNamed('form', 'parent');
|
||||
$child = $this->factory->createNamed('form', 'child');
|
||||
$view = $parent->add($child)->createView();
|
||||
|
||||
$this->assertFalse($view['child']->get('read_only'));
|
||||
}
|
||||
|
||||
public function testPassMaxLengthToView()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('max_length' => 10));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame(10, $view->get('max_length'));
|
||||
}
|
||||
|
||||
public function testPassTranslationDomainToView()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('translation_domain' => 'test'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame('test', $view->get('translation_domain'));
|
||||
}
|
||||
|
||||
public function testPassDefaultLabelToView()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', '__test___field');
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame('Test field', $view->get('label'));
|
||||
}
|
||||
|
||||
public function testPassLabelToView()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', '__test___field', null, array('label' => 'My label'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame('My label', $view->get('label'));
|
||||
}
|
||||
|
||||
public function testDefaultTranslationDomain()
|
||||
{
|
||||
$form = $this->factory->create('form');
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame('messages', $view->get('translation_domain'));
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataCreatesObjectIfClassAvailable()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
$form->add($this->factory->createNamed('form', 'lastName'));
|
||||
|
||||
$form->setData(null);
|
||||
// partially empty, still an object is created
|
||||
$form->bind(array('firstName' => 'Bernhard', 'lastName' => ''));
|
||||
|
||||
$author = new Author();
|
||||
$author->firstName = 'Bernhard';
|
||||
$author->setLastName('');
|
||||
|
||||
$this->assertEquals($author, $form->getData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
// data class is inferred from the passed object
|
||||
'data' => new Author(),
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
$form->add($this->factory->createNamed('form', 'lastName'));
|
||||
|
||||
$form->setData(null);
|
||||
// partially empty, still an object is created
|
||||
$form->bind(array('firstName' => 'Bernhard', 'lastName' => ''));
|
||||
|
||||
$author = new Author();
|
||||
$author->firstName = 'Bernhard';
|
||||
$author->setLastName('');
|
||||
|
||||
$this->assertEquals($author, $form->getData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataDoesNotCreateObjectIfDataClassIsNull()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data' => new Author(),
|
||||
'data_class' => null,
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
|
||||
$this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
|
||||
}
|
||||
|
||||
public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => false,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
$form->add($this->factory->createNamed('form', 'lastName'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => '', 'lastName' => ''));
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
}
|
||||
|
||||
public function testBindEmptyWithEmptyDataCreatesObjectIfRequired()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'required' => true,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
$form->add($this->factory->createNamed('form', 'lastName'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => '', 'lastName' => ''));
|
||||
|
||||
$this->assertEquals(new Author(), $form->getData());
|
||||
}
|
||||
|
||||
/*
|
||||
* We need something to write the field values into
|
||||
*/
|
||||
public function testBindWithEmptyDataStoresArrayIfNoClassAvailable()
|
||||
{
|
||||
$form = $this->factory->create('form');
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
|
||||
$form->setData(null);
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
|
||||
$this->assertSame(array('firstName' => 'Bernhard'), $form->getData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataUsesEmptyDataOption()
|
||||
{
|
||||
$author = new Author();
|
||||
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'empty_data' => $author,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
|
||||
$form->bind(array('firstName' => 'Bernhard'));
|
||||
|
||||
$this->assertSame($author, $form->getData());
|
||||
$this->assertEquals('Bernhard', $author->firstName);
|
||||
}
|
||||
|
||||
public function testGetAttributesIsEmpty()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('attr' => array()));
|
||||
|
||||
$this->assertCount(0, $form->getAttribute('attr'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/symfony/symfony/issues/1986
|
||||
*/
|
||||
public function testSetDataThroughParamsWithZero()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('data' => 0));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('0', $view->get('value'));
|
||||
$this->assertSame('0', $form->getData());
|
||||
|
||||
$form = $this->factory->create('form', null, array('data' => '0'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('0', $view->get('value'));
|
||||
$this->assertSame('0', $form->getData());
|
||||
|
||||
$form = $this->factory->create('form', null, array('data' => '00000'));
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertFalse($form->isEmpty());
|
||||
|
||||
$this->assertSame('00000', $view->get('value'));
|
||||
$this->assertSame('00000', $form->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testAttributesException()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('attr' => ''));
|
||||
}
|
||||
|
||||
public function testNameCanBeEmptyString()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', '');
|
||||
|
||||
$this->assertEquals('', $form->getName());
|
||||
}
|
||||
public function testSubformDoesntCallSetters()
|
||||
{
|
||||
$author = new FormTest_AuthorWithoutRefSetter(new Author());
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('reference', 'form');
|
||||
$builder->get('reference')->add('firstName', 'field');
|
||||
$builder->get('reference')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
|
@ -77,7 +438,7 @@ class FormTypeTest extends TypeTestCase
|
|||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('referenceCopy', 'form');
|
||||
$builder->get('referenceCopy')->add('firstName', 'field');
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
|
@ -99,7 +460,7 @@ class FormTypeTest extends TypeTestCase
|
|||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('referenceCopy', 'form', array('by_reference' => false));
|
||||
$builder->get('referenceCopy')->add('firstName', 'field');
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class RepeatedTypeTest extends TypeTestCase
|
|||
parent::setUp();
|
||||
|
||||
$this->form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
$this->form->setData(null);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class RepeatedTypeTest extends TypeTestCase
|
|||
public function testSetOptions()
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'options' => array('label' => 'Global'),
|
||||
));
|
||||
|
||||
|
@ -47,11 +47,11 @@ class RepeatedTypeTest extends TypeTestCase
|
|||
$this->assertTrue($form['second']->isRequired());
|
||||
}
|
||||
|
||||
public function testSetOptionsPerField()
|
||||
public function testSetOptionsPerChild()
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
// the global required value cannot be overriden
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'first_options' => array('label' => 'Test', 'required' => false),
|
||||
'second_options' => array('label' => 'Test2')
|
||||
));
|
||||
|
@ -66,17 +66,17 @@ class RepeatedTypeTest extends TypeTestCase
|
|||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'required' => false,
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
));
|
||||
|
||||
$this->assertFalse($form['first']->isRequired());
|
||||
$this->assertFalse($form['second']->isRequired());
|
||||
}
|
||||
|
||||
public function testSetOptionsPerFieldAndOverwrite()
|
||||
public function testSetOptionsPerChildAndOverwrite()
|
||||
{
|
||||
$form = $this->factory->create('repeated', null, array(
|
||||
'type' => 'field',
|
||||
'type' => 'form',
|
||||
'options' => array('label' => 'Label'),
|
||||
'second_options' => array('label' => 'Second label')
|
||||
));
|
||||
|
|
|
@ -93,6 +93,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
|||
$builder = new FormBuilder($name, $this->factory, $this->dispatcher);
|
||||
$builder->setAttribute('property_path', new PropertyPath($propertyPath ?: $name));
|
||||
$builder->setAttribute('error_mapping', array());
|
||||
$builder->setErrorBubbling(false);
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
|
|
@ -13,18 +13,18 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type;
|
|||
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
|
||||
class FieldTypeValidatorExtensionTest extends TypeTestCase
|
||||
class FormTypeValidatorExtensionTest extends TypeTestCase
|
||||
{
|
||||
public function testValidationGroupNullByDefault()
|
||||
{
|
||||
$form = $this->factory->create('field');
|
||||
$form = $this->factory->create('form');
|
||||
|
||||
$this->assertNull($form->getAttribute('validation_groups'));
|
||||
}
|
||||
|
||||
public function testValidationGroupsCanBeSetToString()
|
||||
{
|
||||
$form = $this->factory->create('field', null, array(
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'validation_groups' => 'group',
|
||||
));
|
||||
|
||||
|
@ -33,7 +33,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||
|
||||
public function testValidationGroupsCanBeSetToArray()
|
||||
{
|
||||
$form = $this->factory->create('field', null, array(
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'validation_groups' => array('group1', 'group2'),
|
||||
));
|
||||
|
||||
|
@ -42,7 +42,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||
|
||||
public function testValidationGroupsCanBeSetToCallback()
|
||||
{
|
||||
$form = $this->factory->create('field', null, array(
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'),
|
||||
));
|
||||
|
||||
|
@ -51,7 +51,7 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||
|
||||
public function testValidationGroupsCanBeSetToClosure()
|
||||
{
|
||||
$form = $this->factory->create('field', null, array(
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'validation_groups' => function(FormInterface $form){ return null; },
|
||||
));
|
||||
|
||||
|
@ -60,10 +60,10 @@ class FieldTypeValidatorExtensionTest extends TypeTestCase
|
|||
|
||||
public function testBindValidatesData()
|
||||
{
|
||||
$builder = $this->factory->createBuilder('field', null, array(
|
||||
$builder = $this->factory->createBuilder('form', null, array(
|
||||
'validation_groups' => 'group',
|
||||
));
|
||||
$builder->add('firstName', 'field');
|
||||
$builder->add('firstName', 'form');
|
||||
$form = $builder->getForm();
|
||||
|
||||
$this->validator->expects($this->once())
|
|
@ -71,7 +71,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
|||
* Changing the name is not allowed, otherwise the name and property path
|
||||
* are not synchronized anymore
|
||||
*
|
||||
* @see FieldType::buildForm
|
||||
* @see FormType::buildForm
|
||||
*/
|
||||
public function testNoSetName()
|
||||
{
|
||||
|
|
|
@ -346,7 +346,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals('foo', $builder->getName());
|
||||
}
|
||||
|
||||
public function testCreateBuilderForPropertyCreatesFieldWithHighestConfidence()
|
||||
public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence()
|
||||
{
|
||||
$this->guesser1->expects($this->once())
|
||||
->method('guessType')
|
||||
|
@ -378,7 +378,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals('builderInstance', $builder);
|
||||
}
|
||||
|
||||
public function testCreateBuilderCreatesTextFieldIfNoGuess()
|
||||
public function testCreateBuilderCreatesTextFormIfNoGuess()
|
||||
{
|
||||
$this->guesser1->expects($this->once())
|
||||
->method('guessType')
|
||||
|
@ -541,7 +541,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
|||
$factory->createNamedBuilder($type, "text", "value", array("unknown" => "opt"));
|
||||
}
|
||||
|
||||
public function testFieldTypeCreatesDefaultValueForEmptyDataOption()
|
||||
public function testFormTypeCreatesDefaultValueForEmptyDataOption()
|
||||
{
|
||||
$factory = new FormFactory(array(new \Symfony\Component\Form\Extension\Core\CoreExtension()));
|
||||
|
||||
|
|
|
@ -159,6 +159,35 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals(array(), $parent->getErrors());
|
||||
}
|
||||
|
||||
public function testErrorsBubbleUpIfNullAndChildren()
|
||||
{
|
||||
$error = new FormError('Error!');
|
||||
$parent = $this->form;
|
||||
$form = $this->getBuilder()
|
||||
->setErrorBubbling(null)
|
||||
->add($this->getBuilder('child'))
|
||||
->getForm();
|
||||
|
||||
$form->setParent($parent);
|
||||
$form->addError($error);
|
||||
|
||||
$this->assertEquals(array(), $form->getErrors());
|
||||
$this->assertEquals(array($error), $parent->getErrors());
|
||||
}
|
||||
|
||||
public function testErrorsDontBubbleUpIfNullAndNoChildren()
|
||||
{
|
||||
$error = new FormError('Error!');
|
||||
$parent = $this->form;
|
||||
$form = $this->getBuilder()->setErrorBubbling(null)->getForm();
|
||||
|
||||
$form->setParent($parent);
|
||||
$form->addError($error);
|
||||
|
||||
$this->assertEquals(array($error), $form->getErrors());
|
||||
$this->assertEquals(array(), $parent->getErrors());
|
||||
}
|
||||
|
||||
public function testValidIfAllChildrenAreValid()
|
||||
{
|
||||
$this->form->add($this->getValidForm('firstName'));
|
||||
|
@ -1026,7 +1055,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* @dataProvider requestMethodProvider
|
||||
*/
|
||||
public function testBindPostOrPutRequestWithSingleFieldForm($method)
|
||||
public function testBindPostOrPutRequestWithSingleChildForm($method)
|
||||
{
|
||||
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
||||
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
||||
|
@ -1063,7 +1092,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* @dataProvider requestMethodProvider
|
||||
*/
|
||||
public function testBindPostOrPutRequestWithSingleFieldFormUploadedFile($method)
|
||||
public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method)
|
||||
{
|
||||
if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
|
||||
$this->markTestSkipped('The "HttpFoundation" component is not available');
|
||||
|
|
Reference in New Issue