merged branch stloyd/datetimetype (PR #1419)
Commits -------aeaf44a
Removed unused code from DateTimeType3c2539f
Throw exception when "date_widget" option is not equal to "time_widget"305c476
Overwrite child options ("widget", "empty_value") if any given7bc19f9
Added to `DateTimeType` extension possibility to render form as `single_text` (similar to `DateType` option) (issue #1323 it requires fix for #1205)17b41b2
Added to `TimeType` extension possibility to render form as `single_text` (similar to DateType option) (issue #1205) Adjusted `DateTimeType` to allow usage of this new feature Discussion ---------- [Form][DateTimeType] Added "widget" and "empty_value" options Hey, I have just added "widget" and "empty_value" options to `DateTimeType`: * `widget` option will overwrite existing `date_widget` and `time_widget`, * `empty_value` behave exacly same way as it does for `ChoiceType`, `DateType` and `TimeType` Also added and `FormException` when `date_widget` is not equal to `time_widget`, now is throwed non intuitive one (this will be changed in next days to allow different values for this options). Closes #1323
This commit is contained in:
commit
cca21a84e3
@ -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 %}
|
||||
|
||||
|
@ -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 ?>
|
||||
|
@ -12,8 +12,11 @@
|
||||
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\Exception\FormException;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
|
||||
@ -27,38 +30,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 +38,63 @@ 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 ($options['date_widget'] !== $options['time_widget']) {
|
||||
throw new FormException(sprintf('Options "date_widget" and "time_widget" need to be identical. Used: "date_widget" = "%s" and "time_widget" = "%s".', $options['date_widget'] ?: 'choice', $options['time_widget'] ?: 'choice'));
|
||||
}
|
||||
|
||||
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 `widget` is set, overwrite widget options from `date` and `time`
|
||||
if (isset($options['widget'])) {
|
||||
$dateOptions['widget'] = $options['widget'];
|
||||
$timeOptions['widget'] = $options['widget'];
|
||||
} else {
|
||||
if (isset($options['date_widget'])) {
|
||||
$dateOptions['widget'] = $options['date_widget'];
|
||||
}
|
||||
|
||||
if (isset($options['time_widget'])) {
|
||||
$timeOptions['widget'] = $options['time_widget'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($options['date_format'])) {
|
||||
$dateOptions['format'] = $options['date_format'];
|
||||
}
|
||||
|
||||
$dateOptions['input'] = 'array';
|
||||
$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 +109,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'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,10 +130,6 @@ class DateTimeType extends AbstractType
|
||||
'input' => 'datetime',
|
||||
'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 +142,13 @@ 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,
|
||||
// This will overwrite "widget" child options
|
||||
'widget' => null,
|
||||
// This will overwrite "empty_value" child options
|
||||
'empty_value' => null,
|
||||
);
|
||||
}
|
||||
|
||||
@ -128,34 +158,49 @@ 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(
|
||||
null, // default, don't overwrite options
|
||||
'single_text',
|
||||
'text',
|
||||
'choice',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent(array $options)
|
||||
{
|
||||
return $options['widget'] === 'single_text' ? 'field' : 'form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -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"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
@ -160,4 +160,40 @@ 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testDifferentWidgets()
|
||||
{
|
||||
$form = $this->factory->create('datetime', null, array(
|
||||
'date_widget' => 'single_text',
|
||||
'time_widget' => 'choice',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testDefinedOnlyOneWidget()
|
||||
{
|
||||
$form = $this->factory->create('datetime', null, array(
|
||||
'date_widget' => 'single_text',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user