Skip to content

Commit c46ddf6

Browse files
Merge pull request #44 from Relaticle/feature/auto-detect-model-context
Feature/auto detect model context
2 parents 98dbb7b + 3f11992 commit c46ddf6

File tree

5 files changed

+183
-4
lines changed

5 files changed

+183
-4
lines changed

src/Filament/Integration/Builders/BaseBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ abstract class BaseBuilder
1919
{
2020
protected Model&HasCustomFields $model;
2121

22+
protected Model|string|null $explicitModel = null;
23+
2224
protected Builder $sections;
2325

2426
protected array $except = [];
@@ -52,6 +54,7 @@ public function forModel(Model|string $model): static
5254
}
5355

5456
$this->model = $model;
57+
$this->explicitModel = $model;
5558

5659
$this->sections = CustomFields::newSectionModel()->query()
5760
->forEntityType($model::class)

src/Filament/Integration/Builders/FormBuilder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ class FormBuilder extends BaseBuilder
1616
{
1717
public function build(): Grid
1818
{
19-
return Grid::make(1)->schema($this->values()->toArray());
19+
return FormContainer::make()
20+
->forModel($this->explicitModel ?? null)
21+
->only($this->only)
22+
->except($this->except);
2023
}
2124

2225
private function getDependentFieldCodes(Collection $fields): array
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace Relaticle\CustomFields\Filament\Integration\Builders;
4+
5+
use Filament\Schemas\Components\Grid;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
final class FormContainer extends Grid
9+
{
10+
private Model|string|null $explicitModel = null;
11+
12+
private array $except = [];
13+
14+
private array $only = [];
15+
16+
public static function make(array|int|null $columns = 1): static
17+
{
18+
$container = new self($columns);
19+
20+
// Defer schema generation until component is in container
21+
$container->schema(fn (): array => $container->generateSchema());
22+
23+
return $container;
24+
}
25+
26+
public function forModel(Model|string|null $model): static
27+
{
28+
$this->explicitModel = $model;
29+
30+
return $this;
31+
}
32+
33+
public function except(array $fieldCodes): static
34+
{
35+
$this->except = $fieldCodes;
36+
37+
return $this;
38+
}
39+
40+
public function only(array $fieldCodes): static
41+
{
42+
$this->only = $fieldCodes;
43+
44+
return $this;
45+
}
46+
47+
private function generateSchema(): array
48+
{
49+
// Inline priority: explicit ?? record ?? model class
50+
$model = $this->explicitModel ?? $this->getRecord() ?? $this->getModel();
51+
52+
if ($model === null) {
53+
return []; // Graceful fallback
54+
}
55+
56+
$builder = app(FormBuilder::class);
57+
58+
return $builder
59+
->forModel($model)
60+
->only($this->only)
61+
->except($this->except)
62+
->values()
63+
->toArray();
64+
}
65+
}

src/Filament/Integration/Builders/InfolistBuilder.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
use Filament\Infolists\Components\Entry;
88
use Filament\Schemas\Components\Component;
9-
use Filament\Schemas\Components\Grid;
9+
use Illuminate\Database\Eloquent\Model;
1010
use Illuminate\Support\Collection;
1111
use Relaticle\CustomFields\Filament\Integration\Factories\FieldInfolistsFactory;
1212
use Relaticle\CustomFields\Filament\Integration\Factories\SectionInfolistsFactory;
13+
use Relaticle\CustomFields\Models\Contracts\HasCustomFields;
1314
use Relaticle\CustomFields\Models\CustomField;
1415
use Relaticle\CustomFields\Models\CustomFieldSection;
1516
use Relaticle\CustomFields\Services\Visibility\BackendVisibilityService;
@@ -24,14 +25,24 @@ final class InfolistBuilder extends BaseBuilder
2425

2526
public function build(): Component
2627
{
27-
return Grid::make(1)->schema($this->values()->toArray());
28+
return InfolistContainer::make()
29+
->forModel($this->explicitModel ?? null)
30+
->hiddenLabels($this->hiddenLabels)
31+
->visibleWhenFilled($this->visibleWhenFilled)
32+
->withoutSections($this->withoutSections)
33+
->only($this->only)
34+
->except($this->except);
2835
}
2936

3037
/**
3138
* @return Collection<int, mixed>
3239
*/
33-
public function values(): Collection
40+
public function values(null|(Model&HasCustomFields) $model = null): Collection
3441
{
42+
if ($model !== null) {
43+
$this->forModel($model);
44+
}
45+
3546
$fieldInfolistsFactory = app(FieldInfolistsFactory::class);
3647
$sectionInfolistsFactory = app(SectionInfolistsFactory::class);
3748
$backendVisibilityService = app(BackendVisibilityService::class);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace Relaticle\CustomFields\Filament\Integration\Builders;
4+
5+
use Filament\Forms\Components\Field;
6+
use Filament\Schemas\Components\Grid;
7+
use Illuminate\Database\Eloquent\Model;
8+
9+
final class InfolistContainer extends Grid
10+
{
11+
private Model|string|null $explicitModel = null;
12+
13+
private array $except = [];
14+
15+
private array $only = [];
16+
17+
private bool $hiddenLabels = false;
18+
19+
private bool $visibleWhenFilled = false;
20+
21+
private bool $withoutSections = false;
22+
23+
public static function make(array|int|null $columns = 1): static
24+
{
25+
$container = new self($columns);
26+
27+
// Defer schema generation until component is in container
28+
$container->schema(fn (): array => $container->generateSchema());
29+
30+
return $container;
31+
}
32+
33+
public function forModel(Model|string|null $model): static
34+
{
35+
$this->explicitModel = $model;
36+
37+
return $this;
38+
}
39+
40+
public function except(array $fieldCodes): static
41+
{
42+
$this->except = $fieldCodes;
43+
44+
return $this;
45+
}
46+
47+
public function only(array $fieldCodes): static
48+
{
49+
$this->only = $fieldCodes;
50+
51+
return $this;
52+
}
53+
54+
public function hiddenLabels(bool $hiddenLabels = true): static
55+
{
56+
$this->hiddenLabels = $hiddenLabels;
57+
58+
return $this;
59+
}
60+
61+
public function visibleWhenFilled(bool $visibleWhenFilled = true): static
62+
{
63+
$this->visibleWhenFilled = $visibleWhenFilled;
64+
65+
return $this;
66+
}
67+
68+
public function withoutSections(bool $withoutSections = true): static
69+
{
70+
$this->withoutSections = $withoutSections;
71+
72+
return $this;
73+
}
74+
75+
/**
76+
* @return array<int, Field>
77+
*/
78+
private function generateSchema(): array
79+
{
80+
// Inline priority: explicit ?? record ?? model class
81+
$model = $this->explicitModel ?? $this->getRecord() ?? $this->getModel();
82+
83+
if ($model === null) {
84+
return []; // Graceful fallback
85+
}
86+
87+
$builder = app(InfolistBuilder::class)
88+
->forModel($model)
89+
->only($this->only)
90+
->except($this->except)
91+
->hiddenLabels($this->hiddenLabels)
92+
->visibleWhenFilled($this->visibleWhenFilled)
93+
->withoutSections($this->withoutSections);
94+
95+
return $builder->values()->toArray();
96+
}
97+
}

0 commit comments

Comments
 (0)