diff --git a/app/Controllers/PluginController.php b/app/Controllers/PluginController.php index 39ec429f..d2f6d8aa 100644 --- a/app/Controllers/PluginController.php +++ b/app/Controllers/PluginController.php @@ -40,9 +40,36 @@ public function index(Request $request, Response $response): Response $plugins = $this->pluginManager->getAllPlugins(); $pluginSettings = []; + // Which plugins expose a settings page (so the list can show a generic + // "Impostazioni" button for ANY such plugin, not just a hardcoded few — + // otherwise e.g. the Mobile API gate is unreachable from the UI). + $pluginHasSettings = []; foreach ($plugins as $plugin) { $settings = $this->pluginManager->getSettings((int) $plugin['id']); + // Settings-page detection: only meaningful for active plugins (the + // instance must be loaded). Mirror the settings-route guard. + $hasSettingsPage = false; + if (!empty($plugin['is_active'])) { + try { + $instance = $this->pluginManager->getPluginInstance((int) $plugin['id']); + if ($instance !== null + && is_callable([$instance, 'hasSettingsPage']) + && $instance->hasSettingsPage() + && is_callable([$instance, 'getSettingsViewPath']) + ) { + // Mirror settingsPage()'s guard exactly: a declared view + // path that doesn't exist on disk must NOT surface a button + // (the click would 404). + $viewPath = $instance->getSettingsViewPath(); + $hasSettingsPage = is_string($viewPath) && is_file($viewPath); + } + } catch (\Throwable $e) { + $hasSettingsPage = false; + } + } + $pluginHasSettings[$plugin['id']] = $hasSettingsPage; + // Handle Google Books API key if (array_key_exists('google_books_api_key', $settings)) { $settings['google_books_api_key_exists'] = $settings['google_books_api_key'] !== ''; @@ -300,6 +327,16 @@ public function updateSettings(Request $request, Response $response, array $args return $response->withHeader('Content-Type', 'application/json')->withStatus(404); } + // Self-rendering settings pages (e.g. Mobile API) post flat form fields and + // handle their OWN POST inside the view — CSRF, persistence via the plugin's + // saveSettings(), success message, re-render. The legacy AJAX handlers below + // require a nested `settings` payload; when it's absent, this is such a + // self-handling form, so render the settings page (which runs that logic) + // instead of falling through to "questo plugin non supporta impostazioni". + if (!is_array($body) || !array_key_exists('settings', $body)) { + return $this->settingsPage($request, $response, $args); + } + error_log('[PluginController] Plugin name: ' . $plugin['name']); $settings = $body['settings'] ?? []; diff --git a/app/Views/admin/plugins.php b/app/Views/admin/plugins.php index 1ef8d3b3..4ddc9ac8 100644 --- a/app/Views/admin/plugins.php +++ b/app/Views/admin/plugins.php @@ -5,6 +5,8 @@ $pageTitle = __('Gestione Plugin'); $pluginSettings = $pluginSettings ?? []; +/** @var array $pluginHasSettings */ +$pluginHasSettings = $pluginHasSettings ?? []; ?>
@@ -296,7 +298,15 @@ class="px-4 py-2 bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 tr - + +