Skip to content

Commit 99b7aed

Browse files
authored
Merge pull request #5747 from Laravel-Backpack/add-enum-collection-cast-support
add enum collection cast support
2 parents c0d1493 + 20d2a3d commit 99b7aed

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

src/resources/views/crud/columns/enum.blade.php

+60
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,69 @@
1111
}
1212
1313
$column['value'] = isset($column['enum_function']) ? $enumClass->{$column['enum_function']}() : $column['value'];
14+
}else{
15+
$column['value'] = $column['value']->transform(function($item) use ($column) {
16+
return $item instanceof \BackedEnum ? $item->value : $item->name;
17+
})->toArray();
1418
}
1519
}
1620
}
21+
22+
if(!isset($column['options']) && is_array($column['value'])) {
23+
$column['options'] = (function() use ($entry, $column) {
24+
25+
// if we are in a PHP version where PHP enums are not available, it can only be a database enum
26+
if(! function_exists('enum_exists')) {
27+
$options = $entity_model::getPossibleEnumValues($column['name']);
28+
return array_combine($options, $options);
29+
}
30+
// developer can provide the enum class so that we extract the available options from it
31+
$enumClassReflection = isset($column['enum_class']) ? new \ReflectionEnum($column['enum_class']) : false;
32+
33+
if(! $enumClassReflection) {
34+
// check for model casting
35+
$possibleEnumCast = $entry->getCasts()[$column['name']] ?? false;
36+
37+
if($possibleEnumCast) {
38+
if(class_exists($possibleEnumCast)) {
39+
$enumClassReflection = new \ReflectionEnum($possibleEnumCast);
40+
}else{
41+
// It's an `AsEnumCollection` cast
42+
if(str_contains($possibleEnumCast, ':')) {
43+
$enumClassReflection = new \ReflectionEnum(explode(':', $possibleEnumCast)[1]);
44+
$allowMultipleValues = true;
45+
}
46+
}
47+
}
48+
}
49+
50+
if($enumClassReflection) {
51+
$options = array_map(function($item) use ($enumClassReflection) {
52+
return $enumClassReflection->isBacked() ? [$item->getBackingValue() => $item->name] : $item->name;
53+
},$enumClassReflection->getCases());
54+
$options = is_multidimensional_array($options) ? array_replace(...$options) : array_combine($options, $options);
55+
}
56+
57+
if(isset($column['enum_function']) && isset($options)) {
58+
$options = array_map(function($item) use ($column, $enumClassReflection) {
59+
if ($enumClassReflection->hasConstant($item)) {
60+
return $enumClassReflection->getConstant($item)->{$column['enum_function']}();
61+
}
62+
return $item;
63+
}, $options);
64+
return $options;
65+
}
66+
67+
// if we have the enum options return them
68+
if(isset($options)) {
69+
return $options;
70+
}
71+
72+
// no enum options, can only be database enum
73+
$options = $entity_model::getPossibleEnumValues($column['name']);
74+
return array_combine($options, $options);
75+
})();
76+
}
1777
@endphp
1878

1979
@include(isset($column['options']) ? 'crud::columns.select_from_array' : 'crud::columns.text')

src/resources/views/crud/fields/enum.blade.php

+28-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
55
$field['value'] = old_empty_or_null($field['name'], '') ?? $field['value'] ?? $field['default'] ?? '';
66
7+
$allowMultipleValues = $field['multiple'] ?? false;
8+
79
$possible_values = (function() use ($entity_model, $field) {
810
$fieldName = $field['baseFieldName'] ?? $field['name'];
911
// if developer provided the options, use them, no need to guess.
@@ -16,15 +18,24 @@
1618
$options = $entity_model::getPossibleEnumValues($fieldName);
1719
return array_combine($options, $options);
1820
}
19-
21+
2022
// developer can provide the enum class so that we extract the available options from it
2123
$enumClassReflection = isset($field['enum_class']) ? new \ReflectionEnum($field['enum_class']) : false;
2224
2325
if(! $enumClassReflection) {
2426
// check for model casting
2527
$possibleEnumCast = (new $entity_model)->getCasts()[$fieldName] ?? false;
26-
if($possibleEnumCast && class_exists($possibleEnumCast)) {
27-
$enumClassReflection = new \ReflectionEnum($possibleEnumCast);
28+
29+
if($possibleEnumCast) {
30+
if(class_exists($possibleEnumCast)) {
31+
$enumClassReflection = new \ReflectionEnum($possibleEnumCast);
32+
}else{
33+
// It's an `AsEnumCollection` cast
34+
if(str_contains($possibleEnumCast, ':')) {
35+
$enumClassReflection = new \ReflectionEnum(explode(':', $possibleEnumCast)[1]);
36+
$allowMultipleValues = true;
37+
}
38+
}
2839
}
2940
}
3041
@@ -55,18 +66,27 @@
5566
return array_combine($options, $options);
5667
})();
5768
58-
59-
if(function_exists('enum_exists') && !empty($field['value']) && $field['value'] instanceof \UnitEnum) {
60-
$field['value'] = $field['value'] instanceof \BackedEnum ? $field['value']->value : $field['value']->name;
69+
if(function_exists('enum_exists') && !empty($field['value'])) {
70+
match(true) {
71+
$field['value'] instanceof \UnitEnum => $field['value'] = $field['value'] instanceof \BackedEnum ? $field['value']->value : $field['value']->name,
72+
$field['value'] instanceof Illuminate\Support\Collection => $field['value'] = $field['value']->map(function($item) {
73+
return $item instanceof \UnitEnum ? $item instanceof \BackedEnum ? $item->value : $item->name : $item;
74+
})->toArray(),
75+
default => null
76+
};
77+
$field['value'] = is_array($field['value']) ? $field['value'] : [$field['value']];
6178
}
6279
@endphp
6380

6481
@include('crud::fields.inc.wrapper_start')
6582
<label>{!! $field['label'] !!}</label>
6683
@include('crud::fields.inc.translatable_icon')
6784
<select
68-
name="{{ $field['name'] }}"
85+
name="{{ $allowMultipleValues ? $field['name'].'[]' : $field['name'] }}"
6986
@include('crud::fields.inc.attributes', ['default_class' => 'form-control form-select'])
87+
@if ($allowMultipleValues)
88+
multiple
89+
@endif
7090
>
7191

7292
@if ($entity_model::isColumnNullable($field['name']))
@@ -76,7 +96,7 @@
7696
@if (count($possible_values))
7797
@foreach ($possible_values as $key => $possible_value)
7898
<option value="{{ $key }}"
79-
@if ($field['value']==$key)
99+
@if (in_array($key, $field['value']))
80100
selected
81101
@endif
82102
>{{ $possible_value }}</option>

0 commit comments

Comments
 (0)