diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d6c9af..0a7dfed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,11 @@ All notable changes to `laravel-ddd` will be documented in this file. ## [Unreleased] +### Breaking +- Stubs are now published to `/stubs/ddd/*` instead of `resources/stubs/ddd/*`. If you have ddd stubs published from a prior version, they should be relocated. + ### Added -- Experimental: Ability to configure the Application Layer, to generate domain objects that don't typically belong inside the domain layer. +- Ability to configure the Application Layer, to generate domain objects that don't typically belong inside the domain layer. ```php // In config/ddd.php 'application' => [ @@ -22,6 +25,7 @@ All notable changes to `laravel-ddd` will be documented in this file. - Added `ddd:middleware` to generate domain-specific middleware in the application layer. - Added `ddd:migration` to generate domain migrations. - Added `ddd:seeder` to generate domain seeders. +- Added `ddd:stub` to list, search, and publish one or more stubs as needed. - Migration folders across domains will be registered and scanned when running `php artisan migrate`, in addition to the standard application `database/migrations` path. ### Changed diff --git a/README.md b/README.md index beb7412..0906314 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Actions: [lorisleiva/laravel-actions](https://github.com/lorisleiva/laravel-acti ```bash composer require lorisleiva/laravel-actions ``` -The default DTO and Action stubs of this package reference classes from these packages. If this doesn't apply to your application, you may customize the stubs accordingly. +The default DTO and Action stubs of this package reference classes from these packages. If this doesn't apply to your application, you may [customize the stubs](#publishing-stubs-advanced) accordingly. ### Deployment In production, run `ddd:optimize` during the deployment process to [optimize autoloading](#autoloading-in-production). @@ -147,8 +147,8 @@ Output: │ └─ UpdateInvoiceRequest.php ├─ src/Domain └─ Invoicing - └─ Models - └─ Invoice.php + └─ Models + └─ Invoice.php ``` ### Nested Objects @@ -211,13 +211,49 @@ php artisan ddd:view-model Reporting.Customer:MonthlyInvoicesReportViewModel ``` ## Customization +### Config File This package ships with opinionated (but sensible) configuration defaults. You may customize by publishing the [config file](#config-file) and generator stubs as needed: ```bash -php artisan vendor:publish --tag="ddd-config" -php artisan vendor:publish --tag="ddd-stubs" +php artisan ddd:publish --config +php artisan ddd:publish --stubs +``` + +### Publishing Stubs (Advanced) +For more granular management of stubs, you may use the `ddd:stub` command: +```bash +# Publish one or more stubs interactively via prompts +php artisan ddd:stub + +# Publish all stubs +php artisan ddd:stub --all + +# Publish and overwrite only the files that have already been published +php artisan ddd:stub --all --existing + +# Overwrite any existing files +php artisan ddd:stub --all --force + +# Publish one or more stubs specified as arguments +php artisan ddd:stub model +php artisan ddd:stub model dto action +php artisan ddd:stub controller controller.plain controller.api +``` +To publish multiple related stubs at once, use `*` or `.` as a wildcard ending. +```bash +php artisan ddd:stub listener. +``` +Output: +```bash +Publishing /stubs/ddd/listener.typed.queued.stub +Publishing /stubs/ddd/listener.queued.stub +Publishing /stubs/ddd/listener.typed.stub +Publishing /stubs/ddd/listener.stub +``` +For a quick reference of available stubs, use the `--list` option: +```bash +php artisan ddd:stub --list ``` -Note that the extended commands do not publish ddd-specific stubs, and inherit the respective application-level stubs published by Laravel. ## Domain Autoloading and Discovery Autoloading behaviour can be configured with the `ddd.autoload` configuration option. By default, domain providers, commands, policies, and factories are auto-discovered and registered. diff --git a/src/Commands/Concerns/HasDomainStubs.php b/src/Commands/Concerns/HasDomainStubs.php new file mode 100644 index 0000000..591511d --- /dev/null +++ b/src/Commands/Concerns/HasDomainStubs.php @@ -0,0 +1,70 @@ +resolvePublishedDddStub($stub)) { + $stub = $publishedStub; + } + + $this->usingPublishedStub(str($stub)->startsWith(app()->basePath('stubs'))); + + 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))) { + return $publishedPath; + } + + // Also check for legacy stub extensions + if (file_exists($legacyPublishedPath = Str::replaceLast('.stub', '.php.stub', $publishedPath))) { + return $legacyPublishedPath; + } + + return null; + } + + protected function resolveDddStubPath($path) + { + $path = str($path) + ->basename() + ->ltrim('/\\') + ->toString(); + + if ($publishedPath = $this->resolvePublishedDddStub($path)) { + return $publishedPath; + } + + return DDD::packagePath('stubs/'.$path); + } +} diff --git a/src/Commands/Concerns/InteractsWithStubs.php b/src/Commands/Concerns/InteractsWithStubs.php new file mode 100644 index 0000000..02e9472 --- /dev/null +++ b/src/Commands/Concerns/InteractsWithStubs.php @@ -0,0 +1,32 @@ +preparePlaceholders(); + + foreach ($placeholders as $placeholder => $value) { + $stub = $this->fillPlaceholder($stub, $placeholder, $value ?? ''); + } + + return $stub; + } + + protected function buildClass($name) + { + return $this->applyPlaceholders(parent::buildClass($name)); + } +} diff --git a/src/Commands/DomainActionMakeCommand.php b/src/Commands/DomainActionMakeCommand.php index c1a14f2..3218457 100644 --- a/src/Commands/DomainActionMakeCommand.php +++ b/src/Commands/DomainActionMakeCommand.php @@ -2,8 +2,12 @@ namespace Lunarstorm\LaravelDDD\Commands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; + class DomainActionMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:action'; /** @@ -17,7 +21,7 @@ class DomainActionMakeCommand extends DomainGeneratorCommand protected function getStub() { - return $this->resolveStubPath('action.php.stub'); + return $this->resolveDddStubPath('action.stub'); } protected function preparePlaceholders(): array diff --git a/src/Commands/DomainBaseModelMakeCommand.php b/src/Commands/DomainBaseModelMakeCommand.php index 559cd59..1dac48f 100644 --- a/src/Commands/DomainBaseModelMakeCommand.php +++ b/src/Commands/DomainBaseModelMakeCommand.php @@ -2,10 +2,13 @@ namespace Lunarstorm\LaravelDDD\Commands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Symfony\Component\Console\Input\InputArgument; class DomainBaseModelMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:base-model'; /** @@ -31,7 +34,7 @@ protected function getArguments() protected function getStub() { - return $this->resolveStubPath('base-model.php.stub'); + return $this->resolveDddStubPath('base-model.stub'); } protected function getRelativeDomainNamespace(): string diff --git a/src/Commands/DomainBaseViewModelMakeCommand.php b/src/Commands/DomainBaseViewModelMakeCommand.php index afac4f7..3436b12 100644 --- a/src/Commands/DomainBaseViewModelMakeCommand.php +++ b/src/Commands/DomainBaseViewModelMakeCommand.php @@ -2,10 +2,13 @@ namespace Lunarstorm\LaravelDDD\Commands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Symfony\Component\Console\Input\InputArgument; class DomainBaseViewModelMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:base-view-model'; /** @@ -31,7 +34,7 @@ protected function getArguments() protected function getStub() { - return $this->resolveStubPath('base-view-model.php.stub'); + return $this->resolveDddStubPath('base-view-model.stub'); } protected function getRelativeDomainNamespace(): string diff --git a/src/Commands/DomainCastMakeCommand.php b/src/Commands/DomainCastMakeCommand.php index 30531e4..da230a0 100644 --- a/src/Commands/DomainCastMakeCommand.php +++ b/src/Commands/DomainCastMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\CastMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainCastMakeCommand extends CastMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:cast'; } diff --git a/src/Commands/DomainChannelMakeCommand.php b/src/Commands/DomainChannelMakeCommand.php index f3e5ba5..3bee9b9 100644 --- a/src/Commands/DomainChannelMakeCommand.php +++ b/src/Commands/DomainChannelMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ChannelMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainChannelMakeCommand extends ChannelMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:channel'; } diff --git a/src/Commands/DomainClassMakeCommand.php b/src/Commands/DomainClassMakeCommand.php index 242788b..a657407 100644 --- a/src/Commands/DomainClassMakeCommand.php +++ b/src/Commands/DomainClassMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ClassMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainClassMakeCommand extends ClassMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:class'; } diff --git a/src/Commands/DomainConsoleMakeCommand.php b/src/Commands/DomainConsoleMakeCommand.php index 6496db9..f78cd39 100644 --- a/src/Commands/DomainConsoleMakeCommand.php +++ b/src/Commands/DomainConsoleMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ConsoleMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainConsoleMakeCommand extends ConsoleMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:command'; } diff --git a/src/Commands/DomainControllerMakeCommand.php b/src/Commands/DomainControllerMakeCommand.php index aa2a373..47f03dc 100644 --- a/src/Commands/DomainControllerMakeCommand.php +++ b/src/Commands/DomainControllerMakeCommand.php @@ -4,6 +4,7 @@ use Illuminate\Routing\Console\ControllerMakeCommand; use Lunarstorm\LaravelDDD\Commands\Concerns\ForwardsToDomainCommands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; use function Laravel\Prompts\confirm; @@ -11,6 +12,7 @@ class DomainControllerMakeCommand extends ControllerMakeCommand { use ForwardsToDomainCommands, + HasDomainStubs, ResolvesDomainFromInput; protected $name = 'ddd:controller'; @@ -79,4 +81,38 @@ protected function buildFormRequestReplacements(array $replace, $modelClass) '{{namespacedRequests}}' => $namespacedRequests, ]); } + + protected function buildClass($name) + { + $stub = parent::buildClass($name); + + if ($this->isUsingPublishedStub()) { + return $stub; + } + + $replace = []; + + // Todo: these were attempted tweaks to counteract failing CI tests + // on Laravel 10, and should be revisited at some point. + // $replace["use {$this->rootNamespace()}Http\Controllers\Controller;\n"] = ''; + // $replace[' extends Controller'] = ''; + + $appRootNamespace = $this->laravel->getNamespace(); + $pathToAppBaseController = parent::getPath("Http\Controllers\Controller"); + + $baseControllerExists = $this->files->exists($pathToAppBaseController); + + if ($baseControllerExists) { + $controllerClass = class_basename($name); + $replace["\nclass {$controllerClass}\n"] = "\nuse {$appRootNamespace}Http\Controllers\Controller;\n\nclass {$controllerClass} extends Controller\n"; + } + + $stub = str_replace( + array_keys($replace), + array_values($replace), + $stub + ); + + return $this->sortImports($stub); + } } diff --git a/src/Commands/DomainDtoMakeCommand.php b/src/Commands/DomainDtoMakeCommand.php index ac4ef3f..b8612cf 100644 --- a/src/Commands/DomainDtoMakeCommand.php +++ b/src/Commands/DomainDtoMakeCommand.php @@ -2,8 +2,12 @@ namespace Lunarstorm\LaravelDDD\Commands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; + class DomainDtoMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:dto'; /** @@ -28,7 +32,7 @@ protected function configure() protected function getStub() { - return $this->resolveStubPath('dto.php.stub'); + return $this->resolveDddStubPath('dto.stub'); } protected function getRelativeDomainNamespace(): string diff --git a/src/Commands/DomainEnumMakeCommand.php b/src/Commands/DomainEnumMakeCommand.php index d3110b7..3348186 100644 --- a/src/Commands/DomainEnumMakeCommand.php +++ b/src/Commands/DomainEnumMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\EnumMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainEnumMakeCommand extends EnumMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:enum'; } diff --git a/src/Commands/DomainEventMakeCommand.php b/src/Commands/DomainEventMakeCommand.php index de4a11b..fcba974 100644 --- a/src/Commands/DomainEventMakeCommand.php +++ b/src/Commands/DomainEventMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\EventMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainEventMakeCommand extends EventMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:event'; } diff --git a/src/Commands/DomainExceptionMakeCommand.php b/src/Commands/DomainExceptionMakeCommand.php index c9871e7..f794dc1 100644 --- a/src/Commands/DomainExceptionMakeCommand.php +++ b/src/Commands/DomainExceptionMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ExceptionMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainExceptionMakeCommand extends ExceptionMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:exception'; } diff --git a/src/Commands/DomainFactoryMakeCommand.php b/src/Commands/DomainFactoryMakeCommand.php index 6a1a104..1c53382 100644 --- a/src/Commands/DomainFactoryMakeCommand.php +++ b/src/Commands/DomainFactoryMakeCommand.php @@ -2,50 +2,27 @@ namespace Lunarstorm\LaravelDDD\Commands; -use Symfony\Component\Console\Input\InputOption; +use Illuminate\Database\Console\Factories\FactoryMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; +use Lunarstorm\LaravelDDD\Commands\Concerns\InteractsWithStubs; +use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; -class DomainFactoryMakeCommand extends DomainGeneratorCommand +class DomainFactoryMakeCommand extends FactoryMakeCommand { - protected $name = 'ddd:factory'; - - /** - * The console command description. - * - * @var string - */ - protected $description = 'Generate a domain model factory'; + use HasDomainStubs, + InteractsWithStubs, + ResolvesDomainFromInput; - protected $type = 'Factory'; - - protected function getOptions() - { - return [ - ...parent::getOptions(), - ['model', 'm', InputOption::VALUE_OPTIONAL, 'The name of the model'], - ]; - } + protected $name = 'ddd:factory'; protected function getStub() { - return $this->resolveStubPath('factory.php.stub'); + return $this->resolveDddStubPath('factory.stub'); } - protected function getPath($name) + protected function getNamespace($name) { - if (! str_ends_with($name, 'Factory')) { - $name .= 'Factory'; - } - - return parent::getPath($name); - } - - protected function getFactoryName() - { - $name = $this->getNameInput(); - - return str_ends_with($name, 'Factory') - ? substr($name, 0, -7) - : $name; + return $this->domain->namespaceFor('factory'); } protected function preparePlaceholders(): array @@ -60,16 +37,10 @@ protected function preparePlaceholders(): array $domainFactory = $domain->factory($name); - // dump('preparing placeholders', [ - // 'name' => $name, - // 'modelName' => $modelName, - // 'domainFactory' => $domainFactory, - // ]); - return [ 'namespacedModel' => $domainModel->fullyQualifiedName, 'model' => class_basename($domainModel->fullyQualifiedName), - 'factory' => $this->getFactoryName(), + 'factory' => $domainFactory->name, 'namespace' => $domainFactory->namespace, ]; } @@ -80,6 +51,6 @@ protected function guessModelName($name) $name = substr($name, 0, -7); } - return $this->domain->model($name)->name; + return $this->domain->model(class_basename($name))->name; } } diff --git a/src/Commands/DomainGeneratorCommand.php b/src/Commands/DomainGeneratorCommand.php index 6421409..9dc8dd2 100644 --- a/src/Commands/DomainGeneratorCommand.php +++ b/src/Commands/DomainGeneratorCommand.php @@ -4,12 +4,14 @@ use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Str; +use Lunarstorm\LaravelDDD\Commands\Concerns\InteractsWithStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; use Lunarstorm\LaravelDDD\Support\DomainResolver; abstract class DomainGeneratorCommand extends GeneratorCommand { - use ResolvesDomainFromInput; + use InteractsWithStubs, + ResolvesDomainFromInput; protected function getRelativeDomainNamespace(): string { @@ -21,40 +23,40 @@ protected function getNameInput() return Str::studly($this->argument('name')); } - protected function resolveStubPath($path) - { - $path = ltrim($path, '/\\'); + // protected function resolveStubPath($path) + // { + // $path = ltrim($path, '/\\'); - $publishedPath = resource_path('stubs/ddd/'.$path); + // $publishedPath = resource_path('stubs/ddd/'.$path); - return file_exists($publishedPath) - ? $publishedPath - : __DIR__.DIRECTORY_SEPARATOR.'../../stubs'.DIRECTORY_SEPARATOR.$path; - } + // return file_exists($publishedPath) + // ? $publishedPath + // : __DIR__.DIRECTORY_SEPARATOR.'../../stubs'.DIRECTORY_SEPARATOR.$path; + // } - protected function fillPlaceholder($stub, $placeholder, $value) - { - return str_replace(["{{$placeholder}}", "{{ $placeholder }}"], $value, $stub); - } + // protected function fillPlaceholder($stub, $placeholder, $value) + // { + // return str_replace(["{{$placeholder}}", "{{ $placeholder }}"], $value, $stub); + // } - protected function preparePlaceholders(): array - { - return []; - } + // protected function preparePlaceholders(): array + // { + // return []; + // } - protected function applyPlaceholders($stub) - { - $placeholders = $this->preparePlaceholders(); + // protected function applyPlaceholders($stub) + // { + // $placeholders = $this->preparePlaceholders(); - foreach ($placeholders as $placeholder => $value) { - $stub = $this->fillPlaceholder($stub, $placeholder, $value ?? ''); - } + // foreach ($placeholders as $placeholder => $value) { + // $stub = $this->fillPlaceholder($stub, $placeholder, $value ?? ''); + // } - return $stub; - } + // return $stub; + // } - protected function buildClass($name) - { - return $this->applyPlaceholders(parent::buildClass($name)); - } + // protected function buildClass($name) + // { + // return $this->applyPlaceholders(parent::buildClass($name)); + // } } diff --git a/src/Commands/DomainInterfaceMakeCommand.php b/src/Commands/DomainInterfaceMakeCommand.php index 3fbccef..82735d6 100644 --- a/src/Commands/DomainInterfaceMakeCommand.php +++ b/src/Commands/DomainInterfaceMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\InterfaceMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainInterfaceMakeCommand extends InterfaceMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:interface'; } diff --git a/src/Commands/DomainJobMakeCommand.php b/src/Commands/DomainJobMakeCommand.php index 7fc5e37..fd9afbd 100644 --- a/src/Commands/DomainJobMakeCommand.php +++ b/src/Commands/DomainJobMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\JobMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainJobMakeCommand extends JobMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:job'; } diff --git a/src/Commands/DomainListenerMakeCommand.php b/src/Commands/DomainListenerMakeCommand.php index 9726d20..0072172 100644 --- a/src/Commands/DomainListenerMakeCommand.php +++ b/src/Commands/DomainListenerMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ListenerMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainListenerMakeCommand extends ListenerMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:listener'; } diff --git a/src/Commands/DomainMailMakeCommand.php b/src/Commands/DomainMailMakeCommand.php index 15f9508..ef6d0e8 100644 --- a/src/Commands/DomainMailMakeCommand.php +++ b/src/Commands/DomainMailMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\MailMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainMailMakeCommand extends MailMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:mail'; } diff --git a/src/Commands/DomainMiddlewareMakeCommand.php b/src/Commands/DomainMiddlewareMakeCommand.php index 2c6b2af..9a2a041 100644 --- a/src/Commands/DomainMiddlewareMakeCommand.php +++ b/src/Commands/DomainMiddlewareMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Routing\Console\MiddlewareMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainMiddlewareMakeCommand extends MiddlewareMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:middleware'; } diff --git a/src/Commands/DomainModelMakeCommand.php b/src/Commands/DomainModelMakeCommand.php index c92ccdd..1bc72b3 100644 --- a/src/Commands/DomainModelMakeCommand.php +++ b/src/Commands/DomainModelMakeCommand.php @@ -5,12 +5,14 @@ use Illuminate\Foundation\Console\ModelMakeCommand; use Illuminate\Support\Str; use Lunarstorm\LaravelDDD\Commands\Concerns\ForwardsToDomainCommands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; use Lunarstorm\LaravelDDD\Support\DomainResolver; class DomainModelMakeCommand extends ModelMakeCommand { use ForwardsToDomainCommands, + HasDomainStubs, ResolvesDomainFromInput; protected $name = 'ddd:model'; @@ -31,32 +33,51 @@ public function handle() $this->afterHandle(); } + protected function buildFactoryReplacements() + { + $replacements = parent::buildFactoryReplacements(); + + if ($this->option('factory')) { + $factoryNamespace = Str::start($this->domain->factory($this->getNameInput())->fullyQualifiedName, '\\'); + + $factoryCode = << */ + use HasFactory; + EOT; + + $replacements['{{ factory }}'] = $factoryCode; + $replacements['{{ factoryImport }}'] = 'use Lunarstorm\LaravelDDD\Factories\HasDomainFactory as HasFactory;'; + } + + return $replacements; + } + protected function buildClass($name) { $stub = parent::buildClass($name); - $replacements = [ - 'use Illuminate\Database\Eloquent\Factories\HasFactory;' => "use Lunarstorm\LaravelDDD\Factories\HasDomainFactory as HasFactory;", - ]; + if ($this->isUsingPublishedStub()) { + return $stub; + } + + $replace = []; if ($baseModel = $this->getBaseModel()) { $baseModelClass = class_basename($baseModel); - $replacements = array_merge($replacements, [ + $replace = array_merge($replace, [ 'extends Model' => "extends {$baseModelClass}", 'use Illuminate\Database\Eloquent\Model;' => "use {$baseModel};", ]); } $stub = str_replace( - array_keys($replacements), - array_values($replacements), + array_keys($replace), + array_values($replace), $stub ); - $stub = $this->sortImports($stub); - - return $stub; + return $this->sortImports($stub); } protected function createBaseModelIfNeeded() diff --git a/src/Commands/DomainModelMakeLegacyCommand.php b/src/Commands/DomainModelMakeLegacyCommand.php deleted file mode 100644 index 37c8164..0000000 --- a/src/Commands/DomainModelMakeLegacyCommand.php +++ /dev/null @@ -1,108 +0,0 @@ -resolveStubPath('model.php.stub'); - } - - protected function preparePlaceholders(): array - { - $baseClass = config('ddd.base_model'); - $baseClassName = class_basename($baseClass); - - return [ - 'extends' => filled($baseClass) ? " extends {$baseClassName}" : '', - 'baseClassImport' => filled($baseClass) ? "use {$baseClass};" : '', - ]; - } - - public function handle() - { - $this->createBaseModelIfNeeded(); - - parent::handle(); - - if ($this->option('factory')) { - $this->createFactory(); - } - } - - protected function createBaseModelIfNeeded() - { - if (! $this->shouldCreateBaseModel()) { - return; - } - - $baseModel = config('ddd.base_model'); - - $this->warn("Base model {$baseModel} doesn't exist, generating..."); - - $domain = DomainResolver::guessDomainFromClass($baseModel); - - $name = Str::after($baseModel, $domain); - - $this->call(DomainBaseModelMakeCommand::class, [ - '--domain' => $domain, - 'name' => $name, - ]); - } - - protected function shouldCreateBaseModel(): bool - { - $baseModel = config('ddd.base_model'); - - // If the class exists, we don't need to create it. - if (class_exists($baseModel)) { - return false; - } - - // If the class is outside of the domain layer, we won't attempt to create it. - if (! DomainResolver::isDomainClass($baseModel)) { - return false; - } - - // At this point the class is probably a domain object, but we should - // check if the expected path exists. - if (file_exists(app()->basePath(DomainResolver::guessPathFromClass($baseModel)))) { - return false; - } - - return true; - } - - protected function createFactory() - { - $this->call(DomainFactoryMakeCommand::class, [ - 'name' => $this->getNameInput().'Factory', - '--domain' => $this->domain->dotName, - '--model' => $this->qualifyClass($this->getNameInput()), - ]); - } -} diff --git a/src/Commands/DomainNotificationMakeCommand.php b/src/Commands/DomainNotificationMakeCommand.php index 04de8ab..099cd9a 100644 --- a/src/Commands/DomainNotificationMakeCommand.php +++ b/src/Commands/DomainNotificationMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\NotificationMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainNotificationMakeCommand extends NotificationMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:notification'; } diff --git a/src/Commands/DomainObserverMakeCommand.php b/src/Commands/DomainObserverMakeCommand.php index 9668230..9351b53 100644 --- a/src/Commands/DomainObserverMakeCommand.php +++ b/src/Commands/DomainObserverMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ObserverMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainObserverMakeCommand extends ObserverMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:observer'; } diff --git a/src/Commands/DomainPolicyMakeCommand.php b/src/Commands/DomainPolicyMakeCommand.php index bbf57f3..180223f 100644 --- a/src/Commands/DomainPolicyMakeCommand.php +++ b/src/Commands/DomainPolicyMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\PolicyMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainPolicyMakeCommand extends PolicyMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:policy'; } diff --git a/src/Commands/DomainProviderMakeCommand.php b/src/Commands/DomainProviderMakeCommand.php index dcc2c8a..8ee4dcc 100644 --- a/src/Commands/DomainProviderMakeCommand.php +++ b/src/Commands/DomainProviderMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ProviderMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainProviderMakeCommand extends ProviderMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:provider'; } diff --git a/src/Commands/DomainRequestMakeCommand.php b/src/Commands/DomainRequestMakeCommand.php index a6a1ddf..88cad30 100644 --- a/src/Commands/DomainRequestMakeCommand.php +++ b/src/Commands/DomainRequestMakeCommand.php @@ -4,20 +4,17 @@ use Illuminate\Foundation\Console\RequestMakeCommand; use Illuminate\Support\Str; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; use Lunarstorm\LaravelDDD\Support\DomainResolver; class DomainRequestMakeCommand extends RequestMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:request'; - // protected function getDefaultNamespace($rootNamespace) - // { - // return $rootNamespace.'\Http\Requests'; - // } - protected function rootNamespace() { $type = $this->guessObjectType(); diff --git a/src/Commands/DomainResourceMakeCommand.php b/src/Commands/DomainResourceMakeCommand.php index 36b3715..4e79208 100644 --- a/src/Commands/DomainResourceMakeCommand.php +++ b/src/Commands/DomainResourceMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ResourceMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainResourceMakeCommand extends ResourceMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:resource'; } diff --git a/src/Commands/DomainRuleMakeCommand.php b/src/Commands/DomainRuleMakeCommand.php index 50c6083..f82aec1 100644 --- a/src/Commands/DomainRuleMakeCommand.php +++ b/src/Commands/DomainRuleMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\RuleMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainRuleMakeCommand extends RuleMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:rule'; } diff --git a/src/Commands/DomainScopeMakeCommand.php b/src/Commands/DomainScopeMakeCommand.php index 9dfe7d7..43e2fd0 100644 --- a/src/Commands/DomainScopeMakeCommand.php +++ b/src/Commands/DomainScopeMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\ScopeMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainScopeMakeCommand extends ScopeMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:scope'; } diff --git a/src/Commands/DomainSeederMakeCommand.php b/src/Commands/DomainSeederMakeCommand.php index 6ee413d..302a073 100644 --- a/src/Commands/DomainSeederMakeCommand.php +++ b/src/Commands/DomainSeederMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Database\Console\Seeds\SeederMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainSeederMakeCommand extends SeederMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:seeder'; } diff --git a/src/Commands/DomainTraitMakeCommand.php b/src/Commands/DomainTraitMakeCommand.php index d377b52..1cb86a5 100644 --- a/src/Commands/DomainTraitMakeCommand.php +++ b/src/Commands/DomainTraitMakeCommand.php @@ -3,11 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Foundation\Console\TraitMakeCommand; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Commands\Concerns\ResolvesDomainFromInput; class DomainTraitMakeCommand extends TraitMakeCommand { - use ResolvesDomainFromInput; + use HasDomainStubs, + ResolvesDomainFromInput; protected $name = 'ddd:trait'; } diff --git a/src/Commands/DomainValueObjectMakeCommand.php b/src/Commands/DomainValueObjectMakeCommand.php index 27de72b..16e7102 100644 --- a/src/Commands/DomainValueObjectMakeCommand.php +++ b/src/Commands/DomainValueObjectMakeCommand.php @@ -2,8 +2,12 @@ namespace Lunarstorm\LaravelDDD\Commands; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; + class DomainValueObjectMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:value'; /** @@ -27,6 +31,6 @@ protected function configure() protected function getStub() { - return $this->resolveStubPath('value-object.php.stub'); + return $this->resolveDddStubPath('value-object.stub'); } } diff --git a/src/Commands/DomainViewModelMakeCommand.php b/src/Commands/DomainViewModelMakeCommand.php index e097cae..c457405 100644 --- a/src/Commands/DomainViewModelMakeCommand.php +++ b/src/Commands/DomainViewModelMakeCommand.php @@ -3,10 +3,13 @@ namespace Lunarstorm\LaravelDDD\Commands; use Illuminate\Support\Str; +use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs; use Lunarstorm\LaravelDDD\Support\DomainResolver; class DomainViewModelMakeCommand extends DomainGeneratorCommand { + use HasDomainStubs; + protected $name = 'ddd:view-model'; /** @@ -29,7 +32,7 @@ protected function configure() protected function getStub() { - return $this->resolveStubPath('view-model.php.stub'); + return $this->resolveDddStubPath('view-model.stub'); } protected function preparePlaceholders(): array diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index 1ad031e..e37d186 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -23,11 +23,7 @@ public function handle(): int $this->registerDomainAutoload(); if ($this->confirm('Would you like to publish stubs?')) { - $this->comment('Publishing stubs...'); - - $this->callSilently('vendor:publish', [ - '--tag' => 'ddd-stubs', - ]); + $this->call('ddd:stub'); } return self::SUCCESS; diff --git a/src/Commands/PublishCommand.php b/src/Commands/PublishCommand.php new file mode 100644 index 0000000..9180b84 --- /dev/null +++ b/src/Commands/PublishCommand.php @@ -0,0 +1,63 @@ + 'Stubs', + 'config' => 'Config File', + ]; + + return multiselect( + label: 'What should be published?', + options: $options, + required: true + ); + } + + public function handle(): int + { + $thingsToPublish = [ + ...$this->option('config') ? ['config'] : [], + ...$this->option('stubs') ? ['stubs'] : [], + ...$this->option('all') ? ['config', 'stubs'] : [], + ] ?: $this->askForThingsToPublish(); + + if (in_array('config', $thingsToPublish)) { + $this->comment('Publishing config...'); + $this->call('vendor:publish', [ + '--tag' => 'ddd-config', + ]); + } + + if (in_array('stubs', $thingsToPublish)) { + $this->comment('Publishing stubs...'); + $this->call('ddd:stub', [ + '--all' => true, + ]); + } + + return self::SUCCESS; + } +} diff --git a/src/Commands/StubCommand.php b/src/Commands/StubCommand.php new file mode 100644 index 0000000..984ad52 --- /dev/null +++ b/src/Commands/StubCommand.php @@ -0,0 +1,163 @@ +stubs()->dddStubs(), + ...app('ddd')->stubs()->frameworkStubs(), + ]; + } + + protected function resolveSelectedStubs(array $names = []) + { + $stubs = $this->getStubChoices(); + + if ($names) { + [$startsWith, $exactNames] = collect($names) + ->partition(fn ($name) => str($name)->endsWith(['*', '.'])); + + $startsWith = $startsWith->map( + fn ($name) => str($name) + ->replaceEnd('*', '.') + ->replaceEnd('.', '') + ); + + return collect($stubs) + ->filter(function ($stub, $path) use ($startsWith, $exactNames) { + $stubWithoutExtension = str($stub)->replaceEnd('.stub', ''); + + return $exactNames->contains($stub) + || $exactNames->contains($stubWithoutExtension) + || str($stub)->startsWith($startsWith); + }) + ->all(); + } + + $selected = multisearch( + label: 'Which stub should be published?', + placeholder: 'Search for a stub...', + options: fn (string $value) => strlen($value) > 0 + ? collect($stubs)->filter(fn ($stub, $path) => str($stub)->contains($value))->all() + : $stubs, + required: true + ); + + return collect($stubs) + ->filter(fn ($stub, $path) => in_array($stub, $selected)) + ->all(); + } + + public function handle(): int + { + $option = match (true) { + $this->option('list') => 'list', + $this->option('all') => 'all', + count($this->argument('name')) > 0 => 'named', + default => select( + label: 'What do you want to do?', + options: [ + 'some' => 'Choose stubs to publish', + 'all' => 'Publish all stubs', + ], + required: true, + default: 'some' + ) + }; + + if ($option === 'list') { + // $this->table( + // ['Stub', 'Path'], + // collect($this->getStubChoices())->map( + // fn($stub, $path) => [ + // $stub, + // Str::after($path, $this->laravel->basePath()) + // ] + // ) + // ); + + table( + headers: ['Stub', 'Source'], + rows: collect($this->getStubChoices())->map( + fn ($stub, $path) => [ + Str::replaceLast('.stub', '', $stub), + str($path)->startsWith(DDD::packagePath()) + ? 'ddd' + : 'laravel', + ] + ) + ); + + return self::SUCCESS; + } + + $stubs = $option === 'all' + ? $this->getStubChoices() + : $this->resolveSelectedStubs($this->argument('name')); + + if (empty($stubs)) { + $this->warn('No matching stubs found.'); + + return self::INVALID; + } + + File::ensureDirectoryExists($stubsPath = $this->laravel->basePath('stubs/ddd')); + + $this->laravel['events']->dispatch($event = new PublishingStubs($stubs)); + + foreach ($event->stubs as $from => $to) { + $to = $stubsPath.DIRECTORY_SEPARATOR.ltrim($to, DIRECTORY_SEPARATOR); + + $relativePath = Str::after($to, $this->laravel->basePath()); + + $this->info("Publishing {$relativePath}"); + + if ((! $this->option('existing') && (! file_exists($to) || $this->option('force'))) + || ($this->option('existing') && file_exists($to)) + ) { + file_put_contents($to, file_get_contents($from)); + } + } + + $this->components->info('Stubs published successfully.'); + + return self::SUCCESS; + } +} diff --git a/src/DomainManager.php b/src/DomainManager.php index 13d465a..317c453 100755 --- a/src/DomainManager.php +++ b/src/DomainManager.php @@ -4,6 +4,7 @@ use Illuminate\Console\Command; use Lunarstorm\LaravelDDD\Support\Domain; +use Lunarstorm\LaravelDDD\Support\Path; use Lunarstorm\LaravelDDD\ValueObjects\DomainCommandContext; class DomainManager @@ -31,12 +32,15 @@ class DomainManager protected ?DomainCommandContext $commandContext; + protected StubManager $stubs; + public function __construct() { $this->autoloadFilter = null; $this->applicationLayerFilter = null; $this->namespaceResolver = null; $this->commandContext = null; + $this->stubs = new StubManager; } public function filterAutoloadPathsUsing(callable $filter): void @@ -78,4 +82,19 @@ public function getCommandContext(): ?DomainCommandContext { return $this->commandContext; } + + public function packagePath($path = ''): string + { + return Path::normalize(realpath(__DIR__.'/../'.$path)); + } + + public function laravelVersion($value) + { + return version_compare(app()->version(), $value, '>='); + } + + public function stubs(): StubManager + { + return $this->stubs; + } } diff --git a/src/Facades/DDD.php b/src/Facades/DDD.php index a5aba45..93ad644 100644 --- a/src/Facades/DDD.php +++ b/src/Facades/DDD.php @@ -3,12 +3,15 @@ namespace Lunarstorm\LaravelDDD\Facades; use Illuminate\Support\Facades\Facade; +use Lunarstorm\LaravelDDD\StubManager; /** * @see \Lunarstorm\LaravelDDD\DomainManager * * @method static void filterAutoloadPathsUsing(callable $filter) * @method static void resolveNamespaceUsing(callable $resolver) + * @method static string packagePath(string $path = '') + * @method static StubManager stubs() */ class DDD extends Facade { diff --git a/src/Factories/DomainFactory.php b/src/Factories/DomainFactory.php index 47f7fe1..5c0b7b8 100644 --- a/src/Factories/DomainFactory.php +++ b/src/Factories/DomainFactory.php @@ -36,7 +36,8 @@ public static function resolveFactoryName(string $modelName) } // First try resolving as a factory class in the domain layer - if (class_exists($factoryClass = DomainResolver::getDomainObjectNamespace($model->domain, 'factory', "{$model->name}Factory"))) { + $factoryClass = DomainResolver::getDomainObjectNamespace($model->domain, 'factory', "{$model->name}Factory"); + if (class_exists($factoryClass)) { return $factoryClass; } diff --git a/src/LaravelDDDServiceProvider.php b/src/LaravelDDDServiceProvider.php index 106ec30..c35ff7b 100644 --- a/src/LaravelDDDServiceProvider.php +++ b/src/LaravelDDDServiceProvider.php @@ -27,6 +27,8 @@ public function configurePackage(Package $package): void ->hasConfigFile() ->hasCommands([ Commands\InstallCommand::class, + Commands\PublishCommand::class, + Commands\StubCommand::class, Commands\UpgradeCommand::class, Commands\OptimizeCommand::class, Commands\OptimizeClearCommand::class, @@ -61,12 +63,22 @@ public function configurePackage(Package $package): void Commands\Migration\DomainMigrateMakeCommand::class, ]); - if (app()->version() >= 11) { + if ($this->laravelVersion(11)) { $package->hasCommand(Commands\DomainClassMakeCommand::class); $package->hasCommand(Commands\DomainEnumMakeCommand::class); $package->hasCommand(Commands\DomainInterfaceMakeCommand::class); $package->hasCommand(Commands\DomainTraitMakeCommand::class); } + + // if ($this->laravelVersion('11.30.0')) { + // $package->hasCommand(Commands\PublishCommand::class); + // $package->hasCommand(Commands\StubCommand::class); + // } + } + + protected function laravelVersion($value) + { + return version_compare(app()->version(), $value, '>='); } protected function registerMigrations() @@ -87,14 +99,14 @@ protected function registerMigrations() public function packageBooted() { $this->publishes([ - $this->package->basePath('/../stubs') => resource_path("stubs/{$this->package->shortName()}"), + $this->package->basePath('/../stubs') => $this->app->basePath("stubs/{$this->package->shortName()}"), ], "{$this->package->shortName()}-stubs"); if ($this->app->runningInConsole() && method_exists($this, 'optimizes')) { $this->optimizes( optimize: 'ddd:optimize', clear: 'ddd:clear', - key: 'ddd cache', + key: 'laravel-ddd', ); } } diff --git a/src/StubManager.php b/src/StubManager.php new file mode 100755 index 0000000..5844f40 --- /dev/null +++ b/src/StubManager.php @@ -0,0 +1,102 @@ +dddStubs(), + ...$this->frameworkStubs(), + ]; + } + + public function dddStubs() + { + return [ + realpath(__DIR__.'/../stubs/action.stub') => 'action.stub', + realpath(__DIR__.'/../stubs/dto.stub') => 'dto.stub', + realpath(__DIR__.'/../stubs/value-object.stub') => 'value-object.stub', + realpath(__DIR__.'/../stubs/view-model.stub') => 'view-model.stub', + realpath(__DIR__.'/../stubs/base-view-model.stub') => 'base-view-model.stub', + realpath(__DIR__.'/../stubs/factory.stub') => 'factory.stub', + ]; + } + + public function frameworkStubs() + { + $laravelStubCommand = new ReflectionClass(new StubPublishCommand); + + $dir = dirname($laravelStubCommand->getFileName()); + + $stubs = [ + $dir.'/stubs/cast.inbound.stub' => 'cast.inbound.stub', + $dir.'/stubs/cast.stub' => 'cast.stub', + $dir.'/stubs/class.stub' => 'class.stub', + $dir.'/stubs/class.invokable.stub' => 'class.invokable.stub', + $dir.'/stubs/console.stub' => 'console.stub', + $dir.'/stubs/enum.stub' => 'enum.stub', + $dir.'/stubs/enum.backed.stub' => 'enum.backed.stub', + $dir.'/stubs/event.stub' => 'event.stub', + $dir.'/stubs/job.queued.stub' => 'job.queued.stub', + $dir.'/stubs/job.stub' => 'job.stub', + $dir.'/stubs/listener.typed.queued.stub' => 'listener.typed.queued.stub', + $dir.'/stubs/listener.queued.stub' => 'listener.queued.stub', + $dir.'/stubs/listener.typed.stub' => 'listener.typed.stub', + $dir.'/stubs/listener.stub' => 'listener.stub', + $dir.'/stubs/mail.stub' => 'mail.stub', + $dir.'/stubs/markdown-mail.stub' => 'markdown-mail.stub', + $dir.'/stubs/markdown-notification.stub' => 'markdown-notification.stub', + $dir.'/stubs/model.pivot.stub' => 'model.pivot.stub', + $dir.'/stubs/model.stub' => 'model.stub', + $dir.'/stubs/notification.stub' => 'notification.stub', + $dir.'/stubs/observer.plain.stub' => 'observer.plain.stub', + $dir.'/stubs/observer.stub' => 'observer.stub', + // $dir . '/stubs/pest.stub' => 'pest.stub', + // $dir . '/stubs/pest.unit.stub' => 'pest.unit.stub', + $dir.'/stubs/policy.plain.stub' => 'policy.plain.stub', + $dir.'/stubs/policy.stub' => 'policy.stub', + $dir.'/stubs/provider.stub' => 'provider.stub', + $dir.'/stubs/request.stub' => 'request.stub', + $dir.'/stubs/resource.stub' => 'resource.stub', + $dir.'/stubs/resource-collection.stub' => 'resource-collection.stub', + $dir.'/stubs/rule.stub' => 'rule.stub', + $dir.'/stubs/scope.stub' => 'scope.stub', + // $dir.'/stubs/test.stub' => 'test.stub', + // $dir.'/stubs/test.unit.stub' => 'test.unit.stub', + $dir.'/stubs/trait.stub' => 'trait.stub', + $dir.'/stubs/view-component.stub' => 'view-component.stub', + // Factories will use a ddd-specific stub + // realpath($dir . '/../../Database/Console/Factories/stubs/factory.stub') => 'factory.stub', + realpath($dir.'/../../Database/Console/Seeds/stubs/seeder.stub') => 'seeder.stub', + realpath($dir.'/../../Database/Migrations/stubs/migration.create.stub') => 'migration.create.stub', + realpath($dir.'/../../Database/Migrations/stubs/migration.stub') => 'migration.stub', + realpath($dir.'/../../Database/Migrations/stubs/migration.update.stub') => 'migration.update.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.api.stub') => 'controller.api.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.invokable.stub') => 'controller.invokable.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.model.api.stub') => 'controller.model.api.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.model.stub') => 'controller.model.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.nested.api.stub') => 'controller.nested.api.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.nested.singleton.api.stub') => 'controller.nested.singleton.api.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.nested.singleton.stub') => 'controller.nested.singleton.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.nested.stub') => 'controller.nested.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.plain.stub') => 'controller.plain.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.singleton.api.stub') => 'controller.singleton.api.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.singleton.stub') => 'controller.singleton.stub', + realpath($dir.'/../../Routing/Console/stubs/controller.stub') => 'controller.stub', + realpath($dir.'/../../Routing/Console/stubs/middleware.stub') => 'middleware.stub', + ]; + + // Some stubs are not available across all Laravel versions, + // so we'll just skip the files that don't exist. + return collect($stubs)->filter(function ($stub, $path) { + return file_exists($path); + })->all(); + } +} diff --git a/src/Support/Domain.php b/src/Support/Domain.php index 225fe61..e36fab8 100644 --- a/src/Support/Domain.php +++ b/src/Support/Domain.php @@ -140,6 +140,7 @@ public function object(string $type, string $name, bool $absolute = false): Doma $baseName = str($name)->replace($namespace, '') ->replace(['\\', '/'], '\\') ->trim('\\') + ->when($type === 'factory', fn ($name) => $name->finish('Factory')) ->toString(); $fullyQualifiedName = $namespace.'\\'.$baseName; diff --git a/stubs/action.php.stub b/stubs/action.stub similarity index 100% rename from stubs/action.php.stub rename to stubs/action.stub diff --git a/stubs/base-model.php.stub b/stubs/base-model.stub similarity index 100% rename from stubs/base-model.php.stub rename to stubs/base-model.stub diff --git a/stubs/base-view-model.php.stub b/stubs/base-view-model.stub similarity index 100% rename from stubs/base-view-model.php.stub rename to stubs/base-view-model.stub diff --git a/stubs/dto.php.stub b/stubs/dto.stub similarity index 100% rename from stubs/dto.php.stub rename to stubs/dto.stub diff --git a/stubs/factory.php.stub b/stubs/factory.stub similarity index 100% rename from stubs/factory.php.stub rename to stubs/factory.stub diff --git a/stubs/model.php.stub b/stubs/model.php.stub deleted file mode 100644 index e775c33..0000000 --- a/stubs/model.php.stub +++ /dev/null @@ -1,13 +0,0 @@ -cleanSlate(); + + $path = app()->configPath('ddd.php'); + + if (file_exists($path)) { + unlink($path); + } + + expect(file_exists($path))->toBeFalse(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + File::deleteDirectory($publishedStubFolder); + + assertDirectoryDoesNotExist($publishedStubFolder); +}); + +afterEach(function () { + $this->cleanSlate(); +}); + +it('can publish config using --config option', function () { + $path = app()->configPath('ddd.php'); + + $this + ->artisan('ddd:publish --config') + ->expectsOutputToContain('Publishing config...') + ->doesntExpectOutput('Publishing stubs...') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeTrue(); +}); + +it('can publish everything', function ($options) { + $path = app()->configPath('ddd.php'); + $publishedStubFolder = app()->basePath('stubs/ddd'); + + $this + ->artisan('ddd:publish', $options) + ->expectsOutputToContain('Publishing config...') + ->expectsOutputToContain('Publishing stubs...') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeTrue(); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toBeGreaterThan(0); +})->with([ + '--all' => [['--all' => true]], + '--config --stubs' => [['--config' => true, '--stubs' => true]], +]); + +it('can publish config interactively', function () { + $path = app()->configPath('ddd.php'); + + $this + ->artisan('ddd:publish') + ->expectsQuestion('What should be published?', ['config']) + ->expectsOutputToContain('Publishing config...') + ->doesntExpectOutput('Publishing stubs...') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeTrue(); +}); + +it('can publish stubs interactively', function () { + $path = app()->configPath('ddd.php'); + $publishedStubFolder = app()->basePath('stubs/ddd'); + + $this + ->artisan('ddd:publish') + ->expectsQuestion('What should be published?', ['stubs']) + ->expectsOutputToContain('Publishing stubs...') + ->doesntExpectOutput('Publishing config...') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeFalse(); + + assertDirectoryExists($publishedStubFolder); +}); + +it('can publish everything interactively', function () { + $path = app()->configPath('ddd.php'); + $publishedStubFolder = app()->basePath('stubs/ddd'); + + $this + ->artisan('ddd:publish') + ->expectsQuestion('What should be published?', ['config', 'stubs']) + ->expectsOutputToContain('Publishing config...') + ->expectsOutputToContain('Publishing stubs...') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeTrue(); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toBeGreaterThan(0); +}); diff --git a/tests/Command/StubTest.php b/tests/Command/StubTest.php new file mode 100644 index 0000000..abdfbd3 --- /dev/null +++ b/tests/Command/StubTest.php @@ -0,0 +1,182 @@ +cleanSlate(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + File::deleteDirectory($publishedStubFolder); + + assertDirectoryDoesNotExist($publishedStubFolder); +}); + +afterEach(function () { + $this->cleanSlate(); +}); + +it('can publish all stubs using --all option', function () { + $this + ->artisan('ddd:stub --all') + ->doesntExpectOutput('Publishing stubs...') + ->assertSuccessful() + ->execute(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toBeGreaterThan(0); + + expect(count($stubFiles))->toEqual(count([ + ...app('ddd')->stubs()->dddStubs(), + ...app('ddd')->stubs()->frameworkStubs(), + ])); +}); + +it('can publish all stubs interactively', function () { + $path = app()->configPath('ddd.php'); + $publishedStubFolder = app()->basePath('stubs/ddd'); + + $this + ->artisan('ddd:stub') + ->expectsQuestion('What do you want to do?', 'all') + ->assertSuccessful() + ->execute(); + + expect(file_exists($path))->toBeFalse(); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toBeGreaterThan(0); + + expect(count($stubFiles))->toEqual(count([ + ...app('ddd')->stubs()->dddStubs(), + ...app('ddd')->stubs()->frameworkStubs(), + ])); +}); + +it('can publish specific stubs using arguments', function ($stubsToPublish) { + $expectedStubFilenames = collect($stubsToPublish) + ->map(fn ($stub) => $stub.'.stub') + ->all(); + + $arguments = collect($stubsToPublish)->join(' '); + + $this + ->artisan("ddd:stub {$arguments}") + ->assertSuccessful() + ->execute(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toEqual(count($stubsToPublish)); + + foreach ($stubFiles as $file) { + expect($file->getFilename())->toBeIn($expectedStubFilenames); + } +})->with([ + 'model' => [['model']], + 'model/action/dto' => [['model', 'action', 'dto']], + 'model/model.pivot' => [['model', 'model.pivot']], + 'controller' => [['controller']], +]); + +it('can publish stubs using wildcard', function ($argument, $stubsToPublish) { + $expectedStubFilenames = collect($stubsToPublish) + ->map(fn ($stub) => $stub.'.stub') + ->all(); + + $this + ->artisan("ddd:stub {$argument}") + ->assertSuccessful() + ->execute(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toEqual(count($stubsToPublish)); + + foreach ($stubFiles as $file) { + expect($file->getFilename())->toBeIn($expectedStubFilenames); + } +})->with([ + 'model*' => ['model*', ['model', 'model.pivot']], + 'model.' => ['model.', ['model', 'model.pivot']], + 'policy.' => ['policy.', ['policy', 'policy.plain']], +]); + +it('can publish stubs using wildcard (laravel 11 stubs)', function ($argument, $stubsToPublish) { + $expectedStubFilenames = collect($stubsToPublish) + ->map(fn ($stub) => $stub.'.stub') + ->all(); + + $this + ->artisan("ddd:stub {$argument}") + ->assertSuccessful() + ->execute(); + + $publishedStubFolder = app()->basePath('stubs/ddd'); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toEqual(count($stubsToPublish)); + + foreach ($stubFiles as $file) { + expect($file->getFilename())->toBeIn($expectedStubFilenames); + } +})->with([ + 'listener*' => ['listener*', ['listener', 'listener.typed', 'listener.queued', 'listener.typed.queued']], + 'listener.' => ['listener.', ['listener', 'listener.typed', 'listener.queued', 'listener.typed.queued']], + 'enum.' => ['enum.', ['enum', 'enum.backed']], +])->skipOnLaravelVersionsBelow(11); + +it('can publish specific stubs interactively', function () { + $publishedStubFolder = app()->basePath('stubs/ddd'); + + assertDirectoryDoesNotExist($publishedStubFolder); + + $options = app('ddd')->stubs()->allStubs(); + + $matches = collect($options) + ->filter(fn ($stub, $path) => str($stub)->contains('model')) + ->all(); + + $this + ->artisan('ddd:stub') + ->expectsQuestion('What do you want to do?', 'some') + ->expectsSearch( + 'Which stub should be published?', + search: 'model', + answers: $matches, + answer: ['model.stub'] + ) + ->assertSuccessful() + ->execute(); + + assertDirectoryExists($publishedStubFolder); + + $stubFiles = File::files($publishedStubFolder); + + expect(count($stubFiles))->toEqual(1); + + expect($stubFiles[0]->getFilename())->toEqual('model.stub'); +})->skip(fn () => Feature::PromptMultiSearchAssertion->missing(), 'Multi-search assertion not available'); diff --git a/tests/Factory/DomainFactoryTest.php b/tests/Factory/DomainFactoryTest.php index 7c44d46..82e6e54 100644 --- a/tests/Factory/DomainFactoryTest.php +++ b/tests/Factory/DomainFactoryTest.php @@ -1,9 +1,11 @@ setupTestApplication(); @@ -26,8 +28,15 @@ ]); it('can instantiate a domain model factory', function ($domainParameter, $modelName, $modelClass) { + $this->afterApplicationCreated(function () { + (new DomainAutoloader)->autoload(); + }); + + $this->setupTestApplication(); + Config::set('ddd.base_model', 'Lunarstorm\LaravelDDD\Models\DomainModel'); Artisan::call("ddd:model -f {$domainParameter}:{$modelName}"); + expect(class_exists($modelClass))->toBeTrue(); expect($modelClass::factory())->toBeInstanceOf(Factory::class); })->with([ diff --git a/tests/Fixtures/Enums/Feature.php b/tests/Fixtures/Enums/Feature.php index 9b82fbb..d43587c 100644 --- a/tests/Fixtures/Enums/Feature.php +++ b/tests/Fixtures/Enums/Feature.php @@ -6,8 +6,10 @@ enum Feature: string { case PromptForMissingInput = '9.49.0'; case IncludeFilepathInGeneratorCommandOutput = '9.32.0'; + case Laravel11 = '11.0.0'; case LaravelPromptsPackage = '10.17'; case LaravelPackageOptimizeCommands = '11.27.1'; + case PromptMultiSearchAssertion = '11.30.0'; public function exists(): bool { diff --git a/tests/Generator/ControllerMakeTest.php b/tests/Generator/ControllerMakeTest.php index 5aae081..e814913 100644 --- a/tests/Generator/ControllerMakeTest.php +++ b/tests/Generator/ControllerMakeTest.php @@ -2,9 +2,13 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\File; use Lunarstorm\LaravelDDD\Tests\Fixtures\Enums\Feature; beforeEach(function () { + $this->cleanSlate(); + $this->setupTestApplication(); + Config::set('ddd.domain_path', 'src/Domain'); Config::set('ddd.domain_namespace', 'Domain'); @@ -13,8 +17,6 @@ 'namespace' => 'App\Modules', 'objects' => ['controller', 'request'], ]); - - $this->setupTestApplication(); }); it('can generate domain controller', function ($domainName, $controllerName, $relativePath, $expectedNamespace) { @@ -35,8 +37,15 @@ expect(file_exists($expectedPath))->toBeTrue(); - expect(file_get_contents($expectedPath)) + expect($contents = file_get_contents($expectedPath)) ->toContain("namespace {$expectedNamespace};"); + + if (Feature::Laravel11->exists()) { + // These assertions don't seem to pass on Laravel 10 + expect($contents) + ->toContain("use App\Http\Controllers\Controller;") + ->toContain('extends Controller'); + } })->with([ 'Invoicing:InvoiceController' => [ 'Invoicing', @@ -175,3 +184,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($contents = file_get_contents($expectedPath)) + ->toContain("namespace {$expectedNamespace};"); + + if (Feature::Laravel11->exists()) { + // These assertions don't seem to pass on Laravel 10 + expect($contents) + ->not->toContain("use App\Http\Controllers\Controller;") + ->not->toContain('extends Controller'); + } +})->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) { + $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 = <<<'STUB' +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/MakeTest.php b/tests/Generator/Model/MakeTest.php index 4b841a5..5367043 100644 --- a/tests/Generator/Model/MakeTest.php +++ b/tests/Generator/Model/MakeTest.php @@ -2,9 +2,15 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\File; use Lunarstorm\LaravelDDD\Support\Domain; use Lunarstorm\LaravelDDD\Tests\Fixtures\Enums\Feature; +beforeEach(function () { + $this->cleanSlate(); + $this->setupTestApplication(); +}); + it('can generate domain models', function ($domainPath, $domainRoot) { Config::set('ddd.domain_path', $domainPath); Config::set('ddd.domain_namespace', $domainRoot); @@ -211,3 +217,53 @@ ['Illuminate\Database\Eloquent\NonExistentModel', 'NonExistentModel'], ['OtherVendor\OtherPackage\Models\NonExistentModel', 'NonExistentModel'], ]); + +it('does not attempt to extend custom base models when using custom stubs', function ($baseModelClass, $baseModelName, $stubFolder) { + Config::set('ddd.base_model', $baseModelClass); + + $domain = 'Fruits'; + $modelName = 'Lemon'; + + $expectedModelPath = base_path(implode('/', [ + config('ddd.domain_path'), + $domain, + config('ddd.namespaces.model'), + "{$modelName}.php", + ])); + + if (file_exists($expectedModelPath)) { + unlink($expectedModelPath); + } + + // Publish a custom stub + $customStub = <<<'STUB' +basePath($stubFolder)); + file_put_contents(app()->basePath($stubFolder.'/model.stub'), $customStub); + expect(file_exists(app()->basePath($stubFolder.'/model.stub')))->toBeTrue(); + + Artisan::call("ddd:model {$domain}:{$modelName}"); + + expect(file_exists($expectedModelPath))->toBeTrue(); + + expect(file_get_contents($expectedModelPath)) + ->toContain('use CustomModelTrait;') + ->not->toContain("use {$baseModelClass};") + ->not->toContain("extends {$baseModelName}"); + + $this->cleanStubs(); +})->with([ + ['Domain\Shared\Models\BaseModel', 'BaseModel'], +])->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/Pest.php b/tests/Pest.php index 1691c65..d31d21e 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -9,7 +9,7 @@ function skipOnLaravelVersionsBelow($minimumVersion) $version = app()->version(); if (version_compare($version, $minimumVersion, '<')) { - test()->markTestSkipped("Only relevant from Laravel {$minimumVersion} onwards (Current version: {$version})."); + test()->markTestSkipped("Only available on Laravel {$minimumVersion}+ (Current version: {$version})."); } } diff --git a/tests/Setup/PublishTest.php b/tests/Setup/PublishTest.php index ac0410e..69858bc 100644 --- a/tests/Setup/PublishTest.php +++ b/tests/Setup/PublishTest.php @@ -20,7 +20,7 @@ }); it('can publish stubs', function () { - $dir = resource_path('stubs/ddd'); + $dir = base_path('stubs/ddd'); if (File::exists($dir)) { File::deleteDirectory($dir); diff --git a/tests/TestCase.php b/tests/TestCase.php index b04ef5a..f2baed7 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -136,6 +136,8 @@ protected function composerReload() (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1'])) ->setTimeout(null) ->run(function ($type, $output) {}); + + return $this; } protected function cleanSlate() @@ -148,13 +150,24 @@ 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')); File::deleteDirectory(base_path('src/App')); + File::deleteDirectory(app_path('Modules')); File::deleteDirectory(app_path('Models')); File::deleteDirectory(base_path('bootstrap/cache/ddd')); + + return $this; + } + + protected function cleanStubs() + { + File::cleanDirectory(base_path('stubs')); + + return $this; } protected function setupTestApplication() @@ -166,6 +179,8 @@ protected function setupTestApplication() File::ensureDirectoryExists(app_path('Models')); $this->setDomainPathInComposer('Domain', 'src/Domain'); + + return $this; } protected function setDomainPathInComposer($domainNamespace, $domainPath, bool $reload = true)