Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/foundation/src/Http/Casts/AsDataObjectArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Casts;

use ArrayObject;
use Hypervel\Foundation\Http\Contracts\Castable;
use Hypervel\Foundation\Http\Contracts\CastInputs;
use RuntimeException;

class AsDataObjectArray implements Castable
{
/**
* Get the caster class to use when casting from / to this cast target.
*
* @param string $class The data object class name
*/
public static function of(string $class): string
{
return static::class . ':' . $class;
}

/**
* Get the caster class to use when casting from / to this cast target.
*/
public static function castUsing(array $arguments = []): CastInputs
{
return new class($arguments) implements CastInputs {
public function __construct(protected array $arguments)
{
}

public function get(string $key, mixed $value, array $inputs): mixed
{
if (! isset($inputs[$key]) || ! is_array($value)) {
return null;
}

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

// Check if the class has make static method (provided by DataObject)
if (! method_exists($dataClass, 'make')) {
throw new RuntimeException(
"Class {$dataClass} must implement static make(array \$data) method"
);
}

return new ArrayObject(
array_map(fn ($item) => $dataClass::make($item), $value)
);
}

public function set(string $key, mixed $value, array $inputs): array
{
if ($value === null) {
return [$key => null];
}

$storable = array_map(function ($item) {
if (method_exists($item, 'toArray')) {
return $item->toArray();
}
return $item;
}, (array) $value);

return [$key => $storable];
}
};
}
}
75 changes: 75 additions & 0 deletions src/foundation/src/Http/Casts/AsDataObjectCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Casts;

use Hypervel\Foundation\Http\Contracts\Castable;
use Hypervel\Foundation\Http\Contracts\CastInputs;
use Hypervel\Support\Collection;
use RuntimeException;

class AsDataObjectCollection implements Castable
{
/**
* Get the caster class to use when casting from / to this cast target.
*
* @param string $class The data object class name
*/
public static function of(string $class): string
{
return static::class . ':' . $class;
}

/**
* Get the caster class to use when casting from / to this cast target.
*/
public static function castUsing(array $arguments = []): CastInputs
{
return new class($arguments) implements CastInputs {
public function __construct(protected array $arguments)
{
}

public function get(string $key, mixed $value, array $inputs): mixed
{
if (! isset($inputs[$key]) || ! is_array($value)) {
return new Collection();
}

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

// Check if the class has make static method (provided by DataObject)
if (! method_exists($dataClass, 'make')) {
throw new RuntimeException(
"Class {$dataClass} must implement static make(array \$data) method"
);
}

return new Collection(
array_map(fn ($item) => $dataClass::make($item), $value)
);
}

public function set(string $key, mixed $value, array $inputs): array
{
if ($value === null) {
return [$key => null];
}

if (! $value instanceof Collection) {
return [$key => $value];
}

$storable = $value->map(function ($item) {
if (method_exists($item, 'toArray')) {
return $item->toArray();
}
return $item;
})->toArray();

return [$key => $storable];
}
};
}
}
83 changes: 83 additions & 0 deletions src/foundation/src/Http/Casts/AsEnumArrayObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Casts;

use ArrayObject;
use BackedEnum;
use Hypervel\Foundation\Http\Contracts\Castable;
use Hypervel\Foundation\Http\Contracts\CastInputs;
use Hypervel\Support\Collection;

use function Hypervel\Support\enum_value;

