1: <?php
2: namespace TIC\FormBundle\Form\DataTransformer;
3:
4: use Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer;
5: use Symfony\Component\Form\Exception\TransformationFailedException;
6:
7: /**
8: * Transforms between a time string and a DateTime object.
9: */
10: class StringToTimeTransformer extends BaseDateTimeTransformer
11: {
12: /**
13: * Format used for generating strings.
14: *
15: * @var string
16: */
17: private $generateFormat = 'H:i:s';
18:
19: /**
20: * Transforms a \DateTime instance to a string.
21: *
22: * @see \DateTime::format() for supported formats
23: *
24: * @param string $inputTimezone The name of the input timezone
25: * @param string $outputTimezone The name of the output timezone
26: * @param string $format The date format
27: *
28: * @throws UnexpectedTypeException if a timezone is not a string
29: */
30: public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'H:i:s')
31: {
32: parent::__construct($inputTimezone, $outputTimezone);
33:
34: if (! empty($format)) $this->generateFormat = $format;
35: }
36:
37: /**
38: * Transforms a DateTime object into a time string with the configured format
39: * and timezone.
40: *
41: * @param \DateTimeInterface $dateTime A DateTimeInterface object
42: *
43: * @return string A value as produced by PHP's date() function
44: *
45: * @throws TransformationFailedException If the given value is not a \DateTimeInterface
46: */
47: public function reverseTransform($dateTime)
48: {
49: if (null === $dateTime) {
50: return '';
51: }
52:
53: if (!$dateTime instanceof \DateTimeInterface) {
54: throw new TransformationFailedException('Expected a \DateTimeInterface.');
55: }
56:
57: if (!$dateTime instanceof \DateTimeImmutable) {
58: $dateTime = clone $dateTime;
59: }
60:
61: $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
62:
63: return $dateTime->format($this->generateFormat);
64: }
65:
66: /**
67: * Transforms a time string in the configured timezone into a DateTime object.
68: *
69: * @param string $value A value as produced by PHP's date() function
70: *
71: * @return \DateTime|null An instance of \DateTime
72: *
73: * @throws TransformationFailedException If the given value is not a string,
74: * or could not be transformed
75: */
76: public function transform($value)
77: {
78: if (empty($value)) {
79: return null;
80: }
81:
82: if (preg_match('/(\d{1,2})([h:\s]+(\d{1,2})([m:\s]+(\d{1,2}))?)?/i', (string)$value, $m)) {
83: $value = sprintf('%02d:%02d:%02d', $m[1], isset($m[2]) ? $m[3] : 0, isset($m[4]) ? $m[5] : 0);
84: }
85:
86: $outputTz = new \DateTimeZone($this->outputTimezone);
87: $dateTime = \DateTime::createFromFormat('H:i:s', $value, $outputTz);
88:
89: $lastErrors = \DateTime::getLastErrors();
90:
91: if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
92: throw new TransformationFailedException(implode(', ', array_merge(array_values($lastErrors['warnings']), array_values($lastErrors['errors']))));
93: }
94:
95: try {
96: if ($this->inputTimezone !== $this->outputTimezone) {
97: $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
98: }
99: } catch (\Exception $e) {
100: throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
101: }
102:
103: return $dateTime;
104: }
105: }
106: