feat(form-builder): form_field_validation_rules table + polymorphic owner + scope + cascade

This commit is contained in:
2026-04-24 22:01:36 +02:00
parent 87fc964ead
commit fedaed1b32
17 changed files with 798 additions and 37 deletions

View File

@@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Observers\FormBuilder;
use App\Models\FormBuilder\FormField;
use App\Models\FormBuilder\FormFieldLibrary;
use Illuminate\Support\Facades\DB;
/**
* Cascade deletion of `form_field_bindings` rows when their polymorphic
* owner is deleted. Bindings represent current state (not historical
* intent) they are physically deleted even when the owner is only
* soft-deleted, which matches the Q3 decision that bindings have no
* soft-delete semantic of their own.
*/
final class FormFieldBindingsCascadeObserver
{
public function deleted(FormField|FormFieldLibrary $owner): void
{
$ownerType = $owner instanceof FormField ? 'form_field' : 'form_field_library';
DB::table('form_field_bindings')
->where('owner_type', $ownerType)
->where('owner_id', $owner->getKey())
->delete();
}
}

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\Observers\FormBuilder;
use App\Models\FormBuilder\FormField;
use App\Models\FormBuilder\FormFieldLibrary;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
/**
* Cascades physical deletion of child rows in the three relational tables
* that hang off `form_fields` / `form_field_library`:
*
* - `form_field_bindings` (WS-5a)
* - `form_field_validation_rules` (WS-5b)
* - `form_field_configs` (WS-5b expansion; added in commit 5)
*
* Children represent current state (not historical intent) physically
* deleted even when the owner is only soft-deleted, per addendum Q3: no
* child table in this family carries a soft-delete semantic of its own.
*
* Renamed from `FormFieldBindingsCascadeObserver` during WS-5b commit 1.
* The `Schema::hasTable` guard on the validation-rules cleanup keeps the
* observer safe when this code runs against a database where commit 1's
* migration has not yet been applied (e.g. during the migration step
* itself, where the observer is registered before the table exists).
*/
final class FormFieldChildTablesCascadeObserver
{
public function deleted(FormField|FormFieldLibrary $owner): void
{
$ownerType = $owner instanceof FormField ? 'form_field' : 'form_field_library';
$ownerId = $owner->getKey();
DB::table('form_field_bindings')
->where('owner_type', $ownerType)
->where('owner_id', $ownerId)
->delete();
if (Schema::hasTable('form_field_validation_rules')) {
DB::table('form_field_validation_rules')
->where('owner_type', $ownerType)
->where('owner_id', $ownerId)
->delete();
}
}
}