presseportale/app/Livewire/Concerns/ProvidesPressReleaseFormRules.php
Kevin Adametz fa995e30a2 Optimierung 2.3: formRules() via ProvidesPressReleaseFormRules
Die ~95% identischen Validierungsregeln (Inhaltsfelder, publishMode,
terminabhängiger Scheduling-Block mit zeitzonenbewusster Closure, Embargo)
in baseFormRules() zentralisiert. Die vier Editor-formRules() ergänzen nur
noch die abweichenden Schlüssel (portal nur Admin, companyId mit/ohne
exists). Ungenutzten Rule-Import in customer/edit entfernt.

Tests: volle Suite gruen (794 passed, 1 skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 08:46:27 +00:00

70 lines
2.7 KiB
PHP

<?php
namespace App\Livewire\Concerns;
use Closure;
use Illuminate\Validation\Rule;
/**
* Gemeinsame Validierungsregeln der PM-Editoren (Admin + Customer).
*
* Liefert alle in allen vier Editoren identischen Regeln (Inhaltsfelder,
* Veröffentlichungsmodus, terminabhängiger Scheduling-Block, Embargo). Die
* nutzende Komponente ergänzt in `formRules()` nur die unterschiedlichen
* Schlüssel (`portal` nur im Admin, `companyId` mit/ohne `exists`).
*
* Setzt [[InteractsWithPressReleaseScheduling]] voraus (nutzt `$publishMode`
* und `resolveScheduledAt()`).
*
* @return array<string, array<int, mixed>>
*/
trait ProvidesPressReleaseFormRules
{
/**
* @return array<string, array<int, mixed>>
*/
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;
}
}