diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 80c18aa..99c4632 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -15,14 +15,11 @@ jobs: matrix: php-versions: [ '7.3', '7.4', '8.0' ] phpunit-versions: [ 'latest' ] - phpstan-versions: [ 'latest' ] include: - php-versions: '7.1' phpunit-versions: '7.5.20' - phpstan-versions: [ 'latest' ] - php-versions: '7.2' phpunit-versions: '8.5.15' - phpstan-versions: [ 'latest' ] steps: - uses: actions/checkout@v2 @@ -31,7 +28,7 @@ jobs: with: php-version: ${{ matrix.php-versions }} coverage: xdebug - tools: composer:v2, phpunit:${{ matrix.phpunit-versions }}, phpstan:${{ matrix.phpstan-versions }} + tools: composer:v2, phpunit:${{ matrix.phpunit-versions }}, phpstan - name: Install dependencies run: composer update --prefer-dist --no-progress --no-dev diff --git a/src/Abstraction/AbstractDateTimeImmutableNormalizable.php b/src/Abstraction/AbstractDateTimeImmutableNormalizable.php index 1d19956..3d21f50 100644 --- a/src/Abstraction/AbstractDateTimeImmutableNormalizable.php +++ b/src/Abstraction/AbstractDateTimeImmutableNormalizable.php @@ -12,4 +12,16 @@ abstract class AbstractDateTimeImmutableNormalizable extends DateTimeImmutable implements NormalizableInterface, DenormalizableInterface { use AbstractDateTimeNormalizableTrait; + + /** + * @inheritDoc + * @return static + */ + public static function createFromMutable($object) + { + /** @var static $dateTimeImmutable */ + $dateTimeImmutable = parent::createFromMutable($object); + + return $dateTimeImmutable; + } } diff --git a/src/Abstraction/AbstractThrowableToNormalizableAdapter.php b/src/Abstraction/AbstractThrowableToNormalizableAdapter.php index 622fe9b..55829af 100644 --- a/src/Abstraction/AbstractThrowableToNormalizableAdapter.php +++ b/src/Abstraction/AbstractThrowableToNormalizableAdapter.php @@ -40,7 +40,7 @@ final protected function getNormalized(): array } /** - * @return array + * @return array> */ abstract protected function getTrace(Throwable $throwable): array; diff --git a/src/Object/DateTimeImmutableRfc3339Normalizable.php b/src/Object/DateTimeImmutableRfc3339Normalizable.php index c2dd16c..8e2b694 100644 --- a/src/Object/DateTimeImmutableRfc3339Normalizable.php +++ b/src/Object/DateTimeImmutableRfc3339Normalizable.php @@ -4,12 +4,28 @@ namespace Era269\Normalizable\Object; +use DateTimeInterface; use Era269\Normalizable\Abstraction\AbstractDateTimeImmutableNormalizable; final class DateTimeImmutableRfc3339Normalizable extends AbstractDateTimeImmutableNormalizable { private const FIELD_NAME_DATE_TIME = 'dateTime'; + /** + * @inheritDoc + */ + public static function createFromInterface(DateTimeInterface $object): self + { + $phpVersion = 80000; + if (PHP_VERSION_ID < $phpVersion) { + self::throwInvalidMethodCallException($phpVersion, __METHOD__); + } + /** @var self $dateTime */ + $dateTime = parent::createFromInterface($object); + + return $dateTime; + } + protected static function getDateTimeFieldName(): string { return self::FIELD_NAME_DATE_TIME; diff --git a/src/Object/DateTimeRfc3339Normalizable.php b/src/Object/DateTimeRfc3339Normalizable.php index de9885a..dfd4d2b 100644 --- a/src/Object/DateTimeRfc3339Normalizable.php +++ b/src/Object/DateTimeRfc3339Normalizable.php @@ -4,12 +4,28 @@ namespace Era269\Normalizable\Object; +use DateTimeInterface; use Era269\Normalizable\Abstraction\AbstractDateTimeNormalizable; final class DateTimeRfc3339Normalizable extends AbstractDateTimeNormalizable { private const FIELD_NAME_DATE_TIME = 'dateTime'; + /** + * @inheritDoc + */ + public static function createFromInterface(DateTimeInterface $object): self + { + $phpVersion = 80000; + if (PHP_VERSION_ID < $phpVersion) { + self::throwInvalidMethodCallException($phpVersion, __METHOD__); + } + /** @var self $dateTime */ + $dateTime = parent::createFromInterface($object); + + return $dateTime; + } + protected static function getDateTimeFieldName(): string { return self::FIELD_NAME_DATE_TIME; diff --git a/src/Traits/AbstractDateTimeNormalizableTrait.php b/src/Traits/AbstractDateTimeNormalizableTrait.php index 3d711bc..0919c0d 100644 --- a/src/Traits/AbstractDateTimeNormalizableTrait.php +++ b/src/Traits/AbstractDateTimeNormalizableTrait.php @@ -4,6 +4,7 @@ namespace Era269\Normalizable\Traits; +use BadMethodCallException; use DateTimeInterface; use DateTimeZone; use Exception; @@ -53,4 +54,22 @@ final protected function getObjectForNormalization(): DateTimeInterface } abstract protected function getDateTimeFormat(): string; + + final protected static function throwInvalidMethodCallException(int $phpVersion, string $methodName): void + { + throw new BadMethodCallException(sprintf( + 'Method "%s" is available starting with %s PHP version', + $phpVersion, + $methodName + )); + } + + /** + * @inheritDoc + * @return static|false + */ + public static function createFromFormat($format, $datetime, $timezone = null) + { + return parent::createFromFormat($format, $datetime, $timezone); + } } diff --git a/tests/Object/DateTimeImmutableRfc3339NormalizableTest.php b/tests/Object/DateTimeImmutableRfc3339NormalizableTest.php index a7b573d..45d2526 100644 --- a/tests/Object/DateTimeImmutableRfc3339NormalizableTest.php +++ b/tests/Object/DateTimeImmutableRfc3339NormalizableTest.php @@ -3,6 +3,9 @@ namespace Era269\Normalizable\Tests\Object; +use BadMethodCallException; +use DateTime; +use DateTimeImmutable; use Era269\Normalizable\Object\DateTimeImmutableRfc3339Normalizable; use PHPUnit\Framework\TestCase; use UnexpectedValueException; @@ -24,6 +27,47 @@ public function testNormalize(): DateTimeImmutableRfc3339Normalizable return $datetime; } + public function testCreateFromInterface(): void + { + $dateTime = new DateTimeImmutable(); + if (PHP_VERSION_ID >= 80000) { + $dateTimeFrom = DateTimeImmutableRfc3339Normalizable::createFromInterface($dateTime); + self::assertInstanceOf(DateTimeImmutableRfc3339Normalizable::class, $dateTimeFrom); + self::assertEquals( + $dateTime->format(DATE_RFC3339), + $dateTimeFrom->format(DATE_RFC3339) + ); + } else { + $this->expectException(BadMethodCallException::class); + DateTimeImmutableRfc3339Normalizable::createFromInterface($dateTime); + } + } + + public function testCreateFromFormat(): void + { + $dateTime = new DateTimeImmutable(); + $dateTimeFrom = DateTimeImmutableRfc3339Normalizable::createFromFormat( + DATE_RFC3339, + $dateTime->format(DATE_RFC3339) + ); + self::assertInstanceOf(DateTimeImmutableRfc3339Normalizable::class, $dateTimeFrom); + self::assertEquals( + $dateTime->format(DATE_RFC3339), + $dateTimeFrom->format(DATE_RFC3339) + ); + } + + public function testCreateFromMutable(): void + { + $dateTime = new DateTime(); + $dateTimeFrom = DateTimeImmutableRfc3339Normalizable::createFromMutable($dateTime); + self::assertInstanceOf(DateTimeImmutableRfc3339Normalizable::class, $dateTimeFrom); + self::assertEquals( + $dateTime->format(DATE_RFC3339), + $dateTimeFrom->format(DATE_RFC3339) + ); + } + /** * @depends testNormalize */ diff --git a/tests/Object/DateTimeRfc3339NormalizableTest.php b/tests/Object/DateTimeRfc3339NormalizableTest.php index 08e18f4..690ad0b 100644 --- a/tests/Object/DateTimeRfc3339NormalizableTest.php +++ b/tests/Object/DateTimeRfc3339NormalizableTest.php @@ -3,6 +3,8 @@ namespace Era269\Normalizable\Tests\Object; +use BadMethodCallException; +use DateTime; use Era269\Normalizable\Object\DateTimeRfc3339Normalizable; use PHPUnit\Framework\TestCase; use UnexpectedValueException; @@ -35,6 +37,36 @@ public function testDenormalize(DateTimeRfc3339Normalizable $dateTime): void ); } + public function testCreateFromInterface(): void + { + $dateTime = new DateTime(); + if (PHP_VERSION_ID >= 80000) { + $dateTimeFrom = DateTimeRfc3339Normalizable::createFromInterface($dateTime); + self::assertInstanceOf(DateTimeRfc3339Normalizable::class, $dateTimeFrom); + self::assertEquals( + $dateTime->format(DATE_RFC3339), + $dateTimeFrom->format(DATE_RFC3339) + ); + } else { + $this->expectException(BadMethodCallException::class); + DateTimeRfc3339Normalizable::createFromInterface($dateTime); + } + } + + public function testCreateFromFormat(): void + { + $dateTime = new DateTime(); + $dateTimeFrom = DateTimeRfc3339Normalizable::createFromFormat( + DATE_RFC3339, + $dateTime->format(DATE_RFC3339) + ); + self::assertInstanceOf(DateTimeRfc3339Normalizable::class, $dateTimeFrom); + self::assertEquals( + $dateTime->format(DATE_RFC3339), + $dateTimeFrom->format(DATE_RFC3339) + ); + } + public function testDenormalizeFail(): void { $this->expectException(UnexpectedValueException::class);