Skip to content

Commit 925cc3e

Browse files
committed
Merge branch 'fix/changing-select-multiple-loses-values' of github.com:backstagephp/fields into fix/changing-select-multiple-loses-values
2 parents fb2e074 + 3a2cbf9 commit 925cc3e

File tree

2 files changed

+86
-87
lines changed

2 files changed

+86
-87
lines changed

src/Concerns/CanMapDynamicFields.php

Lines changed: 83 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
/**
2727
* Trait for handling dynamic field mapping and data mutation in forms.
28-
*
28+
*
2929
* This trait provides functionality to:
3030
* - Map database field configurations to form input components
3131
* - Mutate form data before filling (loading from database)
@@ -66,11 +66,11 @@ public function refresh(): void
6666

6767
/**
6868
* Mutate form data before filling the form with existing values.
69-
*
69+
*
7070
* This method processes the record's field values and applies any custom
7171
* transformation logic defined in field classes before populating the form.
72-
*
73-
* @param array $data The form data array
72+
*
73+
* @param array $data The form data array
7474
* @return array The mutated form data
7575
*/
7676
protected function mutateBeforeFill(array $data): array
@@ -90,12 +90,12 @@ protected function mutateBeforeFill(array $data): array
9090

9191
/**
9292
* Mutate form data before saving to the database.
93-
*
93+
*
9494
* This method processes user input and applies any custom transformation logic
9595
* defined in field classes. It also handles special cases for builder blocks
9696
* and nested fields.
97-
*
98-
* @param array $data The form data array
97+
*
98+
* @param array $data The form data array
9999
* @return array The mutated form data ready for saving
100100
*/
101101
protected function mutateBeforeSave(array $data): array
@@ -134,11 +134,11 @@ private function extractFormValues(array $data): array
134134

135135
/**
136136
* Extract builder blocks from form values.
137-
*
137+
*
138138
* Builder blocks are special field types that contain nested fields.
139139
* This method identifies and extracts them for special processing.
140-
*
141-
* @param array $values The form values
140+
*
141+
* @param array $values The form values
142142
* @return array The builder blocks
143143
*/
144144
private function extractBuilderBlocks(array $values): array
@@ -155,8 +155,8 @@ private function extractBuilderBlocks(array $values): array
155155

156156
/**
157157
* Get all fields including those from builder blocks.
158-
*
159-
* @param array $builderBlocks The builder blocks
158+
*
159+
* @param array $builderBlocks The builder blocks
160160
* @return Collection All fields to process
161161
*/
162162
private function getAllFieldsIncludingBuilderFields(array $builderBlocks): Collection
@@ -168,23 +168,23 @@ private function getAllFieldsIncludingBuilderFields(array $builderBlocks): Colle
168168

