Skip to content

Commit

Permalink
ddd:upgrade command to help convert outdated 0.x config files.
Browse files Browse the repository at this point in the history
  • Loading branch information
JasperTey committed Mar 30, 2024
1 parent ba63b7c commit 6734315
Show file tree
Hide file tree
Showing 7 changed files with 411 additions and 1 deletion.
160 changes: 160 additions & 0 deletions config/ddd.php.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

return [

/*
|--------------------------------------------------------------------------
| Domain Path
|--------------------------------------------------------------------------
|
| The path to the domain folder relative to the application root.
|
*/
'domain_path' => {{domain_path}},

/*
|--------------------------------------------------------------------------
| Domain Namespace
|--------------------------------------------------------------------------
|
| The root domain namespace.
|
*/
'domain_namespace' => {{domain_namespace}},

/*
|--------------------------------------------------------------------------
| Domain Object Namespaces
|--------------------------------------------------------------------------
|
| This value contains the default namespaces of generated domain
| objects relative to the domain namespace of which the object
| belongs to.
|
| e.g., Domain\Invoicing\Models\*
| Domain\Invoicing\Data\*
| Domain\Invoicing\ViewModels\*
| Domain\Invoicing\ValueObjects\*
| Domain\Invoicing\Actions\*
|
*/
'namespaces' => [
'model' => {{namespaces.model}},
'data_transfer_object' => {{namespaces.data_transfer_object}},
'view_model' => {{namespaces.view_model}},
'value_object' => {{namespaces.value_object}},
'action' => {{namespaces.action}},
'cast' => 'Casts',
'channel' => 'Channels',
'command' => 'Commands',
'enum' => 'Enums',
'event' => 'Events',
'exception' => 'Exceptions',
'factory' => 'Database\Factories',
'job' => 'Jobs',
'listener' => 'Listeners',
'mail' => 'Mail',
'notification' => 'Notifications',
'observer' => 'Observers',
'policy' => 'Policies',
'provider' => 'Providers',
'resource' => 'Resources',
'rule' => 'Rules',
'scope' => 'Scopes',
],

/*
|--------------------------------------------------------------------------
| Base Model
|--------------------------------------------------------------------------
|
| The base class which generated domain models should extend. By default,
| generated domain models will extend `Domain\Shared\Models\BaseModel`,
| which will be created if it doesn't already exist.
|
*/
'base_model' => {{base_model}},

/*
|--------------------------------------------------------------------------
| Base DTO
|--------------------------------------------------------------------------
|
| The base class which generated data transfer objects should extend. By
| default, generated DTOs will extend `Spatie\LaravelData\Data` from
| Spatie's Laravel-data package, a highly recommended data object
| package to work with.
|
*/
'base_dto' => {{base_dto}},

/*
|--------------------------------------------------------------------------
| Base ViewModel
|--------------------------------------------------------------------------
|
| The base class which generated view models should extend. By default,
| generated domain models will extend `Domain\Shared\ViewModels\BaseViewModel`,
| which will be created if it doesn't already exist.
|
*/
'base_view_model' => {{base_view_model}},

/*
|--------------------------------------------------------------------------
| Base Action
|--------------------------------------------------------------------------
|
| The base class which generated action objects should extend. By default,
| generated actions are based on the `lorisleiva/laravel-actions` package
| and do not extend anything.
|
*/
'base_action' => {{base_action}},

/*
|--------------------------------------------------------------------------
| Autoloading
|--------------------------------------------------------------------------
|
| Configure whether domain providers, commands, policies, and factories
| should be auto-discovered and registered.
|
*/
'autoload' => [
/**
* When enabled, any class within the domain layer extending `Illuminate\Support\ServiceProvider`
* will be auto-registered as a service provider
*/
'providers' => true,

/**
* When enabled, any class within the domain layer extending `Illuminate\Console\Command`
* will be auto-registered as a command when running in console.
*/
'commands' => true,

/**
* When enabled, the package will register a custom policy discovery callback to resolve policy names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'policies' => true,

/**
* When enabled, the package will register a custom factory discovery callback to resolve factory names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'factories' => true,
],

/*
|--------------------------------------------------------------------------
| Caching
|--------------------------------------------------------------------------
|
| The folder where the domain cache files will be stored. Used for domain
| autoloading.
|
*/
'cache_directory' => 'bootstrap/cache/ddd',
];
61 changes: 61 additions & 0 deletions src/Commands/UpgradeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Lunarstorm\LaravelDDD\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Arr;

class UpgradeCommand extends Command
{
protected $name = 'ddd:upgrade';

protected $description = 'Upgrade published config files for compatibility with 1.x.';

public function handle()
{
if (! file_exists(config_path('ddd.php'))) {
$this->components->warn('Config file was not published. Nothing to upgrade!');

return;
}

$replacements = [
'domain_path' => 'paths.domain',
'domain_namespace' => 'domain_namespace',
'namespaces.model' => 'namespaces.models',
'namespaces.data_transfer_object' => 'namespaces.data_transfer_objects',
'namespaces.view_model' => 'namespaces.view_models',
'namespaces.value_object' => 'namespaces.value_objects',
'namespaces.action' => 'namespaces.actions',
'base_model' => 'base_model',
'base_dto' => 'base_dto',
'base_view_model' => 'base_view_model',
'base_action' => 'base_action',
];

$oldConfig = require config_path('ddd.php');
$oldConfig = Arr::dot($oldConfig);

// Grab a flesh copy of the new config
$newConfigContent = file_get_contents(__DIR__.'/../../config/ddd.php.stub');

foreach ($replacements as $dotPath => $legacyKey) {
$value = match (true) {
array_key_exists($dotPath, $oldConfig) => $oldConfig[$dotPath],
array_key_exists($legacyKey, $oldConfig) => $oldConfig[$legacyKey],
default => config("ddd.{$dotPath}"),
};

$newConfigContent = str_replace(
'{{'.$dotPath.'}}',
var_export($value, true),
$newConfigContent
);
}

// Write the new config to the config file
file_put_contents(config_path('ddd.php'), $newConfigContent);

$this->components->info('Configuration upgraded successfully.');
}
}
1 change: 1 addition & 0 deletions src/LaravelDDDServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function configurePackage(Package $package): void
->hasConfigFile()
->hasCommands([
Commands\InstallCommand::class,
Commands\UpgradeCommand::class,
Commands\CacheCommand::class,
Commands\CacheClearCommand::class,
Commands\DomainListCommand::class,
Expand Down
2 changes: 1 addition & 1 deletion tests/InstallTest.php → tests/Command/InstallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
$command->execute();

expect(file_exists($path))->toBeTrue();
expect(file_get_contents($path))->toEqual(file_get_contents(__DIR__.'/../config/ddd.php'));
expect(file_get_contents($path))->toEqual(file_get_contents(__DIR__.'/../../config/ddd.php'));

unlink($path);
});
Expand Down
44 changes: 44 additions & 0 deletions tests/Command/UpgradeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;

it('can upgrade 0.x config to 1.x', function (string $pathToOldConfig, array $expectedValues) {
$path = config_path('ddd.php');

File::copy($pathToOldConfig, $path);

expect(file_exists($path))->toBeTrue();

$this->artisan('ddd:upgrade')
->expectsOutputToContain('Configuration upgraded successfully.')
->execute();

Artisan::call('config:clear');

$expectedValues = Arr::dot($expectedValues);

$configAsArray = require config_path('ddd.php');

foreach ($expectedValues as $path => $value) {
expect(data_get($configAsArray, $path))
->toEqual($value, "Config {$path} does not match expected value.");
}
})->with('configUpgrades');

it('skips upgrade if config file was not published', function () {
$path = config_path('ddd.php');

if (file_exists($path)) {
unlink($path);
}

expect(file_exists($path))->toBeFalse();

$this->artisan('ddd:upgrade')
->expectsOutputToContain('Config file was not published. Nothing to upgrade!')
->execute();

expect(file_exists($path))->toBeFalse();
});
48 changes: 48 additions & 0 deletions tests/Datasets/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

dataset('configUpgrades', [
'0.10.0 config' => [
__DIR__.'/resources/config.0.10.0.php',

// Expected net result
[
'domain_path' => 'src/CustomDomainFolder',
'domain_namespace' => 'CustomDomainNamespace',
'namespaces' => [
'model' => 'CustomModels',
'data_transfer_object' => 'CustomData',
'view_model' => 'CustomViewModels',
'value_object' => 'CustomValueObjects',
'action' => 'CustomActions',
'cast' => 'Casts',
'channel' => 'Channels',
'command' => 'Commands',
'enum' => 'Enums',
'event' => 'Events',
'exception' => 'Exceptions',
'factory' => 'Database\Factories',
'job' => 'Jobs',
'listener' => 'Listeners',
'mail' => 'Mail',
'notification' => 'Notifications',
'observer' => 'Observers',
'policy' => 'Policies',
'provider' => 'Providers',
'resource' => 'Resources',
'rule' => 'Rules',
'scope' => 'Scopes',
],
'base_model' => 'Domain\Shared\Models\CustomBaseModel',
'base_dto' => 'Spatie\LaravelData\Data',
'base_view_model' => 'Domain\Shared\ViewModels\CustomViewModel',
'base_action' => null,
'autoload' => [
'providers' => true,
'commands' => true,
'policies' => true,
'factories' => true,
],
'cache_directory' => 'bootstrap/cache/ddd',
],
],
]);
Loading

0 comments on commit 6734315

Please sign in to comment.