Skip to content

Commit 929ad4c

Browse files
authored
Merge pull request #24 from wiz-develop:endou-mame/issue23
feat: 列挙型の値オブジェクトとファクトリの実装を追加し、テストを実施
2 parents 0e36378 + ec42c0b commit 929ad4c

File tree

9 files changed

+396
-30
lines changed

9 files changed

+396
-30
lines changed

examples/Enum/TestEnumValue.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Examples\Enum;
6+
7+
use WizDevelop\PhpValueObject\Enum\EnumValueFactory;
8+
use WizDevelop\PhpValueObject\Enum\EnumValueObjectDefault;
9+
use WizDevelop\PhpValueObject\Enum\IEnumValue;
10+
use WizDevelop\PhpValueObject\ValueObjectMeta;
11+
12+
#[ValueObjectMeta(name: '列挙型', description: '列挙型の値オブジェクトの例')]
13+
enum TestEnumValue: string implements IEnumValue
14+
{
15+
use EnumValueFactory;
16+
use EnumValueObjectDefault;
17+
18+
case Value1 = 'Value1';
19+
case Value2 = 'Value2';
20+
case Value3 = 'Value3';
21+
}

src/Enum/EnumValueFactory.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Enum;
6+
7+
use Override;
8+
use WizDevelop\PhpMonad\Option;
9+
use WizDevelop\PhpMonad\Result;
10+
11+
/**
12+
* Default implementation of IEnumValueFactory
13+
* @see WizDevelop\PhpValueObject\Enum\IEnumValueFactory
14+
*/
15+
trait EnumValueFactory
16+
{
17+
#[Override]
18+
final public static function fromNullable(string|int|null $value): Option
19+
{
20+
if ($value === null) {
21+
return Option\none();
22+
}
23+
24+
return Option\some(static::from($value));
25+
}
26+
27+
#[Override]
28+
final public static function tryFrom2(string|int $value): Result
29+
{
30+
return static::isValid($value)
31+
->andThen(static fn () => self::isValidEnumValue($value))
32+
->andThen(static fn () => Result\ok(static::from($value)));
33+
}
34+
35+
#[Override]
36+
final public static function tryFromNullable(string|int|null $value): Result
37+
{
38+
if ($value === null) {
39+
// @phpstan-ignore return.type
40+
return Result\ok(Option\none());
41+
}
42+
43+
// @phpstan-ignore return.type
44+
return static::tryFrom2($value)->map(static fn ($result) => Option\some($result));
45+
}
46+
}

src/Enum/EnumValueObjectDefault.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Enum;
6+
7+
use Override;
8+
use WizDevelop\PhpMonad\Result;
9+
use WizDevelop\PhpValueObject\Error\ValueObjectError;
10+
use WizDevelop\PhpValueObject\IValueObject;
11+
12+
/**
13+
* 列挙型の値オブジェクトのデフォルト実装
14+
*/
15+
trait EnumValueObjectDefault
16+
{
17+
#[Override]
18+
public function equals(IValueObject $other): bool
19+
{
20+
return $this === $other;
21+
}
22+
23+
#[Override]
24+
public function jsonSerialize(): string|int
25+
{
26+
return $this->value;
27+
}
28+
29+
/**
30+
* 有効な値かどうか
31+
* NOTE: 実装クラスでのオーバーライド用メソッド
32+
*
33+
* @return Result<bool,ValueObjectError>
34+
*/
35+
private static function isValidEnumValue(string|int $value): Result
36+
{
37+
$tryFromResult = static::tryFrom($value);
38+
39+
if ($tryFromResult === null) {
40+
/**
41+
* @var static[]
42+
* @phpstan-ignore-next-line
43+
*/
44+
$expectedValues = static::cases();
45+
46+
return Result\err(ValueObjectError::enum()->invalidEnumValue(
47+
className: static::class,
48+
expectedValues: $expectedValues,
49+
value: $value,
50+
));
51+
}
52+
53+
return Result\ok();
54+
}
55+
56+
/**
57+
* 有効な値かどうか
58+
* NOTE: 実装クラスでのオーバーライド用メソッド
59+
* @return Result<bool,ValueObjectError>
60+
*/
61+
protected static function isValid(string|int $value): Result
62+
{
63+
return Result\ok(true);
64+
}
65+
}

src/Enum/IEnumValue.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Enum;
6+
7+
use WizDevelop\PhpValueObject\IValueObject;
8+
9+
/**
10+
* 列挙型の値オブジェクト インターフェース
11+
* @see WizDevelop\PhpValueObject\Enum\EnumValueFactory
12+
*/
13+
interface IEnumValue extends IValueObject, IEnumValueFactory
14+
{
15+
}

src/Enum/IEnumValueFactory.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Enum;
6+
7+
use WizDevelop\PhpMonad\Option;
8+
use WizDevelop\PhpMonad\Result;
9+
use WizDevelop\PhpValueObject\Error\ValueObjectError;
10+
11+
/**
12+
* 列挙型の値オブジェクト ファクトリインターフェース
13+
*
14+
* @see WizDevelop\PhpValueObject\Enum\EnumValueFactory
15+
*/
16+
interface IEnumValueFactory
17+
{
18+
/**
19+
* 信頼できるプリミティブ値からインスタンスを生成する(Null許容)
20+
* @return Option<static>
21+
*/
22+
public static function fromNullable(string|int|null $value): Option;
23+
24+
/**
25+
* 信頼できないプリミティブ値からインスタンスを生成する
26+
* @return Result<static,ValueObjectError>
27+
*/
28+
public static function tryFrom2(string|int $value): Result;
29+
30+
/**
31+
* 信頼できないプリミティブ値からインスタンスを生成する(Null許容)
32+
* @return Result<Option<static>,ValueObjectError>
33+
*/
34+
public static function tryFromNullable(string|int|null $value): Result;
35+
}

src/EnumValueObjectDefault.php

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/Error/EnumValueError.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WizDevelop\PhpValueObject\Error;
6+
7+
use BackedEnum;
8+
use WizDevelop\PhpValueObject\Enum\IEnumValue;
9+
10+
/**
11+
* EnumValue エラー
12+
*/
13+
final readonly class EnumValueError
14+
{
15+
/**
16+
* Enumの値が無効
17+
*
18+
* @template TBackedEnum of BackedEnum
19+
* @param class-string<IEnumValue> $className
20+
* @param TBackedEnum[] $expectedValues
21+
*/
22+
public static function invalidEnumValue(
23+
string $className,
24+
array $expectedValues,
25+
string|int $value,
26+
): ValueObjectError {
27+
$displayName = ValueObjectError::getDisplayName($className);
28+
29+
$expectedString = implode(
30+
separator: ', ',
31+
array: array_map(static fn ($e) => $e->value, $expectedValues),
32+
);
33+
34+
return ValueObjectError::of(
35+
code: 'enum.invalidEnumValue',
36+
message: "{$displayName}の値は{$expectedString}のいずれかである必要があります。(値: {$value})",
37+
);
38+
}
39+
}

src/Error/ValueObjectError.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,9 @@ public static function dateTime(): DateTimeValueError
7171
{
7272
return new DateTimeValueError();
7373
}
74+
75+
public static function enum(): EnumValueError
76+
{
77+
return new EnumValueError();
78+
}
7479
}

0 commit comments

Comments
 (0)