Skip to content

Commit

Permalink
Object serialization (#2)
Browse files Browse the repository at this point in the history
* Add DateRange serialziation

* Requere JSON PHP extension in composer
  • Loading branch information
slavcodev authored Nov 16, 2017
1 parent 375403b commit a5a09a5
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 34 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
}
],
"require": {
"php": "^7.1"
"php": "^7.1",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "~6.4.4"
Expand Down
65 changes: 64 additions & 1 deletion src/DateRange.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@

use DateTimeImmutable;
use DateTimeInterface;
use JsonSerializable;
use Serializable;

/**
* Date range implementation.
*/
final class DateRange implements DateRangeInterface
final class DateRange implements DateRangeInterface, Serializable, JsonSerializable
{
/**
* @var DateTimeInterface
Expand All @@ -40,6 +42,27 @@ public function __construct(DateTimeInterface $begin, DateTimeInterface $end = n
$this->end = $end;
}

/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->serialize();
}

/**
* {@inheritdoc}
*/
public function __debugInfo()
{
return [
'begin' => $this->getBegin()->format('c'),
'end' => $this->isFinite()
? $this->getEnd()->format('c')
: '-',
];
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -120,6 +143,46 @@ public function endAt(DateTimeInterface $time): DateRangeInterface
return $this;
}

/**
* {@inheritdoc}
*/
public function serialize()
{
return sprintf(
'%s/%s',
$this->getBegin()->format('c'),
$this->isFinite()
? $this->getEnd()->format('c')
: '-'
);
}

/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
$times = explode('/', $serialized, 2);

if (count($times) !== 2) {
throw new DateRangeException('Invalid range format');
}

$this->begin = new DateTimeImmutable($times[0]);

if ($times[1] !== '-') {
$this->end = new DateTimeImmutable($times[1]);
}
}

/**
* {@inheritdoc}
*/
public function jsonSerialize()
{
return $this->serialize();
}

/**
* @param DateTimeInterface $begin
* @param DateTimeInterface|null $end
Expand Down
56 changes: 55 additions & 1 deletion src/DateRangeImmutable.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@

namespace Zee\DateRange;

use DateTimeImmutable;
use DateTimeInterface;
use JsonSerializable;
use Serializable;

/**
* Immutable implementation of date range.
*
* This class behaves the same as `{@see DateRange}`
* except it never modifies itself but returns a new object instead.
*/
final class DateRangeImmutable implements DateRangeInterface
final class DateRangeImmutable implements DateRangeInterface, Serializable, JsonSerializable
{
/**
* @var DateRange
Expand All @@ -34,6 +37,22 @@ public function __construct(DateTimeInterface $begin, DateTimeInterface $end = n
$this->storage = new DateRange($begin, $end);
}

/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->storage->__toString();
}

/**
* {@inheritdoc}
*/
public function __debugInfo()
{
return $this->storage->__debugInfo();
}

/**
* Clones internal storage.
*/
Expand Down Expand Up @@ -119,4 +138,39 @@ public function endAt(DateTimeInterface $time): DateRangeInterface

return $clone;
}

/**
* {@inheritdoc}
*/
public function serialize()
{
return $this->storage->serialize();
}

/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
$times = explode('/', $serialized, 2);

if (count($times) !== 2) {
throw new DateRangeException('Invalid range format');
}

$this->storage = new DateRange(
new DateTimeImmutable($times[0]),
$times[1] !== '-'
? new DateTimeImmutable($times[1])
: null
);
}

/**
* {@inheritdoc}
*/
public function jsonSerialize()
{
return $this->storage->jsonSerialize();
}
}
36 changes: 36 additions & 0 deletions tests/DateRangeImmutableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use DateTime;
use DateTimeImmutable;
use DomainException;
use PHPUnit\Framework\TestCase;

/**
Expand Down Expand Up @@ -49,4 +50,39 @@ public function checkImmutability()
self::assertNotSame($initial, $actual);
self::assertSame($soon, $actual->getEnd());
}

/**
* @test
*/
public function checkImmutableCopyMutableObjectBehaviors()
{
$yesterday = new DateTime('-1 day');
$tomorrow = new DateTime('+1 day');

$immutable = new DateRangeImmutable($yesterday, $tomorrow);
$mutable = new DateRange($yesterday, $tomorrow);

self::assertSame((string) $mutable, (string) $immutable);
self::assertSame(json_encode($mutable), json_encode($immutable));
self::assertSame($mutable->__debugInfo(), $immutable->__debugInfo());

$immutable = unserialize(serialize($immutable));
$mutable = unserialize(serialize($mutable));

self::assertEquals($mutable->getBegin(), $immutable->getBegin());
self::assertEquals($mutable->getEnd(), $immutable->getEnd());
}

/**
* @test
*/
public function handleInvalidSerializedValue()
{
$range = new DateRangeImmutable(new DateTime());

$this->expectException(DomainException::class);
$this->expectExceptionMessage('Invalid range format');

$range->unserialize('');
}
}
Loading

0 comments on commit a5a09a5

Please sign in to comment.