diff --git a/src/Controller/Component/ApiFormatterComponent.php b/src/Controller/Component/ApiFormatterComponent.php index eab4e25..603b64c 100644 --- a/src/Controller/Component/ApiFormatterComponent.php +++ b/src/Controller/Component/ApiFormatterComponent.php @@ -15,6 +15,7 @@ namespace BEdita\WebTools\Controller\Component; +use BEdita\WebTools\Utility\ApiTools; use Cake\Collection\Collection; use Cake\Controller\Component; use Cake\Utility\Hash; @@ -158,4 +159,18 @@ protected function extractTranslatedFields(array $data, string $lang): array return array_filter((array)array_shift($translatedFields)); } + + /** + * Clean response from unwanted keys (recursively). + * + * @param array $response The response from API + * @param array $options The options to clean response + * @return array + */ + public function cleanResponse( + array $response, + array $options = ['included', 'links', 'schema', 'relationships'] + ): array { + return ApiTools::cleanResponse($response, $options); + } } diff --git a/src/Utility/ApiTools.php b/src/Utility/ApiTools.php new file mode 100644 index 0000000..a2346b0 --- /dev/null +++ b/src/Utility/ApiTools.php @@ -0,0 +1,113 @@ + for more details. + */ +namespace BEdita\WebTools\Utility; + +use Cake\Utility\Hash; + +/** + * Api utility methods + */ +class ApiTools +{ + /** + * Remove included from response. + * + * @param array $response The response from api client + * @return array + */ + public static function removeIncluded(array $response): array + { + return (array)Hash::remove($response, 'included'); + } + + /** + * Remove `links` from response (recursively). + * + * @param array $response The response from api client + * @return array + */ + public static function removeLinks(array $response): array + { + $response = (array)Hash::remove($response, 'links'); + + return self::recursiveRemoveKey($response, 'links'); + } + + /** + * Remove `relationships` from response (recursively). + * + * @param array $response The response from api client + * @return array + */ + public static function removeRelationships(array $response): array + { + return self::recursiveRemoveKey($response, 'relationships'); + } + + /** + * Remove `schema` from response. + * + * @param array $response The response from api client + * @return array + */ + public static function removeSchema(array $response): array + { + return (array)Hash::remove($response, 'meta.schema'); + } + + /** + * Remove a key in an array recursively. + * + * @param array $data The starting data + * @param string $key The key to remove + * @return array + */ + public static function recursiveRemoveKey(array $data, string $key): array + { + foreach ($data as $k => $v) { + if (is_array($v)) { + $data[$k] = self::recursiveRemoveKey($v, $key); + } + } + + return array_filter( + $data, + function ($k) use ($key) { + return $k !== $key; + }, + ARRAY_FILTER_USE_KEY + ); + } + + /** + * Clean response. + * + * @param array $response The response. + * @param array $options The options to clean. + * @return array + */ + public static function cleanResponse( + array $response, + array $options = ['included', 'links', 'schema', 'relationships'] + ): array { + foreach ($options as $option) { + $method = 'remove' . ucfirst($option); + $response = self::$method($response); + } + + return $response; + } +} diff --git a/tests/TestCase/Controller/Component/ApiFormatterComponentTest.php b/tests/TestCase/Controller/Component/ApiFormatterComponentTest.php index 05531fd..b397c84 100644 --- a/tests/TestCase/Controller/Component/ApiFormatterComponentTest.php +++ b/tests/TestCase/Controller/Component/ApiFormatterComponentTest.php @@ -741,4 +741,106 @@ public function testReplaceWithTranslation(array $expected, array $response, str $actual = $this->ApiFormatter->replaceWithTranslation($response, $lang); static::assertEquals($expected, $actual); } + + /** + * Test `cleanResponse()` method. + * + * @return void + * @covers ::cleanResponse() + */ + public function testCleanResponse(): void + { + $response = [ + 'data' => [ + [ + 'id' => 1, + 'attributes' => [ + 'uname' => 'gustavo', + 'title' => 'gustavo supporto', + 'name' => 'gustavo', + 'surname' => 'supporto', + ], + 'links' => [ + 'self' => 'https://api.example.org/users/1', + ], + 'relationships' => [ + 'roles' => [ + 'links' => [ + 'self' => 'https://api.example.org/users/1/relationships/roles', + 'related' => 'https://api.example.org/users/1/roles', + ], + ], + ], + ], + ], + 'meta' => [ + 'pagination' => [ + 'page' => 1, + 'page_count' => 1, + 'page_items' => 1, + 'page_size' => 20, + 'count' => 1, + ], + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + ], + 'type' => [ + 'type' => 'string', + ], + 'attributes' => [ + 'type' => 'object', + ], + 'links' => [ + 'type' => 'object', + ], + 'relationships' => [ + 'type' => 'object', + ], + ], + 'required' => ['id', 'type', 'attributes'], + ], + ], + 'included' => [ + [ + 'id' => 1, + 'type' => 'roles', + 'attributes' => [ + 'name' => 'admin', + ], + ], + ], + 'links' => [ + 'self' => 'https://api.example.org/users', + 'first' => 'https://api.example.org/users?page=1', + 'last' => 'https://api.example.org/users?page=1', + ], + ]; + $actual = $this->ApiFormatter->cleanResponse($response); + $expected = [ + 'data' => [ + [ + 'id' => 1, + 'attributes' => [ + 'uname' => 'gustavo', + 'title' => 'gustavo supporto', + 'name' => 'gustavo', + 'surname' => 'supporto', + ], + ], + ], + 'meta' => [ + 'pagination' => [ + 'page' => 1, + 'page_count' => 1, + 'page_items' => 1, + 'page_size' => 20, + 'count' => 1, + ], + ], + ]; + static::assertEquals($expected, $actual); + } } diff --git a/tests/TestCase/Utility/ApiToolsTest.php b/tests/TestCase/Utility/ApiToolsTest.php new file mode 100644 index 0000000..b970fd1 --- /dev/null +++ b/tests/TestCase/Utility/ApiToolsTest.php @@ -0,0 +1,133 @@ + for more details. + */ +namespace BEdita\WebTools\Test\TestCase\Utility; + +use BEdita\WebTools\Utility\ApiTools; +use Cake\TestSuite\TestCase; + +/** + * {@see \BEdita\WebTools\Utility\ApiTools} Test Case + * + * @coversDefaultClass \BEdita\WebTools\Utility\ApiTools + */ +class ApiToolsTest extends TestCase +{ + /** + * Test clean response + * + * @return void + * @covers ::cleanResponse() + * @covers ::recursiveRemoveKey() + * @covers ::removeIncluded() + * @covers ::removeLinks() + * @covers ::removeRelationships() + * @covers ::removeSchema() + */ + public function testCleanResponse(): void + { + $response = [ + 'data' => [ + [ + 'id' => 1, + 'attributes' => [ + 'uname' => 'gustavo', + 'title' => 'gustavo supporto', + 'name' => 'gustavo', + 'surname' => 'supporto', + ], + 'links' => [ + 'self' => 'https://api.example.org/users/1', + ], + 'relationships' => [ + 'roles' => [ + 'links' => [ + 'self' => 'https://api.example.org/users/1/relationships/roles', + 'related' => 'https://api.example.org/users/1/roles', + ], + ], + ], + ], + ], + 'meta' => [ + 'pagination' => [ + 'page' => 1, + 'page_count' => 1, + 'page_items' => 1, + 'page_size' => 20, + 'count' => 1, + ], + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + ], + 'type' => [ + 'type' => 'string', + ], + 'attributes' => [ + 'type' => 'object', + ], + 'links' => [ + 'type' => 'object', + ], + 'relationships' => [ + 'type' => 'object', + ], + ], + 'required' => ['id', 'type', 'attributes'], + ], + ], + 'included' => [ + [ + 'id' => 1, + 'type' => 'roles', + 'attributes' => [ + 'name' => 'admin', + ], + ], + ], + 'links' => [ + 'self' => 'https://api.example.org/users', + 'first' => 'https://api.example.org/users?page=1', + 'last' => 'https://api.example.org/users?page=1', + ], + ]; + $actual = ApiTools::cleanResponse($response); + $expected = [ + 'data' => [ + [ + 'id' => 1, + 'attributes' => [ + 'uname' => 'gustavo', + 'title' => 'gustavo supporto', + 'name' => 'gustavo', + 'surname' => 'supporto', + ], + ], + ], + 'meta' => [ + 'pagination' => [ + 'page' => 1, + 'page_count' => 1, + 'page_items' => 1, + 'page_size' => 20, + 'count' => 1, + ], + ], + ]; + static::assertEquals($expected, $actual); + } +}