diff --git a/src/Commands/InitCommand.php b/src/Commands/InitCommand.php index 2fc9d80..4226b38 100644 --- a/src/Commands/InitCommand.php +++ b/src/Commands/InitCommand.php @@ -215,6 +215,8 @@ public function handle(): void $this->setAutoDocContactEmail($this->codeOwnerEmail); + $this->addDefaultHttpExceptionRender(); + Artisan::call('migrate'); } @@ -227,6 +229,50 @@ protected function setAutoDocContactEmail(string $email): void $config->write(); } + protected function addDefaultHttpExceptionRender(): void + { + $file = base_path('bootstrap/app.php'); + + $content = file_get_contents($file); + + $find = [ + '$exceptions->render(function (HttpException $exception, Request $request)', + '$exceptions->render(function (\Symfony\Component\HttpKernel\Exception\HttpException $exception, \Illuminate\Http\Request $request)', + ]; + + if (Str::contains($content, $find)) { + return; + } + + $imports = [ + 'use Symfony\Component\HttpKernel\Exception\HttpException;', + 'use Illuminate\Http\Request;', + ]; + + foreach ($imports as $import) { + if (!Str::contains($content, $import)) { + $content = preg_replace('/<\?php\s*/', "render(); + + $baseIndent = ' '; + + $content = preg_replace_callback( + pattern: '/^([ \t]*)(->withExceptions\(function \(Exceptions \$exceptions\)(?:\: void)? \{)/m', + callback: function ($matches) use ($codeToAdd, $baseIndent) { + $currentIndent = $matches[1]; + $indentedCode = preg_replace('/^/m', $currentIndent . $baseIndent, $codeToAdd); + return $matches[0] . "\n" . $indentedCode; + }, + subject: $content, + limit: 1 + ); + + file_put_contents($file, $content); + } + protected function createAdminUser(string $kebabName): void { $defaultPassword = substr(md5(uniqid()), 0, 8); diff --git a/src/ProjectInitializatorServiceProvider.php b/src/ProjectInitializatorServiceProvider.php index b0d1fca..91dec33 100644 --- a/src/ProjectInitializatorServiceProvider.php +++ b/src/ProjectInitializatorServiceProvider.php @@ -22,5 +22,6 @@ public function boot(): void ], 'initializator-web-login'); $this->loadViewsFrom(__DIR__ . '/../resources/views', 'initializator'); + $this->loadViewsFrom(__DIR__ . '/../stubs', 'project-initializator'); } } diff --git a/stubs/default_http_exception.blade.php b/stubs/default_http_exception.blade.php new file mode 100644 index 0000000..2ae584b --- /dev/null +++ b/stubs/default_http_exception.blade.php @@ -0,0 +1,5 @@ +$exceptions->render(function (HttpException $exception, Request $request) { + return ($request->expectsJson()) + ? response()->json(['error' => $exception->getMessage()], $exception->getStatusCode()) + : null; +}); \ No newline at end of file diff --git a/tests/InitCommandTest.php b/tests/InitCommandTest.php index 5591514..cb0be9d 100644 --- a/tests/InitCommandTest.php +++ b/tests/InitCommandTest.php @@ -22,6 +22,10 @@ public function testRunWithoutAdminAndReadmeCreationConvertAppNameToPascalCaseTe 'arguments' => ['.env.development'], 'result' => $this->getFixture('env.development_app_name_pascal_case.yml'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -32,6 +36,10 @@ public function testRunWithoutAdminAndReadmeCreationConvertAppNameToPascalCaseTe "\nAuth::routes();\n", FILE_APPEND, ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockClassExists([ @@ -76,6 +84,10 @@ public function testRunWithoutAdminAndReadmeCreation() 'arguments' => ['.env.development'], 'result' => $this->getFixture('env.development_app_name_pascal_case.yml'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -90,6 +102,10 @@ public function testRunWithoutAdminAndReadmeCreation() 'renovate.json', $this->getFixture('renovate.json'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -132,6 +148,10 @@ public function testRunWithAdminAndWithoutReadmeCreation() 'arguments' => ['.env.development'], 'result' => $this->getFixture('env.development.yml'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -146,6 +166,10 @@ public function testRunWithAdminAndWithoutReadmeCreation() 'database/migrations/2018_11_11_111111_add_default_user.php', $this->getFixture('migration.php'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -240,6 +264,10 @@ public function testRunWithAdminAndDefaultReadmeCreation() 'arguments' => [base_path('/vendor/ronasit/laravel-project-initializator/resources/md/readme/RENOVATE.md')], 'result' => $this->getTemplate('RENOVATE.md'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -282,6 +310,10 @@ public function testRunWithAdminAndDefaultReadmeCreation() 'README.md', $this->getFixture('default_readme_after_using_renovate.md'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -405,6 +437,10 @@ public function testRunWithAdminAndPartialReadmeCreation() 'arguments' => [base_path('/vendor/ronasit/laravel-project-initializator/resources/md/readme/CREDENTIALS_AND_ACCESS.md')], 'result' => $this->getTemplate('CREDENTIALS_AND_ACCESS.md'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -419,6 +455,10 @@ public function testRunWithAdminAndPartialReadmeCreation() 'README.md', $this->getFixture('partial_readme.md'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -541,6 +581,10 @@ public function testRunWithAdminAndFullReadmeCreationAndRemovingInitializatorIns 'arguments' => [base_path('/vendor/ronasit/laravel-project-initializator/resources/md/readme/RENOVATE.md')], 'result' => $this->getTemplate('RENOVATE.md'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -567,6 +611,10 @@ public function testRunWithAdminAndFullReadmeCreationAndRemovingInitializatorIns 'README.md', $this->getFixture('full_readme_after_using_renovate.md'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -687,6 +735,10 @@ public function testRunWithoutAdminAndUsingTelescope() 'arguments' => [base_path('/vendor/ronasit/laravel-project-initializator/resources/md/readme/CREDENTIALS_AND_ACCESS.md')], 'result' => $this->getTemplate('CREDENTIALS_AND_ACCESS.md'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -701,6 +753,10 @@ public function testRunWithoutAdminAndUsingTelescope() 'README.md', $this->getFixture('partial_readme_with_telescope.md'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( @@ -839,6 +895,10 @@ public function testRunWithClerkMobileApp(): void 'arguments' => [base_path('/vendor/ronasit/laravel-project-initializator/resources/md/readme/RENOVATE.md')], 'result' => $this->getTemplate('RENOVATE.md'), ], + [ + 'arguments' => [base_path('bootstrap/app.php')], + 'result' => $this->getFixture('app.php'), + ], ); $this->mockFilePutContent( @@ -881,6 +941,10 @@ public function testRunWithClerkMobileApp(): void 'README.md', $this->getFixture('default_readme_with_mobile_app_after_using_renovate.md'), ], + [ + base_path('bootstrap/app.php'), + $this->getFixture('app_after_changes.php'), + ], ); $this->mockShellExec( diff --git a/tests/fixtures/InitCommandTest/app.php b/tests/fixtures/InitCommandTest/app.php new file mode 100644 index 0000000..c183276 --- /dev/null +++ b/tests/fixtures/InitCommandTest/app.php @@ -0,0 +1,18 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware): void { + // + }) + ->withExceptions(function (Exceptions $exceptions): void { + // + })->create(); diff --git a/tests/fixtures/InitCommandTest/app_after_changes.php b/tests/fixtures/InitCommandTest/app_after_changes.php new file mode 100644 index 0000000..b96ca44 --- /dev/null +++ b/tests/fixtures/InitCommandTest/app_after_changes.php @@ -0,0 +1,25 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware): void { + // + }) + ->withExceptions(function (Exceptions $exceptions): void { + $exceptions->render(function (HttpException $exception, Request $request) { + return ($request->expectsJson()) + ? response()->json(['error' => $exception->getMessage()], $exception->getStatusCode()) + : null; + }); + // + })->create();