DateTimeField.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form;
  11. use Symfony\Component\Form\ValueTransformer\ReversedTransformer;
  12. use Symfony\Component\Form\ValueTransformer\DateTimeToStringTransformer;
  13. use Symfony\Component\Form\ValueTransformer\DateTimeToTimestampTransformer;
  14. use Symfony\Component\Form\ValueTransformer\DateTimeToArrayTransformer;
  15. use Symfony\Component\Form\ValueTransformer\ValueTransformerChain;
  16. /**
  17. * A field for editing a date and a time simultaneously.
  18. *
  19. * Available options:
  20. *
  21. * * date_widget: How to render the date field ("input" or "choice"). Default: "choice".
  22. * * time_widget: How to render the time field ("input" or "choice"). Default: "choice".
  23. * * type: The type of the date stored on the object. Default: "datetime":
  24. * * datetime: A DateTime object;
  25. * * string: A raw string (e.g. 2011-05-01 12:30:00, Y-m-d H:i:s);
  26. * * timestamp: A unix timestamp (e.g. 1304208000).
  27. * * date_pattern: The pattern for the select boxes when date "widget" is "choice".
  28. * You can use the placeholders "{{ year }}", "{{ month }}" and "{{ day }}".
  29. * Default: locale dependent.
  30. * * with_seconds Whether or not to create a field for seconds. Default: false.
  31. *
  32. * * years: An array of years for the year select tag.
  33. * * months: An array of months for the month select tag.
  34. * * days: An array of days for the day select tag.
  35. * * hours: An array of hours for the hour select tag.
  36. * * minutes: An array of minutes for the minute select tag.
  37. * * seconds: An array of seconds for the second select tag.
  38. *
  39. * * date_format: The date format type to use for displaying the date. Default: medium.
  40. * * data_timezone: The timezone of the data. Default: UTC.
  41. * * user_timezone: The timezone of the user entering a new value. Default: UTC.
  42. *
  43. * @author Bernhard Schussek <bernhard.schussek@symfony.com>
  44. */
  45. class DateTimeField extends Form
  46. {
  47. const DATETIME = 'datetime';
  48. const STRING = 'string';
  49. const TIMESTAMP = 'timestamp';
  50. protected static $types = array(
  51. self::DATETIME,
  52. self::STRING,
  53. self::TIMESTAMP,
  54. );
  55. protected static $dateFormats = array(
  56. DateField::FULL,
  57. DateField::LONG,
  58. DateField::MEDIUM,
  59. DateField::SHORT,
  60. );
  61. protected static $dateWidgets = array(
  62. DateField::CHOICE,
  63. DateField::INPUT,
  64. );
  65. protected static $timeWidgets = array(
  66. TimeField::CHOICE,
  67. TimeField::INPUT,
  68. );
  69. /**
  70. * {@inheritDoc}
  71. */
  72. public function __construct($key, array $options = array())
  73. {
  74. // Override parent option
  75. // \DateTime objects are never edited by reference, because
  76. // we treat them like value objects
  77. $this->addOption('by_reference', false);
  78. parent::__construct($key, $options);
  79. }
  80. protected function configure()
  81. {
  82. $this->addOption('date_widget', DateField::CHOICE, self::$dateWidgets);
  83. $this->addOption('time_widget', TimeField::CHOICE, self::$timeWidgets);
  84. $this->addOption('type', self::DATETIME, self::$types);
  85. $this->addOption('date_pattern');
  86. $this->addOption('with_seconds', false);
  87. $this->addOption('years', range(date('Y') - 5, date('Y') + 5));
  88. $this->addOption('months', range(1, 12));
  89. $this->addOption('days', range(1, 31));
  90. $this->addOption('hours', range(0, 23));
  91. $this->addOption('minutes', range(0, 59));
  92. $this->addOption('seconds', range(0, 59));
  93. $this->addOption('data_timezone', date_default_timezone_get());
  94. $this->addOption('user_timezone', date_default_timezone_get());
  95. $this->addOption('date_format', DateField::MEDIUM, self::$dateFormats);
  96. $this->add(new DateField('date', array(
  97. 'type' => DateField::RAW,
  98. 'widget' => $this->getOption('date_widget'),
  99. 'format' => $this->getOption('date_format'),
  100. 'data_timezone' => $this->getOption('user_timezone'),
  101. 'user_timezone' => $this->getOption('user_timezone'),
  102. 'years' => $this->getOption('years'),
  103. 'months' => $this->getOption('months'),
  104. 'days' => $this->getOption('days'),
  105. 'pattern' => $this->getOption('date_pattern'),
  106. )));
  107. $this->add(new TimeField('time', array(
  108. 'type' => TimeField::RAW,
  109. 'widget' => $this->getOption('time_widget'),
  110. 'data_timezone' => $this->getOption('user_timezone'),
  111. 'user_timezone' => $this->getOption('user_timezone'),
  112. 'with_seconds' => $this->getOption('with_seconds'),
  113. 'hours' => $this->getOption('hours'),
  114. 'minutes' => $this->getOption('minutes'),
  115. 'seconds' => $this->getOption('seconds'),
  116. )));
  117. if ($this->getOption('type') == self::STRING) {
  118. $this->setNormalizationTransformer(new ReversedTransformer(
  119. new DateTimeToStringTransformer(array(
  120. 'input_timezone' => $this->getOption('data_timezone'),
  121. 'output_timezone' => $this->getOption('data_timezone'),
  122. ))
  123. ));
  124. } else if ($this->getOption('type') == self::TIMESTAMP) {
  125. $this->setNormalizationTransformer(new ReversedTransformer(
  126. new DateTimeToTimestampTransformer(array(
  127. 'input_timezone' => $this->getOption('data_timezone'),
  128. 'output_timezone' => $this->getOption('data_timezone'),
  129. ))
  130. ));
  131. }
  132. $this->setValueTransformer(new DateTimeToArrayTransformer(array(
  133. 'input_timezone' => $this->getOption('data_timezone'),
  134. 'output_timezone' => $this->getOption('user_timezone'),
  135. )));
  136. }
  137. /**
  138. * {@inheritDoc}
  139. */
  140. protected function transform($value)
  141. {
  142. $value = parent::transform($value);
  143. return array('date' => $value, 'time' => $value);
  144. }
  145. /**
  146. * {@inheritDoc}
  147. */
  148. protected function reverseTransform($value)
  149. {
  150. return parent::reverseTransform(array_merge($value['date'], $value['time']));
  151. }
  152. }