From 4491db71309474c8ba1a51fef261d13b0443c117 Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Sat, 9 Nov 2024 15:29:51 -0500 Subject: [PATCH] Normalize the resolution of published stubs. --- src/Commands/Concerns/HasDomainStubs.php | 48 ++++++--- src/Commands/DomainControllerMakeCommand.php | 6 +- .../app/Http/Controllers/Controller.php | 8 ++ tests/.skeleton/stubs/ddd/dummy.stub | 0 tests/Generator/ControllerMakeTest.php | 100 +++++++++++++++++- .../Model/MakeWithControllerTest.php | 12 --- tests/TestCase.php | 20 ++-- 7 files changed, 158 insertions(+), 36 deletions(-) create mode 100644 tests/.skeleton/app/Http/Controllers/Controller.php create mode 100644 tests/.skeleton/stubs/ddd/dummy.stub diff --git a/src/Commands/Concerns/HasDomainStubs.php b/src/Commands/Concerns/HasDomainStubs.php index 37a9538..82876cc 100644 --- a/src/Commands/Concerns/HasDomainStubs.php +++ b/src/Commands/Concerns/HasDomainStubs.php @@ -7,14 +7,42 @@ trait HasDomainStubs { + protected static $usingPublishedStub = false; + + protected function usingPublishedStub($usingPublishedStub = true) + { + static::$usingPublishedStub = $usingPublishedStub; + + return $this; + } + + protected function isUsingPublishedStub(): bool + { + return static::$usingPublishedStub; + } + protected function getStub() { - $defaultStub = parent::getStub(); + $stub = parent::getStub(); + + if ($publishedStub = $this->resolvePublishedDddStub($stub)) { + $stub = $publishedStub; + } + + $this->usingPublishedStub(str($stub)->startsWith(app()->basePath('stubs'))); - $stubFilename = basename($defaultStub); + return $stub; + } + + protected function resolvePublishedDddStub($path) + { + $stubFilename = str($path) + ->basename() + ->ltrim('/\\') + ->toString(); // Check if there is a user-published stub - if (file_exists($publishedPath = app()->basePath('stubs/ddd/'.$stubFilename))) { + if (file_exists($publishedPath = app()->basePath('stubs/ddd/' . $stubFilename))) { return $publishedPath; } @@ -23,7 +51,7 @@ protected function getStub() return $legacyPublishedPath; } - return $defaultStub; + return null; } protected function resolveDddStubPath($path) @@ -33,18 +61,10 @@ protected function resolveDddStubPath($path) ->ltrim('/\\') ->toString(); - $publishedPath = resource_path('stubs/ddd/'.$path); - - if (file_exists($publishedPath)) { + if($publishedPath = $this->resolvePublishedDddStub($path)) { return $publishedPath; } - $legacyPublishedPath = Str::replaceLast('.stub', '.php.stub', $publishedPath); - - if (file_exists($legacyPublishedPath)) { - return $legacyPublishedPath; - } - - return DDD::packagePath('stubs/'.$path); + return DDD::packagePath('stubs/' . $path); } } diff --git a/src/Commands/DomainControllerMakeCommand.php b/src/Commands/DomainControllerMakeCommand.php index d89eaa9..dfd6b76 100644 --- a/src/Commands/DomainControllerMakeCommand.php +++ b/src/Commands/DomainControllerMakeCommand.php @@ -86,6 +86,10 @@ protected function buildClass($name) { $stub = parent::buildClass($name); + if($this->isUsingPublishedStub()){ + return $stub; + } + $replace = []; $appRootNamespace = $this->laravel->getNamespace(); @@ -95,7 +99,7 @@ protected function buildClass($name) if ($baseControllerExists) { $controllerClass = class_basename($name); - $replace["\nclass {$controllerClass}\n"] = "use {$appRootNamespace}Http\Controllers\Controller;\n\nclass {$controllerClass} extends Controller\n"; + $replace["\nclass {$controllerClass}\n"] = "\nuse {$appRootNamespace}Http\Controllers\Controller;\n\nclass {$controllerClass} extends Controller\n"; } $stub = str_replace( diff --git a/tests/.skeleton/app/Http/Controllers/Controller.php b/tests/.skeleton/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..8677cd5 --- /dev/null +++ b/tests/.skeleton/app/Http/Controllers/Controller.php @@ -0,0 +1,8 @@ + ['controller', 'request'], ]); + $this->cleanSlate(); $this->setupTestApplication(); }); @@ -30,13 +32,15 @@ expect($output = Artisan::output())->when( Feature::IncludeFilepathInGeneratorCommandOutput->exists(), - fn ($output) => $output->toContainFilepath($relativePath), + fn($output) => $output->toContainFilepath($relativePath), ); expect(file_exists($expectedPath))->toBeTrue(); expect(file_get_contents($expectedPath)) - ->toContain("namespace {$expectedNamespace};"); + ->toContain("namespace {$expectedNamespace};") + ->toContain("use App\Http\Controllers\Controller;") + ->toContain("extends Controller"); })->with([ 'Invoicing:InvoiceController' => [ 'Invoicing', @@ -175,3 +179,95 @@ ], ], ]); + +it('does not extend base controller if base controller not found', function ($domainName, $controllerName, $relativePath, $expectedNamespace) { + $expectedPath = base_path($relativePath); + + if (file_exists($expectedPath)) { + unlink($expectedPath); + } + + expect(file_exists($expectedPath))->toBeFalse(); + + // Remove the base controller + $baseControllerPath = base_path('app/Http/Controllers/Controller.php'); + + if (file_exists($baseControllerPath)) { + unlink($baseControllerPath); + } + + expect(file_exists($baseControllerPath))->toBeFalse(); + + Artisan::call("ddd:controller {$domainName}:{$controllerName}"); + + expect(file_exists($expectedPath))->toBeTrue(); + + expect(file_get_contents($expectedPath)) + ->toContain("namespace {$expectedNamespace};") + ->not->toContain("use App\Http\Controllers\Controller;") + ->not->toContain("extends Controller"); + + // Reset the application skeleton + $this->setupTestApplication(); +})->with([ + 'Invoicing:InvoiceController' => [ + 'Invoicing', + 'InvoiceController', + 'app/Modules/Invoicing/Controllers/InvoiceController.php', + 'App\Modules\Invoicing\Controllers', + ], +]); + +it('does not attempt to extend base controller when using custom stubs', function ($domainName, $controllerName, $relativePath, $expectedNamespace, $stubFolder) { + $this->setupTestApplication(); + + $expectedPath = base_path($relativePath); + + if (file_exists($expectedPath)) { + unlink($expectedPath); + } + + expect(file_exists($expectedPath))->toBeFalse(); + + $baseControllerPath = app()->basePath('app/Http/Controllers/Controller.php'); + + expect(file_exists($baseControllerPath))->toBeTrue(); + + // Publish a custom controller.stub + $customStub = <<basePath($stubFolder)); + file_put_contents(app()->basePath($stubFolder.'/controller.plain.stub'), $customStub); + expect(file_exists(app()->basePath($stubFolder.'/controller.plain.stub')))->toBeTrue(); + + Artisan::call("ddd:controller {$domainName}:{$controllerName}"); + + expect(file_exists($expectedPath))->toBeTrue(); + + expect(file_get_contents($expectedPath)) + ->toContain("namespace {$expectedNamespace};") + ->toContain("use CustomControllerTrait;") + ->not->toContain("use App\Http\Controllers\Controller;") + ->not->toContain("extends Controller"); + + $this->cleanStubs(); +})->with([ + 'Invoicing:InvoiceController' => [ + 'Invoicing', + 'InvoiceController', + 'app/Modules/Invoicing/Controllers/InvoiceController.php', + 'App\Modules\Invoicing\Controllers', + ], +])->with([ + 'stubs', + 'stubs/ddd', +]); diff --git a/tests/Generator/Model/MakeWithControllerTest.php b/tests/Generator/Model/MakeWithControllerTest.php index 629933f..c5f1077 100644 --- a/tests/Generator/Model/MakeWithControllerTest.php +++ b/tests/Generator/Model/MakeWithControllerTest.php @@ -75,16 +75,4 @@ 'app/Modules/Reporting/Internal/Controllers/ReportSubmissionController.php', ], ], - - // '--controller --api' => [ - // ['--controller' => true, '--api' => true], - // 'RecordController', - // 'app/Http/Controllers/Invoicing/RecordController.php', - // ], - - // '--controller --requests' => [ - // ['--controller' => true, '--requests' => true], - // 'RecordController', - // 'app/Http/Controllers/Invoicing/RecordController.php', - // ], ]); diff --git a/tests/TestCase.php b/tests/TestCase.php index b04ef5a..acf1c16 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -33,7 +33,7 @@ protected function setUp(): void // ); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Lunarstorm\\LaravelDDD\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn(string $modelName) => 'Lunarstorm\\LaravelDDD\\Database\\Factories\\' . class_basename($modelName) . 'Factory' ); }); @@ -140,7 +140,7 @@ protected function composerReload() protected function cleanSlate() { - File::copy(__DIR__.'/.skeleton/composer.json', base_path('composer.json')); + File::copy(__DIR__ . '/.skeleton/composer.json', base_path('composer.json')); File::delete(base_path('config/ddd.php')); @@ -148,6 +148,7 @@ protected function cleanSlate() File::cleanDirectory(base_path('database/factories')); File::deleteDirectory(resource_path('stubs/ddd')); + File::deleteDirectory(base_path('stubs')); File::deleteDirectory(base_path('Custom')); File::deleteDirectory(base_path('src/Domain')); File::deleteDirectory(base_path('src/Domains')); @@ -157,12 +158,17 @@ protected function cleanSlate() File::deleteDirectory(base_path('bootstrap/cache/ddd')); } + protected function cleanStubs() + { + File::cleanDirectory(base_path('stubs')); + } + protected function setupTestApplication() { - File::copyDirectory(__DIR__.'/.skeleton/app', app_path()); - File::copyDirectory(__DIR__.'/.skeleton/database', base_path('database')); - File::copyDirectory(__DIR__.'/.skeleton/src/Domain', base_path('src/Domain')); - File::copy(__DIR__.'/.skeleton/bootstrap/providers.php', base_path('bootstrap/providers.php')); + File::copyDirectory(__DIR__ . '/.skeleton/app', app_path()); + File::copyDirectory(__DIR__ . '/.skeleton/database', base_path('database')); + File::copyDirectory(__DIR__ . '/.skeleton/src/Domain', base_path('src/Domain')); + File::copy(__DIR__ . '/.skeleton/bootstrap/providers.php', base_path('bootstrap/providers.php')); File::ensureDirectoryExists(app_path('Models')); $this->setDomainPathInComposer('Domain', 'src/Domain'); @@ -172,7 +178,7 @@ protected function setDomainPathInComposer($domainNamespace, $domainPath, bool $ { $this->updateComposer( set: [ - [['autoload', 'psr-4', $domainNamespace.'\\'], $domainPath], + [['autoload', 'psr-4', $domainNamespace . '\\'], $domainPath], ], );