-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from curzio-della-santa/feature/serialization-d…
…ate-time-immutable Serialization of DateTimeImmutable
- Loading branch information
Showing
3 changed files
with
227 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
151 changes: 151 additions & 0 deletions
151
src/Detail/Normalization/JMSSerializer/Handler/DateImmutableHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
<?php | ||
|
||
namespace Detail\Normalization\JMSSerializer\Handler; | ||
|
||
use DateTime; | ||
use DateTimeImmutable; | ||
use DateTimeZone; | ||
|
||
use JMS\Serializer\Context; | ||
use JMS\Serializer\GraphNavigator; | ||
use JMS\Serializer\Handler\DateHandler as BaseDateHandler; | ||
use JMS\Serializer\JsonDeserializationVisitor; | ||
use JMS\Serializer\VisitorInterface; | ||
use JMS\Serializer\XmlDeserializationVisitor; | ||
|
||
use Detail\Normalization\Exception; | ||
use Detail\Normalization\JMSSerializer\PhpDeserializationVisitor; | ||
|
||
class DateImmutableHandler extends BaseDateHandler | ||
{ | ||
use DatePhpDeserializationTrait; | ||
|
||
/** | ||
* @param string $defaultFormat | ||
* @param string $defaultTimezone | ||
*/ | ||
public function __construct($defaultFormat = DateTime::ISO8601, $defaultTimezone = 'UTC') | ||
{ | ||
$this->format = $defaultFormat; | ||
$this->timezone = new DateTimeZone($defaultTimezone); | ||
|
||
parent::__construct($defaultFormat, $defaultTimezone); | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public static function getSubscribingMethods() | ||
{ | ||
$methods = array(); | ||
|
||
// Subscribe deserialization and serialization of 'DateTimeImmutable' for 'json', 'xml' and 'php' formats | ||
foreach (array('json', 'xml', 'php') as $format) { | ||
$methods[] = array( | ||
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, | ||
'type' => 'DateTimeImmutable', | ||
'format' => $format, | ||
); | ||
|
||
$methods[] = array( | ||
'direction' => GraphNavigator::DIRECTION_SERIALIZATION, | ||
'type' => 'DateTimeImmutable', | ||
'format' => $format, | ||
'method' => 'serializeDateTimeImmutable', | ||
); | ||
} | ||
|
||
return $methods; | ||
} | ||
|
||
/** | ||
* @param VisitorInterface $visitor | ||
* @param DateTimeImmutable $date | ||
* @param array $type | ||
* @param Context $context | ||
* @return string | ||
*/ | ||
public function serializeDateTimeImmutable( | ||
VisitorInterface $visitor, | ||
DateTimeImmutable $date, | ||
array $type, | ||
Context $context | ||
) { | ||
return $this->serializeDateTime( | ||
$visitor, | ||
$this->createMutableDateTimeFromImmutable($date), | ||
$type, | ||
$context | ||
); | ||
} | ||
|
||
/** | ||
* @param PhpDeserializationVisitor $visitor | ||
* @param string $data | ||
* @param array $type | ||
* @return DateTimeImmutable|null | ||
*/ | ||
public function deserializeDateTimeImmutableFromPhp(PhpDeserializationVisitor $visitor, $data, array $type) | ||
{ | ||
return $this->createImmutableDateTimeFromMutable( | ||
$this->deserializeDateTimeFromPhp($visitor, $data, $type) | ||
); | ||
} | ||
|
||
/** | ||
* @param XmlDeserializationVisitor $visitor | ||
* @param $data | ||
* @param array $type | ||
* @return DateTimeImmutable|null | ||
*/ | ||
public function deserializeDateTimeImmutableFromXml(XmlDeserializationVisitor $visitor, $data, array $type) | ||
{ | ||
return $this->createImmutableDateTimeFromMutable( | ||
$this->deserializeDateTimeFromXml($visitor, $data, $type) | ||
); | ||
} | ||
|
||
/** | ||
* @param JsonDeserializationVisitor $visitor | ||
* @param $data | ||
* @param array $type | ||
* @return DateTimeImmutable|null | ||
*/ | ||
public function deserializeDateTimeImmutableFromJson(JsonDeserializationVisitor $visitor, $data, array $type) | ||
{ | ||
return $this->createImmutableDateTimeFromMutable( | ||
$this->deserializeDateTimeFromJson($visitor, $data, $type) | ||
); | ||
} | ||
|
||
/** | ||
* @param DateTime|null $date | ||
* @return DateTimeImmutable | ||
*/ | ||
private function createImmutableDateTimeFromMutable(DateTime $date = null) | ||
{ | ||
if ($date === null) { | ||
return null; | ||
} | ||
|
||
if (method_exists(DateTimeImmutable::CLASS, 'createFromMutable')) { | ||
return DateTimeImmutable::createFromMutable($date); | ||
} | ||
|
||
// Fallback for PHP < 5.6 | ||
return new DateTimeImmutable($date->format('Y-m-d H:i:s'), $date->getTimezone()); | ||
} | ||
|
||
/** | ||
* @param DateTimeImmutable|null $date | ||
* @return DateTime | ||
*/ | ||
private function createMutableDateTimeFromImmutable(DateTimeImmutable $date = null) | ||
{ | ||
if ($date === null) { | ||
return null; | ||
} | ||
|
||
return new DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone()); | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
src/Detail/Normalization/JMSSerializer/Handler/DatePhpDeserializationTrait.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
namespace Detail\Normalization\JMSSerializer\Handler; | ||
|
||
use DateTime; | ||
use DateTimeZone; | ||
|
||
use Detail\Normalization\Exception; | ||
use Detail\Normalization\JMSSerializer\PhpDeserializationVisitor; | ||
|
||
trait DatePhpDeserializationTrait | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
protected $format; | ||
|
||
/** | ||
* @var DateTimeZone | ||
*/ | ||
protected $timezone; | ||
|
||
/** | ||
* @param PhpDeserializationVisitor $visitor | ||
* @param string $data | ||
* @param array $type | ||
* @return DateTime|null | ||
*/ | ||
public function deserializeDateTimeFromPhp(PhpDeserializationVisitor $visitor, $data, array $type) | ||
{ | ||
if ($data === null) { | ||
return null; | ||
} | ||
|
||
$format = isset($type['params'][0]) ? $type['params'][0] : $this->format; | ||
|
||
if ($format[0] !== '!') { | ||
$type['params'][0] = '!' . $format; | ||
} | ||
|
||
return $this->createDateTime($data, $type); | ||
} | ||
|
||
/** | ||
* @param string $data | ||
* @param array $type | ||
* @return DateTime | ||
*/ | ||
protected function createDateTime($data, array $type) | ||
{ | ||
$timezone = isset($type['params'][1]) ? new DateTimeZone($type['params'][1]) : $this->timezone; | ||
$format = isset($type['params'][0]) ? $type['params'][0] : $this->format; | ||
|
||
$datetime = DateTime::createFromFormat($format, (string) $data, $timezone); | ||
|
||
if ($datetime === false) { | ||
throw new Exception\RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format)); | ||
} | ||
|
||
return $datetime; | ||
} | ||
} |