diff --git a/src/core/src/Database/Eloquent/Casts/AsArrayObject.php b/src/core/src/Database/Eloquent/Casts/AsArrayObject.php new file mode 100644 index 00000000..8c4d1329 --- /dev/null +++ b/src/core/src/Database/Eloquent/Casts/AsArrayObject.php @@ -0,0 +1,43 @@ +, iterable> + */ + public static function castUsing(array $arguments = []): CastsAttributes + { + return new class implements CastsAttributes { + public function get($model, $key, $value, $attributes) + { + if (! isset($attributes[$key])) { + return; + } + + $data = Json::decode($attributes[$key]); + + return is_array($data) ? new ArrayObject($data, ArrayObject::ARRAY_AS_PROPS) : null; + } + + public function set($model, $key, $value, $attributes) + { + return [$key => Json::encode($value)]; + } + + public function serialize($model, string $key, $value, array $attributes) + { + return $value->getArrayCopy(); + } + }; + } +} diff --git a/src/core/src/Database/Eloquent/Casts/AsCollection.php b/src/core/src/Database/Eloquent/Casts/AsCollection.php new file mode 100644 index 00000000..41ca1a4c --- /dev/null +++ b/src/core/src/Database/Eloquent/Casts/AsCollection.php @@ -0,0 +1,94 @@ +, iterable> + */ + public static function castUsing(array $arguments = []): CastsAttributes + { + return new class($arguments) implements CastsAttributes { + public function __construct(protected array $arguments) + { + $this->arguments = array_pad(array_values($this->arguments), 2, ''); + } + + public function get($model, $key, $value, $attributes) + { + if (! isset($attributes[$key])) { + return; + } + + $data = Json::decode($attributes[$key]); + + $collectionClass = empty($this->arguments[0]) ? Collection::class : $this->arguments[0]; + + if (! is_a($collectionClass, Collection::class, true)) { + throw new InvalidArgumentException('The provided class must extend [' . Collection::class . '].'); + } + + if (! is_array($data)) { + return null; + } + + $instance = new $collectionClass($data); + + if (! isset($this->arguments[1]) || ! $this->arguments[1]) { + return $instance; + } + + if (is_string($this->arguments[1])) { + $this->arguments[1] = Str::parseCallback($this->arguments[1]); + } + + return is_callable($this->arguments[1]) + ? $instance->map($this->arguments[1]) + : $instance->mapInto($this->arguments[1][0]); + } + + public function set($model, $key, $value, $attributes) + { + return [$key => Json::encode($value)]; + } + }; + } + + /** + * Specify the type of object each item in the collection should be mapped to. + * + * @param array{class-string, string}|class-string $map + * @return string + */ + public static function of($map) + { + return static::using('', $map); + } + + /** + * Specify the collection type for the cast. + * + * @param class-string $class + * @param array{class-string, string}|class-string $map + * @return string + */ + public static function using($class, $map = null) + { + if (is_array($map) && is_callable($map)) { + $map = $map[0] . '@' . $map[1]; + } + + return static::class . ':' . implode(',', [$class, $map]); + } +} diff --git a/src/core/src/Database/Eloquent/Casts/Attribute.php b/src/core/src/Database/Eloquent/Casts/Attribute.php new file mode 100644 index 00000000..9e620b1a --- /dev/null +++ b/src/core/src/Database/Eloquent/Casts/Attribute.php @@ -0,0 +1,97 @@ +get = $get; + $this->set = $set; + } + + /** + * Create a new attribute accessor / mutator. + */ + public static function make(?callable $get = null, ?callable $set = null): static + { + return new static($get, $set); + } + + /** + * Create a new attribute accessor. + * + * @return static + */ + public static function get(callable $get) + { + return new static($get); + } + + /** + * Create a new attribute mutator. + * + * @return static + */ + public static function set(callable $set) + { + return new static(null, $set); + } + + /** + * Disable object caching for the attribute. + * + * @return static + */ + public function withoutObjectCaching() + { + $this->withObjectCaching = false; + + return $this; + } + + /** + * Enable caching for the attribute. + * + * @return static + */ + public function shouldCache() + { + $this->withCaching = true; + + return $this; + } +} diff --git a/src/core/src/Database/Eloquent/Casts/Json.php b/src/core/src/Database/Eloquent/Casts/Json.php new file mode 100644 index 00000000..cf8129f9 --- /dev/null +++ b/src/core/src/Database/Eloquent/Casts/Json.php @@ -0,0 +1,58 @@ +