class AsEnumArrayObject implements Castable
{
/**
* Get the caster class to use when casting from / to this cast target.
*
* @param string $class The enum class name
*/
public static function of(string $class): string
{
return static::class . ':' . $class;
}

/**
* Get the caster class to use when casting from / to this cast target.
*/
public static function castUsing(array $arguments = []): CastInputs
{
return new class($arguments) implements CastInputs {
public function __construct(protected array $arguments)
{
}

public function get(string $key, mixed $value, array $inputs): mixed
{
if (! isset($inputs[$key]) || ! is_array($value)) {
return null;
}

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

return new ArrayObject(
(new Collection($value))->map(function ($item) use ($enumClass) {
if ($item instanceof $enumClass) {
return $item;
}

return is_subclass_of($enumClass, BackedEnum::class)
? $enumClass::from($item)
: constant($enumClass . '::' . $item);
})->toArray()
);
}

public function set(string $key, mixed $value, array $inputs): array
{
if ($value === null) {
return [$key => null];
}

$storable = [];

foreach ($value as $enum) {
$storable[] = $this->getStorableEnumValue($enum);
}

return [$key => $storable];
}

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

return enum_value($enum);
}
};
}
}
78 changes: 78 additions & 0 deletions src/foundation/src/Http/Casts/AsEnumCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Casts;

use BackedEnum;
use Hyperf\Collection\Collection;
use Hypervel\Foundation\Http\Contracts\Castable;
use Hypervel\Foundation\Http\Contracts\CastInputs;

use function Hypervel\Support\enum_value;

class AsEnumCollection implements Castable
{
/**
* Get the caster class to use when casting from / to this cast target.
*
* @param string $class The enum class name
*/
public static function of(string $class): string
{
return static::class . ':' . $class;
}

/**
* Get the caster class to use when casting from / to this cast target.
*/
public static function castUsing(array $arguments = []): CastInputs
{
return new class($arguments) implements CastInputs {
public function __construct(protected array $arguments)
{
}

public function get(string $key, mixed $value, array $inputs): mixed
{
if (! isset($inputs[$key]) || ! is_array($value)) {
return null;
}

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

return (new Collection($value))->map(function ($item) use ($enumClass) {
if ($item instanceof $enumClass) {
return $item;
}

return is_subclass_of($enumClass, BackedEnum::class)
? $enumClass::from($item)
: constant($enumClass . '::' . $item);
});
}

public function set(string $key, mixed $value, array $inputs): array
{
if ($value === null) {
return [$key => null];
}

$storable = (new Collection($value))->map(function ($enum) {
return $this->getStorableEnumValue($enum);
})->toArray();

return [$key => $storable];
}

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

return enum_value($enum);
}
};
}
}
28 changes: 28 additions & 0 deletions src/foundation/src/Http/Contracts/CastInputs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Contracts;

interface CastInputs
{
/**
* Transform the inputs from the underlying input value.
*
* @param string $key The inputs key
* @param mixed $value The inputs value
* @param array $inputs All inputs
* @return mixed The transformed value
*/
public function get(string $key, mixed $value, array $inputs): mixed;

/**
* Transform the inputs to its underlying representation for storage.
*
* @param string $key The inputs key
* @param mixed $value The inputs value
* @param array $inputs All inputs
* @return array The transformed value as an array
*/
public function set(string $key, mixed $value, array $inputs): array;
}
13 changes: 13 additions & 0 deletions src/foundation/src/Http/Contracts/Castable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Hypervel\Foundation\Http\Contracts;

interface Castable
{
/**
* Get the name of the caster class to use when casting from / to this cast target.
*/
public static function castUsing(array $arguments = []): CastInputs|string;
}
7 changes: 5 additions & 2 deletions src/foundation/src/Http/FormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Hyperf\Context\Context;
use Hyperf\Context\ResponseContext;
use Hypervel\Auth\Access\AuthorizationException;
use Hypervel\Foundation\Http\Traits\HasCasts;
use Hypervel\Http\Request;
use Hypervel\Validation\Contracts\Factory as ValidationFactory;
use Hypervel\Validation\Contracts\ValidatesWhenResolved;
Expand All @@ -19,6 +20,7 @@

class FormRequest extends Request implements ValidatesWhenResolved
{
use HasCasts;
use ValidatesWhenResolvedTrait;

/**
Expand All @@ -36,8 +38,9 @@ class FormRequest extends Request implements ValidatesWhenResolved
*/
protected array $dontFlash = ['password', 'password_confirmation'];

public function __construct(protected ContainerInterface $container)
{
public function __construct(
protected ContainerInterface $container
) {
}

public function scene(string $scene): static
Expand Down
Loading