diff --git a/packages/panels/src/Resources/Pages/CreateRecord.php b/packages/panels/src/Resources/Pages/CreateRecord.php index 5908ac2dffd..10ed07540b0 100644 --- a/packages/panels/src/Resources/Pages/CreateRecord.php +++ b/packages/panels/src/Resources/Pages/CreateRecord.php @@ -61,15 +61,6 @@ protected function authorizeAccess(): void } protected function fillForm(): void - { - /** @internal Read the DocBlock above the following method. */ - $this->fillFormWithDefaultsAndCallHooks(); - } - - /** - * @internal Never override or call this method. If you completely override `fillForm()`, copy the contents of this method into your override. - */ - protected function fillFormWithDefaultsAndCallHooks(): void { $this->callHook('beforeFill'); @@ -91,40 +82,20 @@ public function create(bool $another = false): void $data = $this->mutateFormDataBeforeCreate($data); - /** @internal Read the DocBlock above the following method. */ - $this->createRecordAndCallHooks($data); - } catch (Halt $exception) { - return; - } - - /** @internal Read the DocBlock above the following method. */ - $this->sendCreatedNotificationAndRedirect(shouldCreateAnotherInsteadOfRedirecting: $another); - } - - /** - * @internal Never override or call this method. If you completely override `create()`, copy the contents of this method into your override. - * - * @param array $data - */ - protected function createRecordAndCallHooks(array $data): void - { - $this->callHook('beforeCreate'); + $this->callHook('beforeCreate'); - $this->record = $this->handleRecordCreation($data); + $this->record = $this->handleRecordCreation($data); - $this->form->model($this->getRecord())->saveRelationships(); + $this->form->model($this->getRecord())->saveRelationships(); - $this->callHook('afterCreate'); - } + $this->callHook('afterCreate'); + } catch (Halt $exception) { + return; + } - /** - * @internal Never override or call this method. If you completely override `create()`, copy the contents of this method into your override. - */ - protected function sendCreatedNotificationAndRedirect(bool $shouldCreateAnotherInsteadOfRedirecting = true): void - { $this->getCreatedNotification()?->send(); - if ($shouldCreateAnotherInsteadOfRedirecting) { + if ($another) { // Ensure that the form record is anonymized so that relationships aren't loaded. $this->form->model($this->getRecord()::class); $this->record = null; diff --git a/packages/panels/src/Resources/Pages/EditRecord.php b/packages/panels/src/Resources/Pages/EditRecord.php index 60dfae2913f..d26fe3138e8 100644 --- a/packages/panels/src/Resources/Pages/EditRecord.php +++ b/packages/panels/src/Resources/Pages/EditRecord.php @@ -128,41 +128,23 @@ public function save(bool $shouldRedirect = true): void $this->authorizeAccess(); try { - /** @internal Read the DocBlock above the following method. */ - $this->validateFormAndUpdateRecordAndCallHooks(); - } catch (Halt $exception) { - return; - } + $this->callHook('beforeValidate'); - /** @internal Read the DocBlock above the following method. */ - $this->sendSavedNotificationAndRedirect(shouldRedirect: $shouldRedirect); - } - - /** - * @internal Never override or call this method. If you completely override `save()`, copy the contents of this method into your override. - */ - protected function validateFormAndUpdateRecordAndCallHooks(): void - { - $this->callHook('beforeValidate'); + $data = $this->form->getState(); - $data = $this->form->getState(); + $this->callHook('afterValidate'); - $this->callHook('afterValidate'); + $data = $this->mutateFormDataBeforeSave($data); - $data = $this->mutateFormDataBeforeSave($data); + $this->callHook('beforeSave'); - $this->callHook('beforeSave'); + $this->handleRecordUpdate($this->getRecord(), $data); - $this->handleRecordUpdate($this->getRecord(), $data); - - $this->callHook('afterSave'); - } + $this->callHook('afterSave'); + } catch (Halt $exception) { + return; + } - /** - * @internal Never override or call this method. If you completely override `save()`, copy the contents of this method into your override. - */ - protected function sendSavedNotificationAndRedirect(bool $shouldRedirect = true): void - { $this->getSavedNotification()?->send(); if ($shouldRedirect && ($redirectUrl = $this->getRedirectUrl())) { diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php index 03cbc69ca32..ed484899364 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/Concerns/HasTranslatableFormWithExistingRecordData.php @@ -2,32 +2,39 @@ namespace Filament\Resources\Pages\Concerns; +use Livewire\Attributes\Locked; + trait HasTranslatableFormWithExistingRecordData { + #[Locked] + public $otherLocaleData = []; + protected function fillForm(): void { - $originalActiveLocale = $this->activeLocale; + $this->activeLocale = $this->getDefaultTranslatableLocale(); + + $record = $this->getRecord(); + $translatableAttributes = static::getResource()::getTranslatableAttributes(); foreach ($this->getTranslatableLocales() as $locale) { - $this->setActiveLocale($locale); + $translatedData = []; - $data = $this->getRecord()->attributesToArray(); + foreach ($translatableAttributes as $attribute) { + $translatedData[$attribute] = $record->getTranslation($attribute, $locale); + } + + if ($locale !== $this->activeLocale) { + $this->otherLocaleData[$locale] = $this->mutateFormDataBeforeFill($translatedData); - foreach (static::getResource()::getTranslatableAttributes() as $attribute) { - $data[$attribute] = $this->getRecord()->getTranslation($attribute, $this->activeLocale); + continue; } /** @internal Read the DocBlock above the following method. */ - $this->fillFormWithDataAndCallHooks($data); + $this->fillFormWithDataAndCallHooks([ + ...$record->attributesToArray(), + ...$translatedData, + ]); } - - $this->setActiveLocale($originalActiveLocale); - } - - protected function setActiveLocale(?string $locale = null): void - { - $this->activeLocale = filled($locale) ? $locale : $this->getDefaultTranslatableLocale(); - $this->cacheForm('form', $this->getForms()['form']); } protected function getDefaultTranslatableLocale(): string @@ -45,9 +52,4 @@ protected function getDefaultTranslatableLocale(): string return array_intersect($availableLocales, $resourceLocales)[0] ?? $defaultLocale; } - - public function getFormStatePath(): ?string - { - return "data.{$this->activeLocale}"; - } } diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php index 530ae35b1e4..6fa0863fae7 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/CreateRecord/Concerns/Translatable.php @@ -2,12 +2,11 @@ namespace Filament\Resources\Pages\CreateRecord\Concerns; -use Filament\Facades\Filament; use Filament\Resources\Concerns\HasActiveLocaleSwitcher; -use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Validation\ValidationException; +use Livewire\Attributes\Locked; trait Translatable { @@ -15,16 +14,12 @@ trait Translatable protected ?string $oldActiveLocale = null; - protected function fillForm(): void - { - foreach ($this->getTranslatableLocales() as $locale) { - $this->setActiveLocale($locale); - - /** @internal Read the DocBlock above the following method. */ - $this->fillFormWithDefaultsAndCallHooks(); - } + #[Locked] + public $otherLocaleData = []; - $this->setActiveLocale(); + public function mountTranslatable(): void + { + $this->activeLocale = static::getResource()::getDefaultTranslatableLocale(); } public function getTranslatableLocales(): array @@ -32,116 +27,46 @@ public function getTranslatableLocales(): array return static::getResource()::getTranslatableLocales(); } - protected function setActiveLocale(?string $locale = null): void - { - $this->activeLocale = filled($locale) ? $locale : static::getResource()::getDefaultTranslatableLocale(); - $this->cacheForm('form', $this->getForms()['form']); - } - - public function create(bool $another = false): void + protected function handleRecordCreation(array $data): Model { - $this->authorizeAccess(); - - try { - $this->callHook('beforeValidate'); - - $data = [ - $this->activeLocale => $this->form->getState(), - ]; - - $this->callHook('afterValidate'); - - $originalActiveLocale = $this->activeLocale; - - $translatableAttributes = app(static::getModel())->getTranslatableAttributes(); - - $nonTranslatableData = Arr::except( - $this->data[$originalActiveLocale] ?? [], - $translatableAttributes, - ); - - foreach ($this->getTranslatableLocales() as $locale) { - if ($locale === $originalActiveLocale) { - continue; - } - - try { - $this->setActiveLocale($locale); - - $this->data[$locale] = array_merge( - $this->data[$locale] ?? [], - $nonTranslatableData, - ); - - $this->callHook('beforeValidate'); - - $data[$locale] = $this->form->getState(); - - $this->callHook('afterValidate'); - } catch (ValidationException $exception) { - // If the validation fails for a non-active locale, - // we'll just ignore it and continue, since it's - // likely that the user hasn't filled out the - // required fields for that locale. - } - } - - $this->setActiveLocale($originalActiveLocale); + $record = app(static::getModel()); - foreach ($data as $locale => $localeData) { - if ($locale !== $this->activeLocale) { - $localeData = Arr::only( - $localeData, - $translatableAttributes, - ); - } + $translatableAttributes = static::getResource()::getTranslatableAttributes(); - $data[$locale] = $this->mutateFormDataBeforeCreate($localeData); - } + $record->fill(Arr::except($data, $translatableAttributes)); - /** @internal Read the DocBlock above the following method. */ - $this->createRecordAndCallHooks($data); - } catch (Halt $exception) { - return; + foreach (Arr::only($data, $translatableAttributes) as $key => $value) { + $record->setTranslation($key, $this->activeLocale, $value); } - /** @internal Read the DocBlock above the following method. */ - $this->sendCreatedNotificationAndRedirect(shouldCreateAnotherInsteadOfRedirecting: $another); - } + $originalData = $this->data; - protected function handleRecordCreation(array $data): Model - { - $record = app(static::getModel()); - - $translatableAttributes = $record->getTranslatableAttributes(); + foreach ($this->otherLocaleData as $locale => $localeData) { + $this->data = [ + ...$this->data, + ...$localeData, + ]; - foreach ($data as $locale => $localeData) { - if ($locale === $this->activeLocale) { - $record->fill(Arr::except($localeData, $translatableAttributes)); + try { + $this->form->validate(); + } catch (ValidationException $exception) { + continue; } + $localeData = $this->mutateFormDataBeforeCreate($localeData); + foreach (Arr::only($localeData, $translatableAttributes) as $key => $value) { $record->setTranslation($key, $locale, $value); } } - if ( - static::getResource()::isScopedToTenant() && - ($tenant = Filament::getTenant()) - ) { - return $this->associateRecordWithTenant($record, $tenant); - } + $this->data = $originalData; $record->save(); return $record; } - public function getFormStatePath(): ?string - { - return "data.{$this->activeLocale}"; - } - public function updatingActiveLocale(): void { $this->oldActiveLocale = $this->activeLocale; @@ -149,25 +74,19 @@ public function updatingActiveLocale(): void public function updatedActiveLocale(string $newActiveLocale): void { - $this->setActiveLocale($newActiveLocale); - if (blank($this->oldActiveLocale)) { return; } - $translatableAttributes = app(static::getModel())->getTranslatableAttributes(); + $translatableAttributes = static::getResource()::getTranslatableAttributes(); + + $this->otherLocaleData[$this->oldActiveLocale] = Arr::only($this->data, $translatableAttributes); - $this->data[$newActiveLocale] = array_merge( - $this->data[$newActiveLocale] ?? [], - Arr::except( - $this->data[$this->oldActiveLocale] ?? [], - $translatableAttributes, - ), - ); + $this->data = [ + ...Arr::except($this->data, $translatableAttributes), + ...$this->otherLocaleData[$this->activeLocale] ?? [], + ]; - $this->data[$this->oldActiveLocale] = Arr::only( - $this->data[$this->oldActiveLocale] ?? [], - $translatableAttributes, - ); + unset($this->otherLocaleData[$this->activeLocale]); } } diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php index b3b7cfd6027..00cf24d0e5e 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/EditRecord/Concerns/Translatable.php @@ -5,7 +5,6 @@ use Filament\Resources\Concerns\HasActiveLocaleSwitcher; use Filament\Resources\Pages\Concerns\HasTranslatableFormWithExistingRecordData; use Filament\Resources\Pages\Concerns\HasTranslatableRecord; -use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Validation\ValidationException; @@ -23,51 +22,38 @@ public function getTranslatableLocales(): array return static::getResource()::getTranslatableLocales(); } - public function save(bool $shouldRedirect = true): void + protected function handleRecordUpdate(Model $record, array $data): Model { - $this->authorizeAccess(); + $translatableAttributes = static::getResource()::getTranslatableAttributes(); - $originalActiveLocale = $this->activeLocale; + $record->fill(Arr::except($data, $translatableAttributes)); - try { - /** @internal Read the DocBlock above the following method. */ - $this->validateFormAndUpdateRecordAndCallHooks(); + foreach (Arr::only($data, $translatableAttributes) as $key => $value) { + $record->setTranslation($key, $this->activeLocale, $value); + } - $nonTranslatableData = Arr::except( - $this->data[$originalActiveLocale] ?? [], - $this->getRecord()->getTranslatableAttributes(), - ); + $originalData = $this->data; - $otherTranslatableLocales = Arr::except($this->getTranslatableLocales(), $originalActiveLocale); + foreach ($this->otherLocaleData as $locale => $localeData) { + $this->data = [ + ...$this->data, + ...$localeData, + ]; - foreach ($otherTranslatableLocales as $locale) { - $this->setActiveLocale($locale); + try { + $this->form->validate(); + } catch (ValidationException $exception) { + continue; + } - $this->data[$locale] = array_merge( - $this->data[$locale] ?? [], - $nonTranslatableData, - ); + $localeData = $this->mutateFormDataBeforeSave($localeData); - /** @internal Read the DocBlock above the following method. */ - $this->validateFormAndUpdateRecordAndCallHooks(); + foreach (Arr::only($localeData, $translatableAttributes) as $key => $value) { + $record->setTranslation($key, $locale, $value); } - } catch (Halt $exception) { - return; } - $this->setActiveLocale($originalActiveLocale); - - /** @internal Read the DocBlock above the following method. */ - $this->sendSavedNotificationAndRedirect(shouldRedirect: $shouldRedirect); - } - - protected function handleRecordUpdate(Model $record, array $data): Model - { - $record->fill(Arr::except($data, $record->getTranslatableAttributes())); - - foreach (Arr::only($data, $record->getTranslatableAttributes()) as $key => $value) { - $record->setTranslation($key, $this->activeLocale, $value); - } + $this->data = $originalData; $record->save(); @@ -85,8 +71,6 @@ public function updatedActiveLocale(string $newActiveLocale): void return; } - $this->setActiveLocale($this->oldActiveLocale); - try { $this->form->validate(); } catch (ValidationException $exception) { @@ -95,25 +79,15 @@ public function updatedActiveLocale(string $newActiveLocale): void throw $exception; } - $this->setActiveLocale($newActiveLocale); - - if (blank($this->oldActiveLocale)) { - return; - } + $translatableAttributes = static::getResource()::getTranslatableAttributes(); - $translatableAttributes = app(static::getModel())->getTranslatableAttributes(); + $this->otherLocaleData[$this->oldActiveLocale] = Arr::only($this->data, $translatableAttributes); - $this->data[$newActiveLocale] = array_merge( - $this->data[$newActiveLocale] ?? [], - Arr::except( - $this->data[$this->oldActiveLocale] ?? [], - $translatableAttributes, - ), - ); + $this->data = [ + ...Arr::except($this->data, $translatableAttributes), + ...$this->otherLocaleData[$this->activeLocale] ?? [], + ]; - $this->data[$this->oldActiveLocale] = Arr::only( - $this->data[$this->oldActiveLocale] ?? [], - $translatableAttributes, - ); + unset($this->otherLocaleData[$this->activeLocale]); } } diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php index 15ba4dfb146..882c6970cd1 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ListRecords/Concerns/Translatable.php @@ -10,7 +10,7 @@ trait Translatable public function mountTranslatable(): void { - $this->setActiveLocale(); + $this->activeLocale = static::getResource()::getDefaultTranslatableLocale(); } public function getTranslatableLocales(): array @@ -22,9 +22,4 @@ public function getActiveTableLocale(): ?string { return $this->activeLocale; } - - protected function setActiveLocale(): void - { - $this->activeLocale = static::getResource()::getDefaultTranslatableLocale(); - } } diff --git a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php index 99b1ec42aec..8b3c70455b1 100644 --- a/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php +++ b/packages/spatie-laravel-translatable-plugin/src/Resources/Pages/ViewRecord/Concerns/Translatable.php @@ -5,6 +5,7 @@ use Filament\Resources\Concerns\HasActiveLocaleSwitcher; use Filament\Resources\Pages\Concerns\HasTranslatableFormWithExistingRecordData; use Filament\Resources\Pages\Concerns\HasTranslatableRecord; +use Illuminate\Support\Arr; trait Translatable { @@ -12,6 +13,28 @@ trait Translatable use HasTranslatableFormWithExistingRecordData; use HasTranslatableRecord; + protected ?string $oldActiveLocale = null; + + public function updatingActiveLocale(): void + { + $this->oldActiveLocale = $this->activeLocale; + } + + public function updatedActiveLocale(string $newActiveLocale): void + { + if (blank($this->oldActiveLocale)) { + return; + } + + $translatableAttributes = static::getResource()::getTranslatableAttributes(); + + $this->otherLocaleData[$this->oldActiveLocale] = Arr::only($this->data, $translatableAttributes); + $this->data = [ + ...$this->data, + ...$this->otherLocaleData[$this->activeLocale] ?? [], + ]; + } + public function getTranslatableLocales(): array { return static::getResource()::getTranslatableLocales();