123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836 |
- <?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\Component\Form;
- use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
- use Symfony\Component\Form\ChoiceList\DefaultChoiceList;
- use Symfony\Component\Form\ChoiceList\PaddedChoiceList;
- use Symfony\Component\Form\ChoiceList\MonthChoiceList;
- use Symfony\Component\Form\ChoiceList\TimeZoneChoiceList;
- use Symfony\Component\Form\ChoiceList\EntityChoiceList;
- use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
- use Symfony\Component\Form\DataProcessor\RadioToArrayConverter;
- use Symfony\Component\Form\DataProcessor\UrlProtocolFixer;
- use Symfony\Component\Form\DataProcessor\CollectionMerger;
- use Symfony\Component\Form\FieldFactory\FieldFactoryInterface;
- use Symfony\Component\Form\Renderer\DefaultRenderer;
- use Symfony\Component\Form\Renderer\Theme\ThemeInterface;
- use Symfony\Component\Form\Renderer\Plugin\IdPlugin;
- use Symfony\Component\Form\Renderer\Plugin\NamePlugin;
- use Symfony\Component\Form\Renderer\Plugin\ParameterPlugin;
- use Symfony\Component\Form\Renderer\Plugin\ChoicePlugin;
- use Symfony\Component\Form\Renderer\Plugin\ParentNamePlugin;
- use Symfony\Component\Form\Renderer\Plugin\DatePatternPlugin;
- use Symfony\Component\Form\Renderer\Plugin\MoneyPatternPlugin;
- use Symfony\Component\Form\Renderer\Plugin\ValuePlugin;
- use Symfony\Component\Form\Renderer\Plugin\PasswordValuePlugin;
- use Symfony\Component\Form\Renderer\Plugin\SelectMultipleNamePlugin;
- use Symfony\Component\Form\ValueTransformer\BooleanToStringTransformer;
- use Symfony\Component\Form\ValueTransformer\NumberToLocalizedStringTransformer;
- use Symfony\Component\Form\ValueTransformer\IntegerToLocalizedStringTransformer;
- use Symfony\Component\Form\ValueTransformer\MoneyToLocalizedStringTransformer;
- use Symfony\Component\Form\ValueTransformer\PercentToLocalizedStringTransformer;
- use Symfony\Component\Form\ValueTransformer\ScalarToChoicesTransformer;
- use Symfony\Component\Form\ValueTransformer\DateTimeToArrayTransformer;
- use Symfony\Component\Form\ValueTransformer\DateTimeToStringTransformer;
- use Symfony\Component\Form\ValueTransformer\DateTimeToLocalizedStringTransformer;
- use Symfony\Component\Form\ValueTransformer\DateTimeToTimestampTransformer;
- use Symfony\Component\Form\ValueTransformer\ReversedTransformer;
- use Symfony\Component\Form\ValueTransformer\EntityToIdTransformer;
- use Symfony\Component\Form\ValueTransformer\EntitiesToArrayTransformer;
- use Symfony\Component\Form\ValueTransformer\ValueTransformerChain;
- use Symfony\Component\Form\ValueTransformer\ArrayToChoicesTransformer;
- use Symfony\Component\Form\ValueTransformer\ArrayToPartsTransformer;
- use Symfony\Component\Validator\ValidatorInterface;
- use Symfony\Component\Locale\Locale;
- class FormFactory
- {
- private $theme;
- private $csrfProvider;
- private $validator;
- private $fieldFactory;
- public function __construct(ThemeInterface $theme, CsrfProviderInterface $csrfProvider, ValidatorInterface $validator, FieldFactoryInterface $fieldFactory)
- {
- $this->theme = $theme;
- $this->csrfProvider = $csrfProvider;
- $this->validator = $validator;
- $this->fieldFactory = $fieldFactory;
- }
- protected function getTheme()
- {
- return $this->theme;
- }
- protected function getCsrfProvider()
- {
- return $this->csrfProvider;
- }
- protected function getValidator()
- {
- return $this->validator;
- }
- protected function getFieldFactory()
- {
- return $this->fieldFactory;
- }
- protected function initField(FieldInterface $field, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'text',
- 'data' => null,
- 'property_path' => (string)$field->getKey(),
- 'trim' => true,
- 'required' => true,
- 'disabled' => false,
- 'value_transformer' => null,
- 'normalization_transformer' => null,
- ), $options);
- return $field
- ->setData($options['data'])
- ->setPropertyPath($options['property_path'])
- ->setTrim($options['trim'])
- ->setRequired($options['required'])
- ->setDisabled($options['disabled'])
- ->setValueTransformer($options['value_transformer'])
- ->setNormalizationTransformer($options['normalization_transformer'])
- ->setRenderer(new DefaultRenderer($this->theme, $options['template']))
- ->addRendererPlugin(new IdPlugin($field))
- ->addRendererPlugin(new NamePlugin($field))
- ->addRendererPlugin(new ValuePlugin($field))
- ->setRendererVar('field', $field)
- ->setRendererVar('class', null)
- ->setRendererVar('max_length', null)
- ->setRendererVar('size', null)
- ->setRendererVar('label', ucfirst(strtolower(str_replace('_', ' ', $field->getKey()))));
- }
- protected function initForm(FormInterface $form, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'form',
- 'data_class' => null,
- 'data_constructor' => null,
- 'csrf_protection' => true,
- 'csrf_field_name' => '_token',
- 'csrf_provider' => $this->csrfProvider,
- 'field_factory' => $this->fieldFactory,
- 'validation_groups' => null,
- 'virtual' => false,
- 'validator' => $this->validator,
- ), $options);
- $this->initField($form, $options);
- if ($options['csrf_protection']) {
- $form->enableCsrfProtection($options['csrf_provider'], $options['csrf_field_name']);
- }
- return $form
- ->setDataClass($options['data_class'])
- ->setDataConstructor($options['data_constructor'])
- ->setFieldFactory($options['field_factory'])
- ->setValidationGroups($options['validation_groups'])
- ->setVirtual($options['virtual'])
- ->setValidator($options['validator']);
- }
- public function getField($key, array $options = array())
- {
- $field = new Field($key);
- $this->initField($field, $options);
- return $field;
- }
- public function getForm($key, array $options = array())
- {
- $form = new Form($key);
- $this->initForm($form, $options);
- return $form;
- }
- public function getTextField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'text',
- 'max_length' => null,
- ), $options);
- return $this->getField($key, $options)
- ->setRendererVar('max_length', $options['max_length']);
- }
- public function getTextareaField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'textarea',
- ), $options);
- return $this->getField($key, $options);
- }
- public function getPasswordField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'password',
- 'always_empty' => true,
- ), $options);
- $field = $this->getTextField($key, $options);
- return $field
- ->addRendererPlugin(new PasswordValuePlugin($field, $options['always_empty']));
- }
- public function getHiddenField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'hidden',
- ), $options);
- return $this->getField($key, $options)
- ->setHidden(true);
- }
- public function getNumberField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'number',
- // default precision is locale specific (usually around 3)
- 'precision' => null,
- 'grouping' => false,
- 'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALFUP,
- ), $options);
- return $this->getField($key, $options)
- ->setValueTransformer(new NumberToLocalizedStringTransformer(array(
- 'precision' => $options['precision'],
- 'grouping' => $options['grouping'],
- 'rounding-mode' => $options['rounding_mode'],
- )));
- }
- public function getIntegerField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'integer',
- // default precision is locale specific (usually around 3)
- 'precision' => null,
- 'grouping' => false,
- // Integer cast rounds towards 0, so do the same when displaying fractions
- 'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN,
- ), $options);
- return $this->getField($key, $options)
- ->setValueTransformer(new IntegerToLocalizedStringTransformer(array(
- 'precision' => $options['precision'],
- 'grouping' => $options['grouping'],
- 'rounding-mode' => $options['rounding_mode'],
- )));
- }
- public function getMoneyField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'money',
- 'precision' => 2,
- 'grouping' => false,
- 'divisor' => 1,
- 'currency' => 'EUR',
- ), $options);
- return $this->getField($key, $options)
- ->setValueTransformer(new MoneyToLocalizedStringTransformer(array(
- 'precision' => $options['precision'],
- 'grouping' => $options['grouping'],
- 'divisor' => $options['divisor'],
- )))
- ->addRendererPlugin(new MoneyPatternPlugin($options['currency']));
- }
- public function getPercentField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'percent',
- 'precision' => 0,
- 'type' => 'fractional',
- ), $options);
- return $this->getField($key, $options)
- ->setValueTransformer(new PercentToLocalizedStringTransformer(array(
- 'precision' => $options['precision'],
- 'type' => $options['type'],
- )));
- }
- public function getCheckboxField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'checkbox',
- 'value' => '1',
- ), $options);
- return $this->getField($key, $options)
- ->setValueTransformer(new BooleanToStringTransformer())
- ->setRendererVar('value', $options['value']);
- }
- public function getRadioField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'radio',
- 'value' => null,
- ), $options);
- $field = $this->getField($key, $options);
- return $field
- ->setValueTransformer(new BooleanToStringTransformer())
- ->addRendererPlugin(new ParentNamePlugin($field))
- ->setRendererVar('value', $options['value']);
- }
- public function getUrlField($key, array $options = array())
- {
- $options = array_merge(array(
- 'default_protocol' => 'http',
- ), $options);
- return $this->getTextField($key, $options)
- ->setDataProcessor(new UrlProtocolFixer($options['default_protocol']));
- }
- protected function getChoiceFieldForList($key, ChoiceListInterface $choiceList, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'choice',
- 'multiple' => false,
- 'expanded' => false,
- ), $options);
- if (!$options['expanded']) {
- $field = $this->getField($key, $options);
- } else {
- $field = $this->getForm($key, $options);
- $choices = array_replace($choiceList->getPreferredChoices(), $choiceList->getOtherChoices());
- foreach ($choices as $choice => $value) {
- if ($options['multiple']) {
- $field->add($this->getCheckboxField($choice, array(
- 'value' => $choice,
- )));
- } else {
- $field->add($this->getRadioField($choice, array(
- 'value' => $choice,
- )));
- }
- }
- }
- $field->addRendererPlugin(new ChoicePlugin($choiceList))
- ->setRendererVar('multiple', $options['multiple'])
- ->setRendererVar('expanded', $options['expanded']);
- if ($options['multiple'] && $options['expanded']) {
- $field->setValueTransformer(new ArrayToChoicesTransformer($choiceList));
- }
- if (!$options['multiple'] && $options['expanded']) {
- $field->setValueTransformer(new ScalarToChoicesTransformer($choiceList));
- $field->setDataPreprocessor(new RadioToArrayConverter());
- }
- if ($options['multiple'] && !$options['expanded']) {
- $field->addRendererPlugin(new SelectMultipleNamePlugin($field));
- }
- return $field;
- }
- public function getChoiceField($key, array $options = array())
- {
- $options = array_merge(array(
- 'choices' => array(),
- 'preferred_choices' => array(),
- ), $options);
- $choiceList = new DefaultChoiceList(
- $options['choices'],
- $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- public function getEntityChoiceField($key, array $options = array())
- {
- $options = array_merge(array(
- 'em' => null,
- 'class' => null,
- 'property' => null,
- 'query_builder' => null,
- 'choices' => array(),
- 'preferred_choices' => array(),
- 'multiple' => false,
- 'expanded' => false,
- ), $options);
- $choiceList = new EntityChoiceList(
- $options['em'],
- $options['class'],
- $options['property'],
- $options['query_builder'],
- $options['choices'],
- $options['preferred_choices']
- );
- $field = $this->getChoiceFieldForList($key, $choiceList, $options);
- $transformers = array();
- if ($options['multiple']) {
- $field->setDataProcessor(new CollectionMerger($field));
- $transformers[] = new EntitiesToArrayTransformer($choiceList);
- if ($options['expanded']) {
- $transformers[] = new ArrayToChoicesTransformer($choiceList);
- }
- } else {
- $transformers[] = new EntityToIdTransformer($choiceList);
- if ($options['expanded']) {
- $transformers[] = new ScalarToChoicesTransformer($choiceList);
- }
- }
- if (count($transformers) > 1) {
- $field->setValueTransformer(new ValueTransformerChain($transformers));
- } else {
- $field->setValueTransformer(current($transformers));
- }
- return $field;
- }
- public function getCountryField($key, array $options = array())
- {
- $options = array_merge(array(
- 'choices' => Locale::getDisplayCountries(\Locale::getDefault()),
- ), $options);
- return $this->getChoiceField($key, $options);
- }
- public function getLanguageField($key, array $options = array())
- {
- $options = array_merge(array(
- 'choices' => Locale::getDisplayLanguages(\Locale::getDefault()),
- ), $options);
- return $this->getChoiceField($key, $options);
- }
- public function getLocaleField($key, array $options = array())
- {
- $options = array_merge(array(
- 'choices' => Locale::getDisplayLocales(\Locale::getDefault()),
- ), $options);
- return $this->getChoiceField($key, $options);
- }
- public function getTimeZoneField($key, array $options = array())
- {
- $options = array_merge(array(
- 'preferred_choices' => array(),
- ), $options);
- $choiceList = new TimeZoneChoiceList($options['preferred_choices']);
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- protected function getDayField($key, array $options = array())
- {
- $options = array_merge(array(
- 'days' => range(1, 31),
- 'preferred_choices' => array(),
- ), $options);
- $choiceList = new PaddedChoiceList(
- $options['days'], 2, '0', STR_PAD_LEFT, $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- protected function getMonthField($key, \IntlDateFormatter $formatter, array $options = array())
- {
- $options = array_merge(array(
- 'months' => range(1, 12),
- 'preferred_choices' => array(),
- ), $options);
- $choiceList = new MonthChoiceList(
- $formatter, $options['months'], $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- protected function getYearField($key, array $options = array())
- {
- $options = array_merge(array(
- 'years' => range(date('Y') - 5, date('Y') + 5),
- 'preferred_choices' => array(),
- ), $options);
- $choiceList = new PaddedChoiceList(
- $options['years'], 4, '0', STR_PAD_LEFT, $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- protected function getHourField($key, array $options = array())
- {
- $options = array_merge(array(
- 'widget' => 'choice',
- 'hours' => range(0, 23),
- 'preferred_choices' => array(),
- ), $options);
- if ($options['widget'] == 'text') {
- return $this->getTextField($key, array('max_length' => 2));
- } else {
- $choiceList = new PaddedChoiceList(
- $options['hours'], 2, '0', STR_PAD_LEFT, $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- }
- protected function getMinuteField($key, array $options = array())
- {
- $options = array_merge(array(
- 'widget' => 'choice',
- 'minutes' => range(0, 59),
- 'preferred_choices' => array(),
- ), $options);
- if ($options['widget'] == 'text') {
- return $this->getTextField($key, array('max_length' => 2));
- } else {
- $choiceList = new PaddedChoiceList(
- $options['minutes'], 2, '0', STR_PAD_LEFT, $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- }
- protected function getSecondField($key, array $options = array())
- {
- $options = array_merge(array(
- 'widget' => 'choice',
- 'seconds' => range(0, 59),
- 'preferred_choices' => array(),
- ), $options);
- if ($options['widget'] == 'text') {
- return $this->getTextField($key, array('max_length' => 2));
- } else {
- $choiceList = new PaddedChoiceList(
- $options['seconds'], 2, '0', STR_PAD_LEFT, $options['preferred_choices']
- );
- return $this->getChoiceFieldForList($key, $choiceList, $options);
- }
- }
- public function getDateField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'date',
- 'widget' => 'choice',
- 'type' => 'datetime',
- 'pattern' => null,
- 'format' => \IntlDateFormatter::MEDIUM,
- 'data_timezone' => date_default_timezone_get(),
- 'user_timezone' => date_default_timezone_get(),
- ), $options);
- $formatter = new \IntlDateFormatter(
- \Locale::getDefault(),
- $options['format'],
- \IntlDateFormatter::NONE
- );
- if ($options['widget'] === 'text') {
- $field = $this->getField($key, $options)
- ->setValueTransformer(new DateTimeToLocalizedStringTransformer(array(
- 'date_format' => $options['format'],
- 'time_format' => \IntlDateFormatter::NONE,
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['user_timezone'],
- )));
- } else {
- // Only pass a subset of the options to children
- $childOptions = array_intersect_key($options, array_flip(array(
- 'years',
- 'months',
- 'days',
- )));
- $field = $this->getForm($key, $options)
- ->add($this->getYearField('year', $childOptions))
- ->add($this->getMonthField('month', $formatter, $childOptions))
- ->add($this->getDayField('day', $childOptions))
- ->setValueTransformer(new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['user_timezone'],
- 'fields' => array('year', 'month', 'day'),
- )))
- ->addRendererPlugin(new DatePatternPlugin($formatter))
- // Don't modify \DateTime classes by reference, we treat
- // them like immutable value objects
- ->setModifyByReference(false);
- }
- if ($options['type'] === 'string') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToStringTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- 'format' => 'Y-m-d',
- ))
- ));
- } else if ($options['type'] === 'timestamp') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToTimestampTransformer(array(
- 'output_timezone' => $options['data_timezone'],
- 'input_timezone' => $options['data_timezone'],
- ))
- ));
- } else if ($options['type'] === 'array') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- 'fields' => array('year', 'month', 'day'),
- ))
- ));
- }
- $field->setRendererVar('widget', $options['widget']);
- return $field;
- }
- public function getBirthdayField($key, array $options = array())
- {
- $options = array_merge(array(
- 'years' => range($currentYear-120, $currentYear),
- ), $options);
- return $this->getDateField($key, $options);
- }
- public function getTimeField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'time',
- 'widget' => 'choice',
- 'type' => 'datetime',
- 'with_seconds' => false,
- 'pattern' => null,
- 'data_timezone' => date_default_timezone_get(),
- 'user_timezone' => date_default_timezone_get(),
- ), $options);
- // Only pass a subset of the options to children
- $childOptions = array_intersect_key($options, array_flip(array(
- 'hours',
- 'minutes',
- 'seconds',
- 'widget',
- )));
- $parts = array('hour', 'minute');
- $field = $this->getForm($key, $options)
- ->add($this->getHourField('hour', $childOptions))
- ->add($this->getMinuteField('minute', $childOptions))
- // Don't modify \DateTime classes by reference, we treat
- // them like immutable value objects
- ->setModifyByReference(false);
- if ($options['with_seconds']) {
- $parts[] = 'second';
- $field->add($this->getSecondField('second', $childOptions));
- }
- if ($options['type'] == 'string') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToStringTransformer(array(
- 'format' => 'H:i:s',
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- ))
- ));
- } else if ($options['type'] == 'timestamp') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToTimestampTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- ))
- ));
- } else if ($options['type'] === 'array') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- 'fields' => $parts,
- ))
- ));
- }
- $field
- ->setValueTransformer(new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['user_timezone'],
- // if the field is rendered as choice field, the values should be trimmed
- // of trailing zeros to render the selected choices correctly
- 'pad' => $options['widget'] === 'text',
- 'fields' => $parts,
- )))
- ->setRendererVar('widget', $options['widget'])
- ->setRendererVar('with_seconds', $options['with_seconds']);
- return $field;
- }
- public function getDateTimeField($key, array $options = array())
- {
- $options = array_merge(array(
- 'template' => 'datetime',
- 'type' => 'datetime',
- 'with_seconds' => false,
- 'data_timezone' => date_default_timezone_get(),
- 'user_timezone' => date_default_timezone_get(),
- ), $options);
- // Only pass a subset of the options to children
- $dateFieldOptions = array_intersect_key($options, array_flip(array(
- 'years',
- 'months',
- 'days',
- )));
- $timeFieldOptions = array_intersect_key($options, array_flip(array(
- 'hours',
- 'minutes',
- 'seconds',
- 'with_seconds',
- )));
- if (isset($options['date_pattern'])) {
- $dateFieldOptions['pattern'] = $options['date_pattern'];
- }
- if (isset($options['date_widget'])) {
- $dateFieldOptions['widget'] = $options['date_widget'];
- }
- if (isset($options['date_format'])) {
- $dateFieldOptions['format'] = $options['date_format'];
- }
- $dateFieldOptions['type'] = 'array';
- if (isset($options['time_pattern'])) {
- $timeFieldOptions['pattern'] = $options['time_pattern'];
- }
- if (isset($options['time_widget'])) {
- $timeFieldOptions['widget'] = $options['time_widget'];
- }
- if (isset($options['time_format'])) {
- $timeFieldOptions['format'] = $options['time_format'];
- }
- $timeFieldOptions['type'] = 'array';
- $parts = array('year', 'month', 'day', 'hour', 'minute');
- $timeParts = array('hour', 'minute');
- if ($options['with_seconds']) {
- $parts[] = 'second';
- $timeParts[] = 'second';
- }
- $field = $this->getForm($key, $options)
- ->setValueTransformer(new ValueTransformerChain(array(
- new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['user_timezone'],
- )),
- new ArrayToPartsTransformer(array(
- 'date' => array('year', 'month', 'day'),
- 'time' => $timeParts,
- )),
- )))
- ->add($this->getDateField('date', $dateFieldOptions))
- ->add($this->getTimeField('time', $timeFieldOptions))
- // Don't modify \DateTime classes by reference, we treat
- // them like immutable value objects
- ->setModifyByReference(false)
- ->setData(null); // hack: should be invoked automatically
- if ($options['type'] == 'string') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToStringTransformer(array(
- 'format' => 'Y-m-d H:i:s',
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- ))
- ));
- } else if ($options['type'] == 'timestamp') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToTimestampTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- ))
- ));
- } else if ($options['type'] === 'array') {
- $field->setNormalizationTransformer(new ReversedTransformer(
- new DateTimeToArrayTransformer(array(
- 'input_timezone' => $options['data_timezone'],
- 'output_timezone' => $options['data_timezone'],
- 'fields' => $parts,
- ))
- ));
- }
- return $field;
- }
- }
|