diff --git a/src/Symfony/Component/Clock/CHANGELOG.md b/src/Symfony/Component/Clock/CHANGELOG.md index 5ffa40eff75d9..9bb1c2d4148e1 100644 --- a/src/Symfony/Component/Clock/CHANGELOG.md +++ b/src/Symfony/Component/Clock/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.3 +--- + + * Add `ClockAwareTrait` to help write time-sensitive classes + 6.2 --- diff --git a/src/Symfony/Component/Clock/ClockAwareTrait.php b/src/Symfony/Component/Clock/ClockAwareTrait.php new file mode 100644 index 0000000000000..22f5d4698a0aa --- /dev/null +++ b/src/Symfony/Component/Clock/ClockAwareTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Clock; + +use Psr\Clock\ClockInterface; +use Symfony\Contracts\Service\Attribute\Required; + +/** + * A trait to help write time-sensitive classes. + * + * @author Nicolas Grekas
+ */ +trait ClockAwareTrait +{ + private readonly ClockInterface $clock; + + #[Required] + public function setClock(ClockInterface $clock): void + { + $this->clock = $clock; + } + + protected function now(): \DateTimeImmutable + { + return ($this->clock ??= new NativeClock())->now(); + } +} diff --git a/src/Symfony/Component/Clock/Tests/ClockAwareTraitTest.php b/src/Symfony/Component/Clock/Tests/ClockAwareTraitTest.php new file mode 100644 index 0000000000000..c472541c64934 --- /dev/null +++ b/src/Symfony/Component/Clock/Tests/ClockAwareTraitTest.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Clock\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Clock\ClockAwareTrait; +use Symfony\Component\Clock\MockClock; + +class ClockAwareTraitTest extends TestCase +{ + public function testTrait() + { + $sut = new class() { + use ClockAwareTrait { + now as public; + } + }; + + $this->assertInstanceOf(\DateTimeImmutable::class, $sut->now()); + + $clock = new MockClock(); + $sut = new $sut(); + $sut->setClock($clock); + + $ts = $sut->now()->getTimestamp(); + $this->assertEquals($clock->now(), $sut->now()); + $clock->sleep(1); + $this->assertEquals($clock->now(), $sut->now()); + $this->assertSame(1.0, round($sut->now()->getTimestamp() - $ts, 1)); + } +}