22
33namespace atk4 \api ;
44
5+ use atk4 \data \Field ;
56use atk4 \data \Model ;
67use Laminas \Diactoros \Request ;
78use Laminas \Diactoros \Response \JsonResponse ;
@@ -41,6 +42,12 @@ class Api
4142 /** @var int Response options */
4243 protected $ response_options = JSON_PRETTY_PRINT | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT ;
4344
45+ /**
46+ * @var bool If set to true, the first array element of Model->export
47+ * will be returned (GET single record)
48+ * If not, the array will be returned as-is
49+ */
50+ public $ single_record = true ;
4451
4552 /**
4653 * Reads everything off globals.
@@ -149,14 +156,45 @@ public function exec($callable, $vars = [])
149156 // if callable function returns agile data model, then export it
150157 // this is important for REST API implementation
151158 if ($ ret instanceof Model) {
152- $ ret = $ this ->exportModel ($ ret );
159+
160+ $ data = [];
161+
162+ $ allowed_fields = $ this ->getAllowedFields ($ ret , 'read ' );
163+ if ($ this ->single_record ) {
164+ /** @var Field $field */
165+ foreach ($ ret ->getFields () as $ fieldName => $ field ) {
166+ if (!in_array ($ fieldName , $ allowed_fields )) {
167+ continue ;
168+ }
169+ $ data [$ field ->actual ?? $ fieldName ] = $ field ->toString ();
170+ }
171+ } else {
172+ foreach ($ ret as $ m ) {
173+ /** @var Model $m */
174+ $ record = [];
175+ /** @var Field $field */
176+ foreach ($ ret ->getFields () as $ fieldName => $ field ) {
177+ if (!in_array ($ fieldName , $ allowed_fields )) {
178+ continue ;
179+ }
180+ $ record [$ field ->actual ?? $ fieldName ] = $ field ->toString ();
181+ }
182+ $ data [] = $ record ;
183+ }
184+ }
185+
186+ $ ret = $ data ;
153187 }
154188
155189 // no response, just step out
156190 if ($ ret === null ) {
157191 return ;
158192 }
159193
194+ if ($ ret === true ) { // manage delete
195+ $ ret = [];
196+ }
197+
160198 // emit successful response
161199 $ this ->successResponse ($ ret );
162200 }
@@ -194,7 +232,7 @@ protected function call($callable, $vars = [])
194232 */
195233 protected function exportModel (Model $ m )
196234 {
197- return $ m ->export ($ this ->getAllowedFields ($ m , 'read ' ), null , false );
235+ return $ m ->export ($ this ->getAllowedFields ($ m , 'read ' ), null , true );
198236 }
199237
200238 /**
@@ -242,7 +280,7 @@ protected function loadModelByValue(Model $m, $value)
242280 protected function getAllowedFields (Model $ m , $ action = 'read ' )
243281 {
244282 // take model only_fields into account
245- $ fields = is_array ($ m ->only_fields ) ? $ m ->only_fields : [] ;
283+ $ fields = is_array ($ m ->only_fields ) && ! empty ( $ m -> only_fields ) ? $ m ->only_fields : array_keys ( $ m -> getFields ()) ;
246284
247285 // limit by apiFields
248286 if (isset ($ m ->apiFields , $ m ->apiFields [$ action ])) {
@@ -297,7 +335,7 @@ protected function successResponse($response)
297335 // for testing purposes there can be situations when emitter is disabled. then do nothing.
298336 if ($ this ->emitter ) {
299337 $ this ->emitter ->emit ($ this ->response );
300- exit ;
338+ exit ; // @todo find a solution to remove this exit.
301339 }
302340
303341 // @todo Should we also stop script execution if no emitter is defined or just ignore that?
@@ -395,6 +433,7 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del
395433 // GET all records
396434 if (in_array ('read ' , $ methods )) {
397435 $ f = function (...$ params ) use ($ model ) {
436+ $ this ->single_record = false ;
398437 if (is_callable ($ model )) {
399438 $ model = $ this ->call ($ model , $ params );
400439 }
@@ -413,24 +452,11 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del
413452 $ model = $ this ->call ($ model , $ params );
414453 }
415454
416- $ this ->loadModelByValue ($ model , $ id );
417-
418- //calculate only once
419- $ allowed_fields = $ this ->getAllowedFields ($ model , 'read ' );
420- $ data = [];
421- // get all field-elements
422- foreach ($ model ->elements as $ field => $ f ) {
423- //only use allowed fields
424- if (!in_array ($ field , $ allowed_fields )) {
425- continue ;
426- }
427-
428- if ($ f instanceof \atk4 \data \Field) {
429- $ data [$ field ] = $ f ->toString ();
430- }
431- }
455+ // limit fields
456+ $ model ->onlyFields ($ this ->getAllowedFields ($ model , 'read ' ));
432457
433- return $ data ;
458+ // load model and get field values
459+ return $ this ->loadModelByValue ($ model , $ id );
434460 };
435461
436462 $ this ->get ($ pattern .'/:id ' , $ f );
@@ -452,7 +478,7 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del
452478 $ this ->loadModelByValue ($ model , $ id )->save ($ this ->request_data );
453479 $ model ->onlyFields ($ this ->getAllowedFields ($ model , 'read ' ));
454480
455- return $ model-> get () ;
481+ return $ model ;
456482 };
457483 $ this ->patch ($ pattern .'/:id ' , $ f );
458484 $ this ->post ($ pattern .'/:id ' , $ f );
@@ -472,7 +498,8 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del
472498 $ model ->onlyFields ($ this ->getAllowedFields ($ model , 'read ' ));
473499
474500 $ this ->response_code = 201 ; // http code for created
475- return $ model ->get ();
501+
502+ return $ model ;
476503 };
477504 $ this ->post ($ pattern , $ f );
478505 }
0 commit comments