[Form] Deprecated FieldType, which has been merged into FormType

This commit is contained in:
Bernhard Schussek 2012-04-13 16:06:32 +02:00
parent bfa7ef2d9b
commit fcb2227ac9
72 changed files with 1016 additions and 826 deletions

View File

@ -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

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -1,3 +1,3 @@
{% block field_label %}
{% block form_label %}
<label>child</label>
{% endblock field_label %}
{% endblock form_label %}

View File

@ -1,3 +1,3 @@
{% block field_label %}
{% block form_label %}
<label>parent</label>
{% endblock field_label %}
{% endblock form_label %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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>

View File

@ -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(

View File

@ -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']) ?>

View File

@ -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')) ?>

View File

@ -1 +1 @@
<?php if ($form->get('multipart')): ?>enctype="multipart/form-data"<?php endif ?>
<?php echo $view['form']->renderBlock('form_enctype') ?>

View File

@ -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') ?>

View File

@ -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') ?>

View File

@ -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') ?>

View File

@ -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') ?>

View File

@ -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') ?>

View File

@ -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') ?>

View File

@ -0,0 +1 @@
<?php if ($form->get('multipart')): ?>enctype="multipart/form-data"<?php endif ?>

View File

@ -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 ?>

View File

@ -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>

View File

@ -0,0 +1,5 @@
<?php foreach ($form as $child): ?>
<?php if (!$child->isRendered()): ?>
<?php echo $view['form']->row($child) ?>
<?php endif; ?>
<?php endforeach; ?>

View File

@ -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>

View File

@ -0,0 +1,4 @@
<?php echo $view['form']->errors($form) ?>
<?php foreach ($form as $child) : ?>
<?php echo $view['form']->row($child) ?>
<?php endforeach; ?>

View File

@ -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 ?>

View File

@ -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")) ?>

View File

@ -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') ?>
/>

View File

@ -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")) ?>

View File

@ -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) ?>

View File

@ -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")) ?>

View File

@ -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")) ?>

View File

@ -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")) ?> %

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('field_rows') ?>
<?php echo $view['form']->renderBlock('form_rows') ?>

View File

@ -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")) ?>

View File

@ -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

View File

@ -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")) ?>

View File

@ -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>

View File

@ -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; ?>

View File

@ -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>

View File

@ -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 ?>

View File

@ -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()

View File

@ -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

View File

@ -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(),

View File

@ -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';
}
/**

View File

@ -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';
}
/**

View File

@ -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))));
}
}

View File

@ -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';

View File

@ -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))));
}
}

View File

@ -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';
}
/**

View File

@ -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';
}
}

View File

@ -38,7 +38,7 @@ class ValidatorExtension extends AbstractExtension
protected function loadTypeExtensions()
{
return array(
new Type\FieldTypeValidatorExtension($this->validator),
new Type\FormTypeValidatorExtension($this->validator),
);
}
}

View File

@ -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));
}
/**

View File

@ -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;
}

View File

@ -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

View File

@ -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)
{

View File

@ -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!'));

View File

@ -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!'));

View File

@ -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,

View File

@ -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__',

View File

@ -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());
}
}

View File

@ -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();

View File

@ -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')
));

View File

@ -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;
}

View File

@ -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())

View File

@ -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()
{

View File

@ -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()));

View File

@ -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');