1
0
Fork 0
mirror of https://github.com/archtechx/enums.git synced 2025-12-12 16:54:03 +00:00

Extend functionality to work with pure enums

This commit is contained in:
Samuel Levy 2022-03-12 22:56:43 +10:00
parent 20fa78c2b1
commit c2f0e7faf7
8 changed files with 99 additions and 15 deletions

View file

@ -21,7 +21,7 @@ composer require archtechx/enums
### InvokableCases ### InvokableCases
This helper lets you get the value of a backed enum by "invoking" it — either statically (`MyEnum::FOO()` instead of `MyEnum::FOO`), or as an instance (`$enum()`). This helper lets you get the value of a backed enum, or the name of a pure enum by "invoking" it — either statically (`MyEnum::FOO()` instead of `MyEnum::FOO`), or as an instance (`$enum()`).
That way, you can use enums as array keys: That way, you can use enums as array keys:
```php ```php
@ -58,6 +58,15 @@ enum TaskStatus: int
case COMPLETED = 1; case COMPLETED = 1;
case CANCELED = 2; case CANCELED = 2;
} }
enum Role
{
use InvokableCases;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
``` ```
#### Use static calls to get the primitive value #### Use static calls to get the primitive value
@ -65,13 +74,16 @@ enum TaskStatus: int
TaskStatus::INCOMPLETE(); // 0 TaskStatus::INCOMPLETE(); // 0
TaskStatus::COMPLETED(); // 1 TaskStatus::COMPLETED(); // 1
TaskStatus::CANCELED(); // 2 TaskStatus::CANCELED(); // 2
Role::ADMINISTRATOR(); // 'ADMINISTRATOR'
Role::SUBSCRIBER(); // 'SUBSCRIBER'
Role::GUEST(); // 'GUEST'
``` ```
#### Invoke instances to get the primitive value #### Invoke instances to get the primitive value
```php ```php
public function updateStatus(TaskStatus $status) public function updateStatus(TaskStatus $status, Role $role)
{ {
$this->record->setStatus($status()); $this->record->setStatus($status(), $role());
} }
``` ```
@ -91,16 +103,26 @@ enum TaskStatus: int
case COMPLETED = 1; case COMPLETED = 1;
case CANCELED = 2; case CANCELED = 2;
} }
enum Role
{
use Names;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
``` ```
#### Use the `names()` method #### Use the `names()` method
```php ```php
TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED'] TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
``` ```
### Values ### Values
This helper returns a list of case *values* in the enum. This helper returns a list of case *values* in the enum. _**NB:** pure enums don't have values, so this will only ever return an empty array._
#### Apply the trait on your enum #### Apply the trait on your enum
```php ```php
@ -114,16 +136,26 @@ enum TaskStatus: int
case COMPLETED = 1; case COMPLETED = 1;
case CANCELED = 2; case CANCELED = 2;
} }
enum Role
{
use Values;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
``` ```
#### Use the `values()` method #### Use the `values()` method
```php ```php
TaskStatus::values(); // [0, 1, 2] TaskStatus::values(); // [0, 1, 2]
Role::values(); // []
``` ```
### Options ### Options
This helper returns an associative array of case names and values. This helper returns an associative array of case names and values for backed enums, or an array of names for pure enums (making this functionally equivalent to `::names()` for pure Enums).
#### Apply the trait on your enum #### Apply the trait on your enum
```php ```php
@ -137,11 +169,21 @@ enum TaskStatus: int
case COMPLETED = 1; case COMPLETED = 1;
case CANCELED = 2; case CANCELED = 2;
} }
enum Role
{
use Options;
case ADMINISTRATOR;
case SUBSCRIBER;
case GUEST;
}
``` ```
#### Use the `options()` method #### Use the `options()` method
```php ```php
TaskStatus::options(); // ['INCOMPLETE' => 0, 'COMPLETED' => 1, 'CANCELED' => 2] TaskStatus::options(); // ['INCOMPLETE' => 0, 'COMPLETED' => 1, 'CANCELED' => 2]
Role::options(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
``` ```
## Development ## Development

View file

@ -9,17 +9,17 @@ trait InvokableCases
/** Return the enum's value when it's $invoked(). */ /** Return the enum's value when it's $invoked(). */
public function __invoke() public function __invoke()
{ {
return $this->value; return $this->value ?? $this->name;
} }
/** Return the enum's value when it's called ::STATICALLY(). */ /** Return the enum's value or name when it's called ::STATICALLY(). */
public static function __callStatic($name, $args) public static function __callStatic($name, $args)
{ {
$cases = static::cases(); $cases = static::cases();
foreach ($cases as $case) { foreach ($cases as $case) {
if ($case->name === $name) { if ($case->name === $name) {
return $case->value; return $case instanceof \BackedEnum ? $case->value : $case->name;
} }
} }

View file

@ -9,6 +9,11 @@ trait Options
/** Get an associative array of [case name => case value]. */ /** Get an associative array of [case name => case value]. */
public static function options(): array public static function options(): array
{ {
return array_column(static::cases(), 'value', 'name'); $cases = static::cases();
if (reset($cases) instanceof \BackedEnum) {
return array_column($cases, 'value', 'name');
}
return array_column($cases, 'name');
} }
} }

View file

@ -56,3 +56,11 @@ enum Status: int
case PENDING = 0; case PENDING = 0;
case DONE = 1; case DONE = 1;
} }
enum Role
{
use InvokableCases, Options, Names, Values;
case ADMIN;
case GUEST;
}

