44
55use Closure ;
66use RuntimeException ;
7- use Tobyz \JsonApiServer \Endpoint \ProvidesResourceLinks ;
87use Tobyz \JsonApiServer \Schema \Field \Field ;
98use Tobyz \JsonApiServer \Schema \Field \Relationship ;
109
@@ -48,90 +47,11 @@ private function addToMap(Context $context): array
4847
4948 $ key = $ this ->key ($ type = $ resource ->type (), $ id = $ context ->id ($ resource , $ model ));
5049
51- if (!isset ($ this ->map [$ key ])) {
52- $ this ->map [$ key ] = [
53- 'type ' => $ type ,
54- 'id ' => $ id ,
55- ];
56-
57- static $ linkFieldsCache = [];
58-
59- if (!isset ($ linkFieldsCache [$ type ])) {
60- foreach ($ context ->api ->getResourceCollections ($ type ) as $ collection ) {
61- $ collectionContext = $ context ->withCollection ($ collection );
62-
63- foreach ($ context ->endpoints ($ collection ) as $ endpoint ) {
64- if ($ endpoint instanceof ProvidesResourceLinks) {
65- foreach ($ endpoint ->resourceLinks ($ collectionContext ) as $ field ) {
66- $ linkFieldsCache [$ type ][$ field ->name ] ??= [$ field , $ collection ];
67- }
68- }
69- }
70- }
71- }
72-
73- foreach ($ linkFieldsCache [$ type ] ?? [] as [$ field , $ collection ]) {
74- $ linkContext = $ context ->withCollection ($ collection )->withField ($ field );
75-
76- if (!$ field ->isVisible ($ linkContext )) {
77- continue ;
78- }
79-
80- $ value = $ field ->getValue ($ linkContext );
81-
82- $ this ->resolveLinkValue ($ key , $ field , $ linkContext , $ value );
83- }
84- }
85-
86- foreach ($ context ->sparseFields ($ resource ) as $ field ) {
87- if (in_array ($ field , $ this ->processedFields [$ key ] ?? [])) {
88- continue ;
89- }
90-
91- $ this ->processedFields [$ key ][] = $ field ;
92-
93- $ fieldContext = $ context
94- ->withField ($ field )
95- ->withInclude ($ context ->include [$ field ->name ] ?? null );
96-
97- if (!$ field ->isVisible ($ fieldContext )) {
98- continue ;
99- }
100-
101- $ value = $ field ->getValue ($ fieldContext );
102-
103- $ this ->resolveFieldValue ($ key , $ field , $ fieldContext , $ value );
104- }
105-
106- foreach ($ context ->meta ($ resource ) as $ field ) {
107- if (
108- array_key_exists ($ field ->name , $ this ->map [$ key ]['meta ' ] ?? []) ||
109- !$ field ->isVisible ($ metaContext = $ context ->withField ($ field ))
110- ) {
111- continue ;
112- }
113-
114- $ value = $ field ->getValue ($ metaContext );
115-
116- $ this ->resolveMetaValue ($ key , $ field , $ metaContext , $ value );
117- }
118-
119- foreach ($ context ->resourceMeta [$ model ] ?? [] as $ k => $ v ) {
120- $ this ->map [$ key ]['meta ' ][$ k ] = $ v ;
121- }
122-
123- foreach ($ context ->links ($ resource ) as $ link ) {
124- if (
125- array_key_exists ($ link ->name , $ this ->map [$ key ]['links ' ] ?? []) ||
126- !$ link ->isVisible ($ linkContext = $ context ->withField ($ link ))
127- ) {
128- continue ;
129- }
130-
131- $ value = $ link ->getValue ($ linkContext );
132-
133- $ this ->resolveLinkValue ($ key , $ link , $ linkContext , $ value );
134- }
50+ $ this ->initializeResource ($ key , $ type , $ id , $ context );
51+ $ this ->serializeFields ($ key , $ context );
52+ $ this ->serializeMeta ($ key , $ context );
53+ $ this ->mergeResourceMeta ($ key , $ context );
54+ $ this ->serializeLinks ($ key , $ context );
13555
13656 return $ this ->map [$ key ];
13757 }
@@ -147,14 +67,7 @@ private function resolveFieldValue(
14767 Context $ context ,
14868 mixed $ value ,
14969 ): void {
150- if ($ value instanceof Closure) {
151- $ this ->deferred [] = fn () => $ this ->resolveFieldValue ($ key , $ field , $ context , $ value ());
152- } elseif (
153- ($ value = $ field ->serializeValue ($ value , $ context )) ||
154- !$ field instanceof Relationship
155- ) {
156- set_value ($ this ->map [$ key ], $ field , $ value );
157- }
70+ $ this ->resolveValue ($ value , fn ($ value ) => $ this ->writeFieldValue ($ key , $ field , $ context , $ value ));
15871 }
15972
16073 private function resolveMetaValue (
@@ -163,11 +76,10 @@ private function resolveMetaValue(
16376 Context $ context ,
16477 mixed $ value ,
16578 ): void {
166- if ($ value instanceof Closure) {
167- $ this ->deferred [] = fn () => $ this ->resolveMetaValue ($ key , $ field , $ context , $ value ());
168- } else {
169- $ this ->map [$ key ]['meta ' ][$ field ->name ] = $ field ->serializeValue ($ value , $ context );
170- }
79+ $ this ->resolveValue (
80+ $ value ,
81+ fn ($ value ) => $ this ->map [$ key ]['meta ' ][$ field ->name ] = $ field ->serializeValue ($ value , $ context ),
82+ );
17183 }
17284
17385 private function resolveLinkValue (
@@ -176,11 +88,10 @@ private function resolveLinkValue(
17688 Context $ context ,
17789 mixed $ value ,
17890 ): void {
179- if ($ value instanceof Closure) {
180- $ this ->deferred [] = fn () => $ this ->resolveLinkValue ($ key , $ field , $ context , $ value ());
181- } else {
182- $ this ->map [$ key ]['links ' ][$ field ->name ] = $ field ->serializeValue ($ value , $ context );
183- }
91+ $ this ->resolveValue (
92+ $ value ,
93+ fn ($ value ) => $ this ->map [$ key ]['links ' ][$ field ->name ] = $ field ->serializeValue ($ value , $ context ),
94+ );
18495 }
18596
18697 /**
@@ -207,6 +118,102 @@ public function addIncluded(Context $context): array
207118 ];
208119 }
209120
121+ private function initializeResource (
122+ string $ key ,
123+ string $ type ,
124+ string $ id ,
125+ Context $ context ,
126+ ): void {
127+ if (isset ($ this ->map [$ key ])) {
128+ return ;
129+ }
130+
131+ $ this ->map [$ key ] = [
132+ 'type ' => $ type ,
133+ 'id ' => $ id ,
134+ ];
135+
136+ foreach ($ context ->resourceLinkDefinitions () as [$ field , $ collection ]) {
137+ $ linkContext = $ context ->withCollection ($ collection )->withField ($ field );
138+
139+ if (!$ field ->isVisible ($ linkContext )) {
140+ continue ;
141+ }
142+
143+ $ this ->resolveLinkValue ($ key , $ field , $ linkContext , $ field ->getValue ($ linkContext ));
144+ }
145+ }
146+
147+ private function serializeFields (string $ key , Context $ context ): void
148+ {
149+ foreach ($ context ->sparseFields ($ context ->resource ) as $ field ) {
150+ if ($ this ->fieldProcessed ($ key , $ field )) {
151+ continue ;
152+ }
153+
154+ $ fieldContext = $ context
155+ ->withField ($ field )
156+ ->withInclude ($ context ->include [$ field ->name ] ?? null );
157+
158+ if (!$ field ->isVisible ($ fieldContext )) {
159+ continue ;
160+ }
161+
162+ $ this ->resolveFieldValue ($ key , $ field , $ fieldContext , $ field ->getValue ($ fieldContext ));
163+ }
164+ }
165+
166+ private function serializeMeta (string $ key , Context $ context ): void
167+ {
168+ foreach ($ context ->meta ($ context ->resource ) as $ field ) {
169+ if (array_key_exists ($ field ->name , $ this ->map [$ key ]['meta ' ] ?? [])) {
170+ continue ;
171+ }
172+
173+ $ metaContext = $ context ->withField ($ field );
174+
175+ if (!$ field ->isVisible ($ metaContext )) {
176+ continue ;
177+ }
178+
179+ $ this ->resolveMetaValue ($ key , $ field , $ metaContext , $ field ->getValue ($ metaContext ));
180+ }
181+ }
182+
183+ private function mergeResourceMeta (string $ key , Context $ context ): void
184+ {
185+ foreach ($ context ->resourceMeta [$ context ->model ] ?? [] as $ name => $ value ) {
186+ $ this ->map [$ key ]['meta ' ][$ name ] = $ value ;
187+ }
188+ }
189+
190+ private function serializeLinks (string $ key , Context $ context ): void
191+ {
192+ foreach ($ context ->links ($ context ->resource ) as $ field ) {
193+ if (array_key_exists ($ field ->name , $ this ->map [$ key ]['links ' ] ?? [])) {
194+ continue ;
195+ }
196+
197+ $ linkContext = $ context ->withField ($ field );
198+
199+ if (!$ field ->isVisible ($ linkContext )) {
200+ continue ;
201+ }
202+
203+ $ this ->resolveLinkValue ($ key , $ field , $ linkContext , $ field ->getValue ($ linkContext ));
204+ }
205+ }
206+
207+ private function fieldProcessed (string $ key , Field $ field ): bool
208+ {
209+ if (in_array ($ field , $ this ->processedFields [$ key ] ?? [])) {
210+ return true ;
211+ }
212+
213+ $ this ->processedFields [$ key ][] = $ field ;
214+
215+ return false ;
216+ }
210217 private function resolveDeferred (): void
211218 {
212219 $ i = 0 ;
@@ -221,4 +228,25 @@ private function resolveDeferred(): void
221228 }
222229 }
223230 }
231+
232+ private function resolveValue (mixed $ value , callable $ resolve ): void
233+ {
234+ if ($ value instanceof Closure) {
235+ $ this ->deferred [] = fn () => $ resolve ($ value ());
236+ return ;
237+ }
238+
239+ $ resolve ($ value );
240+ }
241+
242+ private function writeFieldValue (
243+ string $ key ,
244+ Field $ field ,
245+ Context $ context ,
246+ mixed $ value ,
247+ ): void {
248+ if (($ value = $ field ->serializeValue ($ value , $ context )) || !$ field instanceof Relationship) {
249+ set_value ($ this ->map [$ key ], $ field , $ value );
250+ }
251+ }
224252}
0 commit comments