Skip to content

Commit

Permalink
[Form] Renamed the option "empty_value" to "placeholder"
Browse files Browse the repository at this point in the history
  • Loading branch information
webmozart committed Sep 23, 2014
1 parent aa59445 commit 2b440f3
Show file tree
Hide file tree
Showing 12 changed files with 319 additions and 170 deletions.
49 changes: 49 additions & 0 deletions UPGRADE-2.6.md
@@ -1,6 +1,55 @@
UPGRADE FROM 2.5 to 2.6
=======================

Form
----

* The "empty_value" option in the types "choice", "date", "datetime" and "time"
was deprecated and replaced by a new option "placeholder". You should use
the option "placeholder" together with the view variables "placeholder" and
"placeholder_in_choices" now.

The option "empty_value" and the view variables "empty_value" and
"empty_value_in_choices" will be removed in Symfony 3.0.

Before:

```php
$form->add('category', 'choice', array(
'choices' => array('politics', 'media'),
'empty_value' => 'Select a category...',
));
```

After:

```php
$form->add('category', 'choice', array(
'choices' => array('politics', 'media'),
'placeholder' => 'Select a category...',
));
```

Before:

```
{{ form.vars.empty_value }}
{% if form.vars.empty_value_in_choices %}
...
{% endif %}
```

After:

```
{{ form.vars.placeholder }}
{% if form.vars.placeholder_in_choices %}
...
{% endif %}
```

Validator
---------

Expand Down
Expand Up @@ -52,12 +52,12 @@
{% endblock choice_widget_expanded %}

{% block choice_widget_collapsed -%}
{% if required and empty_value is none and not empty_value_in_choices and not multiple -%}
{% if required and placeholder is none and not placeholder_in_choices and not multiple -%}
{% set required = false %}
{%- endif -%}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none -%}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
{% if placeholder is not none -%}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder|trans({}, translation_domain) }}</option>
{%- endif %}
{%- if preferred_choices|length > 0 -%}
{% set options = preferred_choices %}
Expand Down
@@ -1,13 +1,13 @@
<select
<?php if ($required && null === $empty_value && $empty_value_in_choices === false && $multiple === false):
<?php if ($required && null === $placeholder && $placeholder_in_choices === false && $multiple === false):
$required = false;
endif; ?>
<?php echo $view['form']->block($form, 'widget_attributes', array(
'required' => $required
)) ?>
<?php if ($multiple): ?> multiple="multiple"<?php endif ?>
>
<?php if (null !== $empty_value): ?><option value=""<?php if ($required and empty($value) && "0" !== $value): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($empty_value, array(), $translation_domain)) ?></option><?php endif; ?>
<?php if (null !== $placeholder): ?><option value=""<?php if ($required and empty($value) && "0" !== $value): ?> selected="selected"<?php endif?>><?php echo $view->escape($view['translator']->trans($placeholder, array(), $translation_domain)) ?></option><?php endif; ?>
<?php if (count($preferred_choices) > 0): ?>
<?php echo $view['form']->block($form, 'choice_widget_options', array('choices' => $preferred_choices)) ?>
<?php if (count($choices) > 0 && null !== $separator): ?>
Expand Down
35 changes: 23 additions & 12 deletions src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php
Expand Up @@ -57,8 +57,8 @@ public function buildForm(FormBuilderInterface $builder, array $options)

// Check if the choices already contain the empty value
// Only add the empty value option if this is not the case
if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) {
$placeholderView = new ChoiceView(null, '', $options['empty_value']);
if (null !== $options['placeholder'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) {
$placeholderView = new ChoiceView(null, '', $options['placeholder']);

// "placeholder" is a reserved index
// see also ChoiceListInterface::getIndicesForChoices()
Expand Down Expand Up @@ -101,7 +101,7 @@ public function buildView(FormView $view, FormInterface $form, array $options)
'preferred_choices' => $options['choice_list']->getPreferredViews(),
'choices' => $options['choice_list']->getRemainingViews(),
'separator' => '-------------------',
'empty_value' => null,
'placeholder' => null,
));

// The decision, whether a choice is selected, is potentially done
Expand All @@ -119,13 +119,17 @@ public function buildView(FormView $view, FormInterface $form, array $options)
}

