From 9431c88ef0c2779430761622a54399a0dec23d02 Mon Sep 17 00:00:00 2001 From: Kofi Date: Thu, 2 Oct 2025 20:43:56 +0100 Subject: [PATCH 1/2] fix: Hide debug logs on production --- config/plugins.php | 10 ++++++ src/Services/PluginManager.php | 30 ++++++++-------- src/Traits/Loggable.php | 63 ++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 src/Traits/Loggable.php diff --git a/config/plugins.php b/config/plugins.php index f4913e5..b9355bf 100644 --- a/config/plugins.php +++ b/config/plugins.php @@ -22,4 +22,14 @@ | */ 'namespace' => 'Plugins', + + /* + |-------------------------------------------------------------------------- + | App Environment + |-------------------------------------------------------------------------- + | + | This value is used to determine if debug logs are shown + | + */ + 'environment' => env('APP_ENV', 'production'), ]; diff --git a/src/Services/PluginManager.php b/src/Services/PluginManager.php index 13862da..6fc5a07 100644 --- a/src/Services/PluginManager.php +++ b/src/Services/PluginManager.php @@ -7,12 +7,14 @@ use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Collection; use Illuminate\Support\Facades\File; -use Illuminate\Support\Facades\Log; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; +use WhileSmart\LaravelPluginEngine\Traits\Loggable; class PluginManager { + use Loggable; + protected Application $app; protected string $pluginsPath; @@ -85,7 +87,7 @@ protected function setPluginEnabled(string $pluginId, bool $enabled): bool return true; } catch (\Exception $e) { - Log::error('Failed to update plugin manifest: '.$e->getMessage(), [ + $this->error('Failed to update plugin manifest: '.$e->getMessage(), [ 'plugin' => $pluginId, 'path' => $manifestPath, 'exception' => $e, @@ -123,15 +125,15 @@ public function findPlugin(string $pluginId): ?array public function discover(): Collection { if (! empty($this->plugins)) { - Log::debug('Returning cached plugins'); + $this->debug('Returning cached plugins'); return collect($this->plugins); } - Log::debug('Starting plugin discovery', ['path' => $this->pluginsPath]); + $this->debug('Starting plugin discovery', ['path' => $this->pluginsPath]); if (! is_dir($this->pluginsPath)) { - Log::warning("Plugins directory not found: {$this->pluginsPath}"); + $this->warning("Plugins directory not found: {$this->pluginsPath}"); return collect(); } @@ -144,17 +146,17 @@ public function discover(): Collection $foundDirs[] = $directory->getBasename(); if (! $directory->isDir() || $directory->isDot()) { - Log::debug('Skipping non-directory or dot file', ['path' => $directory->getPathname()]); + $this->debug('Skipping non-directory or dot file', ['path' => $directory->getPathname()]); continue; } $pluginPath = $directory->getPathname(); $manifestPath = $pluginPath.'/plugin.json'; - Log::debug('Checking plugin directory', ['path' => $pluginPath]); + $this->debug('Checking plugin directory', ['path' => $pluginPath]); if (! file_exists($manifestPath)) { - Log::debug("Plugin manifest not found in: {$pluginPath}"); + $this->debug("Plugin manifest not found in: {$pluginPath}"); // Include in results with error $plugins[] = [ 'path' => $pluginPath, @@ -165,7 +167,7 @@ public function discover(): Collection continue; } - Log::debug('Found plugin manifest', ['path' => $manifestPath]); + $this->debug('Found plugin manifest', ['path' => $manifestPath]); $plugin = $this->loadPlugin($pluginPath); // Always include the plugin in the results, even if there was an error @@ -180,7 +182,7 @@ public function discover(): Collection $actualDirName, $expectedDirName ); - Log::warning($warning); + $this->warning($warning); $plugin['warning'] = $warning; } @@ -202,7 +204,7 @@ protected function loadPlugin(string $pluginPath): ?array if (! isset($manifest['id'])) { $error = "Plugin manifest missing required 'id' field"; - Log::error($error, ['path' => $manifestPath]); + $this->error($error, ['path' => $manifestPath]); return [ 'path' => $pluginPath, @@ -219,7 +221,7 @@ protected function loadPlugin(string $pluginPath): ?array return $plugin; } catch (\JsonException $e) { $error = 'Invalid JSON in plugin manifest: '.$e->getMessage(); - Log::error($error, [ + $this->error($error, [ 'path' => $manifestPath, 'exception' => $e, ]); @@ -290,13 +292,13 @@ public function registerPlugins() if (class_exists($plugin['provider'])) { $this->app->register($plugin['provider']); } else { - Log::error("Plugin service provider class not found: {$plugin['provider']}", [ + $this->error("Plugin service provider class not found: {$plugin['provider']}", [ 'plugin' => $plugin['id'] ?? 'unknown', 'path' => $plugin['path'] ?? null, ]); } } catch (\Exception $e) { - Log::error('Failed to register plugin: '.$e->getMessage(), [ + $this->error('Failed to register plugin: '.$e->getMessage(), [ 'plugin' => $plugin['id'] ?? 'unknown', 'exception' => $e, ]); diff --git a/src/Traits/Loggable.php b/src/Traits/Loggable.php new file mode 100644 index 0000000..62b264d --- /dev/null +++ b/src/Traits/Loggable.php @@ -0,0 +1,63 @@ +info("$class: $message", $context); + } + + private function error(string $message, array $context = []): void + { + $class = get_class($this); + logger()->error("$class: $message", $context); + } + + private function warning(string $message, array $context = []): void + { + $class = get_class($this); + logger()->warning("$class: $message", $context); + } + + private function debug(string $message, array $context = []): void + { + // Show debug logs only on development environments + if (config('plugins.environment', 'production') != 'production') { + $class = get_class($this); + logger()->debug("$class: $message", $context); + } + } + + private function critical(string $message, array $context = []): void + { + $class = get_class($this); + logger()->critical("$class: $message", $context); + } + + private function alert(string $message, array $context = []): void + { + $class = get_class($this); + logger()->alert("$class: $message", $context); + } + + private function emergency(string $message, array $context = []): void + { + $class = get_class($this); + logger()->emergency("$class: $message", $context); + } + + private function notice(string $message, array $context = []): void + { + $class = get_class($this); + logger()->notice("$class: $message", $context); + } + + private function log($level, string $message, array $context = []): void + { + $class = get_class($this); + logger()->log($level, "$class: $message", $context); + } +} From e37cc1d96c43d062661d275298bac57e3daefb37 Mon Sep 17 00:00:00 2001 From: Kofi Date: Thu, 2 Oct 2025 20:44:44 +0100 Subject: [PATCH 2/2] chore: Fix deprecated error in test files --- tests/Feature/Plugin/PluginCommandsTest.php | 24 +++++++-------------- tests/Feature/Plugin/PluginManagerTest.php | 24 +++++++-------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/tests/Feature/Plugin/PluginCommandsTest.php b/tests/Feature/Plugin/PluginCommandsTest.php index 1063ce9..213adc0 100644 --- a/tests/Feature/Plugin/PluginCommandsTest.php +++ b/tests/Feature/Plugin/PluginCommandsTest.php @@ -51,24 +51,21 @@ protected function resetExamplePluginState(): void } } - /** @test */ - public function it_lists_plugins() + public function test_it_lists_plugins() { $this->artisan('plugin:list') ->assertExitCode(0) ->expectsOutputToContain('Example Plugin'); } - /** @test */ - public function it_shows_plugin_info() + public function test_it_shows_plugin_info() { $this->artisan('plugin:info example') ->assertExitCode(0) ->expectsOutputToContain('Example Plugin'); } - /** @test */ - public function it_enables_plugins() + public function test_it_enables_plugins() { $this->artisan('plugin:disable example') ->assertExitCode(0); @@ -81,32 +78,28 @@ public function it_enables_plugins() ->assertExitCode(0); } - /** @test */ - public function it_disables_plugins() + public function test_it_disables_plugins() { $this->artisan('plugin:disable example') ->assertExitCode(0) ->expectsOutputToContain('disabled successfully'); } - /** @test */ - public function it_handles_nonexistent_plugin() + public function test_it_handles_nonexistent_plugin() { $this->artisan('plugin:info nonexistent') ->expectsOutputToContain('not found') ->assertExitCode(1); } - /** @test */ - public function it_suggests_similar_plugin_names() + public function test_it_suggests_similar_plugin_names() { $this->artisan('plugin:info examp') ->expectsOutputToContain('Did you mean one of these?') ->assertExitCode(1); } - /** @test */ - public function it_handles_invalid_plugin_manifest() + public function test_it_handles_invalid_plugin_manifest() { $pluginPath = $this->createTestPlugin('invalid_plugin', [ 'name' => 'Invalid Plugin', @@ -123,8 +116,7 @@ public function it_handles_invalid_plugin_manifest() ->expectsOutputToContain("Plugin 'invalid_plugin' has errors: Invalid JSON in plugin manifest: Syntax error"); } - /** @test */ - public function it_handles_missing_id_in_manifest() + public function test_it_handles_missing_id_in_manifest() { $pluginId = 'missing_id_plugin'; $pluginPath = "{$this->pluginsPath}/{$pluginId}"; diff --git a/tests/Feature/Plugin/PluginManagerTest.php b/tests/Feature/Plugin/PluginManagerTest.php index bb615ce..f25843d 100644 --- a/tests/Feature/Plugin/PluginManagerTest.php +++ b/tests/Feature/Plugin/PluginManagerTest.php @@ -89,8 +89,7 @@ public function boot() {} return $pluginPath; } - /** @test */ - public function it_can_discover_plugins() + public function test_it_can_discover_plugins() { $plugins = $this->pluginManager->discover(); @@ -106,8 +105,7 @@ public function it_can_discover_plugins() $this->assertNull($plugin, 'Should return null for non-existent plugin'); } - /** @test */ - public function it_can_find_a_plugin_by_id_case_insensitive() + public function test_it_can_find_a_plugin_by_id_case_insensitive() { $plugin = $this->pluginManager->findPlugin('EXAMPLE'); @@ -115,16 +113,14 @@ public function it_can_find_a_plugin_by_id_case_insensitive() $this->assertEquals('example', $plugin['id']); } - /** @test */ - public function it_returns_null_for_nonexistent_plugin() + public function test_it_returns_null_for_nonexistent_plugin() { $plugin = $this->pluginManager->findPlugin('nonexistent'); $this->assertNull($plugin, 'Should return null for non-existent plugin'); } - /** @test */ - public function it_validates_plugin_manifest() + public function test_it_validates_plugin_manifest() { $tempPath = storage_path('framework/testing/temp_plugin'); File::ensureDirectoryExists($tempPath); @@ -147,8 +143,7 @@ public function it_validates_plugin_manifest() $this->pluginManager = new PluginManager($this->app); } - /** @test */ - public function it_requires_plugin_id_to_match_directory_name() + public function test_it_requires_plugin_id_to_match_directory_name() { $tempPath = storage_path('framework/testing/mismatched_plugin'); File::ensureDirectoryExists($tempPath); @@ -179,8 +174,7 @@ public function it_requires_plugin_id_to_match_directory_name() $this->pluginManager = new PluginManager($this->app); } - /** @test */ - public function it_can_enable_and_disable_plugins() + public function test_it_can_enable_and_disable_plugins() { $this->assertTrue($this->pluginManager->isPluginEnabled('example')); $this->assertTrue($this->pluginManager->enablePlugin('example')); @@ -189,8 +183,7 @@ public function it_can_enable_and_disable_plugins() $this->assertTrue($this->pluginManager->disablePlugin('example')); } - /** @test */ - public function it_allows_access_to_protected_route_when_authenticated() + public function test_it_allows_access_to_protected_route_when_authenticated() { $this->pluginManager->enablePlugin('example'); $user = User::factory()->create(); @@ -211,8 +204,7 @@ public function it_allows_access_to_protected_route_when_authenticated() ]); } - /** @test */ - public function it_prevents_access_to_disabled_plugin_routes() + public function test_it_prevents_access_to_disabled_plugin_routes() { $this->pluginManager->enablePlugin('example');