1+ <?php
2+
3+ namespace Vormkracht10 \Fields \Concerns ;
4+
5+ use Filament \Forms ;
6+ use Illuminate \Support \Str ;
7+ use Filament \Forms \Components \Grid ;
8+ use Illuminate \Support \Facades \Schema ;
9+ use Filament \Forms \Components \Fieldset ;
10+ use Filament \Forms \Components \Repeater ;
11+
12+ trait HasOptions
13+ {
14+ public static function addOptionsToInput (mixed $ input , mixed $ field ): mixed
15+ {
16+ if (isset ($ field ->config ['optionType ' ]) && $ field ->config ['optionType ' ] === 'relationship ' ) {
17+ $ options = [];
18+
19+ foreach ($ field ->config ['relations ' ] as $ relation ) {
20+ $ resources = config ('filament-fields.select.resource_options ' );
21+ $ resourceClass = collect ($ resources )->first (function ($ resource ) use ($ relation ) {
22+ $ res = new $ resource ();
23+ $ model = $ res ->getModel ();
24+ $ model = new $ model ();
25+ return $ model ->getTable () === $ relation ['resource ' ];
26+ });
27+
28+ if (!$ resourceClass ) {
29+ continue ;
30+ }
31+
32+ $ resource = new $ resourceClass ();
33+ $ model = $ resource ->getModel ();
34+ $ query = $ model ::query ();
35+
36+ // Apply filters if they exist
37+ if (isset ($ relation ['relationValue_filters ' ])) {
38+ foreach ($ relation ['relationValue_filters ' ] as $ filter ) {
39+ if (isset ($ filter ['column ' ], $ filter ['operator ' ], $ filter ['value ' ])) {
40+ $ query ->where ($ filter ['column ' ], $ filter ['operator ' ], $ filter ['value ' ]);
41+ }
42+ }
43+ }
44+
45+ $ results = $ query ->get ();
46+
47+ if ($ results ->isEmpty ()) {
48+ continue ;
49+ }
50+
51+ $ opts = $ results ->pluck ($ relation ['relationValue ' ] ?? 'name ' , $ relation ['relationKey ' ])->toArray ();
52+
53+ if (count ($ opts ) === 0 ) {
54+ continue ;
55+ }
56+
57+ $ options [] = $ opts ;
58+ }
59+
60+ if (!empty ($ options )) {
61+ $ options = array_merge (...$ options );
62+ $ input ->options ($ options );
63+ }
64+ }
65+
66+ if (isset ($ field ->config ['optionType ' ]) && $ field ->config ['optionType ' ] === 'array ' ) {
67+ $ input ->options ($ field ->config ['options ' ]);
68+ }
69+
70+ return $ input ;
71+ }
72+
73+ public static function getOptionsConfig (): array
74+ {
75+ return [
76+ 'optionType ' => null ,
77+ 'options ' => [],
78+ 'descriptions ' => [],
79+ 'relations ' => [],
80+ 'contentType ' => null ,
81+ 'relationKey ' => null ,
82+ 'relationValue ' => null ,
83+ ];
84+ }
85+
86+ public function optionFormFields (): Fieldset
87+ {
88+ return Forms \Components \Fieldset::make ('Options ' )
89+ ->columnSpanFull ()
90+ ->label (__ ('Options ' ))
91+ ->schema ([
92+ Forms \Components \Grid::make (2 )
93+ ->schema ([
94+ Forms \Components \Select::make ('config.optionType ' )
95+ ->options ([
96+ 'array ' => __ ('Array ' ),
97+ 'relationship ' => __ ('Relationship ' ),
98+ ])
99+ ->searchable ()
100+ ->live (onBlur: true )
101+ ->reactive ()
102+ ->label (__ ('Type ' )),
103+ // Array options
104+ Forms \Components \KeyValue::make ('config.options ' )
105+ ->label (__ ('Options ' ))
106+ ->columnSpanFull ()
107+ ->visible (fn (Forms \Get $ get ): bool => $ get ('config.optionType ' ) == 'array ' )
108+ ->required (fn (Forms \Get $ get ): bool => $ get ('config.optionType ' ) == 'array ' ),
109+ // Relationship options
110+ Repeater::make ('config.relations ' )
111+ ->label (__ ('Relations ' ))
112+ ->schema ([
113+ Grid::make ()
114+ ->columns (2 )
115+ ->schema ([
116+ Forms \Components \Select::make ('resource ' )
117+ ->label (__ ('Resource ' ))
118+ ->searchable ()
119+ ->preload ()
120+ ->columnSpanFull ()
121+ ->live (debounce: 250 )
122+ ->afterStateUpdated (function (Forms \Set $ set , ?string $ state ) {
123+ $ resources = config ('filament-fields.select.resource_options ' );
124+ $ resourceClass = collect ($ resources )->first (function ($ resource ) use ($ state ) {
125+ $ res = new $ resource ();
126+ $ model = $ res ->getModel ();
127+ $ model = new $ model ();
128+ return $ model ->getTable () === $ state ;
129+ });
130+
131+ if (!$ resourceClass ) {
132+ return ;
133+ }
134+
135+ $ resource = new $ resourceClass ();
136+ $ model = $ resource ->getModel ();
137+ $ model = new $ model ();
138+
139+ // Get all column names from the table
140+ $ columns = Schema::getColumnListing ($ model ->getTable ());
141+
142+ // Create options array with column names
143+ $ columnOptions = collect ($ columns )->mapWithKeys (function ($ column ) {
144+ return [$ column => Str::title ($ column )];
145+ })->toArray ();
146+
147+ $ set ('relationValue ' , null );
148+ $ set ('relationValue_options ' , $ columnOptions );
149+ })
150+ ->options (function () {
151+ $ resources = config ('filament-fields.select.resource_options ' );
152+
153+ return collect ($ resources )->map (function ($ resource ) {
154+ $ res = new $ resource ();
155+ $ model = $ res ->getModel ();
156+ $ model = new $ model ();
157+
158+ return [
159+ $ model ->getTable () => Str::title ($ model ->getTable ())
160+ ];
161+ })
162+ ->collapse ()
163+ ->toArray ();
164+ })
165+ ->noSearchResultsMessage (__ ('No types found ' ))
166+ ->required (fn (Forms \Get $ get ): bool => $ get ('config.optionType ' ) == 'relationship ' ),
167+ Forms \Components \Hidden::make ('relationKey ' )
168+ ->default ('ulid ' )
169+ ->label (__ ('Key ' ))
170+ ->required (fn (Forms \Get $ get ): bool => $ get ('config.optionType ' ) == 'relationship ' ),
171+ Forms \Components \Repeater::make ('relationValue_filters ' )
172+ ->label (__ ('Filters ' ))
173+ ->visible (fn (Forms \Get $ get ): bool => ! empty ($ get ('resource ' )))
174+ ->schema ([
175+ Forms \Components \Grid::make (3 )
176+ ->schema ([
177+ Forms \Components \Select::make ('column ' )
178+ ->options (fn (\Filament \Forms \Get $ get ) => $ get ('../../relationValue_options ' ) ?? [
179+ 'slug ' => __ ('Slug ' ),
180+ 'name ' => __ ('Name ' ),
181+ ])
182+ ->live ()
183+ ->label (__ ('Column ' )),
184+ Forms \Components \Select::make ('operator ' )
185+ ->options ([
186+ '= ' => __ ('Equal ' ),
187+ '!= ' => __ ('Not equal ' ),
188+ '> ' => __ ('Greater than ' ),
189+ '< ' => __ ('Less than ' ),
190+ '>= ' => __ ('Greater than or equal to ' ),
191+ '<= ' => __ ('Less than or equal to ' ),
192+ 'LIKE ' => __ ('Like ' ),
193+ 'NOT LIKE ' => __ ('Not like ' ),
194+ ])
195+ ->label (__ ('Operator ' )),
196+ Forms \Components \TextInput::make ('value ' )
197+ ->datalist (function (Forms \Get $ get ) {
198+ $ resource = $ get ('../../resource ' );
199+ $ column = $ get ('column ' );
200+
201+ if (!$ resource || !$ column ) {
202+ return [];
203+ }
204+
205+ $ resources = config ('filament-fields.select.resource_options ' );
206+ $ resourceClass = collect ($ resources )->first (function ($ r ) use ($ resource ) {
207+ $ res = new $ r ();
208+ $ model = $ res ->getModel ();
209+ $ model = new $ model ();
210+ return $ model ->getTable () === $ resource ;
211+ });
212+
213+ if (!$ resourceClass ) {
214+ return [];
215+ }
216+
217+ $ resource = new $ resourceClass ();
218+ $ model = $ resource ->getModel ();
219+
220+ return $ model ::query ()
221+ ->select ($ column )
222+ ->distinct ()
223+ ->pluck ($ column )
224+ ->toArray ();
225+ })
226+ ->label (__ ('Value ' )),
227+ ])
228+ ])
229+ ->columnSpanFull (),
230+ ]),
231+ ])
232+ ->visible (fn (Forms \Get $ get ): bool => $ get ('config.optionType ' ) == 'relationship ' )
233+ ->columnSpanFull (),
234+ ]),
235+ ]);
236+ }
237+ }
0 commit comments