|null $translations * @property \Illuminate\Support\Carbon $created_at * @property \Illuminate\Support\Carbon $updated_at */ final class FormFieldOption extends Model { use HasFactory; use HasUlids; protected $table = 'form_field_options'; protected static function booted(): void { static::addGlobalScope(new FormFieldOptionScope()); } protected $fillable = [ 'owner_type', 'owner_id', 'value', 'label', 'sort_order', 'translations', ]; /** @var array */ protected $casts = [ 'translations' => 'array', 'sort_order' => 'int', ]; public function owner(): MorphTo { return $this->morphTo('owner', 'owner_type', 'owner_id'); } /** * Single source of truth for the per-row JSON shape consumed by * snapshot writer, API resources, and activity-log diff * reconstruction. Empty translations bag is omitted (preserves the * current contract for monolingual schemas). * * @return array{value:string,label:string,sort_order:int,translations?:array} */ public function toJsonShape(): array { $shape = [ 'value' => $this->value, 'label' => $this->label, 'sort_order' => $this->sort_order, ]; if (is_array($this->translations) && $this->translations !== []) { $shape['translations'] = $this->translations; } return $shape; } }