diff --git a/src/Mooc/Videos/Application/Create/CreateVideoCommandHandler.php b/src/Mooc/Videos/Application/Create/CreateVideoCommandHandler.php index 6cabf783b..608900a2e 100644 --- a/src/Mooc/Videos/Application/Create/CreateVideoCommandHandler.php +++ b/src/Mooc/Videos/Application/Create/CreateVideoCommandHandler.php @@ -18,7 +18,7 @@ public function __construct(private VideoCreator $creator) {} public function __invoke(CreateVideoCommand $command): void { $id = new VideoId($command->id()); - $type = new VideoType($command->type()); + $type = VideoType::from($command->type()); $title = new VideoTitle($command->title()); $url = new VideoUrl($command->url()); $courseId = new CourseId($command->courseId()); diff --git a/src/Mooc/Videos/Application/Find/VideoResponseConverter.php b/src/Mooc/Videos/Application/Find/VideoResponseConverter.php index 6ee2b7b5f..23d890eb8 100644 --- a/src/Mooc/Videos/Application/Find/VideoResponseConverter.php +++ b/src/Mooc/Videos/Application/Find/VideoResponseConverter.php @@ -12,7 +12,7 @@ public function __invoke(Video $video): VideoResponse { return new VideoResponse( $video->id()->value(), - $video->type()->value(), + $video->type()->value, $video->title()->value(), $video->url()->value(), $video->courseId()->value() diff --git a/src/Mooc/Videos/Domain/Video.php b/src/Mooc/Videos/Domain/Video.php index a8626df49..567d7231a 100644 --- a/src/Mooc/Videos/Domain/Video.php +++ b/src/Mooc/Videos/Domain/Video.php @@ -30,7 +30,7 @@ public static function create( $video->record( new VideoCreatedDomainEvent( $id->value(), - $type->value(), + $type->value, $title->value(), $url->value(), $courseId->value() diff --git a/src/Mooc/Videos/Domain/VideoType.php b/src/Mooc/Videos/Domain/VideoType.php index 3b20ed338..7560b64cf 100644 --- a/src/Mooc/Videos/Domain/VideoType.php +++ b/src/Mooc/Videos/Domain/VideoType.php @@ -4,20 +4,8 @@ namespace CodelyTv\Mooc\Videos\Domain; -use CodelyTv\Shared\Domain\ValueObject\Enum; -use InvalidArgumentException; - -/** - * @method static VideoType screencast() - * @method static VideoType interview() - */ -final class VideoType extends Enum +enum VideoType: string { - public const SCREENCAST = 'screencast'; - public const INTERVIEW = 'interview'; - - protected function throwExceptionForInvalidValue($value): never - { - throw new InvalidArgumentException(sprintf('The <%s> value is not a valid video type', $value)); - } + case SCREENCAST = 'screencast'; + case INTERVIEW = 'interview'; } diff --git a/src/Shared/Domain/Criteria/Filter.php b/src/Shared/Domain/Criteria/Filter.php index 48c61445a..05afbb66c 100644 --- a/src/Shared/Domain/Criteria/Filter.php +++ b/src/Shared/Domain/Criteria/Filter.php @@ -16,7 +16,7 @@ public static function fromValues(array $values): self { return new self( new FilterField($values['field']), - new FilterOperator($values['operator']), + FilterOperator::from($values['operator']), new FilterValue($values['value']) ); } @@ -38,6 +38,6 @@ public function value(): FilterValue public function serialize(): string { - return sprintf('%s.%s.%s', $this->field->value(), $this->operator->value(), $this->value->value()); + return sprintf('%s.%s.%s', $this->field->value(), $this->operator->value, $this->value->value()); } } diff --git a/src/Shared/Domain/Criteria/FilterOperator.php b/src/Shared/Domain/Criteria/FilterOperator.php index 8a888019a..5f6f151ac 100644 --- a/src/Shared/Domain/Criteria/FilterOperator.php +++ b/src/Shared/Domain/Criteria/FilterOperator.php @@ -4,31 +4,17 @@ namespace CodelyTv\Shared\Domain\Criteria; -use CodelyTv\Shared\Domain\ValueObject\Enum; -use InvalidArgumentException; - -/** - * @method static FilterOperator gt() - * @method static FilterOperator lt() - * @method static FilterOperator like() - */ -final class FilterOperator extends Enum +enum FilterOperator: string { - public const EQUAL = '='; - public const NOT_EQUAL = '!='; - public const GT = '>'; - public const LT = '<'; - public const CONTAINS = 'CONTAINS'; - public const NOT_CONTAINS = 'NOT_CONTAINS'; - private static array $containing = [self::CONTAINS, self::NOT_CONTAINS]; + case EQUAL = '='; + case NOT_EQUAL = '!='; + case GT = '>'; + case LT = '<'; + case CONTAINS = 'CONTAINS'; + case NOT_CONTAINS = 'NOT_CONTAINS'; public function isContaining(): bool { - return in_array($this->value(), self::$containing, true); - } - - protected function throwExceptionForInvalidValue($value): never - { - throw new InvalidArgumentException(sprintf('The filter <%s> is invalid', $value)); + return in_array($this->value, [self::CONTAINS->value, self::NOT_CONTAINS->value], true); } } diff --git a/src/Shared/Domain/Criteria/Order.php b/src/Shared/Domain/Criteria/Order.php index c86595764..331571c9a 100644 --- a/src/Shared/Domain/Criteria/Order.php +++ b/src/Shared/Domain/Criteria/Order.php @@ -10,17 +10,17 @@ public function __construct(private OrderBy $orderBy, private OrderType $orderTy public static function createDesc(OrderBy $orderBy): self { - return new self($orderBy, OrderType::desc()); + return new self($orderBy, OrderType::DESC); } public static function fromValues(?string $orderBy, ?string $order): self { - return $orderBy === null ? self::none() : new self(new OrderBy($orderBy), new OrderType($order)); + return $orderBy === null ? self::none() : new self(new OrderBy($orderBy), OrderType::from($order)); } public static function none(): self { - return new self(new OrderBy(''), OrderType::none()); + return new self(new OrderBy(''), OrderType::NONE); } public function orderBy(): OrderBy @@ -40,6 +40,6 @@ public function isNone(): bool public function serialize(): string { - return sprintf('%s.%s', $this->orderBy->value(), $this->orderType->value()); + return sprintf('%s.%s', $this->orderBy->value(), $this->orderType->value); } } diff --git a/src/Shared/Domain/Criteria/OrderType.php b/src/Shared/Domain/Criteria/OrderType.php index 50f2f5213..2ce357a95 100644 --- a/src/Shared/Domain/Criteria/OrderType.php +++ b/src/Shared/Domain/Criteria/OrderType.php @@ -4,27 +4,14 @@ namespace CodelyTv\Shared\Domain\Criteria; -use CodelyTv\Shared\Domain\ValueObject\Enum; -use InvalidArgumentException; - -/** - * @method static OrderType asc() - * @method static OrderType desc() - * @method static OrderType none() - */ -final class OrderType extends Enum +enum OrderType: string { - public const ASC = 'asc'; - public const DESC = 'desc'; - public const NONE = 'none'; + case ASC = 'asc'; + case DESC = 'desc'; + case NONE = 'none'; public function isNone(): bool { - return $this->equals(self::none()); - } - - protected function throwExceptionForInvalidValue($value): never - { - throw new InvalidArgumentException($value); + return $this->value === self::NONE->value; } } diff --git a/src/Shared/Domain/ValueObject/Enum.php b/src/Shared/Domain/ValueObject/Enum.php deleted file mode 100644 index 76825cecf..000000000 --- a/src/Shared/Domain/ValueObject/Enum.php +++ /dev/null @@ -1,83 +0,0 @@ -ensureIsBetweenAcceptedValues($value); - } - - abstract protected function throwExceptionForInvalidValue($value); - - public static function __callStatic(string $name, $args) - { - return new static(self::values()[$name]); - } - - final public static function fromString(string $value): self - { - return new static($value); - } - - final public static function values(): array - { - $class = static::class; - - if (!isset(self::$cache[$class])) { - $reflected = new ReflectionClass($class); - self::$cache[$class] = reindex(self::keysFormatter(), $reflected->getConstants()); - } - - return self::$cache[$class]; - } - - final public static function randomValue() - { - return self::values()[array_rand(self::values())]; - } - - final public static function random(): static - { - return new static(self::randomValue()); - } - - private static function keysFormatter(): callable - { - return static fn ($unused, string $key): string => Utils::toCamelCase(strtolower($key)); - } - - final public function value() - { - return $this->value; - } - - final public function equals(self $other): bool - { - return $other->value() === $this->value(); - } - - public function __toString(): string - { - return (string) $this->value(); - } - - private function ensureIsBetweenAcceptedValues($value): void - { - if (!in_array($value, static::values(), true)) { - $this->throwExceptionForInvalidValue($value); - } - } -} diff --git a/src/Shared/Infrastructure/Persistence/Doctrine/DoctrineCriteriaConverter.php b/src/Shared/Infrastructure/Persistence/Doctrine/DoctrineCriteriaConverter.php index fd2930ab9..ca4e91d24 100644 --- a/src/Shared/Infrastructure/Persistence/Doctrine/DoctrineCriteriaConverter.php +++ b/src/Shared/Infrastructure/Persistence/Doctrine/DoctrineCriteriaConverter.php @@ -60,7 +60,7 @@ private function buildComparison(): callable ? $this->hydrate($field, $filter->value()->value()) : $filter->value()->value(); - return new Comparison($field, $filter->operator()->value(), $value); + return new Comparison($field, $filter->operator()->value, $value); }; } diff --git a/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticQueryGenerator.php b/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticQueryGenerator.php index 611585223..55c34782d 100644 --- a/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticQueryGenerator.php +++ b/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticQueryGenerator.php @@ -6,7 +6,6 @@ use CodelyTv\Shared\Domain\Criteria\Filter; use CodelyTv\Shared\Domain\Criteria\FilterOperator; -use Exception; final class ElasticQueryGenerator { @@ -38,17 +37,16 @@ public function __invoke(array $query, Filter $filter): array private function typeFor(FilterOperator $operator): string { - return in_array($operator->value(), self::$mustNotFields, true) ? self::MUST_NOT_TYPE : self::MUST_TYPE; + return in_array($operator->value, self::$mustNotFields, true) ? self::MUST_NOT_TYPE : self::MUST_TYPE; } private function termLevelFor(FilterOperator $operator): string { - return match ($operator->value()) { + return match ($operator) { FilterOperator::EQUAL => self::TERM_TERM, FilterOperator::NOT_EQUAL => '!=', FilterOperator::GT, FilterOperator::LT => self::TERM_RANGE, FilterOperator::CONTAINS, FilterOperator::NOT_CONTAINS => self::TERM_WILDCARD, - default => throw new Exception("Unexpected match value {$operator->value()}"), }; } } diff --git a/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticsearchCriteriaConverter.php b/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticsearchCriteriaConverter.php index b541f941e..d215a7e33 100644 --- a/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticsearchCriteriaConverter.php +++ b/src/Shared/Infrastructure/Persistence/Elasticsearch/ElasticsearchCriteriaConverter.php @@ -42,7 +42,7 @@ private function formatSort(Criteria $criteria): array return [ 'sort' => [ $order->orderBy()->value() => [ - 'order' => $order->orderType()->value(), + 'order' => $order->orderType()->value, ], ], ]; diff --git a/tests/Shared/Domain/Criteria/FilterMother.php b/tests/Shared/Domain/Criteria/FilterMother.php index 9f3a6fcc5..40473422e 100644 --- a/tests/Shared/Domain/Criteria/FilterMother.php +++ b/tests/Shared/Domain/Criteria/FilterMother.php @@ -8,6 +8,7 @@ use CodelyTv\Shared\Domain\Criteria\FilterField; use CodelyTv\Shared\Domain\Criteria\FilterOperator; use CodelyTv\Shared\Domain\Criteria\FilterValue; +use CodelyTv\Tests\Shared\Domain\RandomElementPicker; final class FilterMother { @@ -18,7 +19,7 @@ public static function create( ): Filter { return new Filter( $field ?? FilterFieldMother::create(), - $operator ?? FilterOperator::random(), + $operator ?? self::randomOperator(), $value ?? FilterValueMother::create() ); } @@ -28,4 +29,17 @@ public static function fromValues(array $values): Filter { return Filter::fromValues($values); } + + + private static function randomOperator(): FilterOperator + { + return RandomElementPicker::from( + FilterOperator::EQUAL, + FilterOperator::NOT_EQUAL, + FilterOperator::GT, + FilterOperator::LT, + FilterOperator::CONTAINS, + FilterOperator::NOT_CONTAINS + ); + } } diff --git a/tests/Shared/Domain/Criteria/OrderMother.php b/tests/Shared/Domain/Criteria/OrderMother.php index 10e791440..81c606e07 100644 --- a/tests/Shared/Domain/Criteria/OrderMother.php +++ b/tests/Shared/Domain/Criteria/OrderMother.php @@ -7,16 +7,22 @@ use CodelyTv\Shared\Domain\Criteria\Order; use CodelyTv\Shared\Domain\Criteria\OrderBy; use CodelyTv\Shared\Domain\Criteria\OrderType; +use CodelyTv\Tests\Shared\Domain\RandomElementPicker; final class OrderMother { public static function create(?OrderBy $orderBy = null, ?OrderType $orderType = null): Order { - return new Order($orderBy ?? OrderByMother::create(), $orderType ?? OrderType::random()); + return new Order($orderBy ?? OrderByMother::create(), $orderType ?? self::randomOrderType()); } public static function none(): Order { return Order::none(); } + + private static function randomOrderType(): Order + { + return RandomElementPicker::from(OrderType::ASC, OrderType::DESC, OrderType::NONE); + } }