From ef61ab75dce0cefe7daf5c41690f10ea9575d91d Mon Sep 17 00:00:00 2001 From: Christian Kolb Date: Sun, 9 Jun 2024 08:04:55 +0200 Subject: [PATCH] Add weekday including type and normalizers --- .../DoctrineTypeRegisterCompilerPass.php | 2 + src/Doctrine/WeekdayType.php | 50 ++++++++ src/Resources/config/services.yaml | 3 + src/Serializer/WeekdayNormalizer.php | 51 ++++++++ src/Weekday.php | 111 +++++++++++++++++ tests/Doctrine/WeekdayTypeTest.php | 54 +++++++++ tests/Serializer/WeekdayNormalizerTest.php | 114 ++++++++++++++++++ 7 files changed, 385 insertions(+) create mode 100644 src/Doctrine/WeekdayType.php create mode 100644 src/Serializer/WeekdayNormalizer.php create mode 100644 src/Weekday.php create mode 100644 tests/Doctrine/WeekdayTypeTest.php create mode 100644 tests/Serializer/WeekdayNormalizerTest.php diff --git a/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php b/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php index 4a6a59c..997a68b 100644 --- a/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php +++ b/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Doctrine\MomentType; use DigitalCraftsman\DateTimePrecision\Doctrine\MonthType; use DigitalCraftsman\DateTimePrecision\Doctrine\TimeType; +use DigitalCraftsman\DateTimePrecision\Doctrine\WeekdayType; use DigitalCraftsman\DateTimePrecision\Doctrine\YearType; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -23,6 +24,7 @@ public function process(ContainerBuilder $container): void $typeDefinitions['dtp_moment'] = ['class' => MomentType::class]; $typeDefinitions['dtp_time'] = ['class' => TimeType::class]; + $typeDefinitions['dtp_weekday'] = ['class' => WeekdayType::class]; $typeDefinitions['dtp_date'] = ['class' => DateType::class]; $typeDefinitions['dtp_month'] = ['class' => MonthType::class]; $typeDefinitions['dtp_year'] = ['class' => YearType::class]; diff --git a/src/Doctrine/WeekdayType.php b/src/Doctrine/WeekdayType.php new file mode 100644 index 0000000..e15c715 --- /dev/null +++ b/src/Doctrine/WeekdayType.php @@ -0,0 +1,50 @@ +value; + } + + /** @param string|null $value */ + public function convertToPHPValue($value, AbstractPlatform $platform): ?Weekday + { + return $value === null + ? null + : Weekday::from($value); + } + + /** @codeCoverageIgnore */ + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string + { + $column['length'] = 9; + + return $platform->getStringTypeDeclarationSQL($column); + } + + /** @codeCoverageIgnore */ + public function requiresSQLCommentHint(AbstractPlatform $platform): bool + { + return true; + } +} diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index aeea9a5..7d5a2f2 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -13,6 +13,9 @@ services: DigitalCraftsman\DateTimePrecision\Serializer\TimeNormalizer: tags: [ { name: 'serializer.normalizer' } ] + DigitalCraftsman\DateTimePrecision\Serializer\WeekdayNormalizer: + tags: [ { name: 'serializer.normalizer' } ] + DigitalCraftsman\DateTimePrecision\Serializer\DateNormalizer: tags: [ { name: 'serializer.normalizer' } ] diff --git a/src/Serializer/WeekdayNormalizer.php b/src/Serializer/WeekdayNormalizer.php new file mode 100644 index 0000000..c337dbd --- /dev/null +++ b/src/Serializer/WeekdayNormalizer.php @@ -0,0 +1,51 @@ +value; + } + + /** @param ?string $data */ + public function denormalize($data, $type, $format = null, array $context = []): ?Weekday + { + return $data === null + ? null + : Weekday::from($data); + } + + /** + * @return array + * + * @codeCoverageIgnore + */ + public function getSupportedTypes(?string $format): array + { + return [ + Weekday::class => true, + ]; + } +} diff --git a/src/Weekday.php b/src/Weekday.php new file mode 100644 index 0000000..17e1a9a --- /dev/null +++ b/src/Weekday.php @@ -0,0 +1,111 @@ +format('N')); + } + + public static function fromDate(Date $date): self + { + return self::fromDayOfWeek((int) $date->format('N')); + } + + public static function fromDayOfWeek(int $dayOfIsoWeek): self + { + return match ($dayOfIsoWeek) { + 1 => self::MONDAY, + 2 => self::TUESDAY, + 3 => self::WEDNESDAY, + 4 => self::THURSDAY, + 5 => self::FRIDAY, + 6 => self::SATURDAY, + 7 => self::SUNDAY, + }; + } + + // -- Accessors + + public function dayOfWeek(): int + { + return match ($this) { + self::MONDAY => 1, + self::TUESDAY => 2, + self::WEDNESDAY => 3, + self::THURSDAY => 4, + self::FRIDAY => 5, + self::SATURDAY => 6, + self::SUNDAY => 7, + }; + } + + public function isEqualTo(self $weekday): bool + { + return $this === $weekday; + } + + public function isNotEqualTo(self $weekday): bool + { + return $this !== $weekday; + } + + public function isBefore(self $date): bool + { + return $this->dayOfWeek() < $date->dayOfWeek(); + } + + public function isNotBefore(self $date): bool + { + return !($this->dayOfWeek() < $date->dayOfWeek()); + } + + public function isBeforeOrEqualTo(self $date): bool + { + return $this->dayOfWeek() <= $date->dayOfWeek(); + } + + public function isNotBeforeOrEqualTo(self $date): bool + { + return !($this->dayOfWeek() <= $date->dayOfWeek()); + } + + public function isAfter(self $date): bool + { + return $this->dayOfWeek() > $date->dayOfWeek(); + } + + public function isNotAfter(self $date): bool + { + return !($this->dayOfWeek() > $date->dayOfWeek()); + } + + public function isAfterOrEqualTo(self $date): bool + { + return $this->dayOfWeek() >= $date->dayOfWeek(); + } + + public function isNotAfterOrEqualTo(self $date): bool + { + return !($this->dayOfWeek() >= $date->dayOfWeek()); + } + + public function compareTo(self $date): int + { + return $this->dayOfWeek() <=> $date->dayOfWeek(); + } +} diff --git a/tests/Doctrine/WeekdayTypeTest.php b/tests/Doctrine/WeekdayTypeTest.php new file mode 100644 index 0000000..fe1e49b --- /dev/null +++ b/tests/Doctrine/WeekdayTypeTest.php @@ -0,0 +1,54 @@ +convertToDatabaseValue($weekday, $platform); + $phpValue = $weekdayType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertEquals($weekday, $phpValue); + } + + /** + * @test + * + * @covers ::convertToDatabaseValue + * @covers ::convertToPHPValue + */ + public function convert_from_and_to_null_value_works(): void + { + // -- Arrange + $weekdayType = new WeekdayType(); + $platform = new PostgreSQLPlatform(); + + // -- Act + $databaseValue = $weekdayType->convertToDatabaseValue(null, $platform); + $phpValue = $weekdayType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertNull($phpValue); + } +} diff --git a/tests/Serializer/WeekdayNormalizerTest.php b/tests/Serializer/WeekdayNormalizerTest.php new file mode 100644 index 0000000..bbcebad --- /dev/null +++ b/tests/Serializer/WeekdayNormalizerTest.php @@ -0,0 +1,114 @@ +normalize($weekday); + $denormalizedData = $normalizer->denormalize($normalizedData, Weekday::class); + + // -- Assert + self::assertEquals($weekday, $denormalizedData); + } + + /** + * @test + * + * @covers ::normalize + */ + public function weekday_normalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act + $normalizedData = $normalizer->normalize(null); + + // -- Assert + self::assertNull($normalizedData); + } + + /** + * @test + * + * @covers ::denormalize + */ + public function weekday_denormalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act + $denormalizedData = $normalizer->denormalize(null, Weekday::class); + + // -- Assert + self::assertNull($denormalizedData); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization(): void + { + // -- Arrange + $weekday = Weekday::TUESDAY; + + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsNormalization($weekday)); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization_fails(): void + { + // -- Arrange + $year = Year::fromString('2022'); + + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertFalse($normalizer->supportsNormalization($year)); + } + + /** + * @test + * + * @covers ::supportsDenormalization + */ + public function supports_denormalization(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsDenormalization(null, Weekday::class)); + } +}