From 2d85f3eb3670283ee80ff8dff0d161f1822a2ec8 Mon Sep 17 00:00:00 2001 From: PhilippGrashoff <33204878+PhilippGrashoff@users.noreply.github.com> Date: Tue, 21 May 2019 00:07:57 +0200 Subject: [PATCH 1/8] Fix data#403 This is supposed as proposal to fix https://github.com/atk4/data/issues/403 going with the solution @DarkSide666 proposed. This change routs all GET requests (single record and multiple record as well) through exportModel() function, with uses Model->export() while typecasting set to false. This way, date, time and datetime fields are not cast into PHP \DateTime objects, but the values are returned as stored in Persistence. The solution posted here works for the mentioned date/time fields, however I see some problems: 1) what about fields that should get casting? In the end, API should return usable values. E.g about type money? API should return them as formatted to display 2 digits after the dot, shouldnt it? Is this still done? 2) getting a single record should throw an Exception when the requested record is not found. For that, it has to be loaded(). export() in exportModel() loads again, causing an unneccessary DB request. --- src/Api.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Api.php b/src/Api.php index e917eb5..6a8a6ea 100644 --- a/src/Api.php +++ b/src/Api.php @@ -22,6 +22,14 @@ class Api /** @var string Request path */ public $path; + /** + * @var bool If set to true, the first array element of Model->export + * will be returned (GET single record) + * If not, the array will be returned as-is + */ + public $singleRecord = false; + + /** * Reads everything off globals. * @@ -178,7 +186,13 @@ protected function call($callable, $vars = []) */ protected function exportModel(\atk4\data\Model $m) { - return $m->export($this->getAllowedFields($m, 'read')); + //on single record request, return first array element if available or null + if($this->singleRecord) { + $records = $m->export($this->getAllowedFields($m, 'read'), null, false); + return $records ? reset($records) : null; + } + //else return array + return $m->export($this->getAllowedFields($m, 'read'), null, false); } /** @@ -407,9 +421,12 @@ public function rest($pattern, $model = null, $methods = null) // limit fields $model->onlyFields($this->getAllowedFields($model, 'read')); + $model->addCondition($model->id_field, $id); + $this->loadModelByValue($model, $id); + $this->singleRecord = true; // load model and get field values - return $this->loadModelByValue($model, $id)->get(); + return $model; }; $this->get($pattern.'/:id', $f); } From f97a75025fea96081da50f705b6693acbd500134 Mon Sep 17 00:00:00 2001 From: PhilippGrashoff <33204878+PhilippGrashoff@users.noreply.github.com> Date: Tue, 21 May 2019 00:26:42 +0200 Subject: [PATCH 2/8] Improve by using Field->toString() on singleRecord --- src/Api.php | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/Api.php b/src/Api.php index 6a8a6ea..f961e2f 100644 --- a/src/Api.php +++ b/src/Api.php @@ -22,13 +22,6 @@ class Api /** @var string Request path */ public $path; - /** - * @var bool If set to true, the first array element of Model->export - * will be returned (GET single record) - * If not, the array will be returned as-is - */ - public $singleRecord = false; - /** * Reads everything off globals. @@ -186,12 +179,6 @@ protected function call($callable, $vars = []) */ protected function exportModel(\atk4\data\Model $m) { - //on single record request, return first array element if available or null - if($this->singleRecord) { - $records = $m->export($this->getAllowedFields($m, 'read'), null, false); - return $records ? reset($records) : null; - } - //else return array return $m->export($this->getAllowedFields($m, 'read'), null, false); } @@ -419,15 +406,26 @@ public function rest($pattern, $model = null, $methods = null) $model = $this->call($model, $args); } - // limit fields - $model->onlyFields($this->getAllowedFields($model, 'read')); - $model->addCondition($model->id_field, $id); $this->loadModelByValue($model, $id); - $this->singleRecord = true; - // load model and get field values - return $model; + //calculate only once + $allowed_fields = $this->getAllowedFields($model, 'read'); + $data = []; + // get all field-elements + foreach ($model->elements as $field => $f) { + //only use allowed fields + if(!in_array($field, $allowed_fields)) { + continue; + } + + if ($f instanceof \atk4\data\Field) { + $data[$field] = $f->toString(); + } + } + + return $data; }; + $this->get($pattern.'/:id', $f); } From fc9d8f9e68c0d37cdea9fb4ef674cd7680d470bb Mon Sep 17 00:00:00 2001 From: abbadon1334 Date: Mon, 6 Apr 2020 20:26:01 +0200 Subject: [PATCH 3/8] drop 7.2 from travis --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 100c353..3644f11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - '7.2' - '7.3' cache: @@ -18,11 +17,11 @@ before_script: after_script: - echo $TRAVIS_BRANCH - - if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.2" ]]; then echo "Sending coverage report"; vendor/bin/test-reporter --coverage-report build/logs/clover.xml; fi - - if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.2" ]]; then echo "Sending codecov report"; TRAVIS_CMD="" bash <(curl -s https://codecov.io/bash) -f build/logs/clover.xml; fi + - if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.3" ]]; then echo "Sending coverage report"; vendor/bin/test-reporter --coverage-report build/logs/clover.xml; fi + - if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.3" ]]; then echo "Sending codecov report"; TRAVIS_CMD="" bash <(curl -s https://codecov.io/bash) -f build/logs/clover.xml; fi script: - - if [[ ${TRAVIS_PHP_VERSION:0:3} != "7.2" ]]; then NC="--no-coverage"; fi + - if [[ ${TRAVIS_PHP_VERSION:0:3} != "7.3" ]]; then NC="--no-coverage"; fi - ./vendor/phpunit/phpunit/phpunit $NC notifications: From ce932c1a745b89f6e378d1f5778e0fe3ead17f6f Mon Sep 17 00:00:00 2001 From: abbadon1334 Date: Wed, 8 Apr 2020 15:16:45 +0200 Subject: [PATCH 4/8] Normalize DateTime/Date/Time and add tests for it as in PR #18 --- src/Api.php | 73 +++++++++---- tests/ApiTesterRestTest.php | 206 ++++++++++++++++++++++++++++-------- 2 files changed, 210 insertions(+), 69 deletions(-) diff --git a/src/Api.php b/src/Api.php index d862893..ab11dc1 100644 --- a/src/Api.php +++ b/src/Api.php @@ -2,6 +2,7 @@ namespace atk4\api; +use atk4\data\Field; use atk4\data\Model; use Laminas\Diactoros\Request; use Laminas\Diactoros\Response\JsonResponse; @@ -41,6 +42,12 @@ class Api /** @var int Response options */ protected $response_options = JSON_PRETTY_PRINT | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT; + /** + * @var bool If set to true, the first array element of Model->export + * will be returned (GET single record) + * If not, the array will be returned as-is + */ + public $single_record = true; /** * Reads everything off globals. @@ -149,7 +156,34 @@ public function exec($callable, $vars = []) // if callable function returns agile data model, then export it // this is important for REST API implementation if ($ret instanceof Model) { - $ret = $this->exportModel($ret); + + $data = []; + + $allowed_fields = $this->getAllowedFields($ret, 'read'); + if ($this->single_record) { + /** @var Field $field */ + foreach($ret->getFields() as $fieldName => $field) { + if(!in_array($fieldName, $allowed_fields)) { + continue; + } + $data[$field->actual ?? $fieldName] = $field->toString(); + } + } else { + foreach ($ret as $m) { + /** @var Model $m */ + $record = []; + /** @var Field $field */ + foreach ($ret->getFields() as $fieldName => $field) { + if(!in_array($fieldName, $allowed_fields)) { + continue; + } + $record[$field->actual ?? $fieldName] = $field->toString(); + } + $data[] = $record; + } + } + + $ret = $data; } // no response, just step out @@ -157,6 +191,10 @@ public function exec($callable, $vars = []) return; } + if ($ret === true) { // manage delete + $ret = []; + } + // emit successful response $this->successResponse($ret); } @@ -194,7 +232,7 @@ protected function call($callable, $vars = []) */ protected function exportModel(Model $m) { - return $m->export($this->getAllowedFields($m, 'read'), null, false); + return $m->export($this->getAllowedFields($m, 'read'), null, true); } /** @@ -242,7 +280,7 @@ protected function loadModelByValue(Model $m, $value) protected function getAllowedFields(Model $m, $action = 'read') { // take model only_fields into account - $fields = is_array($m->only_fields) ? $m->only_fields : []; + $fields = is_array($m->only_fields) && !empty($m->only_fields) ? $m->only_fields : array_keys($m->getFields()); // limit by apiFields if (isset($m->apiFields, $m->apiFields[$action])) { @@ -297,7 +335,7 @@ protected function successResponse($response) // for testing purposes there can be situations when emitter is disabled. then do nothing. if ($this->emitter) { $this->emitter->emit($this->response); - exit; + exit; // @todo find a solution to remove this exit. } // @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 // GET all records if (in_array('read', $methods)) { $f = function (...$params) use ($model) { + $this->single_record = false; if (is_callable($model)) { $model = $this->call($model, $params); } @@ -413,24 +452,11 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del $model = $this->call($model, $params); } - $this->loadModelByValue($model, $id); - - //calculate only once - $allowed_fields = $this->getAllowedFields($model, 'read'); - $data = []; - // get all field-elements - foreach ($model->elements as $field => $f) { - //only use allowed fields - if(!in_array($field, $allowed_fields)) { - continue; - } - - if ($f instanceof \atk4\data\Field) { - $data[$field] = $f->toString(); - } - } + // limit fields + $model->onlyFields($this->getAllowedFields($model, 'read')); - return $data; + // load model and get field values + return $this->loadModelByValue($model, $id); }; $this->get($pattern.'/:id', $f); @@ -452,7 +478,7 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del $this->loadModelByValue($model, $id)->save($this->request_data); $model->onlyFields($this->getAllowedFields($model, 'read')); - return $model->get(); + return $model; }; $this->patch($pattern.'/:id', $f); $this->post($pattern.'/:id', $f); @@ -472,7 +498,8 @@ public function rest($pattern, $model = null, $methods = ['read', 'modify', 'del $model->onlyFields($this->getAllowedFields($model, 'read')); $this->response_code = 201; // http code for created - return $model->get(); + + return $model; }; $this->post($pattern, $f); } diff --git a/tests/ApiTesterRestTest.php b/tests/ApiTesterRestTest.php index b86bd55..ea73a74 100644 --- a/tests/ApiTesterRestTest.php +++ b/tests/ApiTesterRestTest.php @@ -12,32 +12,37 @@ class ApiTesterRestTest extends \atk4\core\PHPUnit_AgileTestCase /** @var Persistence\SQL */ protected $db; - /** @var Country */ - protected $model; - /** @var Api */ - private $api; + protected $api; + + protected static $init = false; public static function tearDownAfterClass() { - unlink('./sqlite.db'); + unlink(__DIR__ . '/sqlite.db'); } public function setUp() { parent::setUp(); - touch('./sqlite.db'); - - $this->db = new Persistence\SQL('sqlite:./sqlite.db'); - $this->model = new Country($this->db); - Migration::of($this->model)->run(); + $filename = __DIR__ . '/sqlite.db'; + touch($filename); + + $this->db = new Persistence\SQL('sqlite:' . $filename); + if(!self::$init) { + self::$init = true; + Migration::of(new Country($this->db))->run(); + } } - public function processRequest(Request $request) + public function processRequest(Request $request, $model = null) { + + $model_default = new Country($this->db); + $this->api = new Api($request); $this->api->emitter = false; - $this->api->rest('/client', $this->model); + $this->api->rest('/client', $model ?? $model_default); return json_decode($this->api->response->getBody()->getContents(), true); } @@ -51,6 +56,9 @@ public function testCreate() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', + 'date' => null, + 'datetime' => null, + 'time' => null ]; $request = new Request( @@ -68,41 +76,61 @@ public function testCreate() $this->assertEquals([ 'id' => '1', 'name' => 'test', - 'sys_name' => 'test', + 'nicename' => 'test', 'iso' => 'IT', 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', + 'date' => null, + 'datetime' => null, + 'time' => null ], $response); } - public function testGETOne() + public function testCreate2() { + $data = [ + 'name' => 'test2', + 'sys_name' => 'test2', + 'iso' => 'DE', + 'iso3' => 'DEU', + 'numcode' => '999', + 'phonecode' => '43', + 'date' => null, + 'datetime' => null, + 'time' => null + ]; + $request = new Request( - 'http://localhost/client/1', - 'GET', + 'http://localhost/client', + 'POST', 'php://memory', [ 'Content-Type' => 'application/json', ] ); + $request->getBody()->write(json_encode($data)); $response = $this->processRequest($request); + $this->assertEquals(201, $this->api->response_code); $this->assertEquals([ - 'id' => '1', - 'name' => 'test', - 'sys_name' => 'test', - 'iso' => 'IT', - 'iso3' => 'ITA', - 'numcode' => '666', - 'phonecode' => '39', + 'id' => '2', + 'name' => 'test2', + 'nicename' => 'test2', + 'iso' => 'DE', + 'iso3' => 'DEU', + 'numcode' => '999', + 'phonecode' => '43', + 'date' => null, + 'datetime' => null, + 'time' => null ], $response); } - public function testGETOneByField() + public function testGETOne() { $request = new Request( - 'http://localhost/client/name:test', + 'http://localhost/client/1', 'GET', 'php://memory', [ @@ -114,11 +142,14 @@ public function testGETOneByField() $this->assertEquals([ 'id' => '1', 'name' => 'test', - 'sys_name' => 'test', + 'nicename' => 'test', 'iso' => 'IT', 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', + 'date' => null, + 'datetime' => null, + 'time' => null ], $response); } @@ -135,7 +166,7 @@ public function testGETAll() $response = $this->processRequest($request); $this->assertEquals([ - 0 => [ + [ 'id' => '1', 'name' => 'test', 'nicename' => 'test', @@ -143,7 +174,22 @@ public function testGETAll() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', + 'date' => null, + 'datetime' => null, + 'time' => null ], + [ + 'id' => '2', + 'name' => 'test2', + 'nicename' => 'test2', + 'iso' => 'DE', + 'iso3' => 'DEU', + 'numcode' => '999', + 'phonecode' => '43', + 'date' => null, + 'datetime' => null, + 'time' => null + ] ], $response); } @@ -159,7 +205,9 @@ public function testModify() ); $data = $this->processRequest($request); - $data['name'] = 'test modified'; + $data['sys_name'] = 'test modified'; + $data['name'] = $data['nicename']; + unset($data['nicename']); $request = $request->withMethod('POST'); $request->getBody()->write(json_encode($data)); @@ -168,11 +216,14 @@ public function testModify() $this->assertEquals([ 'id' => '1', 'name' => 'test modified', - 'sys_name' => 'test', + 'nicename' => 'test', 'iso' => 'IT', 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', + 'date' => null, + 'datetime' => null, + 'time' => null ], $response); } @@ -189,39 +240,97 @@ public function testDelete() ] ); - $this->processRequest($request); + $response = $this->processRequest($request); + $this->assertEquals([], $response); + } + + public function testSerialization() + { + $date = $datetime = new \Datetime(); + $date->setTime(6,6,6); // this is for you imanst ;) + + $data = [ + 'sys_name' => 'test_time', + 'name' => 'test', + 'iso' => 'IT', + 'iso3' => 'ITA', + 'numcode' => '666', + 'phonecode' => '39', + 'date' => $date->format('Y-m-d'), + 'datetime' => $date->format('Y-m-d H:i:s'), + 'time' => $date->format('H:i:s'), + ]; - // check via getAll + // create new record $request = new Request( 'http://localhost/client', - 'GET', + 'POST', 'php://memory', [ 'Content-Type' => 'application/json', ] ); + $request->getBody()->write(json_encode($data)); + $response = $this->processRequest($request); + // check on post + $this->assertEquals([ + 'id' => '3', + 'name' => 'test_time', + 'nicename' => 'test', + 'iso' => 'IT', + 'iso3' => 'ITA', + 'numcode' => '666', + 'phonecode' => '39', + 'date' => $date->format('Y-m-d'), + 'datetime' => $date->format('Y-m-d\TH:i:sP'), + 'time' => $date->format('H:i:s'), + ], $response); + + // retrive created record + $request = new Request( + 'http://localhost/client/sys_name:test_time', + 'GET', + 'php://memory', + [ + 'Content-Type' => 'application/json', + ] + ); $response = $this->processRequest($request); - $this->assertEquals([], $response); + + // check on get + $this->assertEquals([ + 'id' => '3', + 'name' => 'test_time', + 'nicename' => 'test', + 'iso' => 'IT', + 'iso3' => 'ITA', + 'numcode' => '666', + 'phonecode' => '39', + 'date' => $date->format('Y-m-d'), + 'datetime' => $date->format('Y-m-d\TH:i:sP'), + 'time' => $date->format('H:i:s'), + ], $response); } public function testOnlyApiFields() { - $this->model->apiFields = [ + + $model = new Country($this->db); + $model->apiFields = [ 'read' => [ - 'name', + 'sys_name', 'iso', + 'iso3', 'numcode', - ], + ] ]; $data = [ - 'name' => 'test', - 'sys_name' => 'test', - 'iso' => 'IT', - 'iso3' => 'ITA', - 'numcode' => '666', - 'phonecode' => '39', + 'name' => 'USA', + 'iso' => 'US', + 'iso3' => 'USA', + 'numcode' => '999' ]; $request = new Request( @@ -234,12 +343,13 @@ public function testOnlyApiFields() ); $request->getBody()->write(json_encode($data)); - $response = $this->processRequest($request); + $response = $this->processRequest($request, $model); $this->assertEquals(201, $this->api->response_code); $this->assertEquals([ - 'name' => 'test', - 'iso' => 'IT', - 'numcode' => '666', + 'name' => 'USA', + 'iso' => 'US', + 'iso3' => 'USA', + 'numcode' => '999' ], $response); } } @@ -275,6 +385,10 @@ public function init() $this->addField('numcode', ['caption'=>'ISO Numeric Code', 'type'=>'number', 'required'=>true]); $this->addField('phonecode', ['caption'=>'Phone Prefix', 'type'=>'number']); + $this->addField('date', ['caption'=>'Test Datetime', 'type'=>'date']); + $this->addField('datetime', ['caption'=>'Test Datetime', 'type'=>'datetime']); + $this->addField('time', ['caption'=>'Test Datetime', 'type'=>'time']); + $this->onHook('beforeSave', function ($m) { if (!$m['sys_name']) { $m['sys_name'] = strtoupper($m['name']); From 470d2c8a60da92b0fdfc306acf298baae92a18bd Mon Sep 17 00:00:00 2001 From: Romans Malinovskis Date: Wed, 8 Apr 2020 13:17:34 +0000 Subject: [PATCH 5/8] Apply fixes from StyleCI --- src/Api.php | 11 +++--- tests/ApiTesterRestTest.php | 68 ++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/Api.php b/src/Api.php index ab11dc1..be11ff9 100644 --- a/src/Api.php +++ b/src/Api.php @@ -44,8 +44,8 @@ class Api /** * @var bool If set to true, the first array element of Model->export - * will be returned (GET single record) - * If not, the array will be returned as-is + * will be returned (GET single record) + * If not, the array will be returned as-is */ public $single_record = true; @@ -156,14 +156,13 @@ public function exec($callable, $vars = []) // if callable function returns agile data model, then export it // this is important for REST API implementation if ($ret instanceof Model) { - $data = []; $allowed_fields = $this->getAllowedFields($ret, 'read'); if ($this->single_record) { /** @var Field $field */ - foreach($ret->getFields() as $fieldName => $field) { - if(!in_array($fieldName, $allowed_fields)) { + foreach ($ret->getFields() as $fieldName => $field) { + if (!in_array($fieldName, $allowed_fields)) { continue; } $data[$field->actual ?? $fieldName] = $field->toString(); @@ -174,7 +173,7 @@ public function exec($callable, $vars = []) $record = []; /** @var Field $field */ foreach ($ret->getFields() as $fieldName => $field) { - if(!in_array($fieldName, $allowed_fields)) { + if (!in_array($fieldName, $allowed_fields)) { continue; } $record[$field->actual ?? $fieldName] = $field->toString(); diff --git a/tests/ApiTesterRestTest.php b/tests/ApiTesterRestTest.php index ea73a74..2cfa290 100644 --- a/tests/ApiTesterRestTest.php +++ b/tests/ApiTesterRestTest.php @@ -19,17 +19,17 @@ class ApiTesterRestTest extends \atk4\core\PHPUnit_AgileTestCase public static function tearDownAfterClass() { - unlink(__DIR__ . '/sqlite.db'); + unlink(__DIR__.'/sqlite.db'); } public function setUp() { parent::setUp(); - $filename = __DIR__ . '/sqlite.db'; + $filename = __DIR__.'/sqlite.db'; touch($filename); - $this->db = new Persistence\SQL('sqlite:' . $filename); - if(!self::$init) { + $this->db = new Persistence\SQL('sqlite:'.$filename); + if (!self::$init) { self::$init = true; Migration::of(new Country($this->db))->run(); } @@ -37,7 +37,6 @@ public function setUp() public function processRequest(Request $request, $model = null) { - $model_default = new Country($this->db); $this->api = new Api($request); @@ -56,9 +55,9 @@ public function testCreate() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ]; $request = new Request( @@ -81,9 +80,9 @@ public function testCreate() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ], $response); } @@ -96,9 +95,9 @@ public function testCreate2() 'iso3' => 'DEU', 'numcode' => '999', 'phonecode' => '43', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ]; $request = new Request( @@ -121,9 +120,9 @@ public function testCreate2() 'iso3' => 'DEU', 'numcode' => '999', 'phonecode' => '43', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ], $response); } @@ -147,9 +146,9 @@ public function testGETOne() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ], $response); } @@ -174,9 +173,9 @@ public function testGETAll() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ], [ 'id' => '2', @@ -186,10 +185,10 @@ public function testGETAll() 'iso3' => 'DEU', 'numcode' => '999', 'phonecode' => '43', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null - ] + 'time' => null, + ], ], $response); } @@ -221,9 +220,9 @@ public function testModify() 'iso3' => 'ITA', 'numcode' => '666', 'phonecode' => '39', - 'date' => null, + 'date' => null, 'datetime' => null, - 'time' => null + 'time' => null, ], $response); } @@ -247,18 +246,18 @@ public function testDelete() public function testSerialization() { $date = $datetime = new \Datetime(); - $date->setTime(6,6,6); // this is for you imanst ;) + $date->setTime(6, 6, 6); // this is for you imanst ;) $data = [ 'sys_name' => 'test_time', - 'name' => 'test', - 'iso' => 'IT', - 'iso3' => 'ITA', - 'numcode' => '666', - 'phonecode' => '39', - 'date' => $date->format('Y-m-d'), - 'datetime' => $date->format('Y-m-d H:i:s'), - 'time' => $date->format('H:i:s'), + 'name' => 'test', + 'iso' => 'IT', + 'iso3' => 'ITA', + 'numcode' => '666', + 'phonecode' => '39', + 'date' => $date->format('Y-m-d'), + 'datetime' => $date->format('Y-m-d H:i:s'), + 'time' => $date->format('H:i:s'), ]; // create new record @@ -315,7 +314,6 @@ public function testSerialization() public function testOnlyApiFields() { - $model = new Country($this->db); $model->apiFields = [ 'read' => [ @@ -323,14 +321,14 @@ public function testOnlyApiFields() 'iso', 'iso3', 'numcode', - ] + ], ]; $data = [ 'name' => 'USA', 'iso' => 'US', 'iso3' => 'USA', - 'numcode' => '999' + 'numcode' => '999', ]; $request = new Request( @@ -349,7 +347,7 @@ public function testOnlyApiFields() 'name' => 'USA', 'iso' => 'US', 'iso3' => 'USA', - 'numcode' => '999' + 'numcode' => '999', ], $response); } } From 7002d824e69e7b34a936886f1913a3864ffa904f Mon Sep 17 00:00:00 2001 From: abbadon1334 Date: Wed, 8 Apr 2020 15:42:50 +0200 Subject: [PATCH 6/8] Extract and rewrite exportModel method --- src/Api.php | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Api.php b/src/Api.php index be11ff9..c3c0034 100644 --- a/src/Api.php +++ b/src/Api.php @@ -160,25 +160,10 @@ public function exec($callable, $vars = []) $allowed_fields = $this->getAllowedFields($ret, 'read'); if ($this->single_record) { - /** @var Field $field */ - foreach ($ret->getFields() as $fieldName => $field) { - if (!in_array($fieldName, $allowed_fields)) { - continue; - } - $data[$field->actual ?? $fieldName] = $field->toString(); - } + $data = $this->exportModel($ret, $allowed_fields); } else { foreach ($ret as $m) { - /** @var Model $m */ - $record = []; - /** @var Field $field */ - foreach ($ret->getFields() as $fieldName => $field) { - if (!in_array($fieldName, $allowed_fields)) { - continue; - } - $record[$field->actual ?? $fieldName] = $field->toString(); - } - $data[] = $record; + $data[] = $this->exportModel($ret, $allowed_fields); } } @@ -223,15 +208,23 @@ protected function call($callable, $vars = []) * * Extend this method to implement your own field restrictions. * - * @param Model $m + * @param Model $m Model + * @param array $allowed_fields Allowed fields * * @throws \atk4\data\Exception + * @throws \atk4\core\Exception * * @return array */ - protected function exportModel(Model $m) + protected function exportModel(Model $m, array $allowed_fields = []) { - return $m->export($this->getAllowedFields($m, 'read'), null, true); + $data = []; + foreach ($allowed_fields as $fieldName) { + $field = $m->getField($fieldName); + $data[$field->actual ?? $fieldName] = $field->toString(); + } + + return $data; } /** From 1cb05baeeda661812b5ee2539ea67b7a9484e29d Mon Sep 17 00:00:00 2001 From: Romans Malinovskis Date: Wed, 8 Apr 2020 13:43:12 +0000 Subject: [PATCH 7/8] Apply fixes from StyleCI --- src/Api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api.php b/src/Api.php index c3c0034..45be75e 100644 --- a/src/Api.php +++ b/src/Api.php @@ -208,7 +208,7 @@ protected function call($callable, $vars = []) * * Extend this method to implement your own field restrictions. * - * @param Model $m Model + * @param Model $m Model * @param array $allowed_fields Allowed fields * * @throws \atk4\data\Exception From 2b0e14ff8df5958f53f92fa00bd956094e1df934 Mon Sep 17 00:00:00 2001 From: abbadon1334 Date: Wed, 8 Apr 2020 15:49:09 +0200 Subject: [PATCH 8/8] cleanup --- src/Api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api.php b/src/Api.php index c3c0034..d6a8a34 100644 --- a/src/Api.php +++ b/src/Api.php @@ -163,7 +163,7 @@ public function exec($callable, $vars = []) $data = $this->exportModel($ret, $allowed_fields); } else { foreach ($ret as $m) { - $data[] = $this->exportModel($ret, $allowed_fields); + $data[] = $this->exportModel($m, $allowed_fields); } }