feat(form-builder): add BindingTypeRegistry as single source of truth for target shapes (WS-6)
Config-driven mapping from (target_entity, target_attribute) to storage shape (scalar/collection/relation), PHP type, and identity-key eligibility. Replaces any name-suffix matching (e.g. _tags, _skills) — those are convention-not-contract and reject by design. Used by publish guards now and (in session 2) by FormBindingApplicator. Refs: RFC-WS-6.md §4 (V1) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
49
api/config/form_builder/binding_targets.php
Normal file
49
api/config/form_builder/binding_targets.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RFC-WS-6 §4 (V1) — single source of truth for binding-target storage
|
||||
* shape. Consulted by `BindingTypeRegistry`, `AppendStrategyRequiresCollectionTarget`
|
||||
* publish guard, and (in session 2) by `FormBindingApplicator`.
|
||||
*
|
||||
* `type` values:
|
||||
* - 'scalar' — single column (string/int/datetime/email/...)
|
||||
* - 'collection' — JSON array column or pivot relation with set semantics
|
||||
* - 'relation' — FK column resolving to another entity
|
||||
*
|
||||
* `php` values map to native PHP / cast types: 'string', 'int', 'bool',
|
||||
* 'date', 'datetime', 'array'. Validated by
|
||||
* BindingTypeRegistryConsistencyTest.
|
||||
*
|
||||
* `identity_key_eligible` permits a binding to set `is_identity_key=true`
|
||||
* on this attribute. PurposeGuardProvider's RequiresIdentityKeyBinding
|
||||
* may only target attributes that are eligible.
|
||||
*/
|
||||
return [
|
||||
'person' => [
|
||||
'email' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'first_name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'last_name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'date_of_birth' => ['type' => 'scalar', 'php' => 'date', 'identity_key_eligible' => false],
|
||||
'phone_number' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'dietary_preferences' => ['type' => 'collection', 'php' => 'array', 'identity_key_eligible' => false],
|
||||
],
|
||||
'artist' => [
|
||||
'email' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'stage_name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'tech_rider' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'hospitality_rider' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
],
|
||||
'company' => [
|
||||
'name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'email' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'kvk_number' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'phone_number' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
],
|
||||
'user' => [
|
||||
'email' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => true],
|
||||
'first_name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
'last_name' => ['type' => 'scalar', 'php' => 'string', 'identity_key_eligible' => false],
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user