Skip to content

Commit

Permalink
Add weekday including type and normalizers
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Kolb committed Jun 9, 2024
1 parent fcec99c commit ef61ab7
Show file tree
Hide file tree
Showing 7 changed files with 385 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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];
Expand Down
50 changes: 50 additions & 0 deletions src/Doctrine/WeekdayType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace DigitalCraftsman\DateTimePrecision\Doctrine;

use DigitalCraftsman\DateTimePrecision\Weekday;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\StringType;

final class WeekdayType extends StringType
{
/** @codeCoverageIgnore */
public function getName(): string
{
return 'dtp_weekday';
}

/** @param Weekday|null $value */
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{
if ($value === null) {
return null;
}

return $value->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;
}
}
3 changes: 3 additions & 0 deletions src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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' } ]

Expand Down
51 changes: 51 additions & 0 deletions src/Serializer/WeekdayNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace DigitalCraftsman\DateTimePrecision\Serializer;

use DigitalCraftsman\DateTimePrecision\Weekday;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

final class WeekdayNormalizer implements NormalizerInterface, DenormalizerInterface
{
public function supportsNormalization($data, $format = null, array $context = []): bool
{
return $data instanceof Weekday;
}

/** @param class-string $type */
public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
{
return $type === Weekday::class;
}

/** @param Weekday|null $object */
public function normalize($object, $format = null, array $context = []): ?string
{
return $object === null
? null
: $object->value;
}

/** @param ?string $data */
public function denormalize($data, $type, $format = null, array $context = []): ?Weekday
{
return $data === null
? null
: Weekday::from($data);
}

/**
* @return array<class-string, bool>
*
* @codeCoverageIgnore
*/
public function getSupportedTypes(?string $format): array
{
return [
Weekday::class => true,
];
}
}
111 changes: 111 additions & 0 deletions src/Weekday.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare(strict_types=1);

namespace DigitalCraftsman\DateTimePrecision;

enum Weekday: string
{
case MONDAY = 'MONDAY';
case TUESDAY = 'TUESDAY';
case WEDNESDAY = 'WEDNESDAY';
case THURSDAY = 'THURSDAY';
case FRIDAY = 'FRIDAY';
case SATURDAY = 'SATURDAY';
case SUNDAY = 'SUNDAY';

// -- Construction

public static function fromDateTime(\DateTimeImmutable $dateTime): self
{
return self::fromDayOfWeek((int) $dateTime->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();
}
}
54 changes: 54 additions & 0 deletions tests/Doctrine/WeekdayTypeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace DigitalCraftsman\DateTimePrecision\Doctrine;

use DigitalCraftsman\DateTimePrecision\Weekday;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use PHPUnit\Framework\TestCase;

/** @coversDefaultClass \DigitalCraftsman\DateTimePrecision\Doctrine\WeekdayType */
final class WeekdayTypeTest extends TestCase
{
/**
* @test
*
* @covers ::convertToDatabaseValue
* @covers ::convertToPHPValue
*/
public function convert_from_and_to_month_php_value_works(): void
{
// -- Arrange
$weekday = Weekday::MONDAY;
$weekdayType = new WeekdayType();
$platform = new PostgreSQLPlatform();

// -- Act
$databaseValue = $weekdayType->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);
}
}
Loading

0 comments on commit ef61ab7

Please sign in to comment.