Completed
Pull Request — master (#708)
by Asmir
11:37
created

DateHandler::deserializeDateTimeFromJson()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 3
cts 4
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 3
crap 2.0625
1
<?php
2
3
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer\Handler;
20
21
use JMS\Serializer\Context;
22
use JMS\Serializer\Exception\RuntimeException;
23
use JMS\Serializer\GraphNavigator;
24
use JMS\Serializer\JsonDeserializationVisitor;
25
use JMS\Serializer\VisitorInterface;
26
use JMS\Serializer\XmlDeserializationVisitor;
27
use JMS\Serializer\XmlSerializationVisitor;
28
29
class DateHandler implements SubscribingHandlerInterface
30
{
31
    private $defaultFormat;
32
    private $defaultTimezone;
33
    private $xmlCData;
34
35 309
    public static function getSubscribingMethods()
36
    {
37 309
        $methods = array();
38 309
        $deserialisationTypes = array('DateTime', 'DateTimeImmutable', 'DateInterval');
39 309
        $serialisationTypes = array('DateTime', 'DateTimeImmutable', 'DateInterval');
40
41 309
        foreach (array('json', 'xml', 'yml') as $format) {
42
43 309
            foreach ($deserialisationTypes as $type) {
44 309
                $methods[] = [
45 309
                    'type'      => $type,
46 309
                    'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
47 309
                    'format'    => $format,
48
                ];
49 309
            }
50
51 309
            foreach ($serialisationTypes as $type) {
52 309
                $methods[] = array(
53 309
                    'type' => $type,
54 309
                    'format' => $format,
55 309
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
56 309
                    'method' => 'serialize'.$type,
57
                );
58 309
            }
59 309
        }
60
61 309
        return $methods;
62
    }
63
64 310
    public function __construct($defaultFormat = \DateTime::ISO8601, $defaultTimezone = 'UTC', $xmlCData = true)
65
    {
66 310
        $this->defaultFormat = $defaultFormat;
67 310
        $this->defaultTimezone = new \DateTimeZone($defaultTimezone);
68 310
        $this->xmlCData = $xmlCData;
69 310
    }
70
71 27
    private function serializeDateTimeInterface(
72
        VisitorInterface $visitor,
73
        \DateTimeInterface $date,
74
        array $type,
75
        Context $context
76
    )
77
    {
78 27
        if ($visitor instanceof XmlSerializationVisitor && false === $this->xmlCData) {
79 2
            return $visitor->visitSimpleString($date->format($this->getFormat($type)), $type, $context);
80
        }
81
82 25
        $format = $this->getFormat($type);
83 25
        if ('U' === $format) {
84 3
            return $visitor->visitInteger($date->format($format), $type, $context);
85
        }
86
87 22
        return $visitor->visitString($date->format($this->getFormat($type)), $type, $context);
88
    }
89
90 21
    public function serializeDateTime(VisitorInterface $visitor, \DateTime $date, array $type, Context $context)
91
    {
92 21
        return $this->serializeDateTimeInterface($visitor, $date, $type, $context);
93
    }
94
95 6
    public function serializeDateTimeImmutable(
96
        VisitorInterface $visitor,
97
        \DateTimeImmutable $date,
98
        array $type,
99
        Context $context
100
    )
101
    {
102 6
        return $this->serializeDateTimeInterface($visitor, $date, $type, $context);
103
    }
104
105 3
    public function serializeDateInterval(VisitorInterface $visitor, \DateInterval $date, array $type, Context $context)
106
    {
107 3
        $iso8601DateIntervalString = $this->format($date);
108
109 3
        if ($visitor instanceof XmlSerializationVisitor && false === $this->xmlCData) {
110
            return $visitor->visitSimpleString($iso8601DateIntervalString, $type, $context);
111
        }
112
113 3
        return $visitor->visitString($iso8601DateIntervalString, $type, $context);
114
    }
115
116 7
    private function isDataXmlNull($data)
117
    {
118 7
        $attributes = $data->attributes('xsi', true);
119 7
        return isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true';
120
    }
121
122 6
    public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
123
    {
124 6
        if ($this->isDataXmlNull($data)) {
125 1
            return null;
126
        }
127
128 5
        return $this->parseDateTime($data, $type);
129
    }
130
131 1
    public function deserializeDateTimeImmutableFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
132
    {
133 1
        if ($this->isDataXmlNull($data)) {
134
            return null;
135
        }
136
137 1
        return $this->parseDateTime($data, $type, true);
138
    }
139
140 7
    public function deserializeDateIntervalFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
141
    {
142 7
        if ($this->isDataXmlNull($data)) {
143 1
            return null;
144
        }
145
146 6
        return $this->parseDateInterval($data);
147
    }
148
149 2
    public function deserializeDateTimeFromJson(JsonDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
150
    {
151 2
        if (null === $data) {
152
            return null;
153
        }
154
155 2
        return $this->parseDateTime($data, $type);
156
    }
157
158 14
    public function deserializeDateTimeImmutableFromJson(JsonDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
159
    {
160 14
        if (null === $data) {
161 14
            return null;
162
        }
163 14
164 3
        return $this->parseDateTime($data, $type, true);
165 3
    }
166 11
167
    public function deserializeDateIntervalFromJson(JsonDeserializationVisitor $visitor, $data, array $type)
0 ignored issues
show
Unused Code introduced by
The parameter $visitor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
    {
169 14
        if (null === $data) {
170
            return null;
171
        }
172
173 14
        return $this->parseDateInterval($data);
174
    }
175
176
    private function parseDateTime($data, array $type, $immutable = false)
177
    {
178
        $timezone = isset($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone;
179
        $format = $this->getFormat($type);
180 27
181
        if ($immutable) {
182 27
            $datetime = \DateTimeImmutable::createFromFormat($format, (string) $data, $timezone);
183
        } else {
184
            $datetime = \DateTime::createFromFormat($format, (string) $data, $timezone);
185
        }
186
187
        if (false === $datetime) {
188
            throw new RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format));
189 4
        }
190
191 4
        return $datetime;
192
    }
193 4
194 1
    private function parseDateInterval($data)
195 1
    {
196
        $dateInterval = null;
197 4
        try {
198
            $dateInterval = new \DateInterval($data);
199
        } catch (\Exception $e) {
200
            throw new RuntimeException(sprintf('Invalid dateinterval "%s", expected ISO 8601 format', $data), null, $e);
201 4
        }
202 1
203 1
        return $dateInterval;
204
    }
205 4
206 4
    /**
207 4
     * @return string
208
     * @param array $type
209 4
     */
210 1
    private function getFormat(array $type)
211 1
    {
212
        return isset($type['params'][0]) ? $type['params'][0] : $this->defaultFormat;
213 4
    }
214 4
215 4
    /**
216
     * @param \DateInterval $dateInterval
217 4
     * @return string
218 1
     */
219 1
    public function format(\DateInterval $dateInterval)
220
    {
221 4
        $format = 'P';
222
223
        if (0 < $dateInterval->y) {
224
            $format .= $dateInterval->y.'Y';
225
        }
226
227
        if (0 < $dateInterval->m) {
228
            $format .= $dateInterval->m.'M';
229
        }
230
231
        if (0 < $dateInterval->d) {
232
            $format .= $dateInterval->d.'D';
233
        }
234
235
        if (0 < $dateInterval->h || 0 < $dateInterval->i || 0 < $dateInterval->s) {
236
            $format .= 'T';
237
        }
238
239
        if (0 < $dateInterval->h) {
240
            $format .= $dateInterval->h.'H';
241
        }
242
243
        if (0 < $dateInterval->i) {
244
            $format .= $dateInterval->i.'M';
245
        }
246
247
        if (0 < $dateInterval->s) {
248
            $format .= $dateInterval->s.'S';
249
        }
250
251
        if ($format === 'P') {
252
            $format = 'P0DT0S';
253
        }
254
255
        return $format;
256
    }
257
}
258