Skip to content

Commit

Permalink
Introduce ddd:publish and ddd:stub commands.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaspertey committed Nov 9, 2024
1 parent b7a2fa2 commit 203df61
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 24 deletions.
22 changes: 0 additions & 22 deletions src/Commands/Concerns/HasDomainStubs.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,4 @@ protected function resolveDddStubPath($path)

return DDD::packagePath('stubs/'.$path);
}

// protected function resolveStubPath($stub)
// {
// $defaultStub = parent::resolveStubPath($stub);

// $stubFilename = basename($stub);

// // Check if there is a user-published stub
// $publishedPath = app()->basePath('stubs/ddd/'.$stubFilename);

// if (file_exists($publishedPath)) {
// return $publishedPath;
// }

// $legacyPublishedPath = Str::replaceLast('.stub', '.php.stub', $publishedPath);

// if (file_exists($legacyPublishedPath)) {
// return $legacyPublishedPath;
// }

// return $defaultStub;
// }
}
2 changes: 2 additions & 0 deletions src/Commands/DomainFactoryMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

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 FactoryMakeCommand
{
use HasDomainStubs,
InteractsWithStubs,
ResolvesDomainFromInput;

protected $name = 'ddd:factory';
Expand Down
64 changes: 64 additions & 0 deletions src/Commands/PublishCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Lunarstorm\LaravelDDD\Commands;

use Illuminate\Console\Command;
use Lunarstorm\LaravelDDD\Support\DomainResolver;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\Process;

use function Laravel\Prompts\multiselect;

class PublishCommand extends Command
{
public $signature = 'ddd:publish';

protected $description = 'Publish package resources';

protected function getOptions()
{
return [
['config', 'c', InputOption::VALUE_NONE, 'Publish the config file'],
['stubs', 's', InputOption::VALUE_NONE, 'Publish the stubs'],
];
}

protected function askForThingsToPublish()
{
$options = [
'stubs' => 'Stubs',
'config' => 'Config File',
];

return multiselect(
label: 'What should be published?',
options: $options,
required: true
);
}

public function handle(): int
{
$thingsToPublish = [

Check failure on line 42 in src/Commands/PublishCommand.php

View workflow job for this annotation

GitHub Actions / phpstan

Ternary operator condition is always false.
...$this->hasOption('config') ? ['config'] : [],

Check failure on line 43 in src/Commands/PublishCommand.php

View workflow job for this annotation

GitHub Actions / phpstan

Ternary operator condition is always false.
...$this->hasOption('stubs') ? ['stubs'] : [],

Check failure on line 44 in src/Commands/PublishCommand.php

View workflow job for this annotation

GitHub Actions / phpstan

Ternary operator condition is always false.
] ?: $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->callSilently('vendor:publish', [
'--tag' => 'ddd-stubs',
]);
}

return self::SUCCESS;
}
}
195 changes: 195 additions & 0 deletions src/Commands/StubCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<?php

namespace Lunarstorm\LaravelDDD\Commands;

use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Foundation\Console\StubPublishCommand;
use Illuminate\Foundation\Events\PublishingStubs;
use Illuminate\Support\Str;
use Lunarstorm\LaravelDDD\Support\DomainResolver;
use ReflectionClass;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\Process;

use function Laravel\Prompts\multisearch;
use function Laravel\Prompts\multiselect;
use function Laravel\Prompts\select;

class StubCommand extends Command
{
public $name = 'ddd:stub';

protected $description = 'Publish one or more stubs';

protected function getArguments()
{
return [
new InputArgument('name', InputArgument::IS_ARRAY, 'One or more names of specific stubs to publish'),
];
}

protected function getOptions()
{
return [
['all', 'a', InputOption::VALUE_NONE, 'Publish all stubs'],
['existing', null, InputOption::VALUE_NONE, 'Publish and overwrite only the files that have already been published'],
['force', null, InputOption::VALUE_NONE, 'Overwrite any existing files'],
];
}

protected function getNativeLaravelStubs()
{
$laravelStubCommand = new ReflectionClass(new StubPublishCommand());

$dir = dirname($laravelStubCommand->getFileName());

return [
$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',
// 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',
];
}

protected function resolveSelectedStubs(array $names = [])
{
$stubs = [
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',
...$this->getNativeLaravelStubs(),
];

if ($names) {
return collect($stubs)
->filter(
fn($stub, $path) => in_array($stub, $names)
|| in_array(str($stub)->replaceEnd('.stub', '')->toString(), $names)
)
->all();
}

return 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
);
}

public function handle(): int
{
$option = match (true) {
$this->option('all') => 'all',
count($this->argument('name')) > 0 => 'named',
default => select(
label: 'What do you want to do?',
options: [
'all' => 'Publish all stubs',
'some' => 'Choose stubs to publish',
],
required: true,
default: 'all'
)
};

if ($option === 'all') {
$this->comment('Publishing all stubs...');

$this->call('vendor:publish', [
'--tag' => 'ddd-stubs',
]);

return self::SUCCESS;
}

$stubs = $this->resolveSelectedStubs($this->argument('name'));

if (! is_dir($stubsPath = $this->laravel->basePath('stubs/ddd'))) {
(new Filesystem)->makeDirectory($stubsPath, recursive: true);
}

if (empty($stubs)) {
$this->warn('No matching stubs found.');

return self::INVALID;
}

$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;
}
}
6 changes: 4 additions & 2 deletions src/LaravelDDDServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -87,14 +89,14 @@ protected function registerMigrations()
public function packageBooted()
{
$this->publishes([
$this->package->basePath('/../stubs') => base_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',
);
}
}
Expand Down

0 comments on commit 203df61

Please sign in to comment.