Merge pull request #22 from ploi/rjs/fix-laravel-data

RJS/Upgrade to Laravel 10 – Fix testsuite / Laravel Data implementation
This commit is contained in:
Dennis Smink
2023-09-27 08:44:45 +02:00
committed by GitHub
25 changed files with 512 additions and 574 deletions

View File

@@ -26,24 +26,17 @@ class ServerData extends Data
public ?int $id = null,
#[StringType]
public ?string $status = null,
#[StringType,
AlphaDash,
Max(40)]
#[StringType, AlphaDash, Max(40)]
public string $name,
#[NotIn(0),
Exists(Provider::class, 'id')]
#[NotIn(0), Exists(Provider::class, 'id')]
public int $provider_id,
#[NotIn(0),
Exists(ProviderRegion::class, 'id')]
#[NotIn(0), Exists(ProviderRegion::class, 'id')]
public int $provider_region_id,
#[NotIn(0),
Exists(ProviderPlan::class, 'id')]
#[NotIn(0), Exists(ProviderPlan::class, 'id')]
public int $provider_plan_id,
#[StringType,
In(['mysql', 'mariadb', 'postgresql', 'postgresql13'])]
#[StringType, In(['mysql', 'mariadb', 'postgresql', 'postgresql13'])]
public string $database_type,
#[Exists(User::class, 'id'),
IntegerType]
#[Exists(User::class, 'id'), IntegerType]
public ?int $user_id = null,
public ?Carbon $created_at = null,
) {

View File

@@ -23,14 +23,11 @@ class SiteData extends Data
public function __construct(
public ?int $id = null,
public ?string $status = null,
#[Exists(Server::class, 'id'),
IntegerType]
#[Exists(Server::class, 'id'), IntegerType]
public ?int $server_id = null,
#[StringType,
CustomRule(Hostname::class, ValidateMaximumSites::class)]
#[StringType, CustomRule(Hostname::class, ValidateMaximumSites::class)]
public ?string $domain = null,
#[Exists(User::class, 'id'),
IntegerType]
#[Exists(User::class, 'id'), IntegerType]
public ?int $user_id = null,
public ?Carbon $created_at = null,
) {

View File

@@ -8,7 +8,7 @@ use Spatie\LaravelData\Support\DataProperty;
class CarbonCast implements Cast
{
public function cast(DataProperty $property, mixed $value, array $context): mixed
public function cast(DataProperty $property, mixed $value, array $context): Carbon
{
return Carbon::parse($value);
}

View File

@@ -2,16 +2,13 @@
namespace App\DataTransferObjects\Support;
use Illuminate\Support\Enumerable;
use Spatie\LaravelData\DataCollection;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Pagination\AbstractCursorPaginator;
class Data extends \Spatie\LaravelData\Data
{
public static function collection(Paginator|Enumerable|array|AbstractCursorPaginator|DataCollection|AbstractPaginator|\Illuminate\Contracts\Pagination\CursorPaginator|null $items): \App\DataTransferObjects\Support\DataCollection
{
return new \App\DataTransferObjects\Support\DataCollection(static::class, $items);
}
/**
* When working with paginated data, we want to include pagination details in JSON
* responses from the API. However, due to legacy requirements Ploi Core is using
* a different structure than this package assumes. Therefore, we will override
* the data collection, register a custom transformer and output the structure.
*/
protected static string $_paginatedCollectionClass = PaginatedDataCollection::class;
}

View File

@@ -2,14 +2,14 @@
namespace App\DataTransferObjects\Support;
use Illuminate\Support\Arr;
class DataCollectionTransformer extends \Spatie\LaravelData\Transformers\DataCollectionTransformer
class DataCollectableTransformer extends \Spatie\LaravelData\Transformers\DataCollectableTransformer
{
protected function wrapPaginatedArray(array $paginated): array
{
$wrapKey = $this->wrap->getKey() ?? 'data';
return [
'data' => $paginated['data'],
$wrapKey => $paginated['data'],
'links' => [
'first' => $paginated['first_page_url'],
'last' => $paginated['last_page_url'],
@@ -27,14 +27,5 @@ class DataCollectionTransformer extends \Spatie\LaravelData\Transformers\DataCol
'total' => $paginated['total'],
],
];
return [
'data' => $paginated['data'],
'links' => $paginated['links'] ?? [],
'meta' => Arr::except($paginated, [
'data',
'links',
]),
];
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace App\DataTransferObjects\Support;
use Spatie\LaravelData\Support\TransformationType;
class DataCollection extends \Spatie\LaravelData\DataCollection
{
// public function transform($type): array
// {
// $transformer = new DataCollectionTransformer(
// $this->dataClass,
// $type,
// $this->getInclusionTree(),
// $this->getExclusionTree(),
// $this->items,
// $this->through,
// $this->filter
// );
//
// return $transformer->transform();
// }
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\DataTransferObjects\Support;
use Spatie\LaravelData\Support\Wrapping\WrapExecutionType;
class PaginatedDataCollection extends \Spatie\LaravelData\PaginatedDataCollection
{
public function transform(bool $transformValues = true, WrapExecutionType $wrapExecutionType = WrapExecutionType::Disabled, bool $mapPropertyNames = true): array
{
$transformer = new DataCollectableTransformer(
$this->dataClass,
$transformValues,
$wrapExecutionType,
$mapPropertyNames,
$this->getPartialTrees(),
$this->items,
$this->getWrap(),
);
return $transformer->transform();
}
}

View File

@@ -3,10 +3,11 @@
namespace App\DataTransferObjects\Support\Rules;
use Attribute;
use Spatie\LaravelData\Attributes\Validation\ValidationAttribute;
use Spatie\LaravelData\Support\Validation\ValidationPath;
use Spatie\LaravelData\Attributes\Validation\CustomValidationAttribute;
#[Attribute(Attribute::TARGET_PROPERTY)]
class CustomRule extends ValidationAttribute
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)]
class CustomRule extends CustomValidationAttribute
{
protected array $rules = [];
@@ -15,20 +16,14 @@ class CustomRule extends ValidationAttribute
$this->rules = $rules;
}
public function getRules(): array
/**
* @return array<object|string>|object|string
*/
public function getRules(ValidationPath $path): array|object|string
{
return collect($this->rules)
->map(fn (string $rule) => new $rule())
->all();
}
public static function keyword(): string
{
// TODO: Implement keyword() method.
}
public static function create(string ...$parameters): static
{
// TODO: Implement create() method.
return array_map(
fn (string $ruleClass) => new $ruleClass(),
$this->rules
);
}
}

View File

@@ -2,13 +2,15 @@
namespace App\DataTransferObjects\Support\Transformers;
use Illuminate\Support\Carbon;
use Spatie\LaravelData\Support\DataProperty;
use Spatie\LaravelData\Transformers\Transformer;
class CarbonTransformer implements Transformer
{
public function transform(DataProperty $property, mixed $value): mixed
public function transform(DataProperty $property, mixed $value): string
{
/** @var Carbon $value */
return $value->toISOString();
}
}

View File

@@ -19,16 +19,11 @@ class UserData extends Data
public function __construct(
public ?int $id = null,
public ?string $avatar = null,
#[StringType,
Max(255)]
#[StringType, Max(255)]
public ?string $name = null,
#[StringType,
Email,
Max(255),
Unique(User::class)]
#[StringType, Email, Max(255), Unique(User::class)]
public ?string $email = null,
#[Exists(Package::class, 'id'),
IntegerType]
#[Exists(Package::class, 'id'), IntegerType]
public ?int $package_id = null,
#[StringType]
public ?string $blocked = null,