View file

@ -2,18 +2,33 @@
use ArchTech\Enums\Exceptions\UndefinedCaseError; use ArchTech\Enums\Exceptions\UndefinedCaseError;
it('can be used as a static method', function () { it('can be used as a static method with backed enums', function () {
expect(Status::PENDING())->toBe(0); expect(Status::PENDING())->toBe(0);
expect(Status::DONE())->toBe(1); expect(Status::DONE())->toBe(1);
}); });
it('can be invoked as an instance', function () { it('can be used as a static method with pure enums', function () {
expect(Role::ADMIN())->toBe('ADMIN');
expect(Role::GUEST())->toBe('GUEST');
});
it('can be invoked as an instance as a backed enum', function () {
$status = Status::PENDING; $status = Status::PENDING;
expect($status())->toBe(0); expect($status())->toBe(0);
expect($status())->toBe($status->value); expect($status())->toBe($status->value);
}); });
it('throws an error when a nonexistent case is being used', function () { it('can be invoked as an instance as a pure enum', function () {
$role = Role::ADMIN;
expect($role())->toBe('ADMIN');
});
it('throws an error when a nonexistent case is being used for backed enums', function () {
Status::INVALID(); Status::INVALID();
})->expectException(UndefinedCaseError::class); })->expectException(UndefinedCaseError::class);
it('throws an error when a nonexistent case is being used for pure enums', function () {
Role::INVALID();
})->expectException(UndefinedCaseError::class);

View file

@ -1,5 +1,9 @@
<?php <?php
it('can return an array of case names') it('can return an array of case names from backed enums')
->expect(Status::names()) ->expect(Status::names())
->toBe(['PENDING', 'DONE']); ->toBe(['PENDING', 'DONE']);
it('can return an array of case names from pure enums')
->expect(Role::names())
->toBe(['ADMIN', 'GUEST']);

View file

@ -1,7 +1,13 @@
<?php <?php
it('can return an associative array of options') it('can return an associative array of options from a backed enum')
->expect(Status::options())->toBe([ ->expect(Status::options())->toBe([
'PENDING' => 0, 'PENDING' => 0,
'DONE' => 1, 'DONE' => 1,
]); ]);
it('can return an indexed array of options from a pure enum')
->expect(Role::options())->toBe([
0 => 'ADMIN',
1 => 'GUEST',
]);

View file

@ -1,5 +1,9 @@
<?php <?php
it('can return an array of case values') it('can return an array of case values from a backed enum')
->expect(Status::values()) ->expect(Status::values())
->toBe([0, 1]); ->toBe([0, 1]);
it('can returns an empty array from a pure enum')
->expect(Role::values())
->toBe([]);