Skip to content

feat: 列挙型の値オブジェクトとファクトリの実装を追加し、テストを実施 #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions examples/Enum/TestEnumValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Examples\Enum;

use WizDevelop\PhpValueObject\Enum\EnumValueFactory;
use WizDevelop\PhpValueObject\Enum\EnumValueObjectDefault;
use WizDevelop\PhpValueObject\Enum\IEnumValue;
use WizDevelop\PhpValueObject\ValueObjectMeta;

#[ValueObjectMeta(name: '列挙型', description: '列挙型の値オブジェクトの例')]
enum TestEnumValue: string implements IEnumValue
{
use EnumValueFactory;
use EnumValueObjectDefault;

case Value1 = 'Value1';
case Value2 = 'Value2';
case Value3 = 'Value3';
}
46 changes: 46 additions & 0 deletions src/Enum/EnumValueFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Enum;

use Override;
use WizDevelop\PhpMonad\Option;
use WizDevelop\PhpMonad\Result;

/**
* Default implementation of IEnumValueFactory
* @see WizDevelop\PhpValueObject\Enum\IEnumValueFactory
*/
trait EnumValueFactory
{
#[Override]
final public static function fromNullable(string|int|null $value): Option
{
if ($value === null) {
return Option\none();
}

return Option\some(static::from($value));
}

#[Override]
final public static function tryFrom2(string|int $value): Result
{
return static::isValid($value)
->andThen(static fn () => self::isValidEnumValue($value))
->andThen(static fn () => Result\ok(static::from($value)));
}

#[Override]
final public static function tryFromNullable(string|int|null $value): Result
{
if ($value === null) {
// @phpstan-ignore return.type
return Result\ok(Option\none());
}

// @phpstan-ignore return.type
return static::tryFrom2($value)->map(static fn ($result) => Option\some($result));
}
}
65 changes: 65 additions & 0 deletions src/Enum/EnumValueObjectDefault.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Enum;

use Override;
use WizDevelop\PhpMonad\Result;
use WizDevelop\PhpValueObject\Error\ValueObjectError;
use WizDevelop\PhpValueObject\IValueObject;

/**
* 列挙型の値オブジェクトのデフォルト実装
*/
trait EnumValueObjectDefault
{
#[Override]
public function equals(IValueObject $other): bool
{
return $this === $other;
}

#[Override]
public function jsonSerialize(): string|int
{
return $this->value;
}

/**
* 有効な値かどうか
* NOTE: 実装クラスでのオーバーライド用メソッド
*
* @return Result<bool,ValueObjectError>
*/
private static function isValidEnumValue(string|int $value): Result
{
$tryFromResult = static::tryFrom($value);

if ($tryFromResult === null) {
/**
* @var static[]
* @phpstan-ignore-next-line
*/
$expectedValues = static::cases();

return Result\err(ValueObjectError::enum()->invalidEnumValue(
className: static::class,
expectedValues: $expectedValues,
value: $value,
));
}

return Result\ok();
}

/**
* 有効な値かどうか
* NOTE: 実装クラスでのオーバーライド用メソッド
* @return Result<bool,ValueObjectError>
*/
protected static function isValid(string|int $value): Result
{
return Result\ok(true);
}
}
15 changes: 15 additions & 0 deletions src/Enum/IEnumValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Enum;

use WizDevelop\PhpValueObject\IValueObject;

/**
* 列挙型の値オブジェクト インターフェース
* @see WizDevelop\PhpValueObject\Enum\EnumValueFactory
*/
interface IEnumValue extends IValueObject, IEnumValueFactory
{
}
35 changes: 35 additions & 0 deletions src/Enum/IEnumValueFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Enum;

use WizDevelop\PhpMonad\Option;
use WizDevelop\PhpMonad\Result;
use WizDevelop\PhpValueObject\Error\ValueObjectError;

/**
* 列挙型の値オブジェクト ファクトリインターフェース
*
* @see WizDevelop\PhpValueObject\Enum\EnumValueFactory
*/
interface IEnumValueFactory
{
/**
* 信頼できるプリミティブ値からインスタンスを生成する(Null許容)
* @return Option<static>
*/
public static function fromNullable(string|int|null $value): Option;

/**
* 信頼できないプリミティブ値からインスタンスを生成する
* @return Result<static,ValueObjectError>
*/
public static function tryFrom2(string|int $value): Result;

/**
* 信頼できないプリミティブ値からインスタンスを生成する(Null許容)
* @return Result<Option<static>,ValueObjectError>
*/
public static function tryFromNullable(string|int|null $value): Result;
}
30 changes: 0 additions & 30 deletions src/EnumValueObjectDefault.php

This file was deleted.

39 changes: 39 additions & 0 deletions src/Error/EnumValueError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace WizDevelop\PhpValueObject\Error;

use BackedEnum;
use WizDevelop\PhpValueObject\Enum\IEnumValue;

/**
* EnumValue エラー
*/
final readonly class EnumValueError
{
/**
* Enumの値が無効
*
* @template TBackedEnum of BackedEnum
* @param class-string<IEnumValue> $className
* @param TBackedEnum[] $expectedValues
*/
public static function invalidEnumValue(
string $className,
array $expectedValues,
string|int $value,
): ValueObjectError {
$displayName = ValueObjectError::getDisplayName($className);

$expectedString = implode(
separator: ', ',
array: array_map(static fn ($e) => $e->value, $expectedValues),
);

return ValueObjectError::of(
code: 'enum.invalidEnumValue',
message: "{$displayName}の値は{$expectedString}のいずれかである必要があります。(値: {$value})",
);
}
}
5 changes: 5 additions & 0 deletions src/Error/ValueObjectError.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ public static function dateTime(): DateTimeValueError
{
return new DateTimeValueError();
}

public static function enum(): EnumValueError
{
return new EnumValueError();
}
}
Loading
Loading