Skip to content

Commit cfd90e9

Browse files
author
Backstage
committed
Use stack instead of slots
1 parent aeee991 commit cfd90e9

File tree

9 files changed

+327
-467
lines changed

9 files changed

+327
-467
lines changed

README.md

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -478,33 +478,6 @@ To register your own fields, you can add them to the `fields.fields` config arra
478478
'custom_fields' => [
479479
App\Fields\CustomField::class,
480480
],
481-
482-
### Value Hydration
483-
484-
The `hydrate` method allows you to transform the raw value stored in the database into a runtime representation. This is useful when you want to convert stored IDs into models, format dates, or process JSON data into specific objects.
485-
486-
To use this feature, your field class must implement the `Backstage\Fields\Contracts\HydratesValues` interface.
487-
488-
```php
489-
use Backstage\Fields\Fields\Base;
490-
use Backstage\Fields\Contracts\HydratesValues;
491-
use Illuminate\Database\Eloquent\Model;
492-
493-
class MyCustomField extends Base implements HydratesValues
494-
{
495-
/**
496-
* Hydrate the raw field value into its runtime representation.
497-
*/
498-
public function hydrate(mixed $value, ?Model $model = null): mixed
499-
{
500-
// Transform the raw value
501-
// For example, convert a stored ID to a model instance
502-
return MyModel::find($value);
503-
}
504-
}
505-
```
506-
507-
The `hydrate` method is automatically called when accessing the value of the field.
508481
```
509482

510483
## Documentation

src/Concerns/CanMapDynamicFields.php

Lines changed: 291 additions & 130 deletions
Large diffs are not rendered by default.

src/Concerns/PersistsContentData.php

Lines changed: 0 additions & 122 deletions
This file was deleted.

src/Contracts/HydratesValues.php

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/Fields/Base.php

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Filament\Schemas\Components\Grid;
1717
use Filament\Schemas\Components\Utilities\Get;
1818
use Filament\Support\Colors\Color;
19-
use Illuminate\Database\Eloquent\Model;
2019
use ReflectionObject;
2120

2221
abstract class Base implements FieldContract
@@ -191,49 +190,4 @@ protected static function applyAdditionalValidation($input, ?Field $field = null
191190

192191
return $input;
193192
}
194-
195-
public static function getFieldValueFromRecord(Model $record, Field $field): mixed
196-
{
197-
$result = null;
198-
199-
// Check if record has values method
200-
if (method_exists($record, 'values')) {
201-
$values = $record->values();
202-
203-
// Handle relationship-based values (like Content model)
204-
if (self::isRelationship($values)) {
205-
$fieldValue = $values->where(function ($query) use ($field) {
206-
$query->where('field_ulid', $field->ulid)
207-
->orWhere('ulid', $field->ulid);
208-
})->first();
209-
210-
$result = $fieldValue ? self::resolveHydratedValue($fieldValue) : null;
211-
}
212-
}
213-
214-
if ($result === null) {
215-
$values = $record->values ?? [];
216-
217-
// Handle array/collection-based values (like Settings model)
218-
if (is_array($values) || $values instanceof \Illuminate\Support\Collection) {
219-
$result = $values[$field->ulid] ?? $values[$field->slug] ?? null;
220-
}
221-
}
222-
223-
return $result;
224-
}
225-
226-
protected static function isRelationship(mixed $values): bool
227-
{
228-
return $values instanceof \Illuminate\Database\Eloquent\Relations\Relation;
229-
}
230-
231-
protected static function resolveHydratedValue(Model $fieldValue): mixed
232-
{
233-
if (method_exists($fieldValue, 'getHydratedValue')) {
234-
return $fieldValue->getHydratedValue();
235-
}
236-
237-
return $fieldValue->value ?? null;
238-
}
239193
}

src/Fields/Radio.php

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
use Filament\Forms\Components\Toggle;
1010
use Filament\Schemas\Components\Tabs;
1111
use Filament\Schemas\Components\Tabs\Tab;
12-
use Illuminate\Database\Eloquent\Collection;
13-
use Illuminate\Database\Eloquent\Model;
1412

1513
class Radio extends Base implements FieldContract
1614
{
@@ -46,59 +44,6 @@ public static function make(string $name, ?Field $field = null): Input
4644
return $input;
4745
}
4846

49-
public static function mutateFormDataCallback(Model $record, Field $field, array $data): array
50-
{
51-
if (! property_exists($record, 'valueColumn')) {
52-
return $data;
53-
}
54-
55-
$value = self::getFieldValueFromRecord($record, $field);
56-
57-
if ($value === null) {
58-
return $data;
59-
}
60-
61-
$data[$record->valueColumn][$field->ulid] = self::normalizeValue($value, $field);
62-
63-
return $data;
64-
}
65-
66-
public static function mutateBeforeSaveCallback(Model $record, Field $field, array $data): array
67-
{
68-
if (! property_exists($record, 'valueColumn')) {
69-
return $data;
70-
}
71-
72-
$value = $data[$record->valueColumn][$field->ulid] ?? $data[$record->valueColumn][$field->slug] ?? null;
73-
74-
if ($value === null && ! isset($data[$record->valueColumn][$field->ulid]) && ! isset($data[$record->valueColumn][$field->slug])) {
75-
return $data;
76-
}
77-
78-
$data[$record->valueColumn][$field->ulid] = self::normalizeValue($value, $field);
79-
80-
return $data;
81-
}
82-
83-
protected static function normalizeValue($value, Field $field): mixed
84-
{
85-
if ($value instanceof Collection) {
86-
$value = $value->toArray();
87-
}
88-
89-
// Handle JSON string values
90-
if (is_string($value) && json_validate($value)) {
91-
$value = json_decode($value, true);
92-
}
93-
94-
// Convert array to single value for Radio
95-
if (is_array($value)) {
96-
$value = empty($value) ? null : reset($value);
97-
}
98-
99-
return $value;
100-
}
101-
10247
public function getForm(): array
10348
{
10449
return [

src/Fields/Repeater.php

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use Backstage\Fields\Concerns\HasFieldTypeResolver;
77
use Backstage\Fields\Concerns\HasOptions;
88
use Backstage\Fields\Contracts\FieldContract;
9-
use Backstage\Fields\Contracts\HydratesValues;
109
use Backstage\Fields\Enums\Field as FieldEnum;
1110
use Backstage\Fields\Facades\Fields;
1211
use Backstage\Fields\Models\Field;
@@ -22,12 +21,11 @@
2221
use Filament\Schemas\Components\Tabs\Tab;
2322
use Filament\Schemas\Components\Utilities\Get;
2423
use Filament\Schemas\Components\Utilities\Set;
25-
use Illuminate\Database\Eloquent\Model;
2624
use Illuminate\Support\Collection;
2725
use Illuminate\Support\Str;
2826
use Saade\FilamentAdjacencyList\Forms\Components\AdjacencyList;
2927

30-
class Repeater extends Base implements FieldContract, HydratesValues
28+
class Repeater extends Base implements FieldContract
3129
{
3230
use HasConfigurableFields;
3331
use HasFieldTypeResolver;
@@ -38,59 +36,6 @@ public function getFieldType(): ?string
3836
return 'repeater';
3937
}
4038

41-
public function hydrate(mixed $value, ?Model $model = null): mixed
42-
{
43-
if (! is_array($value)) {
44-
return $value;
45-
}
46-
47-
if (empty($this->field_model)) {
48-
file_put_contents('/tmp/repeater_debug.log', "Field model missing for repeater.\n", FILE_APPEND);
49-
50-
return $value;
51-
}
52-
53-
$children = $this->field_model->children->keyBy('ulid');
54-
$slugMap = $this->field_model->children->pluck('ulid', 'slug');
55-
56-
file_put_contents('/tmp/repeater_debug.log', 'Hydrating Repeater ' . $this->field_model->ulid . ' with children slugs: ' . implode(', ', $slugMap->keys()->toArray()) . "\n", FILE_APPEND);
57-
58-
$hydrated = [];
59-
60-
foreach ($value as $key => $row) {
61-
$hydratedRow = $row;
62-
63-
if (is_array($row)) {
64-
foreach ($row as $fieldSlug => $fieldValue) {
65-
$fieldUlid = $slugMap[$fieldSlug] ?? null;
66-
if ($fieldUlid && isset($children[$fieldUlid])) {
67-
$fieldModel = $children[$fieldUlid];
68-
$fieldClass = self::resolveFieldTypeClassName($fieldModel->field_type);
69-
70-
file_put_contents('/tmp/repeater_debug.log', " > Hydrating field $fieldSlug ($fieldModel->field_type) using $fieldClass\n", FILE_APPEND);
71-
72-
if ($fieldClass && in_array(HydratesValues::class, class_implements($fieldClass))) {
73-
// Instantiate the field class to access its hydrate method
74-
// We need to set the field model on the instance if possible,
75-
// or at least pass context if needed.
76-
// Assuming simpler 'make' or instantiation works for hydration context.
77-
$fieldInstance = new $fieldClass;
78-
if (property_exists($fieldInstance, 'field_model')) {
79-
$fieldInstance->field_model = $fieldModel;
80-
}
81-
82-
$hydratedRow[$fieldSlug] = $fieldInstance->hydrate($fieldValue, $model);
83-
}
84-
}
85-
}
86-
}
87-
88-
$hydrated[$key] = $hydratedRow;
89-
}
90-
91-
return $hydrated;
92-
}
93-
9439
public static function getDefaultConfig(): array
9540
{
9641
return [

0 commit comments

Comments
 (0)