diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ae7e6b8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "clients/Api"] + path = clients/Api + url = git@gitlab.com:service-web-lab/dam-client.git diff --git a/app/Console/Commands/Api/GenerateApiClient.php b/app/Console/Commands/Api/GenerateApiClient.php new file mode 100644 index 0000000..11d946b --- /dev/null +++ b/app/Console/Commands/Api/GenerateApiClient.php @@ -0,0 +1,225 @@ +copyEnums(); + $this->copyExceptions(); + $this->copyRoutesList(); + $this->copyApiConfigInfo(); + return 0; + } + + /** + * Copy config files + * + * @return void + */ + private function copyApiConfigInfo() + { + $this->info('Copy Api Config'); + $rootTarget = app_path('../' . self::TARGET); + if (File::exists("$rootTarget/../apiConfig.readonly.json")) { + File::delete("$rootTarget/../apiConfig.readonly.json"); + } + File::put( + "$rootTarget/../apiConfig.readonly.json", + \json_encode(config('api'), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) + ); + $this->phpcbfFile("$rootTarget/../apiConfig.readonly.json"); + } + + /** + * Copy routes into a json file + * + * @return void + */ + private function copyRoutesList() + { + $this->info('Copy Routes'); + $routes = []; + /** @var \Illuminate\Routing\Route */ + foreach (Route::getRoutes() as $route) { + if (\strpos($route->getPrefix(), 'api') !== false) { + $routes[$route->getName()] = [ + 'uri' => $route->uri(), + 'methods' => $route->methods() + ]; + } + } + $rootTarget = app_path('../' . self::TARGET); + if (File::exists("$rootTarget/routes.json")) { + File::delete("$rootTarget/routes.json"); + } + File::put( + "$rootTarget/routes.json", + \json_encode($routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) + ); + $this->phpcbfFile("$rootTarget/routes.json"); + } + + /** + * Copy Exeption classes + * + * @return void + */ + private function copyExceptions(): void + { + $this->info('Copy Exceptions'); + $rootTarget = app_path('../' . self::TARGET); + $this->copyToFolder([ + DamException::class, + ApiErrorException::class + ], 'Exceptions'); + $this->replaceInPhpFile( + "$rootTarget/Exceptions/ApiErrorException.php", + ApiError::class, + self::CLIENTNAMESPACE . '\\Enums\\ApiError' + ); + $this->replaceInPhpFile( + "$rootTarget/Exceptions/DamException.php", + DamException::class, + self::CLIENTNAMESPACE . '\\Exceptions\\DamException' + ); + $this->replaceInPhpFile( + "$rootTarget/Exceptions/DamException.php", + ApiErrorException::class, + self::CLIENTNAMESPACE . '\\Exceptions\\ApiErrorException' + ); + $this->phpcbfFile("$rootTarget/Exceptions/DamException.php"); + $this->phpcbfFile("$rootTarget/Exceptions/ApiErrorException.php"); + } + + /** + * Copy enums classes + * + * @return void + */ + private function copyEnums(): void + { + $this->info('Copy Enums'); + $classes = [ + ApiError::class, + ApiStatus::class + ]; + $this->copyToFolder($classes, 'Enums'); + $rootTarget = app_path('../' . self::TARGET); + foreach ($classes as $class) { + $classBasename = class_basename($class); + $dest = "$rootTarget/Enums/$classBasename.php"; + $this->replaceInPhpFile($dest, 'BaseEnumRoutable', 'BaseEnum'); + $this->replaceInPhpFile($dest, '\\Legacy', ''); + $this->phpcbfFile($dest); + } + + $mediaExtensionEnum = "name}()\n"; + } + // phpcs:ignore Generic.Files.LineLength.TooLong + $mediaExtensionEnum .= " *\n * @package DAMclient\n * @subpackage enums\n */\nclass MediaExtension extends BaseEnum\n{\n}\n"; + File::put("$rootTarget/Enums/MediaExtension.php", $mediaExtensionEnum); + $this->phpcbfFile("$rootTarget/Enums/MediaExtensio.php"); + } + + /** + * Copy Classes to specified folder + * + * @param array $classes + * @param string $folder + * @return void + */ + private function copyToFolder(array $classes, string $folder): void + { + $rootTarget = app_path('../' . self::TARGET); + foreach ($classes as $class) { + $classFileName = \str_replace("App\\$folder\\", '', sprintf('%s.php', $class)); + $classFileName = \str_replace('\\', '/', $classFileName); + $classBasename = class_basename($class); + $source = \app_path("$folder/$classFileName"); + $dest = "$rootTarget/$folder/$classBasename.php"; + if (File::exists($dest)) { + File::delete($dest); + } + File::copy($source, $dest); + $this->replaceInPhpFile($dest, 'namespace App', 'namespace ' . self::CLIENTNAMESPACE); + } + } + + /** + * Replaces a specific string with another on a file + * + * @param string $source + * @param string $search + * @param string $replace + * @return void + */ + private function replaceInPhpFile(string $source, string $search, string $replace): void + { + $fContent = File::get($source); + + // Remove trailing \Api . + $regex = '/namespace ([a-zA-Z0-9\\\\]+)\\\\Api;/m'; + $fContent = preg_replace($regex, 'namespace $1;', $fContent); + + // Replace namespace top level. + $pos = strpos($fContent, $search); + if ($pos !== false) { + File::put($source, \str_replace($search, $replace, $fContent)); + } + } + + /** + * Lint the file + * + * @param string $path + * @return void + * @throws \Symfony\Component\Process\Exception\RuntimeException If anything goes wrong. + * @throws \Symfony\Component\Process\Exception\ProcessTimedOutException If anything goes wrong. + * @throws \Symfony\Component\Process\Exception\ProcessSignaledException If anything goes wrong. + * @throws \Symfony\Component\Process\Exception\LogicException If anything goes wrong. + */ + private function phpcbfFile(string $path): void + { + $process = new Process(['./vendor/bin/phpcbf', $path]); + $process->run(); + } +} diff --git a/composer.json b/composer.json index c581952..a0e2e96 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,8 @@ }, "autoload-dev": { "psr-4": { - "Tests\\": "tests/" + "Tests\\": "tests/", + "LDC\\DAM\\Client\\": "clients/Api/src/" } }, "scripts": { diff --git a/composer.lock b/composer.lock index e8a2628..e5b409d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d3caf1a99a48f4de736a4a4f8aa14124", + "content-hash": "1731504e63f41b434c0f6639604ae78b", "packages": [ { "name": "adldap2/adldap2",