AsEnumCollection.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Casts;
  3. use BackedEnum;
  4. use Illuminate\Contracts\Database\Eloquent\Castable;
  5. use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
  6. use Illuminate\Support\Collection;
  7. class AsEnumCollection implements Castable
  8. {
  9. /**
  10. * Get the caster class to use when casting from / to this cast target.
  11. *
  12. * @template TEnum of \UnitEnum|\BackedEnum
  13. *
  14. * @param array{class-string<TEnum>} $arguments
  15. * @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Support\Collection<array-key, TEnum>, iterable<TEnum>>
  16. */
  17. public static function castUsing(array $arguments)
  18. {
  19. return new class($arguments) implements CastsAttributes
  20. {
  21. protected $arguments;
  22. public function __construct(array $arguments)
  23. {
  24. $this->arguments = $arguments;
  25. }
  26. public function get($model, $key, $value, $attributes)
  27. {
  28. if (! isset($attributes[$key])) {
  29. return;
  30. }
  31. $data = Json::decode($attributes[$key]);
  32. if (! is_array($data)) {
  33. return;
  34. }
  35. $enumClass = $this->arguments[0];
  36. return (new Collection($data))->map(function ($value) use ($enumClass) {
  37. return is_subclass_of($enumClass, BackedEnum::class)
  38. ? $enumClass::from($value)
  39. : constant($enumClass.'::'.$value);
  40. });
  41. }
  42. public function set($model, $key, $value, $attributes)
  43. {
  44. $value = $value !== null
  45. ? Json::encode((new Collection($value))->map(function ($enum) {
  46. return $this->getStorableEnumValue($enum);
  47. })->jsonSerialize())
  48. : null;
  49. return [$key => $value];
  50. }
  51. public function serialize($model, string $key, $value, array $attributes)
  52. {
  53. return (new Collection($value))->map(function ($enum) {
  54. return $this->getStorableEnumValue($enum);
  55. })->toArray();
  56. }
  57. protected function getStorableEnumValue($enum)
  58. {
  59. if (is_string($enum) || is_int($enum)) {
  60. return $enum;
  61. }
  62. return $enum instanceof BackedEnum ? $enum->value : $enum->name;
  63. }
  64. };
  65. }
  66. /**
  67. * Specify the Enum for the cast.
  68. *
  69. * @param class-string $class
  70. * @return string
  71. */
  72. public static function of($class)
  73. {
  74. return static::class.':'.$class;
  75. }
  76. }