Skip to content

Commit

Permalink
Merge pull request #17 from webfox/feature/enum-collection-casting
Browse files Browse the repository at this point in the history
Add EnumCollection support
  • Loading branch information
hailwood authored Oct 7, 2023
2 parents 79fe7c9 + 2630d5f commit 06536dd
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 2 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,40 @@ public function rules(): array
}
```

## Other Classes

### AsFullEnumCollection
This cast is similar to the Laravel built in `AsEnumCollection` cast but unlike the built in will maintain the full `toArray` structure
when converting to json.

E.g. the Laravel built in `AsEnumCollection` cast will return the following json:
```json
["MILLIGRAMS", "GRAMS"]
```
This cast will return
```json
[
{
"name": "MILLIGRAMS",
"value": "MILLIGRAMS",
"label": "mg",
"meta": {
"background_color": "bg-green-100",
"text_color": "text-green-800"
}
},
{
"name": "GRAMS",
"value": "GRAMS",
"label": "g",
"meta": {
"background_color": "bg-red-100",
"text_color": "text-red-800"
}
}
]
```

## Changelog

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
Expand Down
71 changes: 71 additions & 0 deletions src/Casts/AsFullEnumCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);

namespace Webfox\LaravelBackedEnums\Casts;

use BackedEnum;
use LogicException;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Json;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use function is_int;
use function collect;
use function is_array;
use function constant;
use function is_string;
use function is_subclass_of;

/**
* @template T of \UnitEnum|\BackedEnum
*/
class AsFullEnumCollection implements CastsAttributes
{
/**
* @param class-string<T> $enumClass
*/
public function __construct(protected string $enumClass)
{
}

/**
* @return \Illuminate\Support\Collection<T>|null
*/
public function get(Model $model, string $key, mixed $value, array $attributes): ?Collection
{
if (empty($attributes[$key])) {
return new Collection();
}

$data = Json::decode($attributes[$key]);

if (!is_array($data)) {
throw new LogicException('Invalid data for enum collection cast: ' . $attributes[$key]);
}


return (new Collection($data))->map(function($value) {
return is_subclass_of($this->enumClass, BackedEnum::class)
? $this->enumClass::from($value)
: constant($this->enumClass . '::' . $value);
});
}

public function set(Model $model, string $key, mixed $value, array $attributes): array
{
$valueArray = Collection::wrap($value)
->map(fn($enum) => $this->getStorableEnumValue($enum))
->jsonSerialize();

return [$key => Json::encode($valueArray)];
}

protected function getStorableEnumValue($enum)
{
if (is_string($enum) || is_int($enum)) {
return $enum;
}

return $enum instanceof BackedEnum ? $enum->value : $enum->name;
}
}
16 changes: 14 additions & 2 deletions src/IsBackedEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

namespace Webfox\LaravelBackedEnums;

use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Validation\Rules\Enum as EnumValidationRule;
use function get_class;
use function json_encode;
use function json_last_error;
use function json_last_error_msg;
use const JSON_ERROR_NONE;

/**
* @implements \Webfox\LaravelBackedEnums\BackedEnum<string,string>
Expand Down Expand Up @@ -100,10 +106,16 @@ public function toHtml(): string
return $this->label();
}

public function toJson($options = 0): array
public function toJson($options = 0): string
{
static::ensureImplementsInterface();
return $this->toArray();
$json = json_encode($this->toArray(), $options);

if (json_last_error() !== JSON_ERROR_NONE) {
throw new JsonEncodingException('Error encoding enum ['.get_class($this).'] with value ['.$this->value.'] to JSON: '. json_last_error_msg());
}

return $json;
}

public function is(string|self $value): bool
Expand Down

0 comments on commit 06536dd

Please sign in to comment.