Skip to content

Commit

Permalink
ClockAdapterFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
mabar committed Nov 26, 2023
1 parent 711fa48 commit 988d650
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `Clock` interface has a `sleep()` method
- `PsrToOrisaiClockAdapter` - makes any PSR clock compatible with `Orisai\Clock\Clock`
- `SymfonyToOrisaiClockAdapter` - makes any symfony/clock compatible with `Orisai\Clock\Clock`
- `ClockAdapterFactory` - chooses best supported adapter for `Orisai\Clock\Clock` compatibility

### Changed

Expand Down
16 changes: 16 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Provides current time for runtime and controllable time for testing
- [System clock](#system-clock)
- [Frozen clock](#frozen-clock)
- [Measurement clock](#measurement-clock)
- [Clock adapters](#clock-adapters)
- [PSR to Orisai clock adapter](#psr-to-orisai-clock-adapter)
- [Symfony to Orisai clock adapter](#symfony-to-orisai-clock-adapter)
- [Integrations and extensions](#integrations-and-extensions)
Expand Down Expand Up @@ -150,6 +151,21 @@ use DateTimeZone;
$clock = new MeasurementClock(new DateTimeZone('UTC'));
```

## Clock adapters

Use `ClockAdapterFactory` to automatically create the best adapter for `Orisai\Clock\Clock` compatibility from
your `Psr\Clock\ClockInterface`.

- It creates no adapter for `Orisai\Clock\Clock` instance and just returns it
- It prefers Symfony adapter over PSR adapter for `sleep()` method compatibility

```php
use Orisai\Clock\Adapter\ClockAdapterFactory;
use Symfony\Component\Clock\NativeClock;

$clock = ClockAdapterFactory::create($somePsrCompatibleClock);
```

### PSR to Orisai clock adapter

Decorate any `Psr\Clock\ClockInterface` implementation to conform interface `Orisai\Clock\Clock`.
Expand Down
25 changes: 25 additions & 0 deletions src/Adapter/ClockAdapterFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php declare(strict_types = 1);

namespace Orisai\Clock\Adapter;

use Orisai\Clock\Clock;
use Psr\Clock\ClockInterface;
use Symfony\Component\Clock\ClockInterface as SymfonyClock;

final class ClockAdapterFactory
{

public static function create(ClockInterface $clock): Clock
{
if ($clock instanceof Clock) {
return $clock;
}

if ($clock instanceof SymfonyClock) {

Check warning on line 18 in src/Adapter/ClockAdapterFactory.php

View workflow job for this annotation

GitHub Actions / Test for mutants (ubuntu-latest, 8.1)

Escaped Mutant for Mutator "InstanceOf_": --- Original +++ New @@ @@ if ($clock instanceof Clock) { return $clock; } - if ($clock instanceof SymfonyClock) { + if (false) { return new SymfonyToOrisaiClockAdapter($clock); } return new PsrToOrisaiClockAdapter($clock); } }

Check warning on line 18 in src/Adapter/ClockAdapterFactory.php

View workflow job for this annotation

GitHub Actions / Test for mutants (ubuntu-latest, 8.1)

Escaped Mutant for Mutator "InstanceOf_": --- Original +++ New @@ @@ if ($clock instanceof Clock) { return $clock; } - if ($clock instanceof SymfonyClock) { + if (false) { return new SymfonyToOrisaiClockAdapter($clock); } return new PsrToOrisaiClockAdapter($clock); } }
return new SymfonyToOrisaiClockAdapter($clock);
}

return new PsrToOrisaiClockAdapter($clock);
}

}
65 changes: 65 additions & 0 deletions tests/Unit/Adapter/ClockAdapterFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php declare(strict_types = 1);

namespace Tests\Orisai\Clock\Unit\Adapter;

use DateTimeImmutable;
use Generator;
use Orisai\Clock\Adapter\ClockAdapterFactory;
use Orisai\Clock\Adapter\PsrToOrisaiClockAdapter;
use Orisai\Clock\FrozenClock;
use Orisai\Clock\SystemClock;
use PHPUnit\Framework\TestCase;
use Psr\Clock\ClockInterface;
use Symfony\Component\Clock\ClockInterface as SymfonyClock;
use Symfony\Component\Clock\NativeClock;
use function class_exists;

final class ClockAdapterFactoryTest extends TestCase
{

/**
* @param class-string<ClockInterface> $class
*
* @dataProvider provide
*/
public function test(ClockInterface $clock, string $class): void
{
self::assertInstanceOf(
$class,
ClockAdapterFactory::create($clock),
);
}

public function provide(): Generator
{
yield [
new class implements ClockInterface {

public function now(): DateTimeImmutable
{
return new DateTimeImmutable();
}

},
PsrToOrisaiClockAdapter::class,
];

yield [
new FrozenClock(0),
FrozenClock::class,
];

yield [
new SystemClock(),
SystemClock::class,
];

if (class_exists(SymfonyClock::class)) {
yield [
new NativeClock(),
NativeClock::class,
];
}
}

}

0 comments on commit 988d650

Please sign in to comment.