169169
/**
170170
* Apply field-specific mutation logic for form filling.
171-
*
172-
* @param Model $field The field model
173-
* @param array $fieldConfig The field configuration
174-
* @param object $fieldInstance The field instance
175-
* @param array $data The form data
176-
* @param array $builderBlocks The builder blocks
171+
*
172+
* @param Model $field The field model
173+
* @param array $fieldConfig The field configuration
174+
* @param object $fieldInstance The field instance
175+
* @param array $data The form data
176+
* @param array $builderBlocks The builder blocks
177177
* @return array The mutated data
178178
*/
179179
private function applyFieldFillMutation(Model $field, array $fieldConfig, object $fieldInstance, array $data, array $builderBlocks): array
180180
{
181181
if (! empty($fieldConfig['methods']['mutateFormDataCallback'])) {
182182
$fieldLocation = $this->determineFieldLocation($field, $builderBlocks);
183-
183+
184184
if ($fieldLocation['isInBuilder']) {
185185
return $this->processBuilderFieldFillMutation($field, $fieldInstance, $data, $fieldLocation['builderData'], $builderBlocks);
186186
}
187-
187+
188188
return $fieldInstance->mutateFormDataCallback($this->record, $field, $data);
189189
}
190190

@@ -196,12 +196,12 @@ private function applyFieldFillMutation(Model $field, array $fieldConfig, object
196196

197197
/**
198198
* Extract builder blocks from record values.
199-
*
199+
*
200200
* @return array The builder blocks
201201
*/
202202
private function extractBuilderBlocksFromRecord(): array
203203
{
204-
if (!isset($this->record->values) || !is_array($this->record->values)) {
204+
if (! isset($this->record->values) || ! is_array($this->record->values)) {
205205
return [];
206206
}
207207

@@ -217,26 +217,26 @@ private function extractBuilderBlocksFromRecord(): array
217217

218218
/**
219219
* Process fill mutation for fields inside builder blocks.
220-
*
221-
* @param Model $field The field model
222-
* @param object $fieldInstance The field instance
223-
* @param array $data The form data
224-
* @param array $builderData The builder block data
225-
* @param array $builderBlocks All builder blocks
220+
*
221+
* @param Model $field The field model
222+
* @param object $fieldInstance The field instance
223+
* @param array $data The form data
224+
* @param array $builderData The builder block data
225+
* @param array $builderBlocks All builder blocks
226226
* @return array The updated form data
227227
*/
228228
private function processBuilderFieldFillMutation(Model $field, object $fieldInstance, array $data, array $builderData, array $builderBlocks): array
229229
{
230230
// Create a mock record with the builder data for the callback
231231
$mockRecord = $this->createMockRecordForBuilder($builderData);
232-
232+
233233
// Create a temporary data structure for the callback
234234
$tempData = [$this->record->valueColumn => $builderData];
235235
$tempData = $fieldInstance->mutateFormDataCallback($mockRecord, $field, $tempData);
236-
236+
237237
// Update the original data structure with the mutated values
238238
$this->updateBuilderBlocksWithMutatedData($builderBlocks, $field, $tempData);
239-
239+
240240
// Update the main data structure
241241
$data[$this->record->valueColumn] = array_merge($data[$this->record->valueColumn], $builderBlocks);
242242

@@ -245,24 +245,24 @@ private function processBuilderFieldFillMutation(Model $field, object $fieldInst
245245

246246
/**
247247
* Create a mock record for builder field processing.
248-
*
249-
* @param array $builderData The builder block data
248+
*
249+
* @param array $builderData The builder block data
250250
* @return object The mock record
251251
*/
252252
private function createMockRecordForBuilder(array $builderData): object
253253
{
254254
$mockRecord = clone $this->record;
255255
$mockRecord->values = $builderData;
256-
256+
257257
return $mockRecord;
258258
}
259259

260260
/**
261261
* Update builder blocks with mutated field data.
262-
*
263-
* @param array $builderBlocks The builder blocks to update
264-
* @param Model $field The field being processed
265-
* @param array $tempData The temporary data containing mutated values
262+
*
263+
* @param array $builderBlocks The builder blocks to update
264+
* @param Model $field The field being processed
265+
* @param array $tempData The temporary data containing mutated values
266266
*/
267267
private function updateBuilderBlocksWithMutatedData(array &$builderBlocks, Model $field, array $tempData): void
268268
{
@@ -279,11 +279,11 @@ private function updateBuilderBlocksWithMutatedData(array &$builderBlocks, Model
279279

280280
/**
281281
* Resolve field configuration and create an instance.
282-
*
282+
*
283283
* This method determines whether to use a custom field implementation
284284
* or fall back to the default field type mapping.
285-
*
286-
* @param Model $field The field model
285+
*
286+
* @param Model $field The field model
287287
* @return array Array containing 'config' and 'instance' keys
288288
*/
289289
private function resolveFieldConfigAndInstance(Model $field): array
@@ -301,11 +301,11 @@ private function resolveFieldConfigAndInstance(Model $field): array
301301

302302
/**
303303
* Extract field models from builder blocks.
304-
*
304+
*
305305
* Builder blocks contain nested fields that need to be processed.
306306
* This method extracts those field models for processing.
307-
*
308-
* @param array $blocks The builder blocks
307+
*
308+
* @param array $blocks The builder blocks
309309
* @return Collection The field models from blocks
310310
*/
311311
protected function getFieldsFromBlocks(array $blocks): Collection
@@ -326,13 +326,13 @@ protected function getFieldsFromBlocks(array $blocks): Collection
326326

327327
/**
328328
* Apply mutation strategy to all fields recursively.
329-
*
329+
*
330330
* This method processes each field and its nested children using the provided
331331
* mutation strategy. It handles the hierarchical nature of fields.
332-
*
333-
* @param array $data The form data
334-
* @param Collection $fields The fields to process
335-
* @param callable $mutationStrategy The strategy to apply to each field
332+
*
333+
* @param array $data The form data
334+
* @param Collection $fields The fields to process
335+
* @param callable $mutationStrategy The strategy to apply to each field
336336
* @return array The mutated form data
337337
*/
338338
protected function mutateFormData(array $data, Collection $fields, callable $mutationStrategy): array
@@ -351,10 +351,10 @@ protected function mutateFormData(array $data, Collection $fields, callable $mut
351351

352352
/**
353353
* Process nested fields (children) of a parent field.
354-
*
355-
* @param Model $field The parent field
356-
* @param array $data The form data
357-
* @param callable $mutationStrategy The mutation strategy
354+
*
355+
* @param Model $field The parent field
356+
* @param array $data The form data
357+
* @param callable $mutationStrategy The mutation strategy
358358
* @return array The updated form data
359359
*/
360360
private function processNestedFields(Model $field, array $data, callable $mutationStrategy): array
@@ -373,12 +373,12 @@ private function processNestedFields(Model $field, array $data, callable $mutati
373373

374374
/**
375375
* Resolve form field inputs for rendering.
376-
*
376+
*
377377
* This method converts field models into form input components
378378
* that can be rendered in the UI.
379-
*
380-
* @param mixed $record The record containing fields
381-
* @param bool $isNested Whether this is a nested field
379+
*
380+
* @param mixed $record The record containing fields
381+
* @param bool $isNested Whether this is a nested field
382382
* @return array Array of form input components
383383
*/
384384
private function resolveFormFields(mixed $record = null, bool $isNested = false): array
@@ -406,14 +406,14 @@ private function resolveCustomFields(): Collection
406406

407407
/**
408408
* Resolve a single field input component.
409-
*
409+
*
410410
* This method creates the appropriate form input component for a field,
411411
* prioritizing custom field implementations over default ones.
412-
*
413-
* @param Model $field The field model
414-
* @param Collection $customFields Available custom fields
415-
* @param mixed $record The record
416-
* @param bool $isNested Whether this is a nested field
412+
*
413+
* @param Model $field The field model
414+
* @param Collection $customFields Available custom fields
415+
* @param mixed $record The record
416+
* @param bool $isNested Whether this is a nested field
417417
* @return object|null The form input component or null if not found
418418
*/
419419
private function resolveFieldInput(Model $field, Collection $customFields, mixed $record = null, bool $isNested = false): ?object
@@ -442,15 +442,15 @@ private function generateInputName(Model $field, mixed $record, bool $isNested):
442442

443443
/**
444444
* Apply field-specific mutation logic for form saving.
445-
*
445+
*
446446
* This method handles both regular fields and fields within builder blocks.
447447
* Builder blocks require special processing because they contain nested data structures.
448-
*
449-
* @param Model $field The field model
450-
* @param array $fieldConfig The field configuration
451-
* @param object $fieldInstance The field instance
452-
* @param array $data The form data
453-
* @param array $builderBlocks The builder blocks
448+
*
449+
* @param Model $field The field model
450+
* @param array $fieldConfig The field configuration
451+
* @param object $fieldInstance The field instance
452+
* @param array $data The form data
453+
* @param array $builderBlocks The builder blocks
454454
* @return array The mutated data
455455
*/
456456
private function applyFieldSaveMutation(Model $field, array $fieldConfig, object $fieldInstance, array $data, array $builderBlocks): array
@@ -471,9 +471,9 @@ private function applyFieldSaveMutation(Model $field, array $fieldConfig, object
471471

472472
/**
473473
* Determine if a field is inside a builder block and extract its data.
474-
*
475-
* @param Model $field The field to check
476-
* @param array $builderBlocks The builder blocks
474+
*
475+
* @param Model $field The field to check
476+
* @param array $builderBlocks The builder blocks
477477
* @return array Location information with 'isInBuilder' and 'builderData' keys
478478
*/
479479
private function determineFieldLocation(Model $field, array $builderBlocks): array
@@ -499,29 +499,29 @@ private function determineFieldLocation(Model $field, array $builderBlocks): arr
499499

500500
/**
501501
* Process mutation for fields inside builder blocks.
502-
*
502+
*
503503
* Builder fields require special handling because they're nested within
504504
* a complex data structure that needs to be updated in place.
505-
*
506-
* @param Model $field The field model
507-
* @param object $fieldInstance The field instance
508-
* @param array $data The form data
509-
* @param array $builderData The builder block data
510-
* @param array $builderBlocks All builder blocks
505+
*
506+
* @param Model $field The field model
507+
* @param object $fieldInstance The field instance
508+
* @param array $data The form data
509+
* @param array $builderData The builder block data
510+
* @param array $builderBlocks All builder blocks
511511
* @return array The updated form data
512512
*/
513513
private function processBuilderFieldMutation(Model $field, object $fieldInstance, array $data, array $builderData, array $builderBlocks): array
514514
{
515515
// Create a mock record with the builder data for the callback
516516
$mockRecord = $this->createMockRecordForBuilder($builderData);
517-
517+
518518
// Create a temporary data structure for the callback
519519
$tempData = [$this->record->valueColumn => $builderData];
520520
$tempData = $fieldInstance->mutateBeforeSaveCallback($mockRecord, $field, $tempData);
521-
521+
522522
// Update the original data structure with the mutated values
523523
$this->updateBuilderBlocksWithMutatedData($builderBlocks, $field, $tempData);
524-
524+
525525
// Update the main data structure
526526
$data[$this->record->valueColumn] = array_merge($data[$this->record->valueColumn], $builderBlocks);
527527

src/Fields/Select.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ public static function mutateFormDataCallback($record, $field, array $data): arr
7979
if (! property_exists($record, 'valueColumn') || ! isset($record->values[$field->ulid])) {
8080
return $data;
8181
}
82-
8382

8483
$value = $record->values[$field->ulid];
8584
$data[$record->valueColumn][$field->ulid] = self::normalizeSelectValue($value, $field);
@@ -100,7 +99,7 @@ public static function mutateBeforeSaveCallback($record, $field, array $data): a
10099
}
101100

102101
/**
103-
* Normalize the select value to an array or a single value. This is needed because the select field can be
102+
* Normalize the select value to an array or a single value. This is needed because the select field can be
104103
* changed from single to multiple or vice versa.
105104
*/
106105
private static function normalizeSelectValue($value, Field $field): mixed
@@ -118,12 +117,12 @@ private static function normalizeSelectValue($value, Field $field): mixed
118117
}
119118

120119
// Convert to array if multiple is expected but value is not an array
121-
if ($isMultiple && !is_array($value)) {
120+
if ($isMultiple && ! is_array($value)) {
122121
return [$value];
123122
}
124123

125124
// Convert array to single value if multiple is not expected
126-
if (!$isMultiple && is_array($value)) {
125+
if (! $isMultiple && is_array($value)) {
127126
return empty($value) ? null : reset($value);
128127
}
129128

0 commit comments

Comments
 (0)