AsEnumArrayObject.php 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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 AsEnumArrayObject implements Castable
  8. {
  9. /**
  10. * Get the caster class to use when casting from / to this cast target.
  11. *
  12. * @template TEnum
  13. *
  14. * @param array{class-string<TEnum>} $arguments
  15. * @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Database\Eloquent\Casts\ArrayObject<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 ArrayObject((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. })->toArray());
  41. }
  42. public function set($model, $key, $value, $attributes)
  43. {
  44. if ($value === null) {
  45. return [$key => null];
  46. }
  47. $storable = [];
  48. foreach ($value as $enum) {
  49. $storable[] = $this->getStorableEnumValue($enum);
  50. }
  51. return [$key => Json::encode($storable)];
  52. }
  53. public function serialize($model, string $key, $value, array $attributes)
  54. {
  55. return (new Collection($value->getArrayCopy()))->map(function ($enum) {
  56. return $this->getStorableEnumValue($enum);
  57. })->toArray();
  58. }
  59. protected function getStorableEnumValue($enum)
  60. {
  61. if (is_string($enum) || is_int($enum)) {
  62. return $enum;
  63. }
  64. return $enum instanceof BackedEnum ? $enum->value : $enum->name;
  65. }
  66. };
  67. }
  68. /**
  69. * Specify the Enum for the cast.
  70. *
  71. * @param class-string $class
  72. * @return string
  73. */
  74. public static function of($class)
  75. {
  76. return static::class.':'.$class;
  77. }
  78. }