Skip to content

Commit 2b3b8bc

Browse files
authored
Merge pull request #67 from trakli/feat/show-error-plugin
feat(plugins): List plugins with errors
2 parents 2606f40 + f63023a commit 2b3b8bc

File tree

2 files changed

+154
-33
lines changed

2 files changed

+154
-33
lines changed

app/Console/Commands/Plugin/ListCommand.php

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,75 @@
44

55
class ListCommand extends PluginCommand
66
{
7-
protected $signature = 'plugin:list';
7+
protected $signature = 'plugin:list
8+
{--debug : Show detailed error information for problematic plugins}';
89

9-
protected $description = 'List all available plugins';
10+
protected $description = 'List all available plugins.';
1011

1112
public function handle()
1213
{
1314
$plugins = $this->pluginManager->discover();
15+
$debug = $this->option('debug');
16+
$hasErrors = false;
17+
$errorMessages = [];
1418

1519
if ($plugins->isEmpty()) {
1620
$this->info('No plugins found.');
1721

1822
return 0;
1923
}
2024

21-
$rows = $plugins->map(function ($plugin) {
22-
return [
25+
$rows = [];
26+
27+
foreach ($plugins as $plugin) {
28+
$status = $plugin['enabled'] ? '<fg=green>Enabled</>' : '<fg=red>Disabled</>';
29+
$error = null;
30+
31+
// Check for common plugin issues
32+
if (isset($plugin['error'])) {
33+
$hasErrors = true;
34+
$status = '<fg=yellow>Error</>';
35+
$error = $plugin['error'];
36+
$errorMessages[] = "Plugin {$plugin['id']}: {$error}";
37+
} elseif ($debug) {
38+
// Additional debug checks
39+
if (! class_exists($plugin['provider'] ?? '')) {
40+
$error = "Provider class not found: {$plugin['provider']}";
41+
$status = '<fg=yellow>Error</>';
42+
$errorMessages[] = $error;
43+
}
44+
}
45+
46+
$rows[] = [
2347
'id' => $plugin['id'] ?? '',
24-
'name' => $plugin['name'],
48+
'name' => $plugin['name'] ?? 'Unknown',
2549
'version' => $plugin['manifest']['version'] ?? '1.0.0',
26-
'status' => $plugin['enabled'] ? '<fg=green>Enabled</>' : '<fg=red>Disabled</>',
50+
'status' => $status,
2751
'description' => $plugin['manifest']['description'] ?? 'No description',
52+
'error' => $debug ? ($error ?? '') : '',
2853
];
29-
})->toArray();
54+
}
55+
56+
$headers = ['ID', 'Name', 'Version', 'Status', 'Description'];
57+
if ($debug) {
58+
$headers[] = 'Error';
59+
}
60+
61+
$this->table($headers, $rows);
62+
63+
if ($hasErrors) {
64+
$this->error('Some plugins have issues. Use --debug for more details.');
3065

31-
$this->table(
32-
['ID', 'Name', 'Version', 'Status', 'Description'],
33-
$rows
34-
);
66+
if ($debug) {
67+
$this->line('');
68+
$this->warn('Error Details:');
69+
foreach ($errorMessages as $message) {
70+
$this->line(" - $message");
71+
}
72+
}
73+
74+
return 1;
75+
}
3576

3677
return 0;
3778
}

app/Services/PluginManager.php

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -125,59 +125,118 @@ public function discover(): Collection
125125
protected function loadPlugin(string $path): ?array
126126
{
127127
$manifestPath = "{$path}/plugin.json";
128+
$pluginDir = basename($path);
128129

129130
if (! File::exists($manifestPath)) {
130-
Log::warning("Plugin manifest not found: {$manifestPath}");
131+
$error = "Plugin manifest not found: {$manifestPath}";
132+
Log::error($error);
131133

132-
return null;
134+
return [
135+
'id' => $pluginDir,
136+
'name' => $pluginDir,
137+
'path' => $path,
138+
'error' => $error,
139+
'enabled' => false,
140+
];
133141
}
134142

135143
Log::debug("Loading plugin from: {$path}");
136144

137145
try {
138146
$manifest = $this->readManifest($manifestPath);
139147
if (! $manifest) {
140-
Log::warning("Plugin at {$path} is missing plugin.json");
141-
142-
return null;
148+
$error = "Plugin at {$path} has an invalid plugin.json file";
149+
Log::warning($error);
150+
151+
return [
152+
'id' => $pluginDir,
153+
'name' => $pluginDir,
154+
'path' => $path,
155+
'error' => $error,
156+
'enabled' => false,
157+
];
143158
}
144159

145160
if (! isset($manifest['namespace']) || ! isset($manifest['provider'])) {
146-
Log::warning("Plugin at {$path} is missing required fields in plugin.json");
147-
148-
return null;
161+
$error = 'Plugin is missing required fields in plugin.json (namespace and provider are required)';
162+
Log::warning("Plugin at {$path}: {$error}");
163+
164+
return [
165+
'id' => $manifest['id'] ?? $pluginDir,
166+
'name' => $manifest['name'] ?? $pluginDir,
167+
'path' => $path,
168+
'manifest' => $manifest,
169+
'error' => $error,
170+
'enabled' => false,
171+
];
149172
}
150173

151174
if (! isset($manifest['id'])) {
152-
Log::warning("Plugin manifest missing required 'id' field: {$manifestPath}");
153-
154-
return null;
175+
$error = "Plugin manifest missing required 'id' field";
176+
Log::warning("{$manifestPath}: {$error}");
177+
178+
return [
179+
'id' => $pluginDir,
180+
'name' => $manifest['name'] ?? $pluginDir,
181+
'path' => $path,
182+
'manifest' => $manifest,
183+
'error' => $error,
184+
'enabled' => $manifest['enabled'] ?? false,
185+
];
155186
}
156187

157188
$providerClass = $manifest['provider'];
158-
$namespace = rtrim($manifest['namespace'] ?? basename($path), '\\').'\\';
189+
$namespace = rtrim($manifest['namespace'], '\\').'\\';
159190

160191
$this->registerPluginAutoloading($namespace, $path);
161192

162193
if (! class_exists($providerClass)) {
163-
Log::warning("Plugin provider class not found: {$providerClass} in {$path}");
164-
165-
return null;
194+
$error = "Provider class not found: {$providerClass}";
195+
Log::warning("Plugin {$manifest['id']}: {$error}");
196+
197+
return [
198+
'id' => $manifest['id'],
199+
'name' => $manifest['name'] ?? $pluginDir,
200+
'path' => $path,
201+
'namespace' => $namespace,
202+
'manifest' => $manifest,
203+
'provider' => $providerClass,
204+
'error' => $error,
205+
'enabled' => $manifest['enabled'] ?? false,
206+
];
166207
}
167208

168209
return [
169210
'id' => $manifest['id'],
170-
'name' => $manifest['name'] ?? basename($path),
211+
'name' => $manifest['name'] ?? $pluginDir,
171212
'path' => $path,
172213
'namespace' => $namespace,
173214
'manifest' => $manifest,
174215
'provider' => $providerClass,
175216
'enabled' => $manifest['enabled'] ?? true,
176217
];
177218
} catch (\JsonException $e) {
178-
Log::error("Failed to parse plugin manifest: {$manifestPath} - ".$e->getMessage());
219+
$error = 'Failed to parse plugin manifest: '.$e->getMessage();
220+
Log::error("{$manifestPath}: {$error}");
179221

180-
return null;
222+
return [
223+
'id' => $pluginDir,
224+
'name' => $pluginDir,
225+
'path' => $path,
226+
'error' => $error,
227+
'enabled' => false,
228+
];
229+
} catch (\Exception $e) {
230+
$error = 'Error loading plugin: '.$e->getMessage();
231+
Log::error("{$path}: {$error}");
232+
233+
return [
234+
'id' => $pluginDir,
235+
'name' => $pluginDir,
236+
'path' => $path,
237+
'error' => $error,
238+
'enabled' => false,
239+
];
181240
}
182241
}
183242

@@ -394,7 +453,10 @@ protected function readManifest(string $manifestPath): ?array
394453
}
395454

396455
/**
397-
* Check if a plugin is enabled by its ID
456+
* Check if a plugin is enabled and valid.
457+
*
458+
* @param string $pluginId The plugin ID to check
459+
* @return bool True if the plugin is enabled and valid, false otherwise
398460
*/
399461
public function isPluginEnabled(string $pluginId): bool
400462
{
@@ -403,12 +465,28 @@ public function isPluginEnabled(string $pluginId): bool
403465
return false;
404466
}
405467

468+
if (isset($plugin['error'])) {
469+
return false;
470+
}
471+
472+
// Check if provider exists and is valid
473+
if (! isset($plugin['provider']) || empty($plugin['provider'])) {
474+
return false;
475+
}
476+
477+
if (! class_exists($plugin['provider'])) {
478+
Log::warning("Plugin provider class not found: {$plugin['provider']}");
479+
480+
return false;
481+
}
482+
406483
$manifestPath = $plugin['path'].'/plugin.json';
407484

408485
try {
409486
$manifest = $this->readManifest($manifestPath);
410487

411-
return $manifest ? ($manifest['enabled'] ?? true) : false;
488+
return $manifest ? (bool) ($manifest['enabled'] ?? true) : false;
489+
412490
} catch (\RuntimeException $e) {
413491
Log::error('Error reading plugin manifest', [
414492
'plugin' => $pluginId,
@@ -429,13 +507,15 @@ public function registerPlugins(): void
429507
Log::debug("Registered plugin service provider: {$plugin['provider']}");
430508
} catch (\Exception $e) {
431509
Log::error('Failed to register plugin service provider', [
432-
'provider' => $plugin['provider'] ?? 'unknown',
510+
'plugin' => $plugin['id'],
511+
'provider' => $plugin['provider'],
433512
'error' => $e->getMessage(),
434513
]);
435514
throw $e;
436515
}
437516
} else {
438-
Log::debug("Skipping disabled plugin: {$plugin['id']}");
517+
$reason = isset($plugin['error']) ? "error: {$plugin['error']}" : 'disabled';
518+
Log::debug("Skipping plugin {$plugin['id']}: {$reason}");
439519
}
440520
});
441521
}

0 commit comments

Comments
 (0)