[Form] Fixed results of the FieldType+FormType merge.

This commit is contained in:
Bernhard Schussek 2012-04-20 18:42:21 +02:00
parent a01dec00f4
commit eb75ab1b74
59 changed files with 401 additions and 278 deletions

View File

@ -102,7 +102,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
@ -313,29 +313,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()
{
@ -346,7 +346,7 @@
);
}
```
The second argument `$previousValue` does not have to be specified if not
needed.
@ -366,29 +366,92 @@
(or any other of the BIND events). In case you used the CallbackValidator
class, you should now pass the callback directly to `addEventListener`.
* simplified CSRF protection and removed the csrf type
* Since FormType and FieldType were merged, you need to adapt your form
themes.
* deprecated FieldType and merged it into FormType
The "field_widget" and all references to it should be renamed to
"form_widget_primitive":
Before:
```
{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
{{ block('field_widget') }}
{% endspaceless %}
{% endblock url_widget %}
```
After:
```
{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock url_widget %}
```
All other "field_*" blocks and references to them should be renamed to
"form_*". If you previously defined both a "field_*" and a "form_*"
block, you can merge them into a single "form_*" block and check the new
Boolean variable "primitive":
Before:
```
{% block form_errors %}
{% spaceless %}
... form code ...
{% endspaceless %}
{% endblock form_errors %}
{% block field_errors %}
{% spaceless %}
... field code ...
{% endspaceless %}
{% endblock field_errors %}
```
After:
```
{% block form_errors %}
{% spaceless %}
{% if primitive %}
... field code ...
{% else %}
... form code ...
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
```
Furthermore, the block "generic_label" was merged into "form_label". You
should now override "form_label" in order to customize labels.
Last but not least, the block "widget_choice_options" was renamed to
"choice_widget_options" to be consistent with the rest of the default
theme.
* [BC BREAK] renamed "field_*" theme blocks to "form_*" and "field_widget" to
"input"
* The method `guessMinLength()` of FormTypeGuesserInterface was deprecated
and will be removed in Symfony 2.3. You should use the new method
`guessPattern()` instead which may return any regular expression that
is inserted in the HTML5 attribute "pattern".
Before:
public function guessMinLength($class, $property)
{
if (/* condition */) {
return new ValueGuess($minLength, Guess::LOW_CONFIDENCE);
}
}
After:
public function guessPattern($class, $property)
{
if (/* condition */) {
@ -470,7 +533,7 @@
`validate` and its return value was dropped.
`ConstraintValidator` still contains the deprecated `isValid` method and
forwards `validate` calls to `isValid` by default. This BC layer will be
forwards `validate` calls to `isValid` by default. This BC layer will be
removed in Symfony 2.3. You are advised to rename your methods. You should
also remove the return values, which have never been used by the framework.
@ -500,7 +563,7 @@
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
return;
}
}

View File

@ -2,17 +2,30 @@
{% block form_widget %}
{% spaceless %}
{% if form.children|length > 0 %}
<div {{ block('widget_container_attributes') }}>
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
{% if primitive %}
{{ block('form_widget_primitive') }}
{% else %}
{{ block('input') }}
{{ block('form_widget_complex') }}
{% endif %}
{% endspaceless %}
{% endblock form_widget %}
{% block form_widget_primitive %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_primitive %}
{% block form_widget_complex %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{{ block('form_rows') }}
{{ form_rest(form) }}
</div>
{% endspaceless %}
{% endblock form_widget_complex %}
{% block collection_widget %}
{% spaceless %}
{% if prototype is defined %}
@ -28,7 +41,47 @@
{% endspaceless %}
{% endblock textarea_widget %}
{% block widget_choice_options %}
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
{{ block('choice_widget_expanded') }}
{% else %}
{{ block('choice_widget_collapsed') }}
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block choice_widget_collapsed %}
{% spaceless %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value="">{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_widget_options') }}
</select>
{% endspaceless %}
{% endblock choice_widget_collapsed %}
{% block choice_widget_options %}
{% spaceless %}
{% for index, choice in options %}
{% if _form_is_choice_group(choice) %}
@ -42,35 +95,7 @@
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock widget_choice_options %}
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
{% endfor %}
</div>
{% else %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value="">{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('widget_choice_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('widget_choice_options') }}
</select>
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
{% endblock choice_widget_options %}
{% block checkbox_widget %}
{% spaceless %}
@ -87,7 +112,7 @@
{% block datetime_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% else %}
<div {{ block('widget_container_attributes') }}>
{{ form_errors(form.date) }}
@ -102,7 +127,7 @@
{% block date_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% else %}
<div {{ block('widget_container_attributes') }}>
{{ date_pattern|replace({
@ -118,7 +143,7 @@
{% block time_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% 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 %}
@ -131,81 +156,77 @@
{% spaceless %}
{# type="number" doesn't work with floats #}
{% set type = type|default('text') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock number_widget %}
{% block integer_widget %}
{% spaceless %}
{% set type = type|default('number') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock integer_widget %}
{% block money_widget %}
{% spaceless %}
{{ money_pattern|replace({ '{{ widget }}': block('input') })|raw }}
{{ money_pattern|replace({ '{{ widget }}': block('form_widget_primitive') })|raw }}
{% endspaceless %}
{% endblock money_widget %}
{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock url_widget %}
{% block search_widget %}
{% spaceless %}
{% set type = type|default('search') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock search_widget %}
{% block percent_widget %}
{% spaceless %}
{% set type = type|default('text') %}
{{ block('input') }} %
{{ block('form_widget_primitive') }} %
{% endspaceless %}
{% endblock percent_widget %}
{% block password_widget %}
{% spaceless %}
{% set type = type|default('password') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock password_widget %}
{% block hidden_widget %}
{% spaceless %}
{% set type = type|default('hidden') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock hidden_widget %}
{% block email_widget %}
{% spaceless %}
{% set type = type|default('email') %}
{{ block('input') }}
{{ block('form_widget_primitive') }}
{% endspaceless %}
{% endblock email_widget %}
{# Labels #}
{% block generic_label %}
{% block form_label %}
{% spaceless %}
{% if primitive %}
{% set attr = attr|merge({'for': id}) %}
{% endif %}
{% if required %}
{% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
{% endif %}
<label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
{% endspaceless %}
{% endblock %}
{% block form_label %}
{% spaceless %}
{% if form.children|length == 0 %}
{% set attr = attr|merge({'for': id}) %}
{% endif %}
{{ block('generic_label') }}
{% endspaceless %}
{% endblock form_label %}
{# Rows #}
@ -220,7 +241,9 @@
{% spaceless %}
<div>
{{ form_label(form, label|default(null)) }}
{% if form.children|length == 0 %}
{# If the child is a form, the errors are rendered inside the container #}
{# see block form_rows #}
{% if primitive %}
{{ form_errors(form) }}
{% endif %}
{{ form_widget(form) }}
@ -247,10 +270,8 @@
{% for error in errors %}
<li>{{
error.messagePluralization is null
?
error.messageTemplate|trans(error.messageParameters, 'validators')
:
error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
? error.messageTemplate|trans(error.messageParameters, 'validators')
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
}}</li>
{% endfor %}
</ul>
@ -279,13 +300,6 @@
{% endspaceless %}
{% 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 %}
id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
@ -302,44 +316,12 @@
{# 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 %}
{% block generic_label %}{{ block('form_label') }}{% endblock %}
{% block widget_choice_options %}{{ block('choice_widget_options') }}{% endblock %}
{% block field_widget %}{{ block('form_widget_primitive') }}{% endblock %}
{% block field_label %}{{ block('form_label') }}{% endblock %}
{% block field_row %}{{ block('form_row') }}{% endblock %}
{% block field_enctype %}{{ block('form_enctype') }}{% endblock %}
{% block field_errors %}{{ block('form_errors') }}{% endblock %}
{% block field_rest %}{{ block('form_rest') }}{% endblock %}
{% block field_rows %}{{ block('form_rows') }}{% endblock %}

View File

@ -7,7 +7,7 @@
{{ form_label(form, label|default(null)) }}
</td>
<td>
{% if form.children|length == 0 %}
{% if primitive %}
{{ form_errors(form) }}
{% endif %}
{{ form_widget(form) }}
@ -18,7 +18,9 @@
{% block form_errors %}
{% spaceless %}
{% if form.children|length > 0 %}
{% if primitive %}
{{ parent() }}
{% else %}
{% if errors|length > 0 %}
<tr>
<td colspan="2">
@ -26,8 +28,6 @@
</td>
</tr>
{% endif %}
{% else %}
{{ parent() }}
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
@ -42,15 +42,11 @@
{% endspaceless %}
{% endblock hidden_row %}
{% block form_widget %}
{% block form_widget_complex %}
{% spaceless %}
{% if form.children|length > 0 %}
<table {{ block('widget_container_attributes') }}>
{{ block('form_rows') }}
{{ form_rest(form) }}
</table>
{% else %}
{{ parent() }}
{% endif %}
<table {{ block('widget_container_attributes') }}>
{{ block('form_rows') }}
{{ form_rest(form) }}
</table>
{% endspaceless %}
{% endblock form_widget %}
{% endblock form_widget_complex %}

View File

@ -1,6 +1,6 @@
{% block input %}
{% block form_widget_primitive %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock input %}
{% endblock form_widget_primitive %}

View File

@ -1,8 +1,8 @@
{% extends 'form_div_layout.html.twig' %}
{% block input %}
{% block form_widget_primitive %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock input %}
{% endblock form_widget_primitive %}

View File

@ -1,8 +1,8 @@
{% use 'form_div_layout.html.twig' %}
{% block input %}
{% block form_widget_primitive %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('attributes') }} value="{{ value }}" rel="theme" />
<input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" />
{% endspaceless %}
{% endblock input %}
{% endblock form_widget_primitive %}

View File

@ -1,9 +1 @@
id="<?php echo $view->escape($id) ?>"
name="<?php echo $view->escape($full_name) ?>"
<?php if ($read_only): ?>readonly="readonly" <?php endif ?>
<?php if ($disabled): ?>disabled="disabled" <?php endif ?>
<?php if ($required): ?>required="required" <?php endif ?>
<?php if ($max_length): ?>maxlength="<?php echo $view->escape($max_length) ?>" <?php endif ?>
<?php if ($pattern): ?>pattern="<?php echo $view->escape($pattern) ?>" <?php endif ?>
<?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>
<?php echo $view['form']->renderBlock('widget_attributes') ?>

View File

@ -1,5 +1,5 @@
<input type="checkbox"
<?php echo $view['form']->renderBlock('attributes') ?>
<?php echo $view['form']->renderBlock('widget_attributes') ?>
<?php if ($value): ?> value="<?php echo $view->escape($value) ?>"<?php endif ?>
<?php if ($checked): ?> checked="checked"<?php endif ?>
/>

View File

@ -1,11 +1 @@
<?php foreach ($options as $index => $choice): ?>
<?php if ($view['form']->isChoiceGroup($choice)): ?>
<optgroup label="<?php echo $view->escape($view['translator']->trans($index, array(), $translation_domain)) ?>">
<?php foreach ($choice as $nested_choice): ?>
<option value="<?php echo $view->escape($nested_choice->getValue()) ?>"<?php if ($view['form']->isChoiceSelected($form, $nested_choice)): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($nested_choice->getLabel(), array(), $translation_domain)) ?></option>
<?php endforeach ?>
</optgroup>
<?php else: ?>
<option value="<?php echo $view->escape($choice->getValue()) ?>"<?php if ($view['form']->isChoiceSelected($form, $choice)): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($choice->getLabel(), array(), $translation_domain)) ?></option>
<?php endif ?>
<?php endforeach ?>
<?php echo $view['form']->renderBlock('choice_widget_options') ?>

View File

@ -1,22 +1,5 @@
<?php if ($expanded): ?>
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
<?php foreach ($form as $child): ?>
<?php echo $view['form']->widget($child) ?>
<?php echo $view['form']->label($child) ?>
<?php endforeach ?>
</div>
<?php echo $view['form']->renderBlock('choice_widget_expanded') ?>
<?php else: ?>
<select
<?php echo $view['form']->renderBlock('attributes') ?>
<?php if ($multiple): ?> multiple="multiple"<?php endif ?>
>
<?php if (null !== $empty_value): ?><option value=""><?php echo $view->escape($view['translator']->trans($empty_value, array(), $translation_domain)) ?></option><?php endif; ?>
<?php if (count($preferred_choices) > 0): ?>
<?php echo $view['form']->renderBlock('choice_options', array('options' => $preferred_choices)) ?>
<?php if (count($choices) > 0 && null !== $separator): ?>
<option disabled="disabled"><?php echo $separator ?></option>
<?php endif ?>
<?php endif ?>
<?php echo $view['form']->renderBlock('choice_options', array('options' => $choices)) ?>
</select>
<?php echo $view['form']->renderBlock('choice_widget_collapsed') ?>
<?php endif ?>

View File

@ -0,0 +1,13 @@
<select
<?php echo $view['form']->renderBlock('widget_attributes') ?>
<?php if ($multiple): ?> multiple="multiple"<?php endif ?>
>
<?php if (null !== $empty_value): ?><option value=""><?php echo $view->escape($view['translator']->trans($empty_value, array(), $translation_domain)) ?></option><?php endif; ?>
<?php if (count($preferred_choices) > 0): ?>
<?php echo $view['form']->renderBlock('choice_widget_options', array('options' => $preferred_choices)) ?>
<?php if (count($choices) > 0 && null !== $separator): ?>
<option disabled="disabled"><?php echo $separator ?></option>
<?php endif ?>
<?php endif ?>
<?php echo $view['form']->renderBlock('choice_widget_options', array('options' => $choices)) ?>
</select>

View File

@ -0,0 +1,6 @@
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php foreach ($form as $child): ?>
<?php echo $view['form']->widget($child) ?>
<?php echo $view['form']->label($child) ?>
<?php endforeach ?>
</div>

View File

@ -0,0 +1,11 @@
<?php foreach ($options as $index => $choice): ?>
<?php if ($view['form']->isChoiceGroup($choice)): ?>
<optgroup label="<?php echo $view->escape($view['translator']->trans($index, array(), $translation_domain)) ?>">
<?php foreach ($choice as $nested_choice): ?>
<option value="<?php echo $view->escape($nested_choice->getValue()) ?>"<?php if ($view['form']->isChoiceSelected($form, $nested_choice)): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($nested_choice->getLabel(), array(), $translation_domain)) ?></option>
<?php endforeach ?>
</optgroup>
<?php else: ?>
<option value="<?php echo $view->escape($choice->getValue()) ?>"<?php if ($view['form']->isChoiceSelected($form, $choice)): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($choice->getLabel(), array(), $translation_domain)) ?></option>
<?php endif ?>
<?php endforeach ?>

View File

@ -1,2 +1 @@
<?php if (!empty($id)): ?>id="<?php echo $view->escape($id) ?>" <?php endif; ?>
<?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>
<?php echo $view['form']->renderBlock('widget_container_attributes') ?>

View File

@ -1,7 +1,7 @@
<?php if ($widget == 'single_text'): ?>
<?php echo $view['form']->renderBlock('input'); ?>
<?php echo $view['form']->renderBlock('form_widget_primitive'); ?>
<?php else: ?>
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php echo str_replace(array('{{ year }}', '{{ month }}', '{{ day }}'), array(
$view['form']->widget($form['year']),
$view['form']->widget($form['month']),

View File

@ -1,7 +1,7 @@
<?php if ($widget == 'single_text'): ?>
<?php echo $view['form']->renderBlock('input'); ?>
<?php echo $view['form']->renderBlock('form_widget_primitive'); ?>
<?php else: ?>
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php echo $view['form']->widget($form['date']).' '.$view['form']->widget($form['time']) ?>
</div>
<?php endif ?>

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : 'email')) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : 'email')) ?>

View File

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

View File

@ -1,3 +1,3 @@
<?php if ($required) { $attr['class'] = (isset($attr['class']) ? $attr['class'] : '').' required'; } ?>
<?php if (!$form->hasChildren()) { $attr['for'] = $id; } ?>
<?php if ($primitive) { $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

@ -1,6 +1,6 @@
<div>
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
<?php if (!$form->hasChildren()): ?>
<?php if ($primitive): ?>
<?php echo $view['form']->errors($form) ?>
<?php endif ?>
<?php echo $view['form']->widget($form) ?>

View File

@ -1,8 +1,5 @@
<?php if ($form->hasChildren()): ?>
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
<?php echo $view['form']->renderBlock('form_rows') ?>
<?php echo $view['form']->rest($form) ?>
</div>
<?php if ($primitive): ?>
<?php echo $view['form']->renderBlock('form_widget_primitive')?>
<?php else: ?>
<?php echo $view['form']->renderBlock('input')?>
<?php echo $view['form']->renderBlock('form_widget_complex')?>
<?php endif ?>

View File

@ -0,0 +1,4 @@
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php echo $view['form']->renderBlock('form_rows') ?>
<?php echo $view['form']->rest($form) ?>
</div>

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

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "hidden")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "hidden")) ?>

View File

@ -1,5 +0,0 @@
<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('input', array('type' => isset($type) ? $type : "number")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "number")) ?>

View File

@ -1 +1 @@
<?php echo str_replace('{{ widget }}', $view['form']->renderBlock('input'), $money_pattern) ?>
<?php echo str_replace('{{ widget }}', $view['form']->renderBlock('form_widget_primitive'), $money_pattern) ?>

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "text")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "text")) ?>

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "password")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "password")) ?>

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "text")) ?> %
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "text")) ?> %

View File

@ -1,5 +1,5 @@
<input type="radio"
<?php echo $view['form']->renderBlock('attributes') ?>
<?php echo $view['form']->renderBlock('widget_attributes') ?>
value="<?php echo $view->escape($value) ?>"
<?php if ($checked): ?> checked="checked"<?php endif ?>
/>

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "search")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "search")) ?>

View File

@ -1 +1 @@
<textarea <?php echo $view['form']->renderBlock('attributes') ?>><?php echo $view->escape($value) ?></textarea>
<textarea <?php echo $view['form']->renderBlock('widget_attributes') ?>><?php echo $view->escape($value) ?></textarea>

View File

@ -1,7 +1,7 @@
<?php if ($widget == 'single_text'): ?>
<?php echo $view['form']->renderBlock('input'); ?>
<?php echo $view['form']->renderBlock('form_widget_primitive'); ?>
<?php else: ?>
<div <?php echo $view['form']->renderBlock('container_attributes') ?>>
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php
// There should be no spaces between the colons and the widgets, that's why
// this block is written in a single PHP tag

View File

@ -1 +1 @@
<?php echo $view['form']->renderBlock('input', array('type' => isset($type) ? $type : "url")) ?>
<?php echo $view['form']->renderBlock('form_widget_primitive', array('type' => isset($type) ? $type : "url")) ?>

View File

@ -0,0 +1,9 @@
id="<?php echo $view->escape($id) ?>"
name="<?php echo $view->escape($full_name) ?>"
<?php if ($read_only): ?>readonly="readonly" <?php endif ?>
<?php if ($disabled): ?>disabled="disabled" <?php endif ?>
<?php if ($required): ?>required="required" <?php endif ?>
<?php if ($max_length): ?>maxlength="<?php echo $view->escape($max_length) ?>" <?php endif ?>
<?php if ($pattern): ?>pattern="<?php echo $view->escape($pattern) ?>" <?php endif ?>
<?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>

View File

@ -0,0 +1,2 @@
<?php if (!empty($id)): ?>id="<?php echo $view->escape($id) ?>" <?php endif; ?>
<?php foreach($attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>

View File

@ -1,4 +1,26 @@
<?php if ($form->hasChildren()): ?>
<?php if ($primitive): ?>
<?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 else: ?>
<?php if (count($errors) > 0): ?>
<tr>
<td colspan="2">
@ -26,26 +48,4 @@
</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,7 +3,7 @@
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
</td>
<td>
<?php if (!$form->hasChildren()): ?>
<?php if ($primitive): ?>
<?php echo $view['form']->errors($form) ?>
<?php endif ?>
<?php echo $view['form']->widget($form) ?>

View File

@ -1,8 +0,0 @@
<?php if ($form->hasChildren()): ?>
<table <?php echo $view['form']->renderBlock('container_attributes') ?>>
<?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

@ -0,0 +1,4 @@
<table <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
<?php echo $view['form']->renderBlock('form_rows') ?>
<?php echo $view['form']->rest($form) ?>
</table>

View File

@ -1,2 +1,2 @@
<?php $type = isset($type) ? $type : 'text' ?>
<input type="<?php echo $type ?>" <?php $view['form']->renderBlock('attributes') ?> value="<?php echo $value ?>" rel="theme" />
<input type="<?php echo $type ?>" <?php $view['form']->renderBlock('widget_attributes') ?> value="<?php echo $value ?>" rel="theme" />

View File

@ -25,16 +25,12 @@ CHANGELOG
* [BC BREAK] removed EntitiesToArrayTransformer and EntityToIdTransformer.
The former has been replaced by CollectionToArrayTransformer in combination
with EntityChoiceList, the latter is not required in the core anymore.
* [BC BREAK] renamed
* ArrayToBooleanChoicesTransformer to ChoicesToBooleanArrayTransformer
* ScalarToBooleanChoicesTransformer to ChoiceToBooleanArrayTransformer
* ArrayToChoicesTransformer to ChoicesToValuesTransformer
* ScalarToChoiceTransformer to ChoiceToValueTransformer
to be consistent with the naming in ChoiceListInterface.
to be consistent with the naming in ChoiceListInterface.
* [BC BREAK] removed FormUtil::toArrayKey() and FormUtil::toArrayKeys().
They were merged into ChoiceList and have no public equivalent anymore.
* choice fields now throw a FormException if neither the "choices" nor the
@ -62,8 +58,13 @@ CHANGELOG
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"
* [BC BREAK] renamed theme blocks
* "field_*" to "form_*"
* "field_widget" to "form_widget_primitive"
* "widget_choice_options" to "choice_widget_options"
* "generic_label" to "form_label"
* added theme blocks "form_widget_complex", "choice_widget_expanded" and
"choice_widget_collapsed" to make theming more modular
* ValidatorTypeGuesser now guesses "collection" for array type constraint
* added method `guessPattern` to FormTypeGuesserInterface to guess which pattern to use in the HTML5 attribute "pattern"
* deprecated method `guessMinLength` in favor of `guessPattern`

View File

@ -46,11 +46,14 @@ class CheckboxType extends AbstractType
*/
public function getDefaultOptions()
{
$emptyData = function (FormInterface $form, $clientData) {
return $clientData;
};
return array(
'value' => '1',
'empty_data' => function (FormInterface $form, $clientData) {
return $clientData;
},
'value' => '1',
'empty_data' => $emptyData,
'primitive' => true,
);
}

View File

@ -165,6 +165,10 @@ class ChoiceType extends AbstractType
return $options['required'] ? null : '';
};
$primitive = function (Options $options) {
return !$options['expanded'];
};
return array(
'multiple' => false,
'expanded' => false,
@ -174,6 +178,7 @@ class ChoiceType extends AbstractType
'empty_data' => $emptyData,
'empty_value' => $emptyValue,
'error_bubbling' => false,
'primitive' => $primitive,
);
}

View File

@ -21,6 +21,7 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransfo
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer;
use Symfony\Component\Form\Options;
class DateTimeType extends AbstractType
{
@ -130,6 +131,10 @@ class DateTimeType extends AbstractType
*/
public function getDefaultOptions()
{
$primitive = function (Options $options) {
return $options['widget'] === 'single_text';
};
return array(
'input' => 'datetime',
'data_timezone' => null,
@ -158,6 +163,7 @@ class DateTimeType extends AbstractType
// representation is not \DateTime, but an array, we need to unset
// this option.
'data_class' => null,
'primitive' => $primitive,
);
}

View File

@ -11,18 +11,18 @@
namespace Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\Exception\CreationException;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\Form\Options;
class DateType extends AbstractType
{
@ -163,6 +163,10 @@ class DateType extends AbstractType
*/
public function getDefaultOptions()
{
$primitive = function (Options $options) {
return $options['widget'] === 'single_text';
};
return array(
'years' => range(date('Y') - 5, date('Y') + 5),
'months' => range(1, 12),
@ -182,6 +186,7 @@ class DateType extends AbstractType
// representation is not \DateTime, but an array, we need to unset
// this option.
'data_class' => null,
'primitive' => $primitive,
);
}

View File

@ -38,6 +38,16 @@ class FileType extends AbstractType
;
}
/**
* {@inheritdoc}
*/
public function getDefaultOptions()
{
return array(
'primitive' => true,
);
}
/**
* {@inheritdoc}
*/

View File

@ -61,6 +61,7 @@ class FormType extends AbstractType
->setAttribute('invalid_message_parameters', $options['invalid_message_parameters'])
->setAttribute('translation_domain', $options['translation_domain'])
->setAttribute('virtual', $options['virtual'])
->setAttribute('primitive', $options['primitive'])
->setData($options['data'])
->setDataMapper(new PropertyPathMapper($options['data_class']))
->addEventSubscriber(new ValidationListener())
@ -125,6 +126,7 @@ class FormType extends AbstractType
->set('label', $form->getAttribute('label'))
->set('multipart', false)
->set('attr', $form->getAttribute('attr'))
->set('primitive', $form->getAttribute('primitive'))
->set('types', $types)
->set('translation_domain', $form->getAttribute('translation_domain'))
;
@ -201,6 +203,7 @@ class FormType extends AbstractType
'label' => null,
'attr' => array(),
'virtual' => false,
'primitive' => false,
'invalid_message' => 'This value is not valid.',
'invalid_message_parameters' => array(),
'translation_domain' => 'messages',

View File

@ -25,6 +25,7 @@ class HiddenType extends AbstractType
'required' => false,
// Pass errors to the parent
'error_bubbling' => true,
'primitive' => true,
);
}

View File

@ -41,6 +41,7 @@ class IntegerType extends AbstractType
'grouping' => false,
// Integer cast rounds towards 0, so do the same when displaying fractions
'rounding_mode' => \NumberFormatter::ROUND_DOWN,
'primitive' => true,
);
}

View File

@ -55,6 +55,7 @@ class MoneyType extends AbstractType
'grouping' => false,
'divisor' => 1,
'currency' => 'EUR',
'primitive' => true,
);
}

View File

@ -39,6 +39,7 @@ class NumberType extends AbstractType
'precision' => null,
'grouping' => false,
'rounding_mode' => \NumberFormatter::ROUND_HALFUP,
'primitive' => true,
);
}

View File

@ -33,6 +33,7 @@ class PercentType extends AbstractType
return array(
'precision' => 0,
'type' => 'fractional',
'primitive' => true,
);
}

View File

@ -27,6 +27,16 @@ class TextType extends AbstractType
;
}
/**
* {@inheritdoc}
*/
public function getDefaultOptions()
{
return array(
'primitive' => true,
);
}
/**
* {@inheritdoc}
*/

View File

@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransf
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Options;
class TimeType extends AbstractType
{
@ -136,6 +137,10 @@ class TimeType extends AbstractType
*/
public function getDefaultOptions()
{
$primitive = function (Options $options) {
return $options['widget'] === 'single_text';
};
return array(
'hours' => range(0, 23),
'minutes' => range(0, 59),
@ -155,6 +160,7 @@ class TimeType extends AbstractType
// representation is not \DateTime, but an array, we need to unset
// this option.
'data_class' => null,
'primitive' => $primitive,
);
}

View File

@ -277,6 +277,19 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
);
}
public function testEmptyCollection()
{
$form = $this->factory->createNamed('collection', 'name', array(), array(
'type' => 'text',
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[count(./div)=0]
'
);
}
public function testCollectionRow()
{
$collection = $this->factory->createNamedBuilder(

View File

@ -170,6 +170,19 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
);
}
public function testEmptyCollection()
{
$form = $this->factory->createNamed('collection', 'name', array(), array(
'type' => 'text',
));
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
[count(./tr[./td/input])=0]
'
);
}
public function testForm()
{
$view = $this->factory->createNamedBuilder('form', 'name')

View File

@ -619,8 +619,8 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
'"attr", "by_reference", "data", "data_class", "disabled", ' .
'"empty_data", "error_bubbling", "error_mapping", "invalid_message", ' .
'"invalid_message_parameters", "label", "max_length", "pattern", ' .
'"property_path", "read_only", "required", "translation_domain", ' .
'"trim"'
'"primitive", "property_path", "read_only", "required", ' .
'"translation_domain", "trim"'
);
$factory->createNamedBuilder($type, "text", "value", array("invalid" => "opt", "unknown" => "opt"));
}
@ -636,8 +636,8 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
'"by_reference", "data", "data_class", "disabled", "empty_data", ' .
'"error_bubbling", "error_mapping", "invalid_message", ' .
'"invalid_message_parameters", "label", "max_length", "pattern", ' .
'"property_path", "read_only", "required", "translation_domain", ' .
'"trim"'
'"primitive", "property_path", "read_only", "required", ' .
'"translation_domain", "trim"'
);
$factory->createNamedBuilder($type, "text", "value", array("unknown" => "opt"));
}