From 4f4e121eff7f7b6c0f0daf15939ebc75a4eae4fb Mon Sep 17 00:00:00 2001 From: PhilippeThouvenot Date: Mon, 2 Sep 2024 17:47:37 +0200 Subject: [PATCH 1/4] Resolve get class string instead of an object. (#64) * Resolve get class string instead of an object. This fix resolve a crash with phpstan or ide-helper * Reload composer before test scripts to ensure working clean slate. * Factory autoloading: use DomainFactory::resolveFactoryName() as long as it's not null. * Revert test runner execution command without composer reload. --------- Co-authored-by: Philippe Co-authored-by: Jasper Tey --- composer.json | 5 ++++- src/Support/DomainAutoloader.php | 18 +++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index c1ae6cc..6e3da31 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,10 @@ "scripts": { "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", "analyse": "vendor/bin/phpstan analyse", - "test": "vendor/bin/pest", + "test": [ + "@composer dump-autoload", + "vendor/bin/pest" + ], "test-coverage": "vendor/bin/pest --coverage", "format": "vendor/bin/pint", "lint": "vendor/bin/pint" diff --git a/src/Support/DomainAutoloader.php b/src/Support/DomainAutoloader.php index f107dc0..c203803 100644 --- a/src/Support/DomainAutoloader.php +++ b/src/Support/DomainAutoloader.php @@ -50,7 +50,7 @@ public function autoload(): void protected static function normalizePaths($path): array { return collect($path) - ->filter(fn ($path) => is_dir($path)) + ->filter(fn($path) => is_dir($path)) ->toArray(); } @@ -99,27 +99,27 @@ protected function handlePolicies(): void return Arr::wrap(Collection::times(count($classDirnameSegments), function ($index) use ($class, $classDirnameSegments) { $classDirname = implode('\\', array_slice($classDirnameSegments, 0, $index)); - return $classDirname.'\\Policies\\'.class_basename($class).'Policy'; + return $classDirname . '\\Policies\\' . class_basename($class) . 'Policy'; })->reverse()->values()->first(function ($class) { return class_exists($class); - }) ?: [$classDirname.'\\Policies\\'.class_basename($class).'Policy']); + }) ?: [$classDirname . '\\Policies\\' . class_basename($class) . 'Policy']); }); } protected function handleFactories(): void { Factory::guessFactoryNamesUsing(function (string $modelName) { - if (DomainResolver::isDomainClass($modelName)) { - return DomainFactory::factoryForModel($modelName); + if ($factoryName = DomainFactory::resolveFactoryName($modelName)) { + return $factoryName; } $appNamespace = static::appNamespace(); - $modelName = Str::startsWith($modelName, $appNamespace.'Models\\') - ? Str::after($modelName, $appNamespace.'Models\\') + $modelName = Str::startsWith($modelName, $appNamespace . 'Models\\') + ? Str::after($modelName, $appNamespace . 'Models\\') : Str::after($modelName, $appNamespace); - return 'Database\\Factories\\'.$modelName.'Factory'; + return 'Database\\Factories\\' . $modelName . 'Factory'; }); } @@ -132,7 +132,7 @@ protected static function finder($paths) ->finish('/'); $ignoredFolders = collect(config('ddd.autoload_ignore', [])) - ->map(fn ($path) => Str::finish($path, '/')); + ->map(fn($path) => Str::finish($path, '/')); if ($pathAfterDomain->startsWith($ignoredFolders)) { return false; From 48f9818e56505b92a0b4e1fa5cbaa60a991cb077 Mon Sep 17 00:00:00 2001 From: JasperTey Date: Mon, 2 Sep 2024 15:47:59 +0000 Subject: [PATCH 2/4] Fix styling --- src/LaravelDDDServiceProvider.php | 4 ++-- src/Listeners/CacheClearSubscriber.php | 4 +--- src/Support/DomainAutoloader.php | 14 +++++++------- src/ValueObjects/DomainNamespaces.php | 3 +-- src/ValueObjects/DomainObject.php | 3 +-- src/ValueObjects/DomainObjectNamespace.php | 3 +-- tests/Autoload/CommandTest.php | 8 ++++---- tests/Autoload/FactoryTest.php | 4 ++-- tests/Autoload/PolicyTest.php | 2 +- tests/Autoload/ProviderTest.php | 8 ++++---- tests/Support/AutoloaderTest.php | 2 +- tests/TestCase.php | 3 +-- 12 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/LaravelDDDServiceProvider.php b/src/LaravelDDDServiceProvider.php index 7c38d21..6555823 100644 --- a/src/LaravelDDDServiceProvider.php +++ b/src/LaravelDDDServiceProvider.php @@ -11,7 +11,7 @@ class LaravelDDDServiceProvider extends PackageServiceProvider public function configurePackage(Package $package): void { $this->app->scoped(DomainManager::class, function () { - return new DomainManager(); + return new DomainManager; }); $this->app->bind('ddd', DomainManager::class); @@ -72,6 +72,6 @@ public function packageBooted() public function packageRegistered() { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); } } diff --git a/src/Listeners/CacheClearSubscriber.php b/src/Listeners/CacheClearSubscriber.php index 76886d6..8597073 100644 --- a/src/Listeners/CacheClearSubscriber.php +++ b/src/Listeners/CacheClearSubscriber.php @@ -7,9 +7,7 @@ class CacheClearSubscriber { - public function __construct() - { - } + public function __construct() {} public function handle(): void { diff --git a/src/Support/DomainAutoloader.php b/src/Support/DomainAutoloader.php index c203803..beae39e 100644 --- a/src/Support/DomainAutoloader.php +++ b/src/Support/DomainAutoloader.php @@ -50,7 +50,7 @@ public function autoload(): void protected static function normalizePaths($path): array { return collect($path) - ->filter(fn($path) => is_dir($path)) + ->filter(fn ($path) => is_dir($path)) ->toArray(); } @@ -99,10 +99,10 @@ protected function handlePolicies(): void return Arr::wrap(Collection::times(count($classDirnameSegments), function ($index) use ($class, $classDirnameSegments) { $classDirname = implode('\\', array_slice($classDirnameSegments, 0, $index)); - return $classDirname . '\\Policies\\' . class_basename($class) . 'Policy'; + return $classDirname.'\\Policies\\'.class_basename($class).'Policy'; })->reverse()->values()->first(function ($class) { return class_exists($class); - }) ?: [$classDirname . '\\Policies\\' . class_basename($class) . 'Policy']); + }) ?: [$classDirname.'\\Policies\\'.class_basename($class).'Policy']); }); } @@ -115,11 +115,11 @@ protected function handleFactories(): void $appNamespace = static::appNamespace(); - $modelName = Str::startsWith($modelName, $appNamespace . 'Models\\') - ? Str::after($modelName, $appNamespace . 'Models\\') + $modelName = Str::startsWith($modelName, $appNamespace.'Models\\') + ? Str::after($modelName, $appNamespace.'Models\\') : Str::after($modelName, $appNamespace); - return 'Database\\Factories\\' . $modelName . 'Factory'; + return 'Database\\Factories\\'.$modelName.'Factory'; }); } @@ -132,7 +132,7 @@ protected static function finder($paths) ->finish('/'); $ignoredFolders = collect(config('ddd.autoload_ignore', [])) - ->map(fn($path) => Str::finish($path, '/')); + ->map(fn ($path) => Str::finish($path, '/')); if ($pathAfterDomain->startsWith($ignoredFolders)) { return false; diff --git a/src/ValueObjects/DomainNamespaces.php b/src/ValueObjects/DomainNamespaces.php index 3f1d9d9..44b8382 100644 --- a/src/ValueObjects/DomainNamespaces.php +++ b/src/ValueObjects/DomainNamespaces.php @@ -24,8 +24,7 @@ public function __construct( public readonly string $notifications, public readonly string $resources, public readonly string $rules, - ) { - } + ) {} public static function from(string $domain, ?string $subdomain = null): self { diff --git a/src/ValueObjects/DomainObject.php b/src/ValueObjects/DomainObject.php index 2f1d2da..7744a89 100644 --- a/src/ValueObjects/DomainObject.php +++ b/src/ValueObjects/DomainObject.php @@ -15,8 +15,7 @@ public function __construct( public readonly string $fullyQualifiedName, public readonly string $path, public readonly ?string $type = null, - ) { - } + ) {} public static function fromClass(string $fullyQualifiedClass, ?string $objectType = null): ?self { diff --git a/src/ValueObjects/DomainObjectNamespace.php b/src/ValueObjects/DomainObjectNamespace.php index 23c5240..bcb5ea4 100644 --- a/src/ValueObjects/DomainObjectNamespace.php +++ b/src/ValueObjects/DomainObjectNamespace.php @@ -10,8 +10,7 @@ class DomainObjectNamespace public function __construct( public readonly string $type, public readonly string $namespace, - ) { - } + ) {} public static function make(string $key, string $domain, ?string $subdomain = null): self { diff --git a/tests/Autoload/CommandTest.php b/tests/Autoload/CommandTest.php index 6fe1bf0..57650e7 100644 --- a/tests/Autoload/CommandTest.php +++ b/tests/Autoload/CommandTest.php @@ -18,7 +18,7 @@ $this->setupTestApplication(); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); @@ -35,7 +35,7 @@ $this->setupTestApplication(); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); @@ -82,7 +82,7 @@ DomainCache::set('domain-commands', []); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); // command should not be recognized due to cached empty-state @@ -94,7 +94,7 @@ DomainCache::clear(); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); $this->artisan('invoice:deliver')->assertSuccessful(); diff --git a/tests/Autoload/FactoryTest.php b/tests/Autoload/FactoryTest.php index 26f366c..f496b38 100644 --- a/tests/Autoload/FactoryTest.php +++ b/tests/Autoload/FactoryTest.php @@ -15,7 +15,7 @@ Config::set('ddd.autoload.factories', true); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); @@ -52,7 +52,7 @@ Config::set('ddd.autoload.factories', false); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); diff --git a/tests/Autoload/PolicyTest.php b/tests/Autoload/PolicyTest.php index 5a4212b..160117c 100644 --- a/tests/Autoload/PolicyTest.php +++ b/tests/Autoload/PolicyTest.php @@ -11,7 +11,7 @@ Config::set('ddd.autoload.factories', true); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); diff --git a/tests/Autoload/ProviderTest.php b/tests/Autoload/ProviderTest.php index 7e3e775..6316e54 100644 --- a/tests/Autoload/ProviderTest.php +++ b/tests/Autoload/ProviderTest.php @@ -18,7 +18,7 @@ ]); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); @@ -34,7 +34,7 @@ ]); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); }); @@ -57,7 +57,7 @@ DomainCache::set('domain-providers', []); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); expect(fn () => app('invoicing'))->toThrow(Exception::class); @@ -68,7 +68,7 @@ DomainCache::clear(); $this->afterApplicationCreated(function () { - (new DomainAutoloader())->autoload(); + (new DomainAutoloader)->autoload(); }); expect(app('invoicing'))->toEqual('invoicing-singleton'); diff --git a/tests/Support/AutoloaderTest.php b/tests/Support/AutoloaderTest.php index 6b7edf9..aec470b 100644 --- a/tests/Support/AutoloaderTest.php +++ b/tests/Support/AutoloaderTest.php @@ -7,7 +7,7 @@ }); it('can run', function () { - $autoloader = new DomainAutoloader(); + $autoloader = new DomainAutoloader; $autoloader->autoload(); })->throwsNoExceptions(); diff --git a/tests/TestCase.php b/tests/TestCase.php index ef9b57e..05348a2 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -136,8 +136,7 @@ protected function composerReload() (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1'])) ->setTimeout(null) - ->run(function ($type, $output) { - }); + ->run(function ($type, $output) {}); } protected function cleanSlate() From 35b701ed0cd4a18edf5b73812eca845fa2107e01 Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Mon, 2 Sep 2024 22:03:48 -0400 Subject: [PATCH 3/4] Ensure domain path in composer.json is restored to factory state. --- .github/workflows/run-tests.yml | 2 +- composer.json | 7 ++----- tests/.skeleton/bootstrap/providers.php | 3 +++ tests/Command/InstallTest.php | 7 +++++++ tests/TestCase.php | 10 +++++++--- 5 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 tests/.skeleton/bootstrap/providers.php diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index afe477a..5698f95 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -4,7 +4,7 @@ on: push: branches: [main] pull_request: - branches: [main, next] + branches: [main, next, develop] jobs: test: diff --git a/composer.json b/composer.json index 6e3da31..243d503 100644 --- a/composer.json +++ b/composer.json @@ -53,11 +53,8 @@ "scripts": { "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", "analyse": "vendor/bin/phpstan analyse", - "test": [ - "@composer dump-autoload", - "vendor/bin/pest" - ], - "test-coverage": "vendor/bin/pest --coverage", + "test": "@composer dump-autoload && vendor/bin/pest", + "test-coverage": "@composer dump-autoload && vendor/bin/pest --coverage", "format": "vendor/bin/pint", "lint": "vendor/bin/pint" }, diff --git a/tests/.skeleton/bootstrap/providers.php b/tests/.skeleton/bootstrap/providers.php new file mode 100644 index 0000000..0b67a5f --- /dev/null +++ b/tests/.skeleton/bootstrap/providers.php @@ -0,0 +1,3 @@ +setupTestApplication(); +}); + it('publishes config', function () { $path = config_path('ddd.php'); @@ -47,6 +51,9 @@ expect($after)->toEqual(config('ddd.domain_path')); unlink(config_path('ddd.php')); + + // Reset composer back to the factory state + $this->setDomainPathInComposer('Domain', 'src/Domain', reload: true); })->with([ ['src/Domain', 'Domain'], ['src/Domains', 'Domains'], diff --git a/tests/TestCase.php b/tests/TestCase.php index 05348a2..fb69cab 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -7,7 +7,6 @@ use Illuminate\Support\Arr; use Illuminate\Support\Facades\File; use Lunarstorm\LaravelDDD\LaravelDDDServiceProvider; -use Lunarstorm\LaravelDDD\Support\DomainCache; use Orchestra\Testbench\TestCase as Orchestra; use Symfony\Component\Process\Process; @@ -154,7 +153,7 @@ protected function cleanSlate() File::deleteDirectory(base_path('src/Domains')); File::deleteDirectory(app_path('Models')); - DomainCache::clear(); + File::deleteDirectory(base_path('bootstrap/cache/ddd')); } protected function setupTestApplication() @@ -162,12 +161,13 @@ 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::ensureDirectoryExists(app_path('Models')); $this->setDomainPathInComposer('Domain', 'src/Domain'); } - protected function setDomainPathInComposer($domainNamespace, $domainPath) + protected function setDomainPathInComposer($domainNamespace, $domainPath, bool $reload = true) { $this->updateComposer( set: [ @@ -175,6 +175,10 @@ protected function setDomainPathInComposer($domainNamespace, $domainPath) ], ); + if ($reload) { + $this->composerReload(); + } + return $this; } } From 33f04efe66ae4065f188cec3cf1cf47b2bf25fa6 Mon Sep 17 00:00:00 2001 From: Jasper Tey Date: Mon, 2 Sep 2024 22:16:12 -0400 Subject: [PATCH 4/4] Release 1.1.2 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60eb300..2926890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to `laravel-ddd` will be documented in this file. +## [1.1.2] - 2024-09-02 +### Fixed +- During domain factory autoloading, ensure that `guessFactoryNamesUsing` returns a string when a domain factory is resolved. +- Resolve issues with failing tests caused by mutations to `composer.json` that weren't rolled back. + ## [1.1.1] - 2024-04-17 ### Added - Ability to ignore folders during autoloading via `config('ddd.autoload_ignore')`, or register a custom filter callback via `DDD::filterAutoloadPathsUsing(callable $filter)`.