View File

@@ -8,9 +8,9 @@ use App\Models\Certificate;
use Filament\Resources\Form;
use Filament\Resources\Table;
use Filament\Resources\Resource;
use Illuminate\Support\HtmlString;
use Illuminate\Database\Eloquent\Builder;
use App\Filament\Resources\CertificateResource\Pages;
use Illuminate\Support\HtmlString;
class CertificateResource extends Resource
{

View File

@@ -63,7 +63,7 @@ class UserResource extends Resource
Forms\Components\Select::make('language')
->label(__('Language'))
->default('en')
->options(collect(languages())->mapWithKeys(fn(string $language) => [$language => $language])),
->options(collect(languages())->mapWithKeys(fn (string $language) => [$language => $language])),
Forms\Components\Textarea::make('notes')
->label(__('Notes'))
->maxLength(65535),

View File

@@ -2,9 +2,9 @@
namespace App\Filament\Resources\UserResource\Pages;
use Illuminate\Database\Eloquent\Model;
use App\Filament\Resources\UserResource;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Database\Eloquent\Model;
class CreateUser extends CreateRecord
{

View File

@@ -5,10 +5,10 @@ namespace App\Filament\Resources\UserResource\Pages;
use Filament\Pages\Actions;
use Filament\Forms\Components\Toggle;
use App\Actions\User\DeleteUserAction;
use Illuminate\Database\Eloquent\Model;
use App\Filament\Resources\UserResource;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Database\Eloquent\Model;
class EditUser extends EditRecord
{

View File

@@ -22,7 +22,7 @@ class ServerController extends Controller
]);
$server = app(CreateServerAction::class)->execute(
ServerData::validate($data)
ServerData::validateAndCreate($data)
);
return response(content: ['data' => ServerData::from($server->refresh())->toArray()], status: 201);

View File

@@ -29,7 +29,7 @@ class SiteController extends Controller
]);
$site = app(CreateSiteAction::class)->execute(
SiteData::validate($data)
SiteData::validateAndCreate($data)
);
$site->refresh();

View File

@@ -32,7 +32,7 @@ class UserController extends Controller
'requires_password_for_ftp' => ['nullable'],
]);
$userData = UserData::validate($data);
$userData = UserData::validateAndCreate($data);
$user = User::create($userData->toArray());
@@ -50,7 +50,7 @@ class UserController extends Controller
'requires_password_for_ftp' => [],
]);
$userData = UserData::validate($data);
$userData = UserData::validateAndCreate($data);
$user->update(
Arr::only($userData->toArray(), array_keys($data))

View File

@@ -50,7 +50,7 @@ class ServerController extends Controller
$data['user_id'] = Auth::id();
app(CreateServerAction::class)->execute(
ServerData::validate($data)
ServerData::validateAndCreate($data)
);
return redirect()->route('servers.index');

View File

@@ -77,7 +77,7 @@ class SiteController extends Controller
$request->merge(['user_id' => auth()->id()]);
$site = app(CreateSiteAction::class)->execute(
SiteData::validate($request)
SiteData::validateAndCreate($request)
);
return $site

View File

@@ -3,9 +3,7 @@
namespace App\Http\Middleware;
use Closure;
use Filament\Notifications\Notification;
use Illuminate\Http\Request;
use Livewire\Livewire;
class Demo
{

View File

@@ -27,7 +27,7 @@
"laravel/ui": "^4.2",
"predis/predis": "^1.1",
"saade/filament-laravel-log": "^1.1",
"spatie/laravel-data": "^3.8",
"spatie/laravel-data": "^3.9",
"spiral/roadrunner": "^2.8.2",
"stechstudio/filament-impersonate": "^2.10",
"symfony/http-client": "^6.0",

845
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,73 @@
<?php
use Illuminate\Contracts\Support\Arrayable;
use App\DataTransferObjects\Support\Casts\CarbonCast;
use Spatie\LaravelData\Transformers\ArrayableTransformer;
use App\DataTransferObjects\Support\Transformers\CarbonTransformer;
use App\DataTransferObjects;
return [
/*
* The package will use this date format when working with dates through the app
* The package will use this format when working with dates. If this option
* is an array, it will try to convert from the first format that works,
* and will serialize dates using the first format from the array.
*/
'date_format' => DATE_ATOM,
/*
* Global transformers will take complex types and transform them into simple
* types.
*/
'transformers' => [
DateTimeInterface::class => CarbonTransformer::class,
Arrayable::class => ArrayableTransformer::class,
// BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class,
DateTimeInterface::class => DataTransferObjects\Support\Transformers\CarbonTransformer::class,
\Illuminate\Contracts\Support\Arrayable::class => \Spatie\LaravelData\Transformers\ArrayableTransformer::class,
BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class,
],
/*
* Global casts will cast values into complex types when creating a data
* object from simple types.
*/
'casts' => [
DateTimeInterface::class => CarbonCast::class,
// BackedEnum::class => Spatie\LaravelData\Casts\EnumCast::class,
DateTimeInterface::class => DataTransferObjects\Support\Casts\CarbonCast::class,
BackedEnum::class => Spatie\LaravelData\Casts\EnumCast::class,
],
/*
* Rule inferrers can be configured here. They will automatically add
* validation rules to properties of a data object based upon
* the type of the property.
*/
'rule_inferrers' => [
Spatie\LaravelData\RuleInferrers\BuiltInTypesRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\AttributesRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\SometimesRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\NullableRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\RequiredRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\BuiltInTypesRuleInferrer::class,
Spatie\LaravelData\RuleInferrers\AttributesRuleInferrer::class,
],
/**
* Normalizers return an array representation of the payload, or null if
* it cannot normalize the payload. The normalizers below are used for
* every data object, unless overridden in a specific data object class.
*/
'normalizers' => [
Spatie\LaravelData\Normalizers\ModelNormalizer::class,
// Spatie\LaravelData\Normalizers\FormRequestNormalizer::class,
Spatie\LaravelData\Normalizers\ArrayableNormalizer::class,
Spatie\LaravelData\Normalizers\ObjectNormalizer::class,
Spatie\LaravelData\Normalizers\ArrayNormalizer::class,
Spatie\LaravelData\Normalizers\JsonNormalizer::class,
],
/*
* Data objects can be wrapped into a key like 'data' when used as a resource,
* this key can be set globally here for all data objects. You can pass in
* `null` if you want to disable wrapping.
*/
'wrap' => null,
/**
* Adds a specific caster to the Symphony VarDumper component which hides
* some properties from data objects and collections when being dumped
* by `dump` or `dd`. Can be 'enabled', 'disabled' or 'development'
* which will only enable the caster locally.
*/
'var_dumper_caster_mode' => 'development',
];

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"/app.js": "/app.js?id=7e1968acfd75b8dc843675097962e3ce",
"/app.js": "/app.js?id=ff1533ec4a7afad65c5bd7bcc2cc7d7b",
"/app-dark.css": "/app-dark.css?id=15c72df05e2b1147fa3e4b0670cfb435",
"/app.css": "/app.css?id=4d6a1a7fe095eedc2cb2a4ce822ea8a5",
"/img/favicon.png": "/img/favicon.png?id=1542bfe8a0010dcbee710da13cce367f",