master

laravel/framework

Last updated at: 29/12/2023 09:22

AsEnumCollection.php

TLDR

This file contains a class AsEnumCollection that implements the Castable interface in the Illuminate\Database\Eloquent\Casts namespace. It is used to cast attributes to a collection of enums and vice versa.

Methods

castUsing

This method is a static function that returns an anonymous class that implements the CastsAttributes interface. The anonymous class's constructor receives an array of arguments and assigns it to its $arguments property. This method is responsible for casting attributes from the database to a collection of enums. It decodes the attribute value from JSON format and maps each value to an enum instance, based on the enum class specified in the arguments.

set

This method is used to set the value of an attribute in the database. It encodes the collection of enum values into JSON format, each value is obtained by calling the getStorableEnumValue method on the enum. It returns an array with the attribute key and its value.

serialize

This method is used to serialize the attribute value. It maps each enum value in the collection to its storable representation by calling the getStorableEnumValue method. It returns an array of the transformed enum values.

getStorableEnumValue

This method is a helper method used to determine the storable representation of an enum value. If the value is a string or an integer, it returns the value itself. If the value is an instance of BackedEnum, it returns the value property. Otherwise, it returns the name property of the enum.

Classes

None

<?php

namespace Illuminate\Database\Eloquent\Casts;

use BackedEnum;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Collection;

class AsEnumCollection implements Castable
{
    /**
     * Get the caster class to use when casting from / to this cast target.
     *
     * @template TEnum of \UnitEnum|\BackedEnum
     *
     * @param  array{class-string<TEnum>}  $arguments
     * @return \Illuminate\Contracts\Database\Eloquent\CastsAttributes<\Illuminate\Support\Collection<array-key, TEnum>, iterable<TEnum>>
     */
    public static function castUsing(array $arguments)
    {
        return new class($arguments) implements CastsAttributes
        {
            protected $arguments;

            public function __construct(array $arguments)
            {
                $this->arguments = $arguments;
            }

            public function get($model, $key, $value, $attributes)
            {
                if (! isset($attributes[$key]) || is_null($attributes[$key])) {
                    return;
                }

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

                if (! is_array($data)) {
                    return;
                }

                $enumClass = $this->arguments[0];

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

            public function set($model, $key, $value, $attributes)
            {
                $value = $value !== null
                    ? Json::encode((new Collection($value))->map(function ($enum) {
                        return $this->getStorableEnumValue($enum);
                    })->jsonSerialize())
                    : null;

                return [$key => $value];
            }

            public function serialize($model, string $key, $value, array $attributes)
            {
                return (new Collection($value))->map(function ($enum) {
                    return $this->getStorableEnumValue($enum);
                })->toArray();
            }

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

                return $enum instanceof BackedEnum ? $enum->value : $enum->name;
            }
        };
    }

    /**
     * Specify the Enum for the cast.
     *
     * @param  class-string  $class
     * @return string
     */
    public static function of($class)
    {
        return static::class.':'.$class;
    }
}