diff --git a/app/Livewire/Concerns/ProvidesPressReleaseFormRules.php b/app/Livewire/Concerns/ProvidesPressReleaseFormRules.php new file mode 100644 index 00000000..2b449324 --- /dev/null +++ b/app/Livewire/Concerns/ProvidesPressReleaseFormRules.php @@ -0,0 +1,70 @@ +> + */ +trait ProvidesPressReleaseFormRules +{ + /** + * @return array> + */ + protected function baseFormRules(): array + { + $rules = [ + 'language' => ['required', Rule::in(['de', 'en'])], + 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], + 'contactId' => ['nullable', 'integer'], + 'title' => ['required', 'string', 'min:5', 'max:255'], + 'subtitle' => ['nullable', 'string', 'max:255'], + 'text' => ['required', 'string', 'min:50'], + 'keywords' => ['nullable', 'string', 'max:255'], + 'backlinkUrl' => ['nullable', 'url', 'max:255'], + 'boilerplateOverride' => ['nullable', 'string', 'max:5000'], + 'publishMode' => ['required', Rule::in(['now', 'scheduled'])], + ]; + + // Termin-Pflicht nur, wenn der User explizit Scheduling gewählt hat. + // Min. 5 Minuten in der Zukunft, damit der Background-Job (alle 5 Min) + // die PM verlässlich rechtzeitig fängt. + if ($this->publishMode === 'scheduled') { + $rules['scheduledDate'] = ['required', 'date']; + $rules['scheduledTime'] = ['required', 'date_format:H:i']; + $rules['scheduledAt'] = [ + 'required', + 'date', + // Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen- + // bewusst prüfen statt über die naive `after:`-Regel. + function (string $attribute, mixed $value, Closure $fail): void { + $scheduledAt = $this->resolveScheduledAt(); + + if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) { + $fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.')); + } + }, + ]; + } else { + $rules['scheduledDate'] = ['nullable']; + $rules['scheduledTime'] = ['nullable']; + $rules['scheduledAt'] = ['nullable']; + } + + $rules['embargoAt'] = ['nullable']; + + return $rules; + } +} diff --git a/resources/views/livewire/admin/press-releases/create.blade.php b/resources/views/livewire/admin/press-releases/create.blade.php index 93527744..3ac4c587 100644 --- a/resources/views/livewire/admin/press-releases/create.blade.php +++ b/resources/views/livewire/admin/press-releases/create.blade.php @@ -21,6 +21,7 @@ use Livewire\Volt\Component; new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class extends Component { use \App\Livewire\Concerns\InteractsWithPressReleaseScheduling; use \App\Livewire\Concerns\InteractsWithPressReleaseTags; + use \App\Livewire\Concerns\ProvidesPressReleaseFormRules; public string $portal = 'presseecho'; @@ -97,46 +98,11 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex */ protected function formRules(): array { - $rules = [ + return [ + ...$this->baseFormRules(), 'portal' => ['required', Rule::in(array_map(fn(Portal $p) => $p->value, Portal::cases()))], - 'language' => ['required', Rule::in(['de', 'en'])], 'companyId' => ['required', 'integer', Rule::exists('companies', 'id')], - 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], - 'contactId' => ['nullable', 'integer'], - 'title' => ['required', 'string', 'min:5', 'max:255'], - 'subtitle' => ['nullable', 'string', 'max:255'], - 'text' => ['required', 'string', 'min:50'], - 'keywords' => ['nullable', 'string', 'max:255'], - 'backlinkUrl' => ['nullable', 'url', 'max:255'], - 'boilerplateOverride' => ['nullable', 'string', 'max:5000'], - 'publishMode' => ['required', Rule::in(['now', 'scheduled'])], ]; - - if ($this->publishMode === 'scheduled') { - $rules['scheduledDate'] = ['required', 'date']; - $rules['scheduledTime'] = ['required', 'date_format:H:i']; - $rules['scheduledAt'] = [ - 'required', - 'date', - // Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen- - // bewusst prüfen statt über die naive `after:`-Regel. - function (string $attribute, mixed $value, \Closure $fail): void { - $scheduledAt = $this->resolveScheduledAt(); - - if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) { - $fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.')); - } - }, - ]; - } else { - $rules['scheduledDate'] = ['nullable']; - $rules['scheduledTime'] = ['nullable']; - $rules['scheduledAt'] = ['nullable']; - } - - $rules['embargoAt'] = ['nullable']; - - return $rules; } public function save(string $submitStatus = 'draft'): void diff --git a/resources/views/livewire/admin/press-releases/edit.blade.php b/resources/views/livewire/admin/press-releases/edit.blade.php index cf683532..7b1c889c 100644 --- a/resources/views/livewire/admin/press-releases/edit.blade.php +++ b/resources/views/livewire/admin/press-releases/edit.blade.php @@ -26,6 +26,7 @@ use Livewire\Volt\Component; new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] class extends Component { use \App\Livewire\Concerns\InteractsWithPressReleaseScheduling; use \App\Livewire\Concerns\InteractsWithPressReleaseTags; + use \App\Livewire\Concerns\ProvidesPressReleaseFormRules; #[Locked] public int $id; @@ -143,46 +144,11 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl */ protected function formRules(): array { - $rules = [ + return [ + ...$this->baseFormRules(), 'portal' => ['required', Rule::in(array_map(fn(Portal $p) => $p->value, Portal::cases()))], - 'language' => ['required', Rule::in(['de', 'en'])], 'companyId' => ['required', 'integer', Rule::exists('companies', 'id')], - 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], - 'contactId' => ['nullable', 'integer'], - 'title' => ['required', 'string', 'min:5', 'max:255'], - 'subtitle' => ['nullable', 'string', 'max:255'], - 'text' => ['required', 'string', 'min:50'], - 'keywords' => ['nullable', 'string', 'max:255'], - 'backlinkUrl' => ['nullable', 'url', 'max:255'], - 'boilerplateOverride' => ['nullable', 'string', 'max:5000'], - 'publishMode' => ['required', Rule::in(['now', 'scheduled'])], ]; - - if ($this->publishMode === 'scheduled') { - $rules['scheduledDate'] = ['required', 'date']; - $rules['scheduledTime'] = ['required', 'date_format:H:i']; - $rules['scheduledAt'] = [ - 'required', - 'date', - // Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen- - // bewusst prüfen statt über die naive `after:`-Regel. - function (string $attribute, mixed $value, \Closure $fail): void { - $scheduledAt = $this->resolveScheduledAt(); - - if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) { - $fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.')); - } - }, - ]; - } else { - $rules['scheduledDate'] = ['nullable']; - $rules['scheduledTime'] = ['nullable']; - $rules['scheduledAt'] = ['nullable']; - } - - $rules['embargoAt'] = ['nullable']; - - return $rules; } public function save(): void diff --git a/resources/views/livewire/customer/press-releases/create.blade.php b/resources/views/livewire/customer/press-releases/create.blade.php index 8f494d19..87565500 100644 --- a/resources/views/livewire/customer/press-releases/create.blade.php +++ b/resources/views/livewire/customer/press-releases/create.blade.php @@ -27,6 +27,7 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex { use \App\Livewire\Concerns\InteractsWithPressReleaseScheduling; use \App\Livewire\Concerns\InteractsWithPressReleaseTags; + use \App\Livewire\Concerns\ProvidesPressReleaseFormRules; public string $portal = 'presseecho'; @@ -128,48 +129,10 @@ new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class ex */ protected function formRules(): array { - $rules = [ - 'language' => ['required', Rule::in(['de', 'en'])], + return [ + ...$this->baseFormRules(), 'companyId' => ['required', 'integer'], - 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], - 'contactId' => ['nullable', 'integer'], - 'title' => ['required', 'string', 'min:5', 'max:255'], - 'subtitle' => ['nullable', 'string', 'max:255'], - 'text' => ['required', 'string', 'min:50'], - 'keywords' => ['nullable', 'string', 'max:255'], - 'backlinkUrl' => ['nullable', 'url', 'max:255'], - 'boilerplateOverride' => ['nullable', 'string', 'max:5000'], - 'publishMode' => ['required', Rule::in(['now', 'scheduled'])], ]; - - // Termin-Pflicht nur, wenn der User explizit Scheduling gewählt hat. - // Min. 5 Minuten in der Zukunft, damit der Background-Job (alle 5 Min) - // die PM verlässlich rechtzeitig fängt. - if ($this->publishMode === 'scheduled') { - $rules['scheduledDate'] = ['required', 'date']; - $rules['scheduledTime'] = ['required', 'date_format:H:i']; - $rules['scheduledAt'] = [ - 'required', - 'date', - // Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen- - // bewusst prüfen statt über die naive `after:`-Regel. - function (string $attribute, mixed $value, \Closure $fail): void { - $scheduledAt = $this->resolveScheduledAt(); - - if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) { - $fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.')); - } - }, - ]; - } else { - $rules['scheduledDate'] = ['nullable']; - $rules['scheduledTime'] = ['nullable']; - $rules['scheduledAt'] = ['nullable']; - } - - $rules['embargoAt'] = ['nullable']; - - return $rules; } // Tag-Verwaltung (addTag/removeTag/tagsArray) liegt im Trait diff --git a/resources/views/livewire/customer/press-releases/edit.blade.php b/resources/views/livewire/customer/press-releases/edit.blade.php index 234ff10c..0679cb73 100644 --- a/resources/views/livewire/customer/press-releases/edit.blade.php +++ b/resources/views/livewire/customer/press-releases/edit.blade.php @@ -16,7 +16,6 @@ use App\Services\PressRelease\PressReleaseService; use App\Services\PressRelease\QuotaExceededException; use Flux\Flux; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Validation\Rule; use Livewire\Attributes\Computed; use Livewire\Attributes\Layout; use Livewire\Attributes\Locked; @@ -28,6 +27,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl { use \App\Livewire\Concerns\InteractsWithPressReleaseScheduling; use \App\Livewire\Concerns\InteractsWithPressReleaseTags; + use \App\Livewire\Concerns\ProvidesPressReleaseFormRules; #[Locked] public int $id; @@ -171,45 +171,10 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl */ protected function formRules(): array { - $rules = [ - 'language' => ['required', Rule::in(['de', 'en'])], + return [ + ...$this->baseFormRules(), 'companyId' => ['required', 'integer'], - 'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')], - 'contactId' => ['nullable', 'integer'], - 'title' => ['required', 'string', 'min:5', 'max:255'], - 'subtitle' => ['nullable', 'string', 'max:255'], - 'text' => ['required', 'string', 'min:50'], - 'keywords' => ['nullable', 'string', 'max:255'], - 'backlinkUrl' => ['nullable', 'url', 'max:255'], - 'boilerplateOverride' => ['nullable', 'string', 'max:5000'], - 'publishMode' => ['required', Rule::in(['now', 'scheduled'])], ]; - - if ($this->publishMode === 'scheduled') { - $rules['scheduledDate'] = ['required', 'date']; - $rules['scheduledTime'] = ['required', 'date_format:H:i']; - $rules['scheduledAt'] = [ - 'required', - 'date', - // Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen- - // bewusst prüfen statt über die naive `after:`-Regel. - function (string $attribute, mixed $value, \Closure $fail): void { - $scheduledAt = $this->resolveScheduledAt(); - - if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) { - $fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.')); - } - }, - ]; - } else { - $rules['scheduledDate'] = ['nullable']; - $rules['scheduledTime'] = ['nullable']; - $rules['scheduledAt'] = ['nullable']; - } - - $rules['embargoAt'] = ['nullable']; - - return $rules; } /**