Explorar el Código

Added to `DateTimeType` extension possibility to render form as `single_text` (similar to `DateType` option) (issue #1323 it requires fix for #1205)

stloyd hace 14 años
padre
commit
7bc19f9675

+ 11 - 7
src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

@@ -71,12 +71,16 @@
 
 {% block datetime_widget %}
 {% spaceless %}
-    <div {{ block('widget_container_attributes') }}>
-        {{ form_errors(form.date) }}
-        {{ form_errors(form.time) }}
-        {{ form_widget(form.date) }}
-        {{ form_widget(form.time) }}
-    </div>
+    {% if widget == 'single_text' %}
+        {{ block('field_widget') }}
+    {% else %}
+        <div {{ block('widget_container_attributes') }}>
+            {{ form_errors(form.date) }}
+            {{ form_errors(form.time) }}
+            {{ form_widget(form.date) }}
+            {{ form_widget(form.time) }}
+        </div>
+    {% endif %}
 {% endspaceless %}
 {% endblock datetime_widget %}
 
@@ -99,7 +103,7 @@
 {% block time_widget %}
 {% spaceless %}
     {% if widget == 'single_text' %}
-        {{ block('text_widget') }}
+        {{ block('field_widget') }}
     {% 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 %}

+ 9 - 5
src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/datetime_widget.html.php

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

+ 83 - 51
src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php

@@ -12,7 +12,9 @@
 namespace Symfony\Component\Form\Extension\Core\Type;
 
 use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormInterface;
 use Symfony\Component\Form\FormBuilder;
+use Symfony\Component\Form\FormView;
 use Symfony\Component\Form\ReversedTransformer;
 use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
 use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
@@ -27,38 +29,6 @@ class DateTimeType extends AbstractType
      */
     public function buildForm(FormBuilder $builder, array $options)
     {
-        // Only pass a subset of the options to children
-        $dateOptions = array_intersect_key($options, array_flip(array(
-            'years',
-            'months',
-            'days',
-            'empty_value',
-            'required',
-        )));
-        $timeOptions = array_intersect_key($options, array_flip(array(
-            'hours',
-            'minutes',
-            'seconds',
-            'with_seconds',
-            'empty_value',
-            'required',
-        )));
-
-        if (isset($options['date_widget'])) {
-            $dateOptions['widget'] = $options['date_widget'];
-        }
-        if (isset($options['date_format'])) {
-            $dateOptions['format'] = $options['date_format'];
-        }
-
-        $dateOptions['input'] = 'array';
-
-        if (isset($options['time_widget'])) {
-            $timeOptions['widget'] = $options['time_widget'];
-        }
-
-        $timeOptions['input'] = 'array';
-
         $parts = array('year', 'month', 'day', 'hour', 'minute');
         $timeParts = array('hour', 'minute');
 
@@ -67,17 +37,54 @@ class DateTimeType extends AbstractType
             $timeParts[] = 'second';
         }
 
-        $builder
-            ->appendClientTransformer(new DataTransformerChain(array(
-                new DateTimeToArrayTransformer($options['data_timezone'], $options['user_timezone'], $parts),
-                new ArrayToPartsTransformer(array(
-                    'date' => array('year', 'month', 'day'),
-                    'time' => $timeParts,
-                )),
-            )))
-            ->add('date', 'date', $dateOptions)
-            ->add('time', 'time', $timeOptions)
-        ;
+        // If `widget` is set to `single_text`, ignore widget options from `date` and `time`
+        if ($options['widget'] === 'single_text') {
+            $builder->appendClientTransformer(new DateTimeToStringTransformer($options['data_timezone'], $options['user_timezone'], 'Y-m-d H:i:s'));
+        } else {
+            // Only pass a subset of the options to children
+            $dateOptions = array_intersect_key($options, array_flip(array(
+                'years',
+                'months',
+                'days',
+                'empty_value',
+                'required',
+            )));
+            $timeOptions = array_intersect_key($options, array_flip(array(
+                'hours',
+                'minutes',
+                'seconds',
+                'with_seconds',
+                'empty_value',
+                'required',
+            )));
+
+            if (isset($options['date_widget'])) {
+                $dateOptions['widget'] = $options['date_widget'];
+            }
+            if (isset($options['date_format'])) {
+                $dateOptions['format'] = $options['date_format'];
+            }
+
+            $dateOptions['input'] = 'array';
+
+            if (isset($options['time_widget'])) {
+                $timeOptions['widget'] = $options['time_widget'];
+            }
+
+            $timeOptions['input'] = 'array';
+
+            $builder
+                ->appendClientTransformer(new DataTransformerChain(array(
+                    new DateTimeToArrayTransformer($options['data_timezone'], $options['user_timezone'], $parts),
+                    new ArrayToPartsTransformer(array(
+                        'date' => array('year', 'month', 'day'),
+                        'time' => $timeParts,
+                    )),
+                )))
+                ->add('date', 'date', $dateOptions)
+                ->add('time', 'time', $timeOptions)
+            ;
+        }
 
         if ($options['input'] === 'string') {
             $builder->appendNormTransformer(new ReversedTransformer(
@@ -92,6 +99,16 @@ class DateTimeType extends AbstractType
                 new DateTimeToArrayTransformer($options['data_timezone'], $options['data_timezone'], $parts)
             ));
         }
+
+        $builder->setAttribute('widget', $options['widget']);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function buildView(FormView $view, FormInterface $form)
+    {
+        $view->set('widget', $form->getAttribute('widget'));
     }
 
     /**
@@ -101,12 +118,10 @@ class DateTimeType extends AbstractType
     {
         return array(
             'input'         => 'datetime',
+            // This will overwrite "widget" child options
+            'widget'        => null,
             'data_timezone' => null,
             'user_timezone' => null,
-            'empty_value'   => null,
-            // Don't modify \DateTime classes by reference, we treat
-            // them like immutable value objects
-            'by_reference'  => false,
             'date_widget'   => null,
             'date_format'   => null,
             'time_widget'   => null,
@@ -119,6 +134,9 @@ class DateTimeType extends AbstractType
             'minutes'       => range(0, 59),
             'seconds'       => range(0, 59),
             'with_seconds'  => false,
+            // Don't modify \DateTime classes by reference, we treat
+            // them like immutable value objects
+            'by_reference'  => false,
         );
     }
 
@@ -128,34 +146,48 @@ class DateTimeType extends AbstractType
     public function getAllowedOptionValues(array $options)
     {
         return array(
-            'input'         => array(
+            'input'       => array(
                 'datetime',
                 'string',
                 'timestamp',
                 'array',
             ),
-            'date_widget'   => array(
+            'date_widget' => array(
                 null, // inherit default from DateType
                 'single_text',
                 'text',
                 'choice',
             ),
-            'date_format'   => array(
+            'date_format' => array(
                 null, // inherit default from DateType
                 \IntlDateFormatter::FULL,
                 \IntlDateFormatter::LONG,
                 \IntlDateFormatter::MEDIUM,
                 \IntlDateFormatter::SHORT,
              ),
-            'time_widget'   => array(
+            'time_widget' => array(
                 null, // inherit default from TimeType
                 'single_text',
                 'text',
                 'choice',
             ),
+            // This option will overwrite "date_widget" and "time_widget" options
+            'widget'     => array(
+                'single_text',
+                'text',
+                'choice',
+            ),
         );
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function getParent(array $options)
+    {
+        return $options['widget'] === 'single_text' ? 'field' : 'form';
+    }
+
     /**
      * {@inheritdoc}
      */

+ 4 - 2
src/Symfony/Component/Form/Extension/Core/Type/TimeType.php

@@ -31,7 +31,8 @@ class TimeType extends AbstractType
         if ($options['widget'] === 'single_text') {
             $builder->appendClientTransformer(new DateTimeToStringTransformer($options['data_timezone'], $options['user_timezone'], 'H:i:s'));
         } else if ($options['widget'] === 'choice') {
-            if (is_array($options['empty_value'])) {                $options['empty_value'] = array_merge(array('hour' => null, 'minute' => null, 'second' => null), $options['empty_value']);
+            if (is_array($options['empty_value'])) {
+                $options['empty_value'] = array_merge(array('hour' => null, 'minute' => null, 'second' => null), $options['empty_value']);
             } else {
                 $options['empty_value'] = array('hour' => $options['empty_value'], 'minute' => $options['empty_value'], 'second' => $options['empty_value']);
             }
@@ -65,9 +66,10 @@ class TimeType extends AbstractType
         }
 
         $parts = array('hour', 'minute');
-        if ($options['with_seconds']) {        if ($options['with_seconds']) {
+        if ($options['with_seconds']) {
             $parts[] = 'second';
         }
+
         if ($options['input'] === 'string') {
             $builder->appendNormTransformer(new ReversedTransformer(
                 new DateTimeToStringTransformer($options['data_timezone'], $options['data_timezone'], 'H:i:s')

+ 27 - 18
tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php

@@ -810,6 +810,7 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
 '
         );
     }
+
     public function testDateTimeWithEmptyValueOnTime()
     {
         $form = $this->factory->createNamed('datetime', 'na&me', '2011-02-03', array(
@@ -913,38 +914,46 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
             [@value="Feb 3, 2011"]
         /following-sibling::input
             [@type="text"]
-            [@name="na&me[time]"]
             [@id="na&me_time"]
+            [@name="na&me[time]"]
             [@value="04:05:00"]
     ]
 '
         );
     }
 
-    public function testDateTimeWithSecondsSingleText()
+    public function testDateTimeWithWidgetSingleText()
     {
         $form = $this->factory->createNamed('datetime', 'name', '2011-02-03 04:05:06', array(
             'property_path' => 'name',
             'input' => 'string',
-            'date_widget' => 'single_text',
-            'time_widget' => 'single_text',
-            'with_seconds' => true,
+            'widget' => 'single_text',
         ));
 
         $this->assertWidgetMatchesXpath($form->createView(), array(),
-'/div
-    [
-        ./input
-            [@type="text"]
-            [@id="name_date"]
-            [@name="name[date]"]
-            [@value="Feb 3, 2011"]
-        /following-sibling::input
-            [@type="text"]
-            [@name="name[time]"]
-            [@id="name_time"]
-            [@value="04:05:06"]
-    ]
+'/input
+    [@type="text"]
+    [@name="name"]
+    [@value="2011-02-03 04:05:06"]
+'
+        );
+    }
+
+    public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets()
+    {
+        $form = $this->factory->createNamed('datetime', 'na&me', '2011-02-03 04:05:06', array(
+            'property_path' => 'name',
+            'input' => 'string',
+            'date_widget' => 'choice',
+            'time_widget' => 'choice',
+            'widget' => 'single_text',
+        ));
+
+        $this->assertWidgetMatchesXpath($form->createView(), array(),
+'/input
+    [@type="text"]
+    [@name="na&me"]
+    [@value="2011-02-03 04:05:06"]
 '
         );
     }

+ 15 - 0
tests/Symfony/Tests/Component/Form/Extension/Core/Type/DateTimeTypeTest.php

@@ -160,4 +160,19 @@ class DateTimeTypeTest extends LocalizedTestCase
 
         $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData());
     }
+
+    public function testSubmit_stringSingleText()
+    {
+        $form = $this->factory->create('datetime', null, array(
+            'data_timezone' => 'UTC',
+            'user_timezone' => 'UTC',
+            'input' => 'string',
+            'widget' => 'single_text',
+        ));
+
+        $form->bind('2010-06-02 03:04:00');
+
+        $this->assertEquals('2010-06-02 03:04:00', $form->getData());
+        $this->assertEquals('2010-06-02 03:04:00', $form->getClientData());
+    }
 }