diff --git a/CHANGELOG.md b/CHANGELOG.md index 826fd47e..c95df95c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ Upgrade guide: https://github.com/softberg/quantum-php-docs/blob/master/v3.0/upg - Fixed OpenAPI installer route generation to return `Response` objects via `response()->...` helpers and avoid undefined response-variable usage (#520) - Standardized `defineValidationRules(Request $request): void` in Toolkit middleware templates - Fixed request uploaded-file parsing to preserve multiple top-level multipart file fields in both real and internal request flows (#526) +- Fixed `ModuleLoader` to skip dependency registration for modules where `enabled` is `false`, aligning dependency loading with route loading behavior (#529) ### Added - `AppContext` class representing the runtime identity of a single application execution diff --git a/composer.json b/composer.json index 8a6eb815..22f39530 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "dflydev/dot-access-data": "^3.0", "php-debugbar/php-debugbar": "^1.8", "phpmailer/phpmailer": "^6.0", - "twig/twig": "^3.0", + "twig/twig": ">=3.0 <3.26", "php-curl-class/php-curl-class": "^11.0", "psr/log": "^1.1", "rakibtg/sleekdb": "^2.13", @@ -89,9 +89,7 @@ "prefer-stable": true, "config": { "audit": { - "ignore": [ - "CVE-2025-45769" - ] + "block-insecure": false } } } diff --git a/src/Module/ModuleLoader.php b/src/Module/ModuleLoader.php index 2794bd9e..cf55cbfe 100644 --- a/src/Module/ModuleLoader.php +++ b/src/Module/ModuleLoader.php @@ -118,6 +118,10 @@ public function loadModulesDependencies(): array $modulesDependencies = []; foreach ($this->moduleConfigs as $module => $options) { + if (!$this->isModuleEnabled($options)) { + continue; + } + $modulesDependencies = array_merge($modulesDependencies, $this->getModuleDependencies($module)); } @@ -145,30 +149,30 @@ public function getModuleDependencies(string $module): array } /** + * @return array> * @throws ModuleException */ - private function loadModuleConfig(): void + public function getModuleConfigs(): array { - $configPath = App::getBaseDir() . DS . 'shared' . DS . 'config' . DS . 'modules.php'; - - if (!$this->fs->exists($configPath)) { - throw ModuleException::moduleConfigNotFound(); + if (empty($this->moduleConfigs)) { + $this->loadModuleConfig(); } - $this->moduleConfigs = $this->fs->require($configPath); + return $this->moduleConfigs; } /** - * @return array> * @throws ModuleException */ - public function getModuleConfigs(): array + private function loadModuleConfig(): void { - if (empty($this->moduleConfigs)) { - $this->loadModuleConfig(); + $configPath = App::getBaseDir() . DS . 'shared' . DS . 'config' . DS . 'modules.php'; + + if (!$this->fs->exists($configPath)) { + throw ModuleException::moduleConfigNotFound(); } - return $this->moduleConfigs; + $this->moduleConfigs = $this->fs->require($configPath); } /** diff --git a/tests/Unit/Module/ModuleLoaderTest.php b/tests/Unit/Module/ModuleLoaderTest.php index d8e7abf0..1e5087df 100644 --- a/tests/Unit/Module/ModuleLoaderTest.php +++ b/tests/Unit/Module/ModuleLoaderTest.php @@ -2,6 +2,10 @@ namespace Quantum\Tests\Unit\Module; +use Quantum\Tests\_root\modules\Meme\Services\DisabledTokenService; +use Quantum\Tests\_root\modules\Test\Transformers\PostTransformer; +use Quantum\Transformer\Contracts\TransformerInterface; +use Quantum\Storage\Contracts\TokenServiceInterface; use Quantum\Tests\Unit\AppTestCase; use Quantum\Module\ModuleLoader; use Quantum\Di\Di; @@ -44,6 +48,27 @@ public function testLoadModulesRoutes(): void $this->assertInstanceOf(Closure::class, $modulesRoutes['Test']); } + public function testLoadModulesRoutesSkipsDisabledModule(): void + { + $this->setPrivateProperty($this->moduleLoader, 'moduleConfigs', [ + 'Meme' => [ + 'prefix' => 'meme', + 'enabled' => false, + ], + 'Test' => [ + 'prefix' => 'test', + 'enabled' => true, + ], + ]); + + $modulesRoutes = $this->moduleLoader->loadModulesRoutes(); + + $this->assertIsArray($modulesRoutes); + $this->assertArrayHasKey('Test', $modulesRoutes); + $this->assertArrayNotHasKey('Meme', $modulesRoutes); + $this->assertInstanceOf(Closure::class, $modulesRoutes['Test']); + } + public function testLoadModulesDependencies(): void { $deps = $this->moduleLoader->loadModulesDependencies(); @@ -55,6 +80,27 @@ public function testLoadModulesDependencies(): void $this->assertArrayHasKey(\Quantum\Storage\Contracts\TokenServiceInterface::class, $deps); $this->assertSame(\Quantum\Tests\_root\shared\Services\TokenService::class, $deps[\Quantum\Storage\Contracts\TokenServiceInterface::class]); + $this->assertNotSame(DisabledTokenService::class, $deps[TokenServiceInterface::class]); + } + + public function testLoadModulesDependenciesSkipsDisabledModule(): void + { + $this->setPrivateProperty($this->moduleLoader, 'moduleConfigs', [ + 'Meme' => [ + 'prefix' => 'meme', + 'enabled' => false, + ], + 'Test' => [ + 'prefix' => 'test', + 'enabled' => true, + ], + ]); + + $deps = $this->moduleLoader->loadModulesDependencies(); + + $this->assertArrayHasKey(TransformerInterface::class, $deps); + $this->assertSame(PostTransformer::class, $deps[TransformerInterface::class]); + $this->assertNotSame(DisabledTokenService::class, $deps[TokenServiceInterface::class]); } public function testGetModuleConfigs(): void @@ -65,4 +111,23 @@ public function testGetModuleConfigs(): void $this->assertArrayHasKey('Test', $configs); $this->assertArrayNotHasKey('Mame', $configs); } + + public function testGetModuleConfigsLoadsConfigWhenEmpty(): void + { + $this->setPrivateProperty($this->moduleLoader, 'moduleConfigs', []); + + $configs = $this->moduleLoader->getModuleConfigs(); + + $this->assertIsArray($configs); + $this->assertArrayHasKey('Test', $configs); + $this->assertArrayHasKey('Meme', $configs); + } + + public function testGetModuleDependenciesReturnsEmptyArrayWhenFileMissing(): void + { + $deps = $this->moduleLoader->getModuleDependencies('MissingModule'); + + $this->assertIsArray($deps); + $this->assertSame([], $deps); + } } diff --git a/tests/_root/modules/Meme/Services/DisabledTokenService.php b/tests/_root/modules/Meme/Services/DisabledTokenService.php new file mode 100644 index 00000000..ddd48aa1 --- /dev/null +++ b/tests/_root/modules/Meme/Services/DisabledTokenService.php @@ -0,0 +1,24 @@ + DisabledTokenService::class, +];