refactor(form-builder): pre-publish check reads form_field_bindings; drop binding JSON columns

This commit is contained in:
2026-04-24 20:09:27 +02:00
parent 6933e6d700
commit 61719bf8bf
18 changed files with 375 additions and 97 deletions

View File

@@ -10,6 +10,7 @@ use App\Http\Requests\Api\V1\FormBuilder\UpdateFormFieldLibraryRequest;
use App\Http\Resources\FormBuilder\FormFieldLibraryResource;
use App\Models\FormBuilder\FormFieldLibrary;
use App\Models\Organisation;
use App\Services\FormBuilder\FormFieldBindingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\Gate;
@@ -17,6 +18,10 @@ use Illuminate\Support\Str;
final class FormFieldLibraryController extends Controller
{
public function __construct(
private readonly FormFieldBindingService $bindingService,
) {}
public function index(Organisation $organisation): AnonymousResourceCollection
{
Gate::authorize('viewAny', [FormFieldLibrary::class, $organisation]);
@@ -42,6 +47,7 @@ final class FormFieldLibraryController extends Controller
Gate::authorize('create', [FormFieldLibrary::class, $organisation]);
$data = $request->validated();
$bindingSpec = $this->extractBindingSpec($data);
$data['organisation_id'] = $organisation->id;
$data['is_system'] = false;
$data['is_active'] ??= true;
@@ -50,6 +56,10 @@ final class FormFieldLibraryController extends Controller
/** @var FormFieldLibrary $library */
$library = FormFieldLibrary::create($data);
if ($bindingSpec !== null) {
$this->bindingService->replaceBindings($library, [$bindingSpec]);
}
return $this->created(new FormFieldLibraryResource($library));
}
@@ -58,12 +68,46 @@ final class FormFieldLibraryController extends Controller
$this->assertSameOrg($organisation, $fieldLibrary);
Gate::authorize('update', $fieldLibrary);
$fieldLibrary->fill($request->validated());
$data = $request->validated();
$bindingProvided = array_key_exists('default_binding', $data);
$bindingSpec = $bindingProvided ? $this->extractBindingSpec($data) : null;
$fieldLibrary->fill($data);
$fieldLibrary->save();
if ($bindingProvided) {
$this->bindingService->replaceBindings(
$fieldLibrary,
$bindingSpec === null ? [] : [$bindingSpec],
);
}
return $this->success(new FormFieldLibraryResource($fieldLibrary));
}
/**
* @param array<string, mixed> $data
* @return array{target_entity:string,target_attribute:string,mode:string,sync_direction?:?string}|null
*/
private function extractBindingSpec(array &$data): ?array
{
if (! array_key_exists('default_binding', $data)) {
return null;
}
$raw = $data['default_binding'];
unset($data['default_binding']);
if (! is_array($raw) || $raw === []) {
return null;
}
return [
'target_entity' => (string) ($raw['entity'] ?? ''),
'target_attribute' => (string) ($raw['column'] ?? ''),
'mode' => (string) ($raw['mode'] ?? ''),
'sync_direction' => isset($raw['sync_direction']) ? (string) $raw['sync_direction'] : null,
];
}
public function destroy(Organisation $organisation, FormFieldLibrary $fieldLibrary): JsonResponse
{
$this->assertSameOrg($organisation, $fieldLibrary);