1
1
<?php
2
2
3
- /**
4
- Note this is still experimental
5
- **/
6
-
7
- namespace Phpsa \LaravelApiController \Http \Api \Contracts ;
3
+ namespace App \Models \Contracts ;
8
4
5
+ use Illuminate \Support \Collection ;
9
6
use Illuminate \Support \Facades \DB ;
7
+ use Phpsa \LaravelApiController \Events \Created ;
8
+ use Phpsa \LaravelApiController \Events \Updated ;
10
9
use Phpsa \LaravelApiController \Exceptions \ApiException ;
10
+ use Illuminate \Database \Eloquent \ModelNotFoundException ;
11
11
12
12
trait HasBatchActions
13
13
{
14
14
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 = [])
16
27
{
17
28
$ this ->validateRequestType ($ request );
18
29
$ this ->addCustomParams ($ extraParams );
30
+
19
31
$ this ->authoriseUserAction ('create ' );
20
32
21
33
$ this ->validate ($ this ->request , $ this ->rulesForBatchCreate ());
@@ -25,45 +37,168 @@ public function handleBatchStoreAction($request, array $extraParams)
25
37
$ this ->unguardIfNeeded ();
26
38
27
39
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 ' ;
33
47
34
- $ this ->storeRelated ($ item , $ diff , $ data );
48
+ DB ::rollback ();
49
+ throw new ApiException ($ message , (int ) $ exception ->getCode (), $ exception );
50
+ }
51
+ }
35
52
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 ()));
38
87
39
88
DB ::commit ();
40
89
41
- return $ this ->handleStoreResponse ($ records );
90
+ return $ this ->handleBatchUpdateResponse ($ records );
42
91
} catch (\Exception $ exception ) {
43
92
$ message = config ('app.debug ' ) ? $ exception ->getMessage () : 'Failed to create Records ' ;
44
93
45
94
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
+ };
47
99
}
48
100
}
49
101
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 );
50
113
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 )
52
176
{
53
177
return $ this ->respondWithResource ($ this ->/** @scrutinizer ignore-call */ getResourceCollection (), $ items , 201 );
54
178
}
55
179
56
- protected function handleBatchUpdateResponse ($ items )
180
+ /**
181
+ * @return mixed Response|jsonResponse
182
+ */
183
+ protected function handleBatchUpdateResponse (Collection $ items )
57
184
{
58
185
return $ this ->respondWithResource ($ this ->/** @scrutinizer ignore-call */ getResourceCollection (), $ items , 200 );
59
186
}
60
187
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
62
197
{
63
198
return [];
64
199
}
65
200
66
- protected function rulesForBatchUpdate () : array
201
+ protected function rulesForBatchUpdate (): array
67
202
{
68
203
return [];
69
204
}
0 commit comments