Skip to content

Commit

Permalink
Merge pull request #4 from curzio-della-santa/feature/serialization-d…
Browse files Browse the repository at this point in the history
…ate-time-immutable

Serialization of DateTimeImmutable
  • Loading branch information
curzio-della-santa committed Dec 9, 2015
2 parents 085814b + 9dfabef commit cc890cb
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 67 deletions.
81 changes: 14 additions & 67 deletions src/Detail/Normalization/JMSSerializer/Handler/DateHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,9 @@
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\DateHandler as BaseDateHandler;

use Detail\Normalization\Exception;
use Detail\Normalization\JMSSerializer\PhpDeserializationVisitor;

class DateHandler extends BaseDateHandler
{
/**
* @var string
*/
protected $format;

/**
* @var DateTimeZone
*/
protected $timezone;
use DatePhpDeserializationTrait;

/**
* @param string $defaultFormat
Expand All @@ -41,66 +30,24 @@ public function __construct($defaultFormat = DateTime::ISO8601, $defaultTimezone
public static function getSubscribingMethods()
{
$methods = array();
$formats = array('php');
$types = array('DateTime', 'DateInterval');

foreach ($formats as $format) {
// Subscribe deserialization of 'DateTime' for 'php' format
$methods[] = array(
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'type' => 'DateTime',
'format' => 'php',
);

// Subscribe serialization of 'DateTime' and 'DateInterval' for 'php' format
foreach (array('DateTime', 'DateInterval') as $type) {
$methods[] = array(
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'type' => 'DateTime',
'format' => $format,
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'type' => $type,
'format' => 'php',
'method' => 'serialize' . $type,
);

foreach ($types as $type) {
$methods[] = array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'type' => $type,
'format' => $format,
'method' => 'serialize' . $type,
);
}
}

return $methods;
}

/**
* @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;
}
}
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());
}
}
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;
}
}

0 comments on commit cc890cb

Please sign in to comment.