Skip to content

Commit

Permalink
added asEnum & tiny validation fix
Browse files Browse the repository at this point in the history
  • Loading branch information
henzeb committed Jan 7, 2023
1 parent e923a92 commit 05247e5
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 3 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

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

## 1.22.0 - 2023-01-07

- added [asEnum](docs/formrequests.md) to laravel's FormRequests
- tiny fix in [isEnum](docs/laravel.validation.md#isEnum)
validation: When [Defaults](docs/defaults.md) are used, it
should fail validation.

## 1.21.0 - 2023-01-06

- added [(basic) enum binding](docs/binding.md) allowing you to bind
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ implemented the methods of `Getters`, `Extractor` and `Reporters`.

- [Blade](docs/blade.md)
- [Casting](docs/casting.md)
- [FormRequest](docs/formrequests.md)
- [Implicit (basic) enum binding](docs/binding.md)
- [Validation](docs/laravel.validation.md)

Expand Down
49 changes: 49 additions & 0 deletions docs/formrequests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Form Requests

Out of the box, Laravel has a decent method called `enum` on their FormRequest
object. In many cases this may be enough.

## asEnum

This method works exactly like Laravel's `enum` method, but when
you are using a backed enum and want to rely on features as
[Defaults](defaults.md) or when want to pass conditional
[Mappers](mappers.md), you want to use this method.

```php
enum Suit: int {
use \Henzeb\Enumhancer\Concerns\Defaults;

private const Default = self::Hearts;

case Hearts = 1;
case Diamonds = 2;
}

# Request: /card/?card=diamonds
$request->enum('suit', Suit::class); // returns Suit::Diamonds
$request->asEnum('suit', Suit::class); // returns Suit::Diamonds

# Request: /card/?card=
$request->enum('suit', Suit::class); // returns null
$request->asEnum('suit', Suit::class); // returns Suit::Hearts

```

## Mappers

You can pass as many mappers as you need.

```php
enum Suit: int {
use \Henzeb\Enumhancer\Concerns\Defaults;

case Hearts;
case Diamonds;
}

$request->asEnum('suit', Suit::class, ['heart'=>'hearts']);
$request->asEnum('suit', Suit::class, new SuitMapper());
$request->asEnum('suit', Suit::class, new SuitMapper(), ['heart'=>'hearts']);
$request->asEnum('suit', Suit::class, SuitMapper::class);
```
2 changes: 1 addition & 1 deletion docs/laravel.validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Laravel supports enum validation out of the box. For other situations Enumhancer
can help you out.

## Validating enums
## isEnum

For validation of unit enums see [From](from.md). This will work for most
cases.
Expand Down
31 changes: 31 additions & 0 deletions src/Laravel/Mixins/FormRequestMixin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Henzeb\Enumhancer\Laravel\Mixins;

use Closure;
use Henzeb\Enumhancer\Contracts\Mapper;
use Henzeb\Enumhancer\Helpers\EnumGetters;
use Henzeb\Enumhancer\Helpers\Mappers\EnumMapper;
use Illuminate\Foundation\Http\FormRequest;
use UnitEnum;

class FormRequestMixin
{
public function asEnum(): Closure
{
return function (
string $key,
string $class,
Mapper|string|array|null ...$mappers
): ?UnitEnum {

/**
* @var FormRequest $this
*/
return EnumGetters::tryGet(
$class,
EnumMapper::map($class, $this->get($key), ...$mappers)
);
};
}
}
7 changes: 5 additions & 2 deletions src/Laravel/Providers/EnumhancerServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
use Henzeb\Enumhancer\Enums\LogLevel;
use Henzeb\Enumhancer\Helpers\EnumReporter;
use Henzeb\Enumhancer\Laravel\Middleware\SubstituteEnums;
use Henzeb\Enumhancer\Laravel\Mixins\FormRequestMixin;
use Henzeb\Enumhancer\Laravel\Mixins\RulesMixin;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rule;

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

$this->setupRules();
$this->setupMacroMixins();

$this->setupEnumBindingMiddleware($kernel);
}
Expand All @@ -28,9 +30,10 @@ protected function setupReporter(): void
EnumReporter::laravel();
}

private function setupRules(): void
private function setupMacroMixins(): void
{
Rule::mixin(new RulesMixin());
FormRequest::mixin(new FormRequestMixin());
}

protected function setupEnumBindingMiddleware(Kernel $kernel): void
Expand Down
115 changes: 115 additions & 0 deletions tests/Unit/Laravel/Mixins/FormRequestMixinTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

namespace Henzeb\Enumhancer\Tests\Unit\Laravel\Mixins;

use Henzeb\Enumhancer\Contracts\Mapper;
use Henzeb\Enumhancer\Laravel\Providers\EnumhancerServiceProvider;
use Henzeb\Enumhancer\Tests\Fixtures\SimpleEnum;
use Henzeb\Enumhancer\Tests\Fixtures\UnitEnums\Defaults\DefaultsEnum;
use Illuminate\Foundation\Http\FormRequest;
use Orchestra\Testbench\TestCase;

class FormRequestMixinTest extends TestCase
{
protected function getPackageProviders($app)
{
return [
EnumhancerServiceProvider::class
];
}

public function testAsEnum()
{
$request = new FormRequest(
[
'myEnum' => 'open',
'myInvalidEnum' => 'invalid',
'myNullEnum' => null,
]
);

$this->assertEquals(
SimpleEnum::Open,
$request->asEnum('myEnum', SimpleEnum::class)
);

$this->assertNull(
$request->asEnum('myInvalidEnum', SimpleEnum::class)
);

$this->assertNull(
$request->asEnum('myDoesNotExistEnum', SimpleEnum::class)
);

$this->assertNull(
$request->asEnum('myNullEnum', SimpleEnum::class)
);
}

public function testAsEnumDefault()
{
$request = new FormRequest([
'myEnum' => 'default',
'myInvalidEnum' => 'invalid',
'NullEnum' => null,
]);

$this->assertEquals(
DefaultsEnum::default(),
$request->asEnum('myEnum', DefaultsEnum::class)
);

$this->assertEquals(
DefaultsEnum::default(),
$request->asEnum('myInvalidEnum', DefaultsEnum::class)
);

$this->assertEquals(
DefaultsEnum::default(),
$request->asEnum('myDoesNotExistEnum', DefaultsEnum::class)
);

$this->assertEquals(
DefaultsEnum::default(),
$request->asEnum('nullEnum', DefaultsEnum::class)
);
}

public function testAsEnumWithMapper()
{
$request = new FormRequest([
'myEnum' => 'opened',
]);

$this->assertEquals(
SimpleEnum::Open,
$request->asEnum('myEnum', SimpleEnum::class, ['opened' => 'open'])
);

$this->assertEquals(
SimpleEnum::Open,
$request->asEnum('myEnum', SimpleEnum::class, ['opened' => 'opening'], ['opening' => 'open'])
);

$mapper = new class extends Mapper
{
protected function mappable(): array
{
return [
'opened'=>'opening'
];
}
};

$this->assertEquals(
SimpleEnum::Open,
$request->asEnum('myEnum', SimpleEnum::class, $mapper, ['opening'=>'open'])
);

$this->assertEquals(
SimpleEnum::Open,
$request->asEnum('myEnum', SimpleEnum::class, $mapper::class, ['opening'=>'open'])
);

}
}

0 comments on commit 05247e5

Please sign in to comment.