Skip to content

Commit f9a3aa7

Browse files
committed
fix: address code review findings
- Add JsonSerializable support via jsonSerialize() in trait - Cache ReflectionEnum in EnumValidationRule constructor - Bump minimum PHP to 8.2 (Pest v3 requirement) - Add IteratorAggregate to EnumCollection for foreach support - Narrow PHPStan return.type ignore to inline comment - Add tests for jsonSerialize and foreach iteration
1 parent 37ee8f4 commit f9a3aa7

11 files changed

Lines changed: 56 additions & 20 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-latest
1212
strategy:
1313
matrix:
14-
php: ['8.1', '8.2', '8.3', '8.4']
14+
php: ['8.2', '8.3', '8.4']
1515

1616
name: PHP ${{ matrix.php }}
1717

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ PHP 8.1 introduced native enums, but the ecosystem still relies on `myclabs/php-
1313
composer require kexxt/enum-utils
1414
```
1515

16-
Requires PHP 8.1+.
16+
Requires PHP 8.2+.
1717

1818
## Quick Start
1919

‎composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"license": "MIT",
66
"minimum-stability": "stable",
77
"require": {
8-
"php": "^8.1"
8+
"php": "^8.2"
99
},
1010
"require-dev": {
1111
"pestphp/pest": "^3.0",

‎phpstan.neon‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,3 @@ parameters:
77
ignoreErrors:
88
- identifier: function.alreadyNarrowedType
99
- identifier: function.impossibleType
10-
- identifier: return.type
11-
path: src/EnumUtilsTrait.php

‎src/EnumCollection.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
/**
88
* @template T of \BackedEnum
9+
* @implements \IteratorAggregate<int, T>
910
*/
10-
class EnumCollection implements \Countable
11+
class EnumCollection implements \Countable, \IteratorAggregate
1112
{
1213
/** @var list<T> */
1314
private array $cases;
@@ -94,4 +95,12 @@ public function count(): int
9495
{
9596
return count($this->cases);
9697
}
98+
99+
/**
100+
* @return \ArrayIterator<int, T>
101+
*/
102+
public function getIterator(): \ArrayIterator
103+
{
104+
return new \ArrayIterator($this->cases);
105+
}
97106
}

‎src/EnumUtilsTrait.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,21 @@ public static function randomCase(): static
112112

113113
/**
114114
* Get the backing value for JSON serialization.
115+
* Implements JsonSerializable when the enum declares it.
115116
*/
116117
public function toJsonValue(): string|int
117118
{
118119
return $this->value;
119120
}
120121

122+
/**
123+
* JsonSerializable implementation.
124+
*/
125+
public function jsonSerialize(): string|int
126+
{
127+
return $this->value;
128+
}
129+
121130
/**
122131
* Create a case from a JSON value.
123132
*/
@@ -133,7 +142,7 @@ public static function fromJsonValue(string|int $value): static
133142
*/
134143
public static function collect(): EnumCollection
135144
{
136-
return new EnumCollection(self::cases());
145+
return new EnumCollection(self::cases()); // @phpstan-ignore return.type
137146
}
138147

139148
/**

‎src/Validation/EnumValidationRule.php‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class EnumValidationRule
99
/** @var class-string<\BackedEnum> */
1010
private string $enumClass;
1111

12+
private string $backingTypeName;
13+
1214
/**
1315
* @param class-string<\BackedEnum> $enumClass
1416
*/
@@ -21,6 +23,10 @@ public function __construct(string $enumClass)
2123
}
2224

2325
$this->enumClass = $enumClass;
26+
27+
$reflection = new \ReflectionEnum($enumClass);
28+
$backingType = $reflection->getBackingType();
29+
$this->backingTypeName = $backingType !== null ? $backingType->getName() : 'string';
2430
}
2531

2632
/**
@@ -40,17 +46,11 @@ public function validate(mixed $value): bool
4046
return false;
4147
}
4248

43-
$reflection = new \ReflectionEnum($this->enumClass);
44-
$backingType = $reflection->getBackingType();
45-
46-
if ($backingType !== null) {
47-
$typeName = $backingType->getName();
48-
if ($typeName === 'string' && !is_string($value)) {
49-
return false;
50-
}
51-
if ($typeName === 'int' && !is_int($value)) {
52-
return false;
53-
}
49+
if ($this->backingTypeName === 'string' && !is_string($value)) {
50+
return false;
51+
}
52+
if ($this->backingTypeName === 'int' && !is_int($value)) {
53+
return false;
5454
}
5555

5656
return $this->enumClass::tryFrom($value) !== null;

‎tests/EnumCollectionTest.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,12 @@
5454
expect($collection->count())->toBe(0);
5555
expect(count($collection))->toBe(0);
5656
});
57+
58+
test('collection is iterable with foreach', function () {
59+
$collection = new EnumCollection([Priority::Low, Priority::High]);
60+
$result = [];
61+
foreach ($collection as $case) {
62+
$result[] = $case;
63+
}
64+
expect($result)->toBe([Priority::Low, Priority::High]);
65+
});

‎tests/EnumUtilsTraitTest.php‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@
109109
->toThrow(ValueError::class);
110110
});
111111

112+
// jsonSerialize()
113+
test('jsonSerialize returns the backing value', function () {
114+
expect(Status::Active->jsonSerialize())->toBe('active');
115+
expect(Priority::High->jsonSerialize())->toBe(3);
116+
});
117+
118+
test('json_encode uses jsonSerialize', function () {
119+
expect(json_encode(Status::Active))->toBe('"active"');
120+
expect(json_encode(Priority::High))->toBe('3');
121+
});
122+
112123
// collect()
113124
test('collect returns an EnumCollection', function () {
114125
$collection = Status::collect();

‎tests/Fixtures/Priority.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Kexxt\EnumUtils\EnumUtilsTrait;
88

9-
enum Priority: int
9+
enum Priority: int implements \JsonSerializable
1010
{
1111
use EnumUtilsTrait;
1212

0 commit comments

Comments
 (0)