12 Commits
Author SHA1 Message Date
Jérôme Gamez 2ba952cc73 Release 2.3.0 2022-11-25 19:02:11 +01:00
Jérôme Gamez 2861280adc Re-introduce support for PHP ^8.0 (instead of only 8.1.x and 8.2.x) 2022-11-25 19:02:11 +01:00
Jérôme Gamez a5e62affe0 Switch to the now released psr/clock-interface 2022-11-25 18:08:55 +01:00
github-actions[bot] 5acec1192d Merge pull request #4 from beste/dependabot/github_actions/ramsey/composer-install-2
github-actions(deps): bump ramsey/composer-install from 1 to 2
2022-11-17 18:20:41 +00:00
dependabot[bot] fd2e55f899 github-actions(deps): bump ramsey/composer-install from 1 to 2
Bumps [ramsey/composer-install](https://github.com/ramsey/composer-install) from 1 to 2.
- [Release notes](https://github.com/ramsey/composer-install/releases)
- [Commits](https://github.com/ramsey/composer-install/compare/v1...v2)

---
updated-dependencies:
- dependency-name: ramsey/composer-install
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2022-11-17 18:20:16 +00:00
Jérôme Gamez 24b2fc5716 Release 2.2.0 2022-11-05 00:08:15 +01:00
github-actions[bot] 04017e5bc2 Merge pull request #3 from beste/dependabot/github_actions/actions/checkout-3
github-actions(deps): bump actions/checkout from 2 to 3
2022-11-04 23:05:44 +00:00
dependabot[bot] b47e76adf3 github-actions(deps): bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2022-11-04 23:05:32 +00:00
Jérôme Gamez 4b16082f08 Set up Dependabot with auto-merge 2022-11-05 00:05:05 +01:00
Jérôme Gamez 317ed729ce Drop support for PHP <8.1 2022-11-05 00:03:47 +01:00
Jérôme Gamez 201ed087ca Re-enable tests for the 1.x and 2.x branches 2022-04-24 15:39:46 +02:00
Jérôme Gamez f3edef9cbc Add a WrappingClock
The `WrappingClock` allows using an object with a `now()` method
returning a `DateTimeImmutable` object as a "real" clock.
2022-04-24 15:38:25 +02:00
15 changed files with 283 additions and 24 deletions
+15
View File
@@ -0,0 +1,15 @@
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
commit-message:
include: "scope"
prefix: "github-actions"
open-pull-requests-limit: 10
labels:
- "dependency"
+2
View File
@@ -0,0 +1,2 @@
# https://probot.github.io/apps/settings/
_extends: beste/.github
@@ -0,0 +1,23 @@
name: "Dependabot auto-merge"
on: [pull_request_target] # yamllint disable-line rule:truthy
permissions:
contents: "write"
jobs:
dependabot:
runs-on: "ubuntu-latest"
if: "${{ github.actor == 'dependabot[bot]' }}"
steps:
- name: "Dependabot metadata"
id: "metadata"
uses: "dependabot/[email protected]"
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: "Enable auto-merge for Dependabot PRs"
if: "${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}"
run: "gh pr merge --auto --merge \"$PR_URL\""
env:
PR_URL: "${{github.event.pull_request.html_url}}"
GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}"
+5 -10
View File
@@ -4,7 +4,8 @@ on:
pull_request: pull_request:
push: push:
branches: branches:
- 'main' - '1.x'
- '2.x'
jobs: jobs:
tests: tests:
@@ -14,16 +15,13 @@ jobs:
strategy: strategy:
matrix: matrix:
php: php:
- "7.4"
- "8.0" - "8.0"
- "8.1" - "8.1"
dependencies: - "8.2"
- "lowest"
- "highest"
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Setup PHP - name: Setup PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
with: with:
@@ -33,10 +31,7 @@ jobs:
env: env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: "ramsey/composer-install@v1" - uses: "ramsey/composer-install@v2"
with:
dependency-versions: "${{ matrix.dependencies }}"
composer-options: "${{ matrix.composer-options }}"
- name: Setup problem matchers for PHP - name: Setup problem matchers for PHP
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
+10
View File
@@ -1,5 +1,15 @@
# CHANGELOG # CHANGELOG
## 2.3.0 - 2022-11-25
This release re-introduces support for PHP ^8.0 and implements the freshly released `psr/clock` (PSR-20) directly.
## 2.2.0 - 2022-11-04
This release drops support for PHP <8.1.
## 2.1.0 - 2022-04-22
Adds the `WrappingClock` which allows using an object with a `now()` method returning a `DateTimeImmutable` object
as a "real" clock.
## 2.0.0 - 2022-04-20 ## 2.0.0 - 2022-04-20
This release introduces a compatibility layer with the PSR-20 draft, allowing us to already This release introduces a compatibility layer with the PSR-20 draft, allowing us to already
get some interoperability by depending on a shared interface. get some interoperability by depending on a shared interface.
+36
View File
@@ -15,6 +15,7 @@ A collection of Clock implementations.
- [`UTCClock`](#utcclock) - The clock that you should™ use - [`UTCClock`](#utcclock) - The clock that you should™ use
- [`FrozenClock`](#frozenclock) - A clock that stopped moving (perfect for tests) - [`FrozenClock`](#frozenclock) - A clock that stopped moving (perfect for tests)
- [`MinuteClock`](#minuteclock) - Who cares about seconds or even less? - [`MinuteClock`](#minuteclock) - Who cares about seconds or even less?
- [`WrappingClock`](#wrappingclock) - Allows wrapping a non-clock with a `now()` method in a clock
- [Running Tests](#running-tests) - [Running Tests](#running-tests)
## Installation ## Installation
@@ -136,7 +137,42 @@ printf("For %s, the minute clock still returns %s\n",
$frozenClock->now()->format('H:i:s'), $frozenClock->now()->format('H:i:s'),
$clock->now()->format('H:i:s') $clock->now()->format('H:i:s')
); );
```
### `WrappingClock`
If you already have an object with a `now()` method returning a `DateTimeImmutable` object, you can wrap it
in a `WrappingClock` to make it a "real" Clock.
as a "real" clock.
```php
# examples/wrapping_clock.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));
``` ```
## Running tests ## Running tests
+9 -9
View File
@@ -11,17 +11,17 @@
} }
], ],
"require": { "require": {
"php": "~7.4.0 || ~8.0.0 || ~8.1.0", "php": "^8.0",
"stella-maris/clock": "^0.1.4" "psr/clock": "^1.0"
}, },
"require-dev": { "require-dev": {
"phpstan/extension-installer": "^1.1", "phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.0", "phpstan/phpstan": "^1.9.1",
"phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-phpunit": "^1.2.2",
"phpstan/phpstan-strict-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4.4",
"phpunit/phpunit": "^9.5.10", "phpunit/phpunit": "^9.5.26",
"psalm/plugin-phpunit": "^0.16.0", "psalm/plugin-phpunit": "^0.16.1",
"vimeo/psalm": "^4.15" "vimeo/psalm": "^4.29"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
+28
View File
@@ -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));
+1 -1
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Beste; namespace Beste;
use StellaMaris\Clock\ClockInterface; use Psr\Clock\ClockInterface;
interface Clock extends ClockInterface interface Clock extends ClockInterface
{ {
+1 -1
View File
@@ -7,7 +7,7 @@ namespace Beste\Clock;
use Beste\Clock; use Beste\Clock;
use DateTimeImmutable; use DateTimeImmutable;
use DateTimeZone; use DateTimeZone;
use StellaMaris\Clock\ClockInterface; use Psr\Clock\ClockInterface;
final class FrozenClock implements Clock final class FrozenClock implements Clock
{ {
+1 -1
View File
@@ -6,7 +6,7 @@ namespace Beste\Clock;
use Beste\Clock; use Beste\Clock;
use DateTimeImmutable; use DateTimeImmutable;
use StellaMaris\Clock\ClockInterface; use Psr\Clock\ClockInterface;
final class MinuteClock implements Clock final class MinuteClock implements Clock
{ {
+62
View File
@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace Beste\Clock;
use Beste\Clock;
use DateTimeImmutable;
use InvalidArgumentException;
use Psr\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 '.ClockInterface::class.' 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();
}
}
+1 -1
View File
@@ -7,7 +7,7 @@ namespace Beste\Clock\Tests;
use Beste\Clock\FrozenClock; use Beste\Clock\FrozenClock;
use DateTimeImmutable; use DateTimeImmutable;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use StellaMaris\Clock\ClockInterface; use Psr\Clock\ClockInterface;
/** /**
* @internal * @internal
+1 -1
View File
@@ -7,7 +7,7 @@ namespace Beste\Clock\Tests;
use Beste\Clock\MinuteClock; use Beste\Clock\MinuteClock;
use DateTimeImmutable; use DateTimeImmutable;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use StellaMaris\Clock\ClockInterface; use Psr\Clock\ClockInterface;
/** /**
* @internal * @internal
+88
View File
@@ -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);
}
}