5
5
use App \Nova \Resource ;
6
6
use Illuminate \Database \Eloquent \Model ;
7
7
use Illuminate \Support \Arr ;
8
+ use Illuminate \Support \Collection ;
8
9
use Illuminate \Support \Str ;
10
+ use Laravel \Nova \Fields \BelongsToMany ;
9
11
use Laravel \Nova \Fields \Field ;
10
- use Laravel \Nova \Fields \ID ;
11
- use Laravel \Nova \Fields \MorphOne ;
12
+ use Laravel \Nova \Fields \HasMany ;
13
+ use Laravel \Nova \Fields \HasOne ;
14
+ use Laravel \Nova \Http \Controllers \ResourceIndexController ;
15
+ use Laravel \Nova \Http \Controllers \ResourceShowController ;
16
+ use Laravel \Nova \Http \Controllers \UpdateFieldController ;
12
17
use Laravel \Nova \Http \Requests \NovaRequest ;
13
18
use Laravel \Nova \Nova ;
14
19
use ReflectionClass ;
@@ -61,15 +66,16 @@ public function types(array $types): self
61
66
62
67
$ types = collect ($ types )->map (function (string $ resource , $ key ) use ($ useKeysAsLabel ) {
63
68
64
- $ fields = (new $ resource ($ resource ::newModel ()))->fields (app (NovaRequest::class));
69
+ /**
70
+ * @var Resource $resourceInstance
71
+ */
72
+ $ resourceInstance = new $ resource ($ resource ::newModel ());
65
73
66
74
return [
67
75
'className ' => $ resource ,
68
76
'uriKey ' => $ resource ::uriKey (),
69
77
'label ' => $ useKeysAsLabel ? $ key : $ this ->convertToHumanCase ($ resource ),
70
- 'fields ' => collect ($ fields )->reject (function ($ field ) {
71
- return $ field instanceof ID ;
72
- })->toArray ()
78
+ 'fields ' => $ this ->resolveFields ($ resourceInstance )
73
79
];
74
80
75
81
});
@@ -80,6 +86,37 @@ public function types(array $types): self
80
86
81
87
}
82
88
89
+ private function resolveFields (Resource $ resourceInstance ): Collection
90
+ {
91
+
92
+ /**
93
+ * @var NovaRequest $request
94
+ */
95
+ $ request = app (NovaRequest::class);
96
+ $ controller = $ request ->route ()->controller ;
97
+
98
+ if ($ controller instanceof UpdateFieldController) {
99
+
100
+ return $ resourceInstance ->updateFields ($ request );
101
+
102
+ }
103
+
104
+ if ($ controller instanceof ResourceShowController) {
105
+
106
+ return $ resourceInstance ->detailFields ($ request );
107
+
108
+ }
109
+
110
+ if ($ controller instanceof ResourceIndexController) {
111
+
112
+ return $ resourceInstance ->indexFields ($ request );
113
+
114
+ }
115
+
116
+ return $ resourceInstance ->availableFields ($ request );
117
+
118
+ }
119
+
83
120
private function convertToHumanCase (string $ resource ): string
84
121
{
85
122
return Str::title (str_replace ('_ ' , ' ' , Str::snake ((new ReflectionClass ($ resource ))->getShortName ())));
@@ -107,7 +144,9 @@ protected function resolveAttribute($resource, $attribute)
107
144
108
145
foreach ($ fields as $ field ) {
109
146
110
- if ($ field instanceof MorphOne) {
147
+ if ($ field instanceof HasOne ||
148
+ $ field instanceof HasMany ||
149
+ $ field instanceof BelongsToMany) {
111
150
112
151
$ field ->meta [ 'inlineMorphTo ' ] = [
113
152
'viaResourceId ' => $ relationInstance ->id ,
@@ -164,11 +203,41 @@ public function fill(NovaRequest $request, $model)
164
203
165
204
}
166
205
167
- private function getFields (Model $ model ): array
206
+ private function getFields (Model $ model ): Collection
168
207
{
169
208
$ resourceClass = Nova::resourceForModel ($ model );
170
209
171
210
return $ this ->meta [ 'resources ' ]->where ('className ' , $ resourceClass )->first ()[ 'fields ' ];
172
211
}
173
212
213
+ public function jsonSerialize ()
214
+ {
215
+
216
+ /**
217
+ * @var NovaRequest $request
218
+ */
219
+ $ request = app (NovaRequest::class);
220
+ $ originalResource = $ request ->route ()->resource ;
221
+
222
+ /**
223
+ * Temporarily remap the route resource key so every sub field thinks it's being resolved by it's original parent
224
+ */
225
+ foreach ($ this ->meta [ 'resources ' ] as $ resource ) {
226
+
227
+ $ resource [ 'fields ' ] = $ resource [ 'fields ' ]->transform (function (&$ field ) use ($ request , $ resource ) {
228
+
229
+ $ request ->route ()->setParameter ('resource ' , $ resource [ 'uriKey ' ]);
230
+
231
+ return $ field ->jsonSerialize ();
232
+
233
+ });
234
+
235
+ }
236
+
237
+ $ request ->route ()->setParameter ('resource ' , $ originalResource );
238
+
239
+ return parent ::jsonSerialize ();
240
+
241
+ }
242
+
174
243
}
0 commit comments