Explorar el Código

[Form] Adding PHPDoc to many Field objects and making other small changes:

 * Added empty_value option on CountryField, LanguageField, LocaleField, TimezoneField
 * Added missing date_pattern to DateTimeField
 * Made the currency option on MoneyField required.
Ryan Weaver hace 14 años
padre
commit
d341e8bccb

+ 4 - 1
src/Symfony/Component/Form/CheckboxField.php

@@ -19,7 +19,10 @@ namespace Symfony\Component\Form;
 class CheckboxField extends ToggleField
 {
     /**
-     * {@inheritDoc}
+     * Available options:
+     *
+     *  * value:    The value of the input checkbox. If the checkbox is checked,
+     *              this value will be posted as the value of the field.
      */
     protected function configure()
     {

+ 6 - 6
src/Symfony/Component/Form/ChoiceField.php

@@ -18,17 +18,17 @@ use Symfony\Component\Form\Exception\InvalidOptionsException;
  *
  * Available options:
  *
- *  * choices:              An array of key-value pairs that will represent the choices.
+ *  * choices:              An array of key-value pairs that will represent the choices
  *  * preferred_choices:    An array of choices (by key) that should be displayed
- *                          above all other options in the field.
+ *                          above all other options in the field
  *
  * The multiple and expanded options control exactly which HTML element
  * that should be used to render this field:
  *
- *  * expanded = false, multiple = false    a drop-down select element;
- *  * expanded = false, multiple = true     a multiple select element;
- *  * expanded = true, multiple = false     a series of input radio elements;
- *  * expanded = true, multiple = true      a series of input checkboxes.
+ *  * expanded = false, multiple = false    A drop-down select element
+ *  * expanded = false, multiple = true     A multiple select element
+ *  * expanded = true, multiple = false     A series of input radio elements
+ *  * expanded = true, multiple = true      A series of input checkboxes
  *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */

+ 17 - 1
src/Symfony/Component/Form/CollectionField.php

@@ -15,6 +15,13 @@ use Symfony\Component\Form\FieldInterface;
 use Symfony\Component\Form\Exception\UnexpectedTypeException;
 
 /**
+ * A field group that repeats the given field multiple times over a collection
+ * specified by the property path if the field.
+ *
+ * Example usage:
+ *
+ *     $form->add(new CollectionField(new TextField('emails')));
+ *
  * @author     Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class CollectionField extends FieldGroup
@@ -32,7 +39,7 @@ class CollectionField extends FieldGroup
     protected $removedFields = array();
 
     /**
-     * Repeats the given field twice to verify the user's input
+     * Repeats the given field multiple times based in the internal collection.
      *
      * @param FieldInterface $innerField
      */
@@ -43,6 +50,15 @@ class CollectionField extends FieldGroup
         parent::__construct($innerField->getKey(), $options);
     }
 
+    /**
+     * Available options:
+     *
+     *  * modifiable:   If true, elements in the collection can be added
+     *                  and removed by the presence of absence of the
+     *                  corresponding field groups. Field groups could be
+     *                  added or removed via Javascript and reflected in
+     *                  the underlying collection. Default: false.
+     */
     protected function configure()
     {
         $this->addOption('modifiable', false);

+ 18 - 5
src/Symfony/Component/Form/CountryField.php

@@ -14,18 +14,31 @@ namespace Symfony\Component\Form;
 use Symfony\Component\Locale\Locale;
 
 /**
- * A field for selecting from a list of countries
+ * A field for selecting from a list of countries.
  *
+ * In addition to the ChoiceField options, this field has the following
+ * options:
+ *
+ *  * empty_value:  If set to a non-false value, an "empty" option will
+ *                  be added to the top of the countries choices. A
+ *                  common value might be "Choose a country". Default: false.
+ *
+ * @see Symfony\Component\Form\ChoiceField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class CountryField extends ChoiceField
 {
-    /**
-     * @inheritDoc
-     */
     protected function configure()
     {
-        $this->addOption('choices', Locale::getDisplayCountries($this->locale));
+        $this->addOption('empty_value', false);
+
+        $choices = Locale::getDisplayCountries($this->locale);
+
+        if (false !== $this->getOption('empty_value')) {
+            $choices = array('' => $this->getOption('empty_value')) + $choices;
+        }
+
+        $this->addOption('choices', $choices);
 
         parent::configure();
     }

+ 29 - 23
src/Symfony/Component/Form/DateField.php

@@ -18,6 +18,30 @@ use Symfony\Component\Form\ValueTransformer\ValueTransformerChain;
 use Symfony\Component\Form\ValueTransformer\DateTimeToLocalizedStringTransformer;
 use Symfony\Component\Form\ValueTransformer\DateTimeToArrayTransformer;
 
+/**
+ * Represents a date field.
+ *
+ * Available options:
+ *
+ *  * widget:         How to render the field ("input" or "choice"). Default: "choice".
+ *  * type:           The type of the date stored on the object. Default: "datetime":
+ *                    * datetime:   A DateTime object;
+ *                    * string:     A raw string (e.g. 2011-05-01, Y-m-d);
+ *                    * timestamp:  A unix timestamp (e.g. 1304208000);
+ *                    * raw:        A year, month, day array.
+ *  * pattern:        The pattern for the select boxes when "widget" is "choice".
+ *                    You can use the placeholders "{{ year }}", "{{ month }}" and "{{ day }}".
+ *                    Default: locale dependent.
+ *
+ *  * years:          An array of years for the year select tag.
+ *  * months:         An array of months for the month select tag.
+ *  * days:           An array of days for the day select tag.
+ *
+ *  * format:         The date format type to use for displaying the data. Default: medium.
+ *  * data_timezone:  The timezone of the data. Default: UTC.
+ *  * user_timezone:  The timezone of the user entering a new value. Default: UTC.
+ *
+ */
 class DateField extends HybridField
 {
     const FULL = 'full';
@@ -65,37 +89,19 @@ class DateField extends HybridField
      */
     protected $formatter;
 
-    /**
-     * Configures the text field.
-     *
-     * Available options:
-     *
-     *  * widget:         How to render the field ("input" or "select"). Default: "input"
-     *  * years:          An array of years for the year select tag (optional)
-     *  * months:         An array of months for the month select tag (optional)
-     *  * days:           An array of days for the day select tag (optional)
-     *  * format:         See DateValueTransformer. Default: medium
-     *  * type:           The type of the date ("date", "datetime" or "timestamp"). Default: "date"
-     *  * data_timezone:  The timezone of the data
-     *  * user_timezone:  The timezone of the user entering a new value
-     *  * pattern:        The pattern for the select boxes when "widget" is "select".
-     *                    You can use the placeholders "{{ year }}", "{{ month }}" and "{{ day }}".
-     *                    Default: locale dependent
-     *
-     * @param array $options Options for this field
-     * @throws \InvalidArgumentException  Thrown if you want to show a timestamp with the select widget.
-     */
     protected function configure()
     {
+        $this->addOption('widget', self::CHOICE, self::$widgets);
+        $this->addOption('type', self::DATETIME, self::$types);
+        $this->addOption('pattern');
+
         $this->addOption('years', range(date('Y') - 5, date('Y') + 5));
         $this->addOption('months', range(1, 12));
         $this->addOption('days', range(1, 31));
+
         $this->addOption('format', self::MEDIUM, self::$formats);
-        $this->addOption('type', self::DATETIME, self::$types);
         $this->addOption('data_timezone', 'UTC');
         $this->addOption('user_timezone', 'UTC');
-        $this->addOption('widget', self::CHOICE, self::$widgets);
-        $this->addOption('pattern');
 
         $this->formatter = new \IntlDateFormatter(
             $this->locale,

+ 34 - 9
src/Symfony/Component/Form/DateTimeField.php

@@ -18,7 +18,31 @@ use Symfony\Component\Form\ValueTransformer\DateTimeToArrayTransformer;
 use Symfony\Component\Form\ValueTransformer\ValueTransformerChain;
 
 /**
- * A field for editing a date and a time simultaneously
+ * A field for editing a date and a time simultaneously.
+ *
+ * Available options:
+ *
+ *  * date_widget:    How to render the date field ("input" or "choice"). Default: "choice".
+ *  * time_widget:    How to render the time field ("input" or "choice"). Default: "choice".
+ *  * type:           The type of the date stored on the object. Default: "datetime":
+ *                    * datetime:   A DateTime object;
+ *                    * string:     A raw string (e.g. 2011-05-01 12:30:00, Y-m-d H:i:s);
+ *                    * timestamp:  A unix timestamp (e.g. 1304208000).
+ *  * date_pattern:   The pattern for the select boxes when date "widget" is "choice".
+ *                    You can use the placeholders "{{ year }}", "{{ month }}" and "{{ day }}".
+ *                    Default: locale dependent.
+ *  * with_seconds    Whether or not to create a field for seconds. Default: false.
+ *
+ *  * years:          An array of years for the year select tag.
+ *  * months:         An array of months for the month select tag.
+ *  * days:           An array of days for the day select tag.
+ *  * hours:          An array of hours for the hour select tag.
+ *  * minutes:        An array of minutes for the minute select tag.
+ *  * seconds:        An array of seconds for the second select tag.
+ *
+ *  * date_format:    The date format type to use for displaying the date. Default: medium.
+ *  * data_timezone:  The timezone of the data. Default: UTC.
+ *  * user_timezone:  The timezone of the user entering a new value. Default: UTC.
  *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
@@ -51,24 +75,24 @@ class DateTimeField extends FieldGroup
         TimeField::INPUT,
     );
 
-    /**
-     * {@inheritDoc}
-     */
-    public function configure()
+    protected function configure()
     {
+        $this->addOption('date_widget', DateField::CHOICE, self::$dateWidgets);
+        $this->addOption('time_widget', TimeField::CHOICE, self::$timeWidgets);
+        $this->addOption('type', self::DATETIME, self::$types);
+        $this->addOption('date_pattern');
+        $this->addOption('with_seconds', false);
+
         $this->addOption('years', range(date('Y') - 5, date('Y') + 5));
         $this->addOption('months', range(1, 12));
         $this->addOption('days', range(1, 31));
         $this->addOption('hours', range(0, 23));
         $this->addOption('minutes', range(0, 59));
         $this->addOption('seconds', range(0, 59));
+
         $this->addOption('data_timezone', 'UTC');
         $this->addOption('user_timezone', 'UTC');
         $this->addOption('date_format', DateField::MEDIUM, self::$dateFormats);
-        $this->addOption('date_widget', DateField::CHOICE, self::$dateWidgets);
-        $this->addOption('time_widget', TimeField::CHOICE, self::$timeWidgets);
-        $this->addOption('type', self::DATETIME, self::$types);
-        $this->addOption('with_seconds', false);
 
         $this->add(new DateField('date', array(
             'type' => DateField::RAW,
@@ -79,6 +103,7 @@ class DateTimeField extends FieldGroup
             'years' => $this->getOption('years'),
             'months' => $this->getOption('months'),
             'days' => $this->getOption('days'),
+            'pattern' => $this->getOption('date_pattern'),
         )));
         $this->add(new TimeField('time', array(
             'type' => TimeField::RAW,

+ 7 - 0
src/Symfony/Component/Form/IntegerField.php

@@ -24,6 +24,13 @@ use Symfony\Component\Form\ValueTransformer\NumberToLocalizedStringTransformer;
 /**
  * A localized field for entering integers.
  *
+ * The rounding-mode option defaults to rounding down. The available values are:
+ *  * NumberToLocalizedStringTransformer::ROUND_DOWN
+ *  * NumberToLocalizedStringTransformer::ROUND_UP
+ *  * NumberToLocalizedStringTransformer::ROUND_FLOOR
+ *  * NumberToLocalizedStringTransformer::ROUND_CEILING
+ *
+ * @see Symfony\Component\Form\NumberField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class IntegerField extends NumberField

+ 18 - 2
src/Symfony/Component/Form/LanguageField.php

@@ -14,8 +14,16 @@ namespace Symfony\Component\Form;
 use Symfony\Component\Locale\Locale;
 
 /**
- * A field for selecting from a list of languages
+ * A field for selecting from a list of languages.
  *
+ * In addition to the ChoiceField options, this field has the following
+ * options:
+ *
+ *  * empty_value:  If set to a non-false value, an "empty" option will
+ *                  be added to the top of the languages choices. A
+ *                  common value might be "Choose a language". Default: false.
+ *
+ * @see Symfony\Component\Form\ChoiceField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class LanguageField extends ChoiceField
@@ -25,7 +33,15 @@ class LanguageField extends ChoiceField
      */
     protected function configure()
     {
-        $this->addOption('choices', Locale::getDisplayLanguages($this->locale));
+        $this->addOption('empty_value', false);
+
+        $choices = Locale::getDisplayLanguages($this->locale);
+
+        if (false !== $this->getOption('empty_value')) {
+            $choices = array('' => $this->getOption('empty_value')) + $choices;
+        }
+
+        $this->addOption('choices', $choices);
 
         parent::configure();
     }

+ 18 - 2
src/Symfony/Component/Form/LocaleField.php

@@ -14,8 +14,16 @@ namespace Symfony\Component\Form;
 use Symfony\Component\Locale\Locale;
 
 /**
- * A field for selecting from a list of locales
+ * A field for selecting from a list of locales.
  *
+ * In addition to the ChoiceField options, this field has the following
+ * options:
+ *
+ *  * empty_value:  If set to a non-false value, an "empty" option will
+ *                  be added to the top of the locale choices. A
+ *                  common value might be "Choose a locale". Default: false.
+ *
+ * @see Symfony\Component\Form\ChoiceField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class LocaleField extends ChoiceField
@@ -25,7 +33,15 @@ class LocaleField extends ChoiceField
      */
     protected function configure()
     {
-        $this->addOption('choices', Locale::getDisplayLocales($this->locale));
+        $this->addOption('empty_value', false);
+
+        $choices = Locale::getDisplayLocales($this->locale);
+
+        if (false !== $this->getOption('empty_value')) {
+            $choices = array('' => $this->getOption('empty_value')) + $choices;
+        }
+
+        $this->addOption('choices', $choices);
 
         parent::configure();
     }

+ 13 - 2
src/Symfony/Component/Form/MoneyField.php

@@ -13,8 +13,19 @@ namespace Symfony\Component\Form;
 use Symfony\Component\Form\ValueTransformer\MoneyToLocalizedStringTransformer;
 
 /**
- * A localized field for entering money values
+ * A localized field for entering money values.
  *
+ * This field will output the money with the correct comma, period or spacing
+ * (e.g. 10,000) as well as the correct currency symbol in the correct location
+ * (i.e. before or after the field).
+ *
+ * Available options:
+ *
+ *  * currency:     The currency to display the money with. This is the 3-letter
+ *                  ISO 4217 currency code.
+ *  * divisor:      A number to divide the money by before displaying. Default 1.
+ * 
+ * @see Symfony\Component\Form\NumberField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class MoneyField extends NumberField
@@ -34,9 +45,9 @@ class MoneyField extends NumberField
      */
     protected function configure()
     {
+        $this->addRequiredOption('currency');
         $this->addOption('precision', 2);
         $this->addOption('divisor', 1);
-        $this->addOption('currency');
 
         parent::configure();
 

+ 15 - 0
src/Symfony/Component/Form/NumberField.php

@@ -16,6 +16,21 @@ use Symfony\Component\Form\ValueTransformer\NumberToLocalizedStringTransformer;
 /**
  * A localized field for entering numbers.
  *
+ * Available options:
+ *
+ *  * precision:        The number of digits to allow when rounding. Default
+ *                      is locale-specific.
+ *  * grouping:
+ *  * rounding-mode:    The method to use to round to get to the needed level
+ *                      of precision. Options include:
+ *                       * NumberToLocalizedStringTransformer::ROUND_FLOOR
+ *                       * NumberToLocalizedStringTransformer::ROUND_DOWN
+ *                       * NumberToLocalizedStringTransformer::ROUND_HALFDOWN
+ *                       * NumberToLocalizedStringTransformer::ROUND_HALFUP (default)
+ *                       * NumberToLocalizedStringTransformer::ROUND_UP
+ *                       * NumberToLocalizedStringTransformer::ROUND_CEILING
+ *
+ * @see \NumberFormatter
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class NumberField extends Field

+ 5 - 0
src/Symfony/Component/Form/PasswordField.php

@@ -14,6 +14,11 @@ namespace Symfony\Component\Form;
 /**
  * A field for entering a password.
  *
+ * Available options:
+ *
+ *  * always_empty      If true, the field will always render empty. Default: true.
+ *
+ * @see Symfony\Component\Form\TextField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class PasswordField extends TextField

+ 13 - 0
src/Symfony/Component/Form/PercentField.php

@@ -16,6 +16,19 @@ use Symfony\Component\Form\ValueTransformer\PercentToLocalizedStringTransformer;
 /**
  * A localized field for entering percentage values.
  *
+ * The percentage is always rendered in its large format (e.g. 75, not .75).
+ *
+ * Available options:
+ *
+ *  * percent_type:     How the source number is stored on the object
+ *                       * self::FRACTIONAL (e.g. stored as .75)
+ *                       * self::INTEGER (e.g. stored as 75)
+ *
+ * By default, the precision option is set to 0, meaning that decimal integer
+ * values will be rounded using the method specified in the rounding-mode
+ * option.
+ *
+ * @see Symfony\Component\Form\NumberField
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class PercentField extends NumberField

+ 7 - 2
src/Symfony/Component/Form/RepeatedField.php

@@ -12,7 +12,12 @@
 namespace Symfony\Component\Form;
 
 /**
- * A field for repeated input of values
+ * A field for repeated input of values.
+ *
+ * Available options:
+ *
+ *  * first_key:        The key to use for the first field.
+ *  * second_key:       The key to use for the second field.
  *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
@@ -25,7 +30,7 @@ class RepeatedField extends FieldGroup
     protected $prototype;
 
     /**
-     * Repeats the given field twice to verify the user's input
+     * Repeats the given field twice to verify the user's input.
      *
      * @param FieldInterface $innerField
      */

+ 4 - 0
src/Symfony/Component/Form/TextField.php

@@ -14,6 +14,10 @@ namespace Symfony\Component\Form;
 /**
  * A text input field.
  *
+ * Available options:
+ *
+ *  * max_length:       The max_length to give the field.
+ *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */
 class TextField extends Field

+ 25 - 3
src/Symfony/Component/Form/TimeField.php

@@ -17,6 +17,26 @@ use Symfony\Component\Form\ValueTransformer\DateTimeToStringTransformer;
 use Symfony\Component\Form\ValueTransformer\DateTimeToTimestampTransformer;
 use Symfony\Component\Form\ValueTransformer\ValueTransformerChain;
 
+/**
+ * Represents a time field.
+ *
+ * Available options:
+ *
+ *  * widget:         How to render the time field ("input" or "choice"). Default: "choice".
+ *  * type:           The type of the date stored on the object. Default: "datetime":
+ *                    * datetime:   A DateTime object;
+ *                    * string:     A raw string (e.g. 2011-05-01 12:30:00, Y-m-d H:i:s);
+ *                    * timestamp:  A unix timestamp (e.g. 1304208000).
+ *                    * raw:        An hour, minute, second array
+ *  * with_seconds    Whether or not to create a field for seconds. Default: false.
+ *
+ *  * hours:          An array of hours for the hour select tag.
+ *  * minutes:        An array of minutes for the minute select tag.
+ *  * seconds:        An array of seconds for the second select tag.
+ *
+ *  * data_timezone:  The timezone of the data. Default: UTC.
+ *  * user_timezone:  The timezone of the user entering a new value. Default: UTC.
+ */
 class TimeField extends FieldGroup
 {
     const INPUT = 'input';
@@ -44,14 +64,16 @@ class TimeField extends FieldGroup
      */
     protected function configure()
     {
+        $this->addOption('widget', self::CHOICE, self::$widgets);
+        $this->addOption('type', self::DATETIME, self::$types);
+        $this->addOption('with_seconds', false);
+
         $this->addOption('hours', range(0, 23));
         $this->addOption('minutes', range(0, 59));
         $this->addOption('seconds', range(0, 59));
-        $this->addOption('widget', self::CHOICE, self::$widgets);
-        $this->addOption('type', self::DATETIME, self::$types);
+
         $this->addOption('data_timezone', 'UTC');
         $this->addOption('user_timezone', 'UTC');
-        $this->addOption('with_seconds', false);
 
         if ($this->getOption('widget') == self::INPUT) {
             $this->add(new TextField('hour', array('max_length' => 2)));

+ 18 - 1
src/Symfony/Component/Form/TimezoneField.php

@@ -11,6 +11,15 @@
 
 namespace Symfony\Component\Form;
 
+/**
+ * Represents a field where each timezone is broken down by continent.
+ *
+ * Available options:
+ *
+ *  * empty_value:   If set to a non-false value, an "empty" option will
+ *                  be added to the top of the timezone choices. A
+ *                  common value might be "Choose a timezone". Default: false.
+ */
 class TimezoneField extends ChoiceField
 {
     /**
@@ -24,7 +33,15 @@ class TimezoneField extends ChoiceField
      */
     public function configure()
     {
-        $this->addOption('choices', self::getTimezoneChoices());
+        $this->addOption('empty_value', false);
+
+        $choices = self::getTimezoneChoices();
+
+        if (false !== $this->getOption('empty_value')) {
+            $choices = array('' => $this->getOption('empty_value')) + $choices;
+        }
+
+        $this->addOption('choices', $choices);
 
         parent::configure();
     }

+ 7 - 1
src/Symfony/Component/Form/UrlField.php

@@ -12,7 +12,13 @@
 namespace Symfony\Component\Form;
 
 /**
- * Field for entering URLs
+ * Field for entering URLs.
+ *
+ * Available options:
+ *
+ *  * default_protocol:     If specified, {default_protocol}:// (e.g. http://)
+ *                          will be prepended onto any input string that
+ *                          doesn't begin with the protocol.
  *
  * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  */

+ 20 - 0
tests/Symfony/Tests/Component/Form/CountryFieldTest.php

@@ -42,4 +42,24 @@ class CountryFieldTest extends \PHPUnit_Framework_TestCase
 
         $this->assertArrayNotHasKey('ZZ', $choices);
     }
+
+    public function testEmptyValueOption()
+    {
+        // empty_value false
+        $field = new CountryField('country', array('empty_value' => false));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayNotHasKey('', $choices);
+
+        // empty_value as a blank string
+        $field = new CountryField('country', array('empty_value' => ''));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('', $choices['']);
+
+        // empty_value as a normal string
+        $field = new CountryField('country', array('empty_value' => 'Choose a country'));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('Choose a country', $choices['']);
+    }
 }

+ 20 - 0
tests/Symfony/Tests/Component/Form/LanguageFieldTest.php

@@ -42,4 +42,24 @@ class LanguageFieldTest extends \PHPUnit_Framework_TestCase
 
         $this->assertArrayNotHasKey('mul', $choices);
     }
+
+    public function testEmptyValueOption()
+    {
+        // empty_value false
+        $field = new LanguageField('language', array('empty_value' => false));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayNotHasKey('', $choices);
+
+        // empty_value as a blank string
+        $field = new LanguageField('language', array('empty_value' => ''));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('', $choices['']);
+
+        // empty_value as a normal string
+        $field = new LanguageField('language', array('empty_value' => 'Choose a language'));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('Choose a language', $choices['']);
+    }
 }

+ 20 - 0
tests/Symfony/Tests/Component/Form/LocaleFieldTest.php

@@ -30,4 +30,24 @@ class LocaleFieldTest extends \PHPUnit_Framework_TestCase
         $this->assertArrayHasKey('zh_Hans_MO', $choices);
         $this->assertEquals('Chinesisch (vereinfacht, Sonderverwaltungszone Macao)', $choices['zh_Hans_MO']);
     }
+
+    public function testEmptyValueOption()
+    {
+        // empty_value false
+        $field = new LocaleField('language', array('empty_value' => false));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayNotHasKey('', $choices);
+
+        // empty_value as a blank string
+        $field = new LocaleField('language', array('empty_value' => ''));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('', $choices['']);
+
+        // empty_value as a normal string
+        $field = new LocaleField('language', array('empty_value' => 'Choose a locale'));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('Choose a locale', $choices['']);
+    }
 }

+ 51 - 0
tests/Symfony/Tests/Component/Form/TimezoneFieldTest.php

@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Form;
+
+use Symfony\Component\Form\TimezoneField;
+
+class TimezoneFieldTest extends \PHPUnit_Framework_TestCase
+{
+    public function testTimezonesAreSelectable()
+    {
+        $field = new TimeZoneField('timezone');
+        $choices = $field->getOtherChoices();
+
+        $this->assertArrayHasKey('Africa', $choices);
+        $this->assertArrayHasKey('Africa/Kinshasa', $choices['Africa']);
+        $this->assertEquals('Kinshasa', $choices['Africa']['Africa/Kinshasa']);
+
+        $this->assertArrayHasKey('America', $choices);
+        $this->assertArrayHasKey('America/New_York', $choices['America']);
+        $this->assertEquals('New York', $choices['America']['America/New_York']);
+    }
+
+    public function testEmptyValueOption()
+    {
+        // empty_value false
+        $field = new TimezoneField('timezone', array('empty_value' => false));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayNotHasKey('', $choices);
+
+        // empty_value as a blank string
+        $field = new TimezoneField('timezone', array('empty_value' => ''));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('', $choices['']);
+
+        // empty_value as a normal string
+        $field = new TimezoneField('timezone', array('empty_value' => 'Choose your timezone'));
+        $choices = $field->getOtherChoices();
+        $this->assertArrayHasKey('', $choices);
+        $this->assertEquals('Choose your timezone', $choices['']);
+    }
+}