-
-
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.
The `WrappingClock` allows using an object with a `now()` method returning a `DateTimeImmutable` object as a "real" clock.
- Loading branch information
1 parent
98d1e6f
commit f3edef9
Showing
5 changed files
with
217 additions
and
0 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
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
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,28 @@ | ||
<?php | ||
|
||
require __DIR__.'/../vendor/autoload.php'; | ||
|
||
use Beste\Clock\WrappingClock; | ||
|
||
// Create a frozen $now so that we can test the wrapping clock. | ||
$now = new DateTimeImmutable('2012-04-24 12:00:00'); | ||
|
||
// Create an object that is NOT a clock, but has a now() method returning the frozen $now. | ||
$clock = new class($now) { | ||
private \DateTimeImmutable $now; | ||
|
||
public function __construct(\DateTimeImmutable $now) | ||
{ | ||
$this->now = $now; | ||
} | ||
|
||
public function now(): \DateTimeImmutable | ||
{ | ||
return $this->now; | ||
} | ||
}; | ||
|
||
// We can now wrap the object in a clock. | ||
$wrappedClock = WrappingClock::wrapping($clock); | ||
|
||
assert($now->format(DATE_ATOM) === $wrappedClock->now()->format(DATE_ATOM)); |
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,61 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Beste\Clock; | ||
|
||
use Beste\Clock; | ||
use DateTimeImmutable; | ||
use StellaMaris\Clock\ClockInterface; | ||
|
||
final class WrappingClock implements Clock | ||
{ | ||
private ClockInterface $wrappedClock; | ||
|
||
private function __construct(ClockInterface $wrappedClock) | ||
{ | ||
$this->wrappedClock = $wrappedClock; | ||
} | ||
|
||
public static function wrapping(object $clock): self | ||
{ | ||
if ($clock instanceof ClockInterface) { | ||
return new self($clock); | ||
} | ||
|
||
if (!method_exists($clock, 'now')) { | ||
throw new \InvalidArgumentException('$clock must implement StellaMaris\Clock\ClockInterface or have a now() method'); | ||
} | ||
|
||
if (!($clock->now() instanceof DateTimeImmutable)) { | ||
throw new \InvalidArgumentException('$clock->now() must return a DateTimeImmutable'); | ||
} | ||
|
||
$wrappedClock = new class($clock) implements ClockInterface { | ||
private object $clock; | ||
|
||
public function __construct(object $clock) | ||
{ | ||
$this->clock = $clock; | ||
} | ||
|
||
public function now(): \DateTimeImmutable | ||
{ | ||
assert(method_exists($this->clock, 'now')); | ||
|
||
$now = $this->clock->now(); | ||
|
||
assert($now instanceof \DateTimeImmutable); | ||
|
||
return $now; | ||
} | ||
}; | ||
|
||
return new self($wrappedClock); | ||
} | ||
|
||
public function now(): DateTimeImmutable | ||
{ | ||
return $this->wrappedClock->now(); | ||
} | ||
} |
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,88 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Beste\Clock\Tests; | ||
|
||
use Beste\Clock\FrozenClock; | ||
use Beste\Clock\WrappingClock; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* @internal | ||
* @coversDefaultClass \Beste\Clock\WrappingClock | ||
*/ | ||
final class WrappingClockTest extends TestCase | ||
{ | ||
/** | ||
* @test | ||
* | ||
* @covers ::__construct | ||
* @covers ::create | ||
* @covers ::now | ||
*/ | ||
public function itWrapsAClockInterface(): void | ||
{ | ||
$clock = FrozenClock::fromUTC(); | ||
|
||
$wrappedClock = WrappingClock::wrapping($clock); | ||
|
||
self::assertSame( | ||
$clock->now()->format(DATE_ATOM), | ||
$wrappedClock->now()->format(DATE_ATOM) | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::__construct | ||
* @covers ::create | ||
* @covers ::now | ||
*/ | ||
public function itWrapsAnObjectWithANowMethod(): void | ||
{ | ||
$now = FrozenClock::fromUTC()->now(); | ||
|
||
$clock = new class($now) { | ||
private \DateTimeImmutable $now; | ||
|
||
public function __construct(\DateTimeImmutable $now) | ||
{ | ||
$this->now = $now; | ||
} | ||
|
||
public function now(): \DateTimeImmutable | ||
{ | ||
return $this->now; | ||
} | ||
}; | ||
|
||
$wrappedClock = WrappingClock::wrapping($clock); | ||
|
||
self::assertSame( | ||
$now->format(DATE_ATOM), | ||
$wrappedClock->now()->format(DATE_ATOM) | ||
); | ||
} | ||
|
||
/** | ||
* @test | ||
* | ||
* @covers ::create | ||
*/ | ||
public function itRejectsObjectsWithANowMethodReturningANonDateTimeImmutable(): void | ||
{ | ||
$clock = new class() { | ||
public function now(): string | ||
{ | ||
return 'foo'; | ||
} | ||
}; | ||
|
||
$this->expectException(\InvalidArgumentException::class); | ||
$this->expectExceptionMessage('$clock->now() must return a DateTimeImmutable'); | ||
|
||
WrappingClock::wrapping($clock); | ||
} | ||
} |