PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php

https://github.com/nattaphat/hgis
PHP | 230 lines | 119 code | 25 blank | 86 comment | 18 complexity | be9d4516c23862ee6fbe6005ae92c1fd MD5 | raw file
  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\Extension\Core\DataTransformer;
  11. use Symfony\Component\Form\Exception\TransformationFailedException;
  12. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  13. /**
  14. * Transforms between a date string and a DateTime object
  15. *
  16. * @author Bernhard Schussek <bschussek@gmail.com>
  17. * @author Florian Eckerstorfer <florian@eckerstorfer.org>
  18. */
  19. class DateTimeToStringTransformer extends BaseDateTimeTransformer
  20. {
  21. /**
  22. * Format used for generating strings
  23. * @var string
  24. */
  25. private $generateFormat;
  26. /**
  27. * Format used for parsing strings
  28. *
  29. * Different than the {@link $generateFormat} because formats for parsing
  30. * support additional characters in PHP that are not supported for
  31. * generating strings.
  32. *
  33. * @var string
  34. */
  35. private $parseFormat;
  36. /**
  37. * Whether to parse by appending a pipe "|" to the parse format.
  38. *
  39. * This only works as of PHP 5.3.7.
  40. *
  41. * @var Boolean
  42. */
  43. private $parseUsingPipe;
  44. /**
  45. * Transforms a \DateTime instance to a string
  46. *
  47. * @see \DateTime::format() for supported formats
  48. *
  49. * @param string $inputTimezone The name of the input timezone
  50. * @param string $outputTimezone The name of the output timezone
  51. * @param string $format The date format
  52. * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format
  53. *
  54. * @throws UnexpectedTypeException if a timezone is not a string
  55. */
  56. public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null)
  57. {
  58. parent::__construct($inputTimezone, $outputTimezone);
  59. $this->generateFormat = $this->parseFormat = $format;
  60. // The pipe in the parser pattern only works as of PHP 5.3.7
  61. // See http://bugs.php.net/54316
  62. $this->parseUsingPipe = null === $parseUsingPipe
  63. ? version_compare(phpversion(), '5.3.7', '>=')
  64. : $parseUsingPipe;
  65. // See http://php.net/manual/en/datetime.createfromformat.php
  66. // The character "|" in the format makes sure that the parts of a date
  67. // that are *not* specified in the format are reset to the corresponding
  68. // values from 1970-01-01 00:00:00 instead of the current time.
  69. // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
  70. // where the time corresponds to the current server time.
  71. // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
  72. // which is at least deterministic and thus used here.
  73. if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) {
  74. $this->parseFormat .= '|';
  75. }
  76. }
  77. /**
  78. * Transforms a DateTime object into a date string with the configured format
  79. * and timezone
  80. *
  81. * @param \DateTime $value A DateTime object
  82. *
  83. * @return string A value as produced by PHP's date() function
  84. *
  85. * @throws UnexpectedTypeException if the given value is not a \DateTime instance
  86. * @throws TransformationFailedException if the output timezone is not supported
  87. */
  88. public function transform($value)
  89. {
  90. if (null === $value) {
  91. return '';
  92. }
  93. if (!$value instanceof \DateTime) {
  94. throw new UnexpectedTypeException($value, '\DateTime');
  95. }
  96. $value = clone $value;
  97. try {
  98. $value->setTimezone(new \DateTimeZone($this->outputTimezone));
  99. } catch (\Exception $e) {
  100. throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
  101. }
  102. return $value->format($this->generateFormat);
  103. }
  104. /**
  105. * Transforms a date string in the configured timezone into a DateTime object.
  106. *
  107. * @param string $value A value as produced by PHP's date() function
  108. *
  109. * @return \DateTime An instance of \DateTime
  110. *
  111. * @throws UnexpectedTypeException if the given value is not a string
  112. * @throws TransformationFailedException if the date could not be parsed
  113. * @throws TransformationFailedException if the input timezone is not supported
  114. */
  115. public function reverseTransform($value)
  116. {
  117. if (empty($value)) {
  118. return null;
  119. }
  120. if (!is_string($value)) {
  121. throw new UnexpectedTypeException($value, 'string');
  122. }
  123. try {
  124. $outputTz = new \DateTimeZone($this->outputTimezone);
  125. $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz);
  126. $lastErrors = \DateTime::getLastErrors();
  127. if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
  128. throw new TransformationFailedException(
  129. implode(', ', array_merge(
  130. array_values($lastErrors['warnings']),
  131. array_values($lastErrors['errors'])
  132. ))
  133. );
  134. }
  135. // On PHP versions < 5.3.7 we need to emulate the pipe operator
  136. // and reset parts not given in the format to their equivalent
  137. // of the UNIX base timestamp.
  138. if (!$this->parseUsingPipe) {
  139. list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s'));
  140. // Check which of the date parts are present in the pattern
  141. preg_match(
  142. '/(' .
  143. '(?P<day>[djDl])|' .
  144. '(?P<month>[FMmn])|' .
  145. '(?P<year>[Yy])|' .
  146. '(?P<hour>[ghGH])|' .
  147. '(?P<minute>i)|' .
  148. '(?P<second>s)|' .
  149. '(?P<dayofyear>z)|' .
  150. '(?P<timestamp>U)|' .
  151. '[^djDlFMmnYyghGHiszU]' .
  152. ')*/',
  153. $this->parseFormat,
  154. $matches
  155. );
  156. // preg_match() does not guarantee to set all indices, so
  157. // set them unless given
  158. $matches = array_merge(array(
  159. 'day' => false,
  160. 'month' => false,
  161. 'year' => false,
  162. 'hour' => false,
  163. 'minute' => false,
  164. 'second' => false,
  165. 'dayofyear' => false,
  166. 'timestamp' => false,
  167. ), $matches);
  168. // Reset all parts that don't exist in the format to the
  169. // corresponding part of the UNIX base timestamp
  170. if (!$matches['timestamp']) {
  171. if (!$matches['dayofyear']) {
  172. if (!$matches['day']) {
  173. $day = 1;
  174. }
  175. if (!$matches['month']) {
  176. $month = 1;
  177. }
  178. }
  179. if (!$matches['year']) {
  180. $year = 1970;
  181. }
  182. if (!$matches['hour']) {
  183. $hour = 0;
  184. }
  185. if (!$matches['minute']) {
  186. $minute = 0;
  187. }
  188. if (!$matches['second']) {
  189. $second = 0;
  190. }
  191. $dateTime->setDate($year, $month, $day);
  192. $dateTime->setTime($hour, $minute, $second);
  193. }
  194. }
  195. if ($this->inputTimezone !== $this->outputTimezone) {
  196. $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone));
  197. }
  198. } catch (TransformationFailedException $e) {
  199. throw $e;
  200. } catch (\Exception $e) {
  201. throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
  202. }
  203. return $dateTime;
  204. }
  205. }