// Check if the choices already contain the empty value
$view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array('')));
$view->vars['placeholder_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array('')));

// Only add the empty value option if this is not the case
if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) {
$view->vars['empty_value'] = $options['empty_value'];
if (null !== $options['placeholder'] && !$view->vars['placeholder_in_choices']) {
$view->vars['placeholder'] = $options['placeholder'];
}

// BC
$view->vars['empty_value'] = $view->vars['placeholder'];
$view->vars['empty_value_in_choices'] = $view->vars['placeholder_in_choices'];

if ($options['multiple'] && !$options['expanded']) {
// Add "[]" to the name in case a select tag with multiple options is
// displayed. Otherwise only one of the selected options is sent in the
Expand Down Expand Up @@ -187,20 +191,25 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
return $options['required'] ? null : '';
};

$emptyValueNormalizer = function (Options $options, $emptyValue) {
// for BC with the "empty_value" option
$placeholder = function (Options $options) {
return $options['empty_value'];
};

$placeholderNormalizer = function (Options $options, $placeholder) {
if ($options['multiple']) {
// never use an empty value for this case
return;
} elseif (false === $emptyValue) {
} elseif (false === $placeholder) {
// an empty value should be added but the user decided otherwise
return;
} elseif ($options['expanded'] && '' === $emptyValue) {
} elseif ($options['expanded'] && '' === $placeholder) {
// never use an empty label for radio buttons
return 'None';
}

// empty value has been set explicitly
return $emptyValue;
return $placeholder;
};

$compound = function (Options $options) {
Expand All @@ -214,7 +223,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'choices' => array(),
'preferred_choices' => array(),
'empty_data' => $emptyData,
'empty_value' => $emptyValue,
'empty_value' => $emptyValue, // deprecated
'placeholder' => $placeholder,
'error_bubbling' => false,
'compound' => $compound,
// The view data is always a string, even if the "data" option
Expand All @@ -224,7 +234,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
));

$resolver->setNormalizers(array(
'empty_value' => $emptyValueNormalizer,
'empty_value' => $placeholderNormalizer,
'placeholder' => $placeholderNormalizer,
));

$resolver->setAllowedTypes(array(
Expand Down
Expand Up @@ -115,6 +115,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
'months',
'days',
'empty_value',
'placeholder',
'required',
'translation_domain',
'html5',
Expand All @@ -127,6 +128,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
'with_minutes',
'with_seconds',
'empty_value',
'placeholder',
'required',
'translation_domain',
'html5',
Expand Down Expand Up @@ -237,7 +239,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
// Don't add some defaults in order to preserve the defaults
// set in DateType and TimeType
$resolver->setOptional(array(
'empty_value',
'empty_value', // deprecated
'placeholder',
'years',
'months',
'days',
Expand Down
32 changes: 19 additions & 13 deletions src/Symfony/Component/Form/Extension/Core/Type/DateType.php
Expand Up @@ -88,11 +88,11 @@ public function buildForm(FormBuilderInterface $builder, array $options)
if ('choice' === $options['widget']) {
// Only pass a subset of the options to children
$yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years']));
$yearOptions['empty_value'] = $options['empty_value']['year'];
$yearOptions['placeholder'] = $options['placeholder']['year'];
$monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months']));
$monthOptions['empty_value'] = $options['empty_value']['month'];
$monthOptions['placeholder'] = $options['placeholder']['month'];
$dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days']));
$dayOptions['empty_value'] = $options['empty_value']['day'];
$dayOptions['placeholder'] = $options['placeholder']['day'];
}

// Append generic carry-along options
Expand Down Expand Up @@ -171,24 +171,28 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
return $options['widget'] !== 'single_text';
};

$emptyValue = $emptyValueDefault = function (Options $options) {
$emptyValue = $placeholderDefault = function (Options $options) {
return $options['required'] ? null : '';
};

$emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
if (is_array($emptyValue)) {
$default = $emptyValueDefault($options);
$placeholder = function (Options $options) {
return $options['empty_value'];
};

$placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) {
if (is_array($placeholder)) {
$default = $placeholderDefault($options);

return array_merge(
array('year' => $default, 'month' => $default, 'day' => $default),
$emptyValue
$placeholder
);
}

return array(
'year' => $emptyValue,
'month' => $emptyValue,
'day' => $emptyValue,
'year' => $placeholder,
'month' => $placeholder,
'day' => $placeholder,
);
};

Expand All @@ -205,7 +209,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'format' => $format,
'model_timezone' => null,
'view_timezone' => null,
'empty_value' => $emptyValue,
'empty_value' => $emptyValue, // deprecated
'placeholder' => $placeholder,
'html5' => true,
// Don't modify \DateTime classes by reference, we treat
// them like immutable value objects
Expand All @@ -220,7 +225,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
));

$resolver->setNormalizers(array(
'empty_value' => $emptyValueNormalizer,
'empty_value' => $placeholderNormalizer,
'placeholder' => $placeholderNormalizer,
));

$resolver->setAllowedValues(array(
Expand Down
33 changes: 20 additions & 13 deletions src/Symfony/Component/Form/Extension/Core/Type/TimeType.php
Expand Up @@ -63,15 +63,15 @@ public function buildForm(FormBuilderInterface $builder, array $options)

// Only pass a subset of the options to children
$hourOptions['choices'] = $hours;
$hourOptions['empty_value'] = $options['empty_value']['hour'];
$hourOptions['placeholder'] = $options['placeholder']['hour'];

if ($options['with_minutes']) {
foreach ($options['minutes'] as $minute) {
$minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT);
}

$minuteOptions['choices'] = $minutes;
$minuteOptions['empty_value'] = $options['empty_value']['minute'];
$minuteOptions['placeholder'] = $options['placeholder']['minute'];
}

if ($options['with_seconds']) {
Expand All @@ -82,7 +82,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
}

$secondOptions['choices'] = $seconds;
$secondOptions['empty_value'] = $options['empty_value']['second'];
$secondOptions['placeholder'] = $options['placeholder']['second'];
}

// Append generic carry-along options
Expand Down Expand Up @@ -163,24 +163,29 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
return $options['widget'] !== 'single_text';
};

$emptyValue = $emptyValueDefault = function (Options $options) {
$emptyValue = $placeholderDefault = function (Options $options) {
return $options['required'] ? null : '';
};

$emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
if (is_array($emptyValue)) {
$default = $emptyValueDefault($options);
// for BC with the "empty_value" option
$placeholder = function (Options $options) {
return $options['empty_value'];
};

$placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) {
if (is_array($placeholder)) {
$default = $placeholderDefault($options);

return array_merge(
array('hour' => $default, 'minute' => $default, 'second' => $default),
$emptyValue
$placeholder
);
}

return array(
'hour' => $emptyValue,
'minute' => $emptyValue,
'second' => $emptyValue,
'hour' => $placeholder,
'minute' => $placeholder,
'second' => $placeholder,
);
};

Expand All @@ -194,7 +199,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'with_seconds' => false,
'model_timezone' => null,
'view_timezone' => null,
'empty_value' => $emptyValue,
'empty_value' => $emptyValue, // deprecated
'placeholder' => $placeholder,
'html5' => true,
// Don't modify \DateTime classes by reference, we treat
// them like immutable value objects
Expand All @@ -209,7 +215,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
));

$resolver->setNormalizers(array(
'empty_value' => $emptyValueNormalizer,
'empty_value' => $placeholderNormalizer,
'placeholder' => $placeholderNormalizer,
));

$resolver->setAllowedValues(array(
Expand Down

0 comments on commit 2b440f3

Please sign in to comment.