11<?php
22
3- /**
4- Note this is still experimental
5- **/
6-
7- namespace Phpsa \LaravelApiController \Http \Api \Contracts ;
3+ namespace App \Models \Contracts ;
84
5+ use Illuminate \Support \Collection ;
96use Illuminate \Support \Facades \DB ;
7+ use Phpsa \LaravelApiController \Events \Created ;
8+ use Phpsa \LaravelApiController \Events \Updated ;
109use Phpsa \LaravelApiController \Exceptions \ApiException ;
10+ use Illuminate \Database \Eloquent \ModelNotFoundException ;
1111
1212trait HasBatchActions
1313{
1414
15- public function handleBatchStoreAction ($ request , array $ extraParams )
15+ public function getBatchData (): Collection
16+ {
17+ return collect ($ this ->request ->get ('data ' , []));
18+ }
19+
20+ /**
21+ * @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
22+ * @param array $extraParams
23+ *
24+ * @return mixed
25+ */
26+ public function handleBatchStoreAction ($ request , array $ extraParams = [])
1627 {
1728 $ this ->validateRequestType ($ request );
1829 $ this ->addCustomParams ($ extraParams );
30+
1931 $ this ->authoriseUserAction ('create ' );
2032
2133 $ this ->validate ($ this ->request , $ this ->rulesForBatchCreate ());
@@ -25,45 +37,168 @@ public function handleBatchStoreAction($request, array $extraParams)
2537 $ this ->unguardIfNeeded ();
2638
2739 try {
28- $ records = collect ($ this ->request ->get ('data ' ), [])->map (function ($ item ) {
29- $ data = $ this ->qualifyStoreQuery ($ item );
30- $ insert = $ this ->addTableData ($ data );
31- $ diff = array_diff (array_keys ($ data ), array_keys ($ insert ));
32- $ item = self ::$ model ->create ($ insert );
40+ $ records = $ this ->processStoreQuery (collect ($ this ->getBatchData ()));
41+
42+ DB ::commit ();
43+
44+ return $ this ->handleBatchStoreResponse ($ records );
45+ } catch (\Exception $ exception ) {
46+ $ message = config ('app.debug ' ) ? $ exception ->getMessage () : 'Failed to create Records ' ;
3347
34- $ this ->storeRelated ($ item , $ diff , $ data );
48+ DB ::rollback ();
49+ throw new ApiException ($ message , (int ) $ exception ->getCode (), $ exception );
50+ }
51+ }
3552
36- return $ item ;
37- });
53+ protected function processStoreQuery (Collection $ items ): Collection
54+ {
55+ return $ items ->map (function ($ item ) {
56+ $ data = $ this ->qualifyStoreQuery ($ item );
57+ $ insert = $ this ->addTableData ($ data );
58+ $ diff = array_diff (array_keys ($ data ), array_keys ($ insert ));
59+ $ item = self ::$ model ->create ($ insert );
60+
61+ $ this ->storeRelated ($ item , $ diff , $ data );
62+
63+ event (new Created ($ item , $ this ->request ));
64+
65+ return $ item ;
66+ });
67+ }
68+
69+ /**
70+ * @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
71+ *
72+ * @return mixed
73+ */
74+ public function handleBatchUpdateAction ($ request , array $ extraParams = [])
75+ {
76+ $ this ->validateRequestType ($ request );
77+ $ this ->addCustomParams ($ extraParams );
78+
79+ $ this ->validate ($ this ->request , $ this ->rulesForBatchUpdate ());
80+
81+ DB ::beginTransaction ();
82+
83+ $ this ->unguardIfNeeded ();
84+
85+ try {
86+ $ records = $ this ->processUpdateQuery (collect ($ this ->getBatchData ()));
3887
3988 DB ::commit ();
4089
41- return $ this ->handleStoreResponse ($ records );
90+ return $ this ->handleBatchUpdateResponse ($ records );
4291 } catch (\Exception $ exception ) {
4392 $ message = config ('app.debug ' ) ? $ exception ->getMessage () : 'Failed to create Records ' ;
4493
4594 DB ::rollback ();
46- throw new ApiException ($ message , (int ) $ exception ->getCode (), $ exception );
95+ match (get_class ($ exception )) {
96+ ModelNotFoundException::class => throw $ exception ,
97+ default => throw new ApiException ($ message , (int ) $ exception ->getCode (), $ exception )
98+ };
4799 }
48100 }
49101
102+ protected function processUpdateQuery (Collection $ items ): Collection
103+ {
104+ return $ items ->map (function ($ item ) {
105+
106+ $ key = self ::$ model ->getKeyName ();
107+
108+ $ id = $ item [$ key ];
109+ $ existing = $ this ->builder ->where ($ key , $ id )->firstOrFail ();
110+ $ this ->authoriseUserAction ('update ' , $ existing );
111+
112+ $ data = $ this ->qualifyUpdateQuery ($ item );
50113
51- protected function handleBatchStoreResponse ($ items )
114+ $ updates = $ this ->addTableData ($ data );
115+
116+ $ diff = array_diff (array_keys ($ data ), array_keys ($ updates ));
117+
118+ $ existing ->fill ($ updates );
119+ $ existing ->save ();
120+
121+ $ this ->storeRelated ($ existing , $ diff , $ data );
122+
123+ event (new Updated ($ existing , $ this ->request ));
124+
125+ return $ existing ;
126+ });
127+ }
128+
129+
130+ /**
131+ * @param \Illuminate\Http\Request|\Illuminate\Foundation\Http\FormRequest $request
132+ *
133+ * @return mixed
134+ */
135+ public function handleBatchStoreOrUpdateAction ($ request , array $ extraParams = [])
136+ {
137+ $ this ->validateRequestType ($ request );
138+ $ this ->addCustomParams ($ extraParams );
139+
140+ $ key = self ::$ model ->getKeyName ();
141+ $ records = $ this ->getBatchData ();
142+
143+ DB ::beginTransaction ();
144+
145+ $ this ->unguardIfNeeded ();
146+
147+ try {
148+ $ existing = $ this ->processUpdateQuery ($ records ->filter (function ($ record ) use ($ key ) {
149+ return ! isset ($ record [$ key ]) || empty ($ record [$ key ]);
150+ }));
151+
152+ $ new = $ this ->processStoreQuery ($ records ->filter (function ($ record ) use ($ key ) {
153+ return isset ($ record [$ key ]) && ! empty ($ record [$ key ]);
154+ }));
155+
156+ DB ::commit ();
157+
158+ return $ this ->handleBatchStoreOrUpdateResponse ($ existing ->merge ($ new ));
159+ } catch (\Exception $ exception ) {
160+ $ message = config ('app.debug ' ) ? $ exception ->getMessage () : 'Failed to create Records ' ;
161+
162+ DB ::rollback ();
163+ match (get_class ($ exception )) {
164+ ModelNotFoundException::class => throw $ exception ,
165+ default => throw new ApiException ($ message , (int ) $ exception ->getCode (), $ exception )
166+ };
167+ }
168+ }
169+
170+
171+
172+ /**
173+ * @return mixed Response|jsonResponse
174+ */
175+ protected function handleBatchStoreResponse (Collection $ items )
52176 {
53177 return $ this ->respondWithResource ($ this ->/** @scrutinizer ignore-call */ getResourceCollection (), $ items , 201 );
54178 }
55179
56- protected function handleBatchUpdateResponse ($ items )
180+ /**
181+ * @return mixed Response|jsonResponse
182+ */
183+ protected function handleBatchUpdateResponse (Collection $ items )
57184 {
58185 return $ this ->respondWithResource ($ this ->/** @scrutinizer ignore-call */ getResourceCollection (), $ items , 200 );
59186 }
60187
61- protected function rulesForBatchCreate () : array
188+ /**
189+ * @return mixed Response|jsonResponse
190+ */
191+ protected function handleBatchStoreOrUpdateResponse (Collection $ items )
192+ {
193+ return $ this ->respondWithResource ($ this ->getResourceCollection (), $ items , 200 );
194+ }
195+
196+ protected function rulesForBatchCreate (): array
62197 {
63198 return [];
64199 }
65200
66- protected function rulesForBatchUpdate () : array
201+ protected function rulesForBatchUpdate (): array
67202 {
68203 return [];
69204 }
0 commit comments