From 0831ed0dcb56b78a6d684db33d636038a014c2a1 Mon Sep 17 00:00:00 2001 From: Sander Van Damme Date: Thu, 29 Aug 2024 15:33:35 +0200 Subject: [PATCH] Hydrate and dehydrate the tabs using the field instead of a trait (#21) * Hydrate and dehydrate the tabs using the field instead of a trait --------- Co-authored-by: AngryMoustache Co-authored-by: Jyrki De Neve --- composer.json | 2 +- phpstan-baseline.neon | 12 +++++ src/Forms/TranslatableTabs.php | 57 ++++++++++++++++++++++-- src/Resources/Traits/HasTranslations.php | 42 ----------------- 4 files changed, 67 insertions(+), 46 deletions(-) diff --git a/composer.json b/composer.json index 65a8761..4fb4dda 100644 --- a/composer.json +++ b/composer.json @@ -17,9 +17,9 @@ "spatie/laravel-package-tools": "^1.12" }, "require-dev": { + "larastan/larastan": "^2.0", "laravel/pint": "^1.0", "nunomaduro/collision": "^7.0|^8.0", - "larastan/larastan": "^2.0", "orchestra/testbench": "^8.0|^9.0", "pestphp/pest": "^2.0", "pestphp/pest-plugin-laravel": "^2.0", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f73df4e..0f1584b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -8,3 +8,15 @@ parameters: message: "#^Access to an undefined property Livewire\\\\Component\\:\\:\\$data\\.$#" count: 2 path: src/Actions/CopyTranslationAction.php + - + message: "#^Call to an undefined method Livewire\\\\Component\\:\\:getRecord\\(\\)\\.$#" + count: 1 + path: src/Forms/TranslatableTabs.php + - + message: "#^Cannot call method getTranslatedLocales\\(\\)\\ on class-string\\|object\\.$#" + count: 1 + path: src/Forms/TranslatableTabs.php + - + message: "#^Cannot call method getTranslation\\(\\)\\ on class-string\\|object\\.$#" + count: 1 + path: src/Forms/TranslatableTabs.php diff --git a/src/Forms/TranslatableTabs.php b/src/Forms/TranslatableTabs.php index abd2ab6..abf6fe5 100644 --- a/src/Forms/TranslatableTabs.php +++ b/src/Forms/TranslatableTabs.php @@ -9,6 +9,8 @@ use Filament\Support\Concerns\CanBeContained; use Filament\Support\Concerns\CanPersistTab; use Filament\Support\Concerns\HasExtraAlpineAttributes; +use Illuminate\Contracts\Support\Arrayable; +use Illuminate\Support\Arr; use Livewire\Component as Livewire; class TranslatableTabs extends Component @@ -38,6 +40,34 @@ final public function __construct(string $label) $this->label($label); $this->columnSpan(['lg' => 2]); + + $this->afterStateHydrated(static function (TranslatableTabs $component, string|array|null $state, Livewire $livewire): void { + if (blank($state)) { + $component->state([]); + + return; + } + + $record = $livewire->getRecord(); + + if (! $record || ! method_exists($record, 'getTranslatableAttributes')) { + return; + } + + foreach ($record->getTranslatableAttributes() as $field) { + foreach ($record->getTranslatedLocales($field) as $locale) { + $value = $record->getTranslation($field, $locale); + + if ($value instanceof Arrayable) { + $value = $value->toArray(); + } + + $state[$locale][$field] = $value; + } + } + + $component->state($state); + }); } public static function make(): static @@ -48,6 +78,23 @@ public static function make(): static return $static; } + public function dehydrateState(array &$state, bool $isDehydrated = true): void + { + parent::dehydrateState($state, $isDehydrated); + + $model = app($this->getModel()); + + foreach (Arr::except($state['data'], $model->getFillable()) as $locale => $values) { + if (! is_array($values)) { + continue; + } + + foreach (Arr::only($values, $model->getTranslatableAttributes()) as $key => $value) { + $state['data'][$key][$locale] = $value; + } + } + } + public function getTabQueryStringKey(): ?string { return 'locale'; @@ -98,6 +145,11 @@ public function locales(array|Closure $locales): static return $this; } + public function getLocales(): array + { + return $this->evaluate($this->locales); + } + public function icon(null|string|Closure $icon): static { $this->icon = $icon; @@ -127,15 +179,14 @@ public function isTabPersistedInQueryString(): bool public function getChildComponents(): array { $tabs = [ - Tab::make('Default') - ->schema($this->evaluate($this->defaultFields)), + Tab::make('Default')->schema($this->evaluate($this->defaultFields)), ]; if (! is_null($this->extraTabs)) { $tabs = array_merge($tabs, $this->evaluate($this->extraTabs)); } - foreach ($this->evaluate($this->locales) as $locale) { + foreach ($this->getLocales() as $locale) { $tabs[] = Tab::make($locale) ->schema($this->evaluate($this->translatableFields, [ 'locale' => $locale, diff --git a/src/Resources/Traits/HasTranslations.php b/src/Resources/Traits/HasTranslations.php index cb3c701..c092292 100644 --- a/src/Resources/Traits/HasTranslations.php +++ b/src/Resources/Traits/HasTranslations.php @@ -3,52 +3,10 @@ namespace Codedor\TranslatableTabs\Resources\Traits; use Filament\Actions\Action; -use Illuminate\Support\Arr; use Illuminate\Support\Js; trait HasTranslations { - protected function mutateFormDataBeforeCreate(array $data): array - { - return $this->mutateData($data); - } - - protected function mutateFormDataBeforeSave(array $data): array - { - return $this->mutateData($data); - } - - protected function mutateFormDataBeforeFill(array $data): array - { - $record = $this->getRecord(); - foreach ($record->getTranslatableAttributes() as $field) { - $locales = array_keys($record->getTranslations($field, config('translatable.allowed-locales', null))); - foreach ($locales as $locale) { - $data[$locale][$field] = $record->getTranslation($field, $locale); - } - } - - return $data; - } - - protected function mutateData(array $data): array - { - $model = app($this->getModel()); - foreach (Arr::except($data, $model->getFillable()) as $locale => $values) { - if (! is_array($values)) { - continue; - } - - foreach (Arr::only($values, $model->getTranslatableAttributes()) as $key => $value) { - $data[$key][$locale] = $value; - } - - // unset($data[$locale]); - } - - return $data; - } - protected function getCancelFormAction(): Action { return Action::make('cancel')