1<?php
2namespace GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler;
3
4use JMS\Serializer\Context;
5use JMS\Serializer\GraphNavigator;
6use JMS\Serializer\Handler\SubscribingHandlerInterface;
7use JMS\Serializer\XmlDeserializationVisitor;
8use JMS\Serializer\XmlSerializationVisitor;
9use RuntimeException;
10
11class XmlSchemaDateHandler implements SubscribingHandlerInterface
12{
13
14    protected $defaultTimezone;
15
16    public static function getSubscribingMethods()
17    {
18        return array(
19            array(
20                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
21                'format' => 'xml',
22                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date',
23                'method' => 'deserializeDate'
24            ),
25            array(
26                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
27                'format' => 'xml',
28                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date',
29                'method' => 'serializeDate'
30            ),
31            array(
32                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
33                'format' => 'xml',
34                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime',
35                'method' => 'deserializeDateTime'
36            ),
37            array(
38                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
39                'format' => 'xml',
40                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime',
41                'method' => 'serializeDateTime'
42            ),
43            array(
44                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
45                'format' => 'xml',
46                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Time',
47                'method' => 'deserializeTime'
48            ),
49            array(
50                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
51                'format' => 'xml',
52                'type' => 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Time',
53                'method' => 'serializeTime'
54            ),
55            array(
56                'type' => 'DateInterval',
57                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
58                'format' => 'xml',
59                'method' => 'deserializeDateIntervalXml',
60            ),
61        );
62    }
63
64    public function __construct($defaultTimezone = 'UTC')
65    {
66        $this->defaultTimezone = new \DateTimeZone($defaultTimezone);
67
68    }
69
70    public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $data, array $type){
71        $attributes = $data->attributes('xsi', true);
72        if (isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true') {
73            return null;
74        }
75        return new \DateInterval((string)$data);
76    }
77
78    public function serializeDate(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
79    {
80
81        $v = $date->format('Y-m-d');
82
83        return $visitor->visitSimpleString($v, $type, $context);
84    }
85
86    public function deserializeDate(XmlDeserializationVisitor $visitor, $data, array $type)
87    {
88        $attributes = $data->attributes('xsi', true);
89        if (isset($attributes['nil'][0]) && (string)$attributes['nil'][0] === 'true') {
90            return null;
91        }
92        if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})(Z|([+-]\d{2}:\d{2}))?$/', $data)) {
93            throw new RuntimeException(sprintf('Invalid date "%s", expected valid XML Schema date string.', $data));
94        }
95
96        return $this->parseDateTime($data, $type);
97    }
98
99    public function serializeDateTime(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
100    {
101
102        $v = $date->format(\DateTime::W3C);
103
104        return $visitor->visitSimpleString($v, $type, $context);
105    }
106
107    public function deserializeDateTime(XmlDeserializationVisitor $visitor, $data, array $type)
108    {
109        $attributes = $data->attributes('xsi', true);
110        if (isset($attributes['nil'][0]) && (string)$attributes['nil'][0] === 'true') {
111            return null;
112        }
113
114        return $this->parseDateTime($data, $type);
115
116    }
117
118    public function serializeTime(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
119    {
120        $v = $date->format('H:i:s');
121        if ($date->getTimezone()->getOffset($date) !== $this->defaultTimezone->getOffset($date)) {
122            $v .= $date->format('P');
123        }
124        return $visitor->visitSimpleString($v, $type, $context);
125    }
126
127    public function deserializeTime(XmlDeserializationVisitor $visitor, $data, array $type)
128    {
129        $attributes = $data->attributes('xsi', true);
130        if (isset($attributes['nil'][0]) && (string)$attributes['nil'][0] === 'true') {
131            return null;
132        }
133
134        $data = (string)$data;
135
136        return new \DateTime($data, $this->defaultTimezone);
137    }
138
139    private function parseDateTime($data, array $type)
140    {
141        $timezone = isset($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone;
142        $datetime = new \DateTime((string)$data, $timezone);
143        if (false === $datetime) {
144            throw new RuntimeException(sprintf('Invalid datetime "%s", expected valid XML Schema dateTime string.', $data));
145        }
146
147        return $datetime;
148    }
149}
150
151