Skip to content

Commit 05247e5

Browse files
committed
added asEnum & tiny validation fix
1 parent e923a92 commit 05247e5

File tree

7 files changed

+209
-3
lines changed

7 files changed

+209
-3
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to `Enumhancer` will be documented in this file
44

5+
## 1.22.0 - 2023-01-07
6+
7+
- added [asEnum](docs/formrequests.md) to laravel's FormRequests
8+
- tiny fix in [isEnum](docs/laravel.validation.md#isEnum)
9+
validation: When [Defaults](docs/defaults.md) are used, it
10+
should fail validation.
11+
512
## 1.21.0 - 2023-01-06
613

714
- added [(basic) enum binding](docs/binding.md) allowing you to bind

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ implemented the methods of `Getters`, `Extractor` and `Reporters`.
8686

8787
- [Blade](docs/blade.md)
8888
- [Casting](docs/casting.md)
89+
- [FormRequest](docs/formrequests.md)
8990
- [Implicit (basic) enum binding](docs/binding.md)
9091
- [Validation](docs/laravel.validation.md)
9192

docs/formrequests.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Form Requests
2+
3+
Out of the box, Laravel has a decent method called `enum` on their FormRequest
4+
object. In many cases this may be enough.
5+
6+
## asEnum
7+
8+
This method works exactly like Laravel's `enum` method, but when
9+
you are using a backed enum and want to rely on features as
10+
[Defaults](defaults.md) or when want to pass conditional
11+
[Mappers](mappers.md), you want to use this method.
12+
13+
```php
14+
enum Suit: int {
15+
use \Henzeb\Enumhancer\Concerns\Defaults;
16+
17+
private const Default = self::Hearts;
18+
19+
case Hearts = 1;
20+
case Diamonds = 2;
21+
}
22+
23+
# Request: /card/?card=diamonds
24+
$request->enum('suit', Suit::class); // returns Suit::Diamonds
25+
$request->asEnum('suit', Suit::class); // returns Suit::Diamonds
26+
27+
# Request: /card/?card=
28+
$request->enum('suit', Suit::class); // returns null
29+
$request->asEnum('suit', Suit::class); // returns Suit::Hearts
30+
31+
```
32+
33+
## Mappers
34+
35+
You can pass as many mappers as you need.
36+
37+
```php
38+
enum Suit: int {
39+
use \Henzeb\Enumhancer\Concerns\Defaults;
40+
41+
case Hearts;
42+
case Diamonds;
43+
}
44+
45+
$request->asEnum('suit', Suit::class, ['heart'=>'hearts']);
46+
$request->asEnum('suit', Suit::class, new SuitMapper());
47+
$request->asEnum('suit', Suit::class, new SuitMapper(), ['heart'=>'hearts']);
48+
$request->asEnum('suit', Suit::class, SuitMapper::class);
49+
```

docs/laravel.validation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Laravel supports enum validation out of the box. For other situations Enumhancer
44
can help you out.
55

6-
## Validating enums
6+
## isEnum
77

88
For validation of unit enums see [From](from.md). This will work for most
99
cases.
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Henzeb\Enumhancer\Laravel\Mixins;
4+
5+
use Closure;
6+
use Henzeb\Enumhancer\Contracts\Mapper;
7+
use Henzeb\Enumhancer\Helpers\EnumGetters;
8+
use Henzeb\Enumhancer\Helpers\Mappers\EnumMapper;
9+
use Illuminate\Foundation\Http\FormRequest;
10+
use UnitEnum;
11+
12+
class FormRequestMixin
13+
{
14+
public function asEnum(): Closure
15+
{
16+
return function (
17+
string $key,
18+
string $class,
19+
Mapper|string|array|null ...$mappers
20+
): ?UnitEnum {
21+
22+
/**
23+
* @var FormRequest $this
24+
*/
25+
return EnumGetters::tryGet(
26+
$class,
27+
EnumMapper::map($class, $this->get($key), ...$mappers)
28+
);
29+
};
30+
}
31+
}

src/Laravel/Providers/EnumhancerServiceProvider.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
use Henzeb\Enumhancer\Enums\LogLevel;
66
use Henzeb\Enumhancer\Helpers\EnumReporter;
77
use Henzeb\Enumhancer\Laravel\Middleware\SubstituteEnums;
8+
use Henzeb\Enumhancer\Laravel\Mixins\FormRequestMixin;
89
use Henzeb\Enumhancer\Laravel\Mixins\RulesMixin;
910
use Illuminate\Contracts\Http\Kernel;
11+
use Illuminate\Foundation\Http\FormRequest;
1012
use Illuminate\Support\ServiceProvider;
1113
use Illuminate\Validation\Rule;
1214

@@ -16,7 +18,7 @@ public function boot(Kernel $kernel): void
1618
{
1719
$this->setupReporter();
1820

19-
$this->setupRules();
21+
$this->setupMacroMixins();
2022

2123
$this->setupEnumBindingMiddleware($kernel);
2224
}
@@ -28,9 +30,10 @@ protected function setupReporter(): void
2830
EnumReporter::laravel();
2931
}
3032

31-
private function setupRules(): void
33+
private function setupMacroMixins(): void
3234
{
3335
Rule::mixin(new RulesMixin());
36+
FormRequest::mixin(new FormRequestMixin());
3437
}
3538

3639
protected function setupEnumBindingMiddleware(Kernel $kernel): void
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace Henzeb\Enumhancer\Tests\Unit\Laravel\Mixins;
4+
5+
use Henzeb\Enumhancer\Contracts\Mapper;
6+
use Henzeb\Enumhancer\Laravel\Providers\EnumhancerServiceProvider;
7+
use Henzeb\Enumhancer\Tests\Fixtures\SimpleEnum;
8+
use Henzeb\Enumhancer\Tests\Fixtures\UnitEnums\Defaults\DefaultsEnum;
9+
use Illuminate\Foundation\Http\FormRequest;
10+
use Orchestra\Testbench\TestCase;
11+
12+
class FormRequestMixinTest extends TestCase
13+
{
14+
protected function getPackageProviders($app)
15+
{
16+
return [
17+
EnumhancerServiceProvider::class
18+
];
19+
}
20+
21+
public function testAsEnum()
22+
{
23+
$request = new FormRequest(
24+
[
25+
'myEnum' => 'open',
26+
'myInvalidEnum' => 'invalid',
27+
'myNullEnum' => null,
28+
]
29+
);
30+
31+
$this->assertEquals(
32+
SimpleEnum::Open,
33+
$request->asEnum('myEnum', SimpleEnum::class)
34+
);
35+
36+
$this->assertNull(
37+
$request->asEnum('myInvalidEnum', SimpleEnum::class)
38+
);
39+
40+
$this->assertNull(
41+
$request->asEnum('myDoesNotExistEnum', SimpleEnum::class)
42+
);
43+
44+
$this->assertNull(
45+
$request->asEnum('myNullEnum', SimpleEnum::class)
46+
);
47+
}
48+
49+
public function testAsEnumDefault()
50+
{
51+
$request = new FormRequest([
52+
'myEnum' => 'default',
53+
'myInvalidEnum' => 'invalid',
54+
'NullEnum' => null,
55+
]);
56+
57+
$this->assertEquals(
58+
DefaultsEnum::default(),
59+
$request->asEnum('myEnum', DefaultsEnum::class)
60+
);
61+
62+
$this->assertEquals(
63+
DefaultsEnum::default(),
64+
$request->asEnum('myInvalidEnum', DefaultsEnum::class)
65+
);
66+
67+
$this->assertEquals(
68+
DefaultsEnum::default(),
69+
$request->asEnum('myDoesNotExistEnum', DefaultsEnum::class)
70+
);
71+
72+
$this->assertEquals(
73+
DefaultsEnum::default(),
74+
$request->asEnum('nullEnum', DefaultsEnum::class)
75+
);
76+
}
77+
78+
public function testAsEnumWithMapper()
79+
{
80+
$request = new FormRequest([
81+
'myEnum' => 'opened',
82+
]);
83+
84+
$this->assertEquals(
85+
SimpleEnum::Open,
86+
$request->asEnum('myEnum', SimpleEnum::class, ['opened' => 'open'])
87+
);
88+
89+
$this->assertEquals(
90+
SimpleEnum::Open,
91+
$request->asEnum('myEnum', SimpleEnum::class, ['opened' => 'opening'], ['opening' => 'open'])
92+
);
93+
94+
$mapper = new class extends Mapper
95+
{
96+
protected function mappable(): array
97+
{
98+
return [
99+
'opened'=>'opening'
100+
];
101+
}
102+
};
103+
104+
$this->assertEquals(
105+
SimpleEnum::Open,
106+
$request->asEnum('myEnum', SimpleEnum::class, $mapper, ['opening'=>'open'])
107+
);
108+
109+
$this->assertEquals(
110+
SimpleEnum::Open,
111+
$request->asEnum('myEnum', SimpleEnum::class, $mapper::class, ['opening'=>'open'])
112+
);
113+
114+
}
115+
}

0 commit comments

Comments
 (0)