PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/matijabelec/bigpandadev
PHP | 231 lines | 119 code | 26 blank | 86 comment | 21 complexity | e2ef91059fde6a6d4415e7d8395e538c 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. *
  24. * @var string
  25. */
  26. private $generateFormat;
  27. /**
  28. * Format used for parsing strings.
  29. *
  30. * Different than the {@link $generateFormat} because formats for parsing
  31. * support additional characters in PHP that are not supported for
  32. * generating strings.
  33. *
  34. * @var string
  35. */
  36. private $parseFormat;
  37. /**
  38. * Whether to parse by appending a pipe "|" to the parse format.
  39. *
  40. * This only works as of PHP 5.3.7.
  41. *
  42. * @var bool
  43. */
  44. private $parseUsingPipe;
  45. /**
  46. * Transforms a \DateTime instance to a string.
  47. *
  48. * @see \DateTime::format() for supported formats
  49. *
  50. * @param string $inputTimezone The name of the input timezone
  51. * @param string $outputTimezone The name of the output timezone
  52. * @param string $format The date format
  53. * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format
  54. *
  55. * @throws UnexpectedTypeException if a timezone is not a string
  56. */
  57. public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = true)
  58. {
  59. parent::__construct($inputTimezone, $outputTimezone);
  60. $this->generateFormat = $this->parseFormat = $format;
  61. $this->parseUsingPipe = $parseUsingPipe || null === $parseUsingPipe;
  62. // See http://php.net/manual/en/datetime.createfromformat.php
  63. // The character "|" in the format makes sure that the parts of a date
  64. // that are *not* specified in the format are reset to the corresponding
  65. // values from 1970-01-01 00:00:00 instead of the current time.
  66. // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
  67. // where the time corresponds to the current server time.
  68. // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
  69. // which is at least deterministic and thus used here.
  70. if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) {
  71. $this->parseFormat .= '|';
  72. }
  73. }
  74. /**
  75. * Transforms a DateTime object into a date string with the configured format
  76. * and timezone.
  77. *
  78. * @param \DateTime|\DateTimeInterface $dateTime A DateTime object
  79. *
  80. * @return string A value as produced by PHP's date() function
  81. *
  82. * @throws TransformationFailedException If the given value is not a \DateTime
  83. * instance or if the output timezone
  84. * is not supported.
  85. */
  86. public function transform($value)
  87. {
  88. if (null === $value) {
  89. return '';
  90. }
  91. if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
  92. throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
  93. }
  94. if (!$value instanceof \DateTimeImmutable) {
  95. $value = clone $value;
  96. }
  97. try {
  98. $value = $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 TransformationFailedException If the given value is not a string,
  112. * if the date could not be parsed or
  113. * if the input timezone is not supported.
  114. */
  115. public function reverseTransform($value)
  116. {
  117. if (empty($value)) {
  118. return;
  119. }
  120. if (!is_string($value)) {
  121. throw new TransformationFailedException('Expected a